[記錄]串接 GOOGLE API 取得資料(二)

前情提要

前篇說明為什麼我要作「精神力評鑑」

原因是為了記錄自已的精力,能更有效率使用時間,進而提昇個人的生產力.

應用

有了數據後, 就要看怎麼運用.
Google 的表單,可以自動產生回應結果試算表,
持之以恒的每天記錄,很快就有上百千筆的資料.

我打算取得這些資料後,繪制成分佈圖
這樣就可以知道,我的黃金時間是在每一天的什麼時段.

如何透過 GOOGLE Sheets API 可以取得資料.

Google Cloud Platform,建立起 Google API 的服務。

  1. 前往Google API Wizard,建立或選擇專案。
  2. 建立憑証,選擇 OAuth Client ID
    • 在這裡我會一次性的建立起所有環境(開發、測試、正式)的憑証 。
  3. 下載 JSON 放置專案的指定位置.
  4. 如何取得授權與取得資料,請參考QuickStart
    • 安全考量,我不會將 client_secret.json 與取回的 token 加入版本控制
    • 以 Google 試算表為例,如何取得spreadsheetId? 很簡單,網址上就可以取得。
      1
      2
      3
      ex:
      https://docs.google.com/spreadsheets/d/1qpyC0XzvTcKT6EISywvqESX3A0MwQoFDE8p-Bll4hps/edit#gid=0
      的spreadsheetId就是1qpyC0XzvTcKT6EISywvqESX3A0MwQoFDE8p-Bll4hps

說明

以 QuickStart 的程式為例 ,
下載回來的檔案 client_secret.json
可以提供 clientSecretclientId 與授權後轉導的 url ,
當程式執行時, 便會透 googleAuth 去取得授權 ,
過程之中會需要使用者作驗証, 驗証完成即取得授權 ,
授權有一定的效期, 故一段時間之後需要重新取得授權

其它

  1. client_secret.json 是機敏資料, 不可以放入版本控制, 需要特殊的流程步驟上傳到你的 Web Server 的位置 - Openshift 可以透過 SSH 或是 SFTP 登入來上傳client_secret.json - CI 以 JENKINS 為例 ; 可以使用 Publish over SSH 上傳檔案
    - 需要注意 CI Server 要有 Web Server 的 SSH Key - LINUX 複製資料夾語法 cp -rf src/folder/. target/folder

  2. 在正式公開的環境上可能會發生Error: invalid_scope的錯誤 ,可以參考

  3. 我最後是使用d3.js作為繪圖的 library , 因為網路上的資源相當的多 , 而且這次的著墨並不多 , 所以不在這裡介紹.

Demo

參考

  1. Openshift SFPT
  2. Linux CP

(fin)

[記錄]串接 GOOGLE API 取得資料(一)

原由

最近看了一本書,「最有生產力的一年」. 書如其名,是一本有關生產力的書,作者用了一年的時間,

以自已作實驗,測試各種方法並檢驗是否有效.

作者認為,時間 x 專注力 x 精力 = 生產力, 在他眾多的方法之中,

「黃金時間」與「精神力評鑑」是一組相關的方法.

簡單的說,一個人的精力狀況,會隨著一天的生理、心理等客觀或主觀因素起起伏伏,

就像潮汐一樣,而作者認為人應該在精力最好的時段,作最有價值的事.

這個時段就被稱作「黃金時間」.

有些人黃金時間在早上,有些人在晚上,每個人都不相同,

因此需要記錄精神狀態來判斷.

規劃

於是我設計一組簡單的方法來記錄精神狀態

透過 google 表單用來作記錄,

狀態我以 10 分制來作為評選, 再兩兩一組, 共分為五組「優、良、佳、可、劣」

在評鑑時先以五分法判斷精力狀況, 再以感覺是好一點或差一點來選取分數.

行動化

以我個人的習慣, 手機其實是不離身的, 如果每次記錄都要在個人電腦上作業, 其實是很不方便的.

所以我參考了電腦玩物的「Excel 記帳雲端進化! Google 表單比記帳 App 還好用

將我的表單(偽)APP 化

如此一來便完成了方便記錄的工具, 至於記錄下來的數據如何應用

又是後話了. 不過順帶一提,我會透過整點報時的工具來提醒自已作記錄,

另外我不像「最有生產力的一年」的作者特別準時睡覺,或是不喝咖啡,

因為不準時睡覺跟嗜飲咖啡是我目前的習慣,我認為抱持平常的狀態去記錄才有意義.

又或者當我戒掉咖啡或是開始早睡早起的習慣時,我就可以用記錄來評量這樣的行為是否有所改善.

(fin)

[活動筆記] 測試即學習

應該知道的事

流程

讀這篇文章的人,或許可以找一位朋友來作相同的流程練習

  1. 一張不明所以的圖片當作受測對象,任意發散的詢問測試問題
  2. 分類所有的問題為 WHY、HOW、WHAT
  3. 畫出 Golden Circle,核心是 WHY
  4. 透過 WHY 揭露受測對象圖片的本質(TAROT),收斂測試範圍
  5. 重新詢問測試問題,儘可能的發散
  6. 所有人交流自已看到可能的測試問題
  7. 重複 5~6 步,有意識的去覺察自已的感覺
    • 別人注意到的問題你為什麼沒發現?
    • 別人如何發現問題?
    • 你有沒有辦法發現相同的問題(殊途同歸)?

測試的概念

  1. 受測者
  2. 問題
  3. 答案
  4. 預期的結果(test oracles)

問題的核心 Know Your Mission(KNW)

  1. WHY ?
    本次分享的重點,如何了解、探索、學習產品的知識,給客戶的價值等… 。
  2. HOW ? => 如何作到?
  3. WHAT ? => 產生測試項目
  4. TEST ? => 執行測試,回饋並且回到第一步 Loop。

應該觀注的資訊 information is learning

  1. Customer
  2. Product
  3. Project
  4. Mission

透過 WHY 的詰問,了解你的任務(Know Your Mission)
學習到受測對象的本質,排除不必要的測試發想。
收斂了測試範圍,決定了測試方向。

探索測試

  1. 儘可能的發散
  2. 摹仿別人看事情的角度
  3. 有意識的學習(mindful learning)
    • 記錄
    • 總結
    • 歸納問題的核心
    • 給它起一個名字(沒有專有名詞的話)
    • 有意識的逃離第一印象
    • 小心不經意的盲區(Inattentional blindness)
    • 數量 X 練習 X 思考 X 學習 = 提昇

回饋

  1. 刻意練習 vs 有意識的練習,類似的東西,但是沒有具體的方法
  2. 課程中提到的影片

(fin)

CI/CD 環境建置筆記(二) - 在 windows 安裝 Jenkins 之旁門左道私有雲

應該要知道的事

問題

在 windows 上安裝了 Jenkins , 也建立了一個新的作業 ,
讓程式可以透過 Jenkins 執行自動化部署。
不過實務上仍有缺點,那就是只有這台機器可以執行部署 ,
最理想的狀況是擁有一個在雲端的 CI Server ,
隨時隨地想部署只需要能連上網 , 登入執行就好
這部份可以試試看 Travis-CICircleCI之類的服務 ;
不過對於只熟悉 Jenkins 的我來說 ,
我想了另一套解決辦法(旁門左道) ,
不過至少解決了我目前的需求 ,
在公司與家中隨時都能透過本機 Jenkins Server 進行部署 ,
並且不用花時間同步設定值.
在花時間研究Travis-CICircleCI的部署方式之前 ,
算是一個折衷的方式 .

方案

  1. 首先你要有 Dropbox
  2. 下載 Windows 版的 Jenkins
  3. 安裝在 Dropbox 資料夾內
  4. 在另外一台電腦 , 進行相同的安裝

想法很簡單 , 透過 Dropbox 與 Jenkins Service
在兩台電腦安裝 Jenkins
只要將 Jenkins Service 的啟動路徑
設定在 Dropbox 中 ,
就可以達成我們的目標 .

問題

  1. Windows 要如何修改 Jenkins Service 的啟動路徑 ?

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Jenkins

修改路徑以符合你本機的檔案位置即可。

(fin)

[活動筆記] 單元測試這樣玩就對了

應該知道的事

案例一、數值區間

1
2
3
4
5
6
假定給任一整數區間
ex:
(1,6] = {2,3,4,5,6}
[-2,4) = {-2,-1,0,1,2,3}
透過一個function(x)檢查x是否包含在整數區間內,
並撰寫測試,驗証 function(x)是對的。

解析

如上範例所示,
「(」「)」小括號(parentheses)表示OPEN(不包含,大於或小於)
「[」「]」中括號(square brackets)表示CLOSE(包含,大於等於或小於等於)
(1,6] , 代表這個區間大於 1 小於等於 6,包含的整數有 2、3、4、5、6
[-2,4), 代表這個區間大於等於-2 小於 4,包含的整數有-2、-1、0、1、2、3

解析

這題比較單純,只需要考慮所有的情況,
並且寫成單元測試即可。

  1. x 落在區間內
  2. x 落在左邊界外
  3. x 落在右邊界外
  4. x 落在左邊界上,左邊界為OPEN
  5. x 落在左邊界上,左邊界為CLOSE
  6. x 落在右邊界上,右邊界為OPEN
  7. x 落在右邊界上,右邊界為CLOSE

有幾種特殊的情境,特別說明一下

  1. 假設區間為(0,1),這個區間是不包含任何整數
  2. 假設區間為(1,1),這個區間是不包含任何整數,且不包含任何數值
  3. 假設區間為[1,1],這個區間恰巧包含 1 個整數,且只包含 1 這個整數
  4. 假設”區間”為[2,1],或任何左邊界大右邊界的表示,這不是一個正確的區間,將要作例外處理。

讓我們回歸單元測試,
這裡的重點是一個測試只作一件事,
只把一個情境釐清,並且在測試的程式碼中
明確的表達測試目的

1
2
3
4
5
6
7
8
9
10
11
12
private int leftBound = 1;
private int rightBound = 6;
private int testNum = 4;

[TestMethod]
public void IncludeWhenLeftOpenRightClose()
{
var checker = new RangeChecker(Bound.Open,this.leftBound,Bound.Close,this.rightBound);
bool expect = false;
bool result = checker.IsContains(testNum);
Assert.IsTrue(result);
}

案例二、現在時間轉字串

1
2
3
寫一個方法GetNowString,不傳入任何參數,
取得現在的時間字串,需要精準到豪秒。
再寫一個測試去測試這個方法是對的‧

版本 1

最簡單的寫法:

1
2
3
4
5
6
7
public class DateHelper
{
public string GetNowString()
{
return DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ff");
}
}

撰寫測試

1
2
3
4
5
6
7
8
9
[TestMethod]
public void GetNowString()
{
var
//// 寫不下去,因為我們無法凍結系統的時間
string expect = "2017-04-19 20:45:17.88";
string result = dater.GetNowString();
Assert.AreEqual(expect, result);
}

解析 1

GetNowString與系統的時間DateTime.Now,
是具有耦合性,要解耦需要透過一些 IoC 的手段去處理。

版本 2

利用繼承的方法,作出假的類別

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class DateHelper
{
protected DateTime now;
protected virtual DateTime GetNow()
{
now = DateTime.Now;
return now;
}

public string GetNowString()
{
GetNow();
return now.ToString("yyyy-MM-dd HH:mm:ss.ff");
}
}

class StubDateHelper: DateHelper
{
protected override DateTime GetNow()
{
return now;
}

public void SetNow(DateTime datetime)
{
now = datetime;
}
}

撰寫測試

1
2
3
4
5
6
7
8
9
10
[TestMethod]
public void GetNowString()
{
StubDateHelper dateHelper = new StubDateHelper();
var fakeNow = new DateTime(2017,4,19,20,45,17,880);
dateHelper.SetNow(fakeNow);
string expect = "2017-04-19 20:45:17.88";
string result = dateHelper.GetNowString();
Assert.AreEqual(expect, result);
}

解析 2

基本上這樣就可以測試了,
原來的代碼,經過一定的重構,
透過virtual方法 GetNow,
Datetime.Now作了隔離
適當利用假類別,取代掉 GetNow 的方法。

這樣夠好了,但是我們可以看看另一種作法

版本 3

先看看我們的DateHelper,
在這裡我們將 GetNow 交由 IDateProvider 的類別去實作,
如此一來就斷開了耦合性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DateHelper
{
private IDateProvider DateProvider;

public DateHelper(IDateProvider dateProvider)
{
this.DateProvider = dateProvider;
}

public string GetNowString()
{
var now = this.DateProvider.GetNow();
return now.ToString("yyyy-MM-dd HH:mm:ss.ff");
}
}

實作 IDateProvider 的類別,
在這裡其實不重要.

1
2
3
4
5
6
7
public class DateProviderV1 : IDateProvider
{
public DateTime GetNow()
{
return DateTime.Now;
}
}

讓我們看看測試,
在這裡我們透過一個假的IDateProvider的實作DateProviderStub,
完成了測試,
IDateProvider 將DateTime.Now作了隔離,
並且提供更容易修改的假物件(僅僅需要實作觀注的方法即可,不用擔心繼承帶來的附作用)

1
2
3
4
5
6
7
8
9
10
[TestMethod]
public void GetNowString()
{
DateProviderStub dateProvider = new DateProviderStub();
dateProvider.now = new DateTime(2017, 4, 19, 20, 45, 17, 880);
var dateHelper = new DateHelper(dateProvider);
string expect = "2017-04-19 20:45:17.88";
string result = dateHelper.GetNowString();
Assert.AreEqual(expect, result);
}
1
2
3
4
5
6
7
8
public class DateProviderStub : IDateProvider
{
public DateTime now;
public DateTime GetNow()
{
return now;
}
}

圖例解析

我們剛剛究竟幹了什麼?
我們剛剛究竟幹了什麼?
看看原本的情況,本來的方法因為相依與Datetime而無法測試
相依Datetime
讓我們開始下刀,
先用一個新的方法GetNow
將它與待測的方法作分割,
但是對整個類來說仍舊是耦合。
耦合
繼續把這刀往下切,
我們墊一層介面,
待測方法不再直接呼叫GetNow
而是透過介面執行,當然會有額外實作介面與注入的功(請參考程式碼,不在此處繪出了.)
透過介面執行
最後,別忘了我們的目的
測試原本的待測方法,
我們可以透過一個假的類,
來操控他的行為(ex:凍結時間).
如此一來,就可進行測試了.
測試
另外,這種被待測方法呼叫後
會回傳一個假值的方法或類
被叫作STUB
STUB

案例三、發送郵件

事先聲明,這題沒有程式碼,
有興趣實作的人可以試試看.
如果可以分享實作後的資訊給我更好 XD

Q:註冊發送郵件如何寫單元測試?

解析
很明顯的發送郵件需要依賴外部的郵件系統,
這裡就會有耦合性,我們可以參考案例 2 的方式解耦
不過發送郵件並不會有回傳值,
我們要如何驗証正確性呢?

A:檢查調用次數、參數

圖例解析
在案例 2 的單元測試,
我們透過 STUB 偽造的回傳值完成測試
並執行驗証.
但是在沒有回傳的值的方法中(被稱作MOCK)
我們只能透過傳遞的參數(如果有多載)
與方法被調用的次數來進行驗証。

MOCK

重點摘要

  • 單元測試要能清楚表達測試的目的(達意)
    • 命名
    • 減少意外的細節
  • 單元測試一次只作一件事
  • new 本身就是一種邏輯 一種偶合
  • static 是一種高偶合
  • 繼承也是高偶合,能使用繼承的情境很少
    • A is a B 通常只有這種情境才適合繼承
  • STUB & MOCK
    • STUB 會有回傳值,可以在 Unit Test 作驗証(ASSERT)
    • MOCK 沒有回傳值,可以在 MOCK 本身中 作驗証(ASSERT)

其它

  • SLIM
  • 注入相依的幾種方式
    • Pool
    • Constructor
    • Property
  • 書單 : XUnit Test Patterns

直播影片

如果連結失效,煩請告知.

文章內容如有謬誤,煩請指正.

(fin)

[閱讀筆記] 其實,你不是沒有時間

六個工具與餐盤

  • 原則:工具簡單至上
  • 面對突發狀況
  1. 月計劃表 (google calendar)
    • 與自已約會(保留給自已的時間)^註 1^
    • 工作與私人不要分開
    • 日期與期限
  2. Todo List (inbox)
    • 提醒與集中管理
    • 每天都要檢查一遍^註 2^
  3. 日計劃表 (google calendar)
    • 當日約會 & 活動清單
    • 活動清單是你當天的籌碼 也是出現突發
  4. 隨手記 (筆記本&Evernote)
    • 接受任務,再轉到其他工具之中^註 3^
  5. 隨身資料庫 (google drive)
    • 將整理過的資料封存在隨手可得的地方
      ex: 上課或分享的簡報、 專案記錄等…有大量圖片、文件等
  6. 溝通工具 (line & slack)
    • 一天檢查電子郵件 3~6 次就夠了

把時間變空間(視覺化)

  • 個人、家庭、工作取得平衡
  • 安排 30 分鐘規劃一天的活動
    • 創造性活動安排在精力最佳的時段
    • 安排獨處的時間
    • 安排恢復精力的時間
    • 預留時間給可能發生的突發事件
  • 將所有的事情分為紅綠黃(灰)^註 4^,綠色應該越多越好,灰色越少越好。
    6 am7 am8 am9 am10 am11 am12 am1 pm
    5 am本日活動隨手記2 pm
    4 am3 pm
    3 am4 pm
    2 am5 pm
    1 am12 am11 pm10 pm9 pm8 pm7 pm6 pm

應變執行,計劃趕不上變化

  • 調整事情的順序
  • 養成習慣
  • 臨機應變
  • 小心多工
  • 保留風格

  1. 分別為聖的時間,請參考與時間作朋友
  2. 利用分別為聖的時間檢查
  3. 餐盤中間的區塊可以用來作當日的活動清單 & 隨手記
  4. 可以參考四象限 重要-緊急(紅)、不重要-緊急(黃)、重要-不緊急(綠)、不重要-不緊急(灰)

(fin)

自動化 Trello 操作

Trello 是一個非常方便的工作管理工具,
最主要的功能只有 Boards 、 Lists 與 Cards,
確可以發揮相當大的綜效功能,
用來當作敏捷開發的白板、安排工作項目與進度,
作為協作的平台與工具。
也有相當多元的外掛可以供不同的情境使用,
開發人員也可以自行串接 API 與系統作整合。
簡單記錄自動化產生 Cards 的兩種方法。

第一種方法,使用 mail

  1. 開啟 Menu > More
  2. 點選 Email-to-board Settings
  3. 選擇你要產生卡片的 List 與 位置(頂部或底部)

  1. 寄信,信件格式如下
    • email 的 subject 會成為卡片的標題
    • email 的內容會成為卡片的描述
    • 如果有附加檔案在郵件中,會附加到卡片中
    • 在 subject 加入 #label 可以在卡片加入標籤(Labels)
    • 在 subject 加入 @member 可以在卡片加入成員(Members)

更多請參考.

第二種方法,使用 API

  1. 登入 Trello
  2. 連線 https://developers.trello.com
    點選Get your Application Key. 連線到 https://trello.com/app-key

取得 Key

生成 Token


點選 allow 後,就會顯示你的 token,特別注意登入的身份權限,
並且千萬不要外洩你的 token 與 key 值。

試打 API,建立一張 Card 到指定的 List 中.
並且設定期限(due)與標籤(labels),
更多的 API 設定請參考.

分析

  • Email:
    • 優點:簡單、方便、可以結合 mail system 、附加檔案簡單
    • 缺點:部份功能無法實現(ex: 設定 due date)
  • API:
    • 優點:靈活、Resful 的 API 可以實現大部份的功能
    • 缺點:實作比較麻煩

(fin)

ASP.NET Thread Pool 監控

前情提要

上一次說明了 .NET Thread Pool 的機制如何影響 Redis,
.NET Thread Pool 的機制會貫穿任何與它互動的系統或服務,
所以這篇會簡單描述如何對 .NET Thread Pool 建立監控

步驟

  1. 建立監控記數器
  2. 在系統寫入監控數值
  3. 開啟效能計數器

建立監控記數器

記數器 說明
Available Worker Threads 目前在 thread-pool 可以使用的 worker threads
Available IO Threads 目前在 thread-pool 可以使用的 I/O threads
Max Worker Threads 最大可以建立的 worker threads 數量
Max IO Threads 最大可以建立的 I/O threads 數量

建立一個 Console 應用程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System;
using System.Diagnostics;

class MyAspNetThreadCounters
{
[STAThread]
static void Main(string[] args)
{
CreateCounters();
Console.WriteLine("MyAspNetThreadCounters performance counter category " +
"is created. [Press Enter]");
Console.ReadLine();
}

public static void CreateCounters()
{
CounterCreationDataCollection col =
new CounterCreationDataCollection();

// Create custom counter objects
CounterCreationData counter1 = new CounterCreationData();
counter1.CounterName = "Available Worker Threads";
counter1.CounterHelp = "The difference between the maximum number " +
"of thread pool worker threads and the " +
"number currently active.";
counter1.CounterType = PerformanceCounterType.NumberOfItems32;

CounterCreationData counter2 = new CounterCreationData();
counter2.CounterName = "Available IO Threads";
counter2.CounterHelp = "The difference between the maximum number of " +
"thread pool IO threads and the number "+
"currently active.";
counter2.CounterType = PerformanceCounterType.NumberOfItems32;

CounterCreationData counter3 = new CounterCreationData();
counter3.CounterName = "Max Worker Threads";
counter3.CounterHelp = "The number of requests to the thread pool "+
"that can be active concurrently. All "+
"requests above that number remain queued until " +
"thread pool worker threads become available.";
counter3.CounterType = PerformanceCounterType.NumberOfItems32;

CounterCreationData counter4 = new CounterCreationData();
counter4.CounterName = "Max IO Threads";
counter4.CounterHelp = "The number of requests to the thread pool " +
"that can be active concurrently. All "+
"requests above that number remain queued until " +
"thread pool IO threads become available.";
counter4.CounterType = PerformanceCounterType.NumberOfItems32;

// Add custom counter objects to CounterCreationDataCollection.
col.Add(counter1);
col.Add(counter2);
col.Add(counter3);
col.Add(counter4);
// delete the category if it already exists
if(PerformanceCounterCategory.Exists("MyAspNetThreadCounters"))
{
PerformanceCounterCategory.Delete("MyAspNetThreadCounters");
}
// bind the counters to the PerformanceCounterCategory
PerformanceCounterCategory category =
PerformanceCounterCategory.Create("MyAspNetThreadCounters",
"", col);
}
}

編譯後並執行即可,
執行 regedit 開啟登錄編輯程式,
輸入機碼 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
將可以找到剛剛建立的 MyAspNetThreadCounters 記數器

在系統寫入監控數值

在站台的 Global.asax 加入以下的程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
public bool MonitorThreadPoolEnabled = true;

protected void Application_Start(Object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(RefreshCounters));
t.Start();
}

public void RefreshCounters()
{
while (MonitorThreadPoolEnabled)
{
ASPNETThreadInfo t = GetThreadInfo();
ShowPerfCounters(t);
System.Threading.Thread.Sleep(500);
}
}

protected void Application_End(Object sender, EventArgs e)
{
MonitorThreadPoolEnabled = false;
}

public struct ASPNETThreadInfo
{
public int MaxWorkerThreads;
public int MaxIOThreads;
public int MinFreeThreads;
public int MinLocalRequestFreeThreads;
public int AvailableWorkerThreads;
public int AvailableIOThreads;

public bool Equals(ASPNETThreadInfo other)
{
return (
MaxWorkerThreads == other.MaxWorkerThreads &&
MaxIOThreads == other.MaxIOThreads &&
MinFreeThreads == other.MinFreeThreads &&
MinLocalRequestFreeThreads == other.MinLocalRequestFreeThreads &&
AvailableWorkerThreads == other.AvailableWorkerThreads &&
AvailableIOThreads == other.AvailableIOThreads
);
}
}

public ASPNETThreadInfo GetThreadInfo()
{
// use ThreadPool to get the current status
int availableWorker, availableIO;
int maxWorker, maxIO;

ThreadPool.GetAvailableThreads( out availableWorker, out availableIO);
ThreadPool.GetMaxThreads(out maxWorker, out maxIO);

ASPNETThreadInfo threadInfo;
threadInfo.AvailableWorkerThreads = (Int16)availableWorker;
threadInfo.AvailableIOThreads = (Int16)availableIO;
threadInfo.MaxWorkerThreads = (Int16)maxWorker;
threadInfo.MaxIOThreads = (Int16)maxIO;
// hard code for now; could get this from machine.config
threadInfo.MinFreeThreads = 8;
threadInfo.MinLocalRequestFreeThreads = 4;
return threadInfo;
}

public void ShowPerfCounters(ASPNETThreadInfo t)
{

// get an instance of our Available Worker Threads counter
PerformanceCounter counter1 = new PerformanceCounter();
counter1.CategoryName = "MyAspNetThreadCounters";
counter1.CounterName = "Available Worker Threads";
counter1.ReadOnly = false;

// set the value of the counter
counter1.RawValue = t.AvailableWorkerThreads;
counter1.Close();

// repeat for other counters

PerformanceCounter counter2 = new PerformanceCounter();
counter2.CategoryName = "MyAspNetThreadCounters";
counter2.CounterName = "Available IO Threads";
counter2.ReadOnly = false;
counter2.RawValue = t.AvailableIOThreads;
counter2.Close();

PerformanceCounter counter3 = new PerformanceCounter();
counter3.CategoryName = "MyAspNetThreadCounters";
counter3.CounterName = "Max Worker Threads";
counter3.ReadOnly = false;
counter3.RawValue = t.MaxWorkerThreads;
counter3.Close();

PerformanceCounter counter4 = new PerformanceCounter();
counter4.CategoryName = "MyAspNetThreadCounters";
counter4.CounterName = "Max IO Threads";
counter4.ReadOnly = false;
counter4.RawValue = t.MaxIOThreads;
counter4.Close();
}

當你的站台重新啟動後,
就會定期將 Worker Thread 與 I/O Threads 的監控數值傳遞給系統。

開啟效能計數器

  1. 執行 perfmon.exe 開啟效能計數器
  2. 新增效能計數器(點選綠色加符號)
  3. 選取前面所建立監控記數器就能看到當前 ThreadPool 的使用狀況。
    開啟效能計數器

(fin)

IIS Tracing Log 設定

緣由

當你需要 Trace 送到 IIS 的每個 Request 的細節(包含在 pipe line 各個模組之間的 input/output 與 傳入的參數、header 等…),
可以透過開啟 tracing log 來作追蹤

環境

  1. Windows Server 2012 R2
  2. IIS 8.5.9600.16384

開啟 tracing log

  1. 新增 Tracing Rules

  2. 開啟網站 Tracing 功能

調整 IE Security 層級

  1. 使用 IE 開啟 Log,因 Security 設定無法套用版型

  2. 調整 ie enhanced security

  1. 開啟 IE > 點選小齒輪,選擇 Internet Options > 點選 Security 頁籤 > 將 Internet 的 Security Level 調整為 Medium-high

  2. 完成

(fin)

CI/CD 環境建置筆記 - 使用Openshift 的 Jenkins (失敗)

前情提要

操作記錄(失敗)

目標:

  • 在 Openshift 新增一個 Jenkins Server

失敗原因:

  • 我找不到方法在 Openshift 上建置的 Jenkins Server

記錄:

  1. 登入 OpenShift 的web console
  2. Add Application 選擇 Jenkins Server,使用預設設定 Create Application.
    Public URL 設定為 http://jenkins-youraccount.rhcloud.com
  3. 連線進 http://jenkins-youraccount.rhcloud.com 會發現需要帳密登入
  4. 取得帳號密碼
    1. 使用 SSH 連線 Openshift 的 Jenkins Server (可以在 web console 查到連結)
      > ssh 4263*****************@jenkins-youraccount.rhcloud.com
    2. 查看以下兩個檔案可以取得帳號密碼
      JENKINS_USERNAME
      JENKINS_PASSWORD
  5. 登入後,管理 Jenkins > 設定系統
    1. 將執行程式數量設定為 1
  6. 選擇新增作業
    1. 第一步要將原始碼自 Github pull 下來;在原始碼管理選擇Git , 設定好RepositoriesBranches to build
  7. 執行一次建置,這個步驟是為了產生 work space 。
  8. SSH 連線 Openshift,切換目錄到你的專案的 work space
    > ssh 4263*****************@jenkins-youraccount.rhcloud.com
    > cd app-root/data/workspace/your_project_name
  9. 檢查一下目前 Git 的遠端 Repo 有哪些
    > git remote -v
  10. 將 Openshift 上的 nodejs 應用程式 repo 設為 remote
    >git remote add openshift ssh://5**********************@nodejs-youraccount.rhcloud.com/~/git/nodejs.git/
  11. 推送到openshift remote
    失敗!!原因是權限問題,Openshift remote 是透過 SSH 連線,
    在認証公鑰的過程中,需要寫入 ~/.ssh/known_hosts 檔案。
    但是 Openshift 建立的 Jenkins Server 登入帳號,權限並不足以寫入而造成失敗

(fin)

Please enable JavaScript to view the LikeCoin. :P