本文裝載自:http://it.dianping.com/using_attribute_wrapping_performance_counter.htm
為要使用效能計數器對程式做監控,所以去MSDN查了一下效能計數器的實現,看完第一個感覺就是。。好麻煩。。如果要用計數器,要實現以下幾步:
- 建立計數器分類
- 建立計數器集合
- 建立計數器
- 建立計數器執行個體
- 初始化計數器執行個體
- 使用計數器執行個體
我想如果對於開發人員來說,為了實現監控,要寫那麼一大坨初始化代碼,肯定暈倒。。所以有必要對效能計數器的實現做一下封裝,讓開發變得更加方便簡單。
網上也看了很多種計數器的封裝實現,大多是用原廠模式進行的封裝,但感覺還是會有一定的冗餘代碼。於是嘗試了一下使用Attribute方式進行封裝,感覺效果還不錯,所以和大家分享一下。
我預期的效果是這樣的,首先是定義計數器集合:
Code
[CounterCategory("test")]
class XCounters
{
[CounterUnit("x", "value x", PerformanceCounterType.NumberOfItems64)]
public PerformanceCounter x;
[CounterUnit("y", "value y", PerformanceCounterType.RateOfCountsPerSecond64)]
public PerformanceCounter y;
}
通過Attribute,我希望達到以上這樣的結果,即可以定義計數器分類名,以及分類下每個計數器的名字,描述和計數器類型。
然後是使用:
Code
CounterContainer.Register<XCounters>();
XCounters counter = DPCounterContainer.Resolve<XCounters>();
for (int i = 0; i < 10000000; i++)
{
counter.x.Increment();
counter.y.Increment();
Thread.Sleep(300);
}
第一句話是將XCounter在Container裡註冊,由Container負責把XCounter裡定義的計數器分類,計數器集合進行建立初始化綁定工作。
第二句話是從Container裡擷取到XCounter計數器集合的執行個體。
第三第四句話就是對計數器的使用。每隔0.3秒,x,y計數器加1。最後啟動並執行效果如下:
所以進行了封裝以後,開發人員需要關注只是計數器集合的定義和使用,而不必關心那一大坨噁心的初始化代碼。
那以上的效果實現的話,Container到底是如何?的呢,我們再繼續討論下去:
其實最關鍵的就是Container的Register函數了,請看實現:
Code
public static bool Register<T>() where T : class, new()
{
//取得category名字
object[] attribs = typeof(T).GetCustomAttributes(typeof(CounterCategoryAttribute), false);
if (attribs.Length == 0) return false;
CounterCategoryAttribute attr = (CounterCategoryAttribute)attribs[0];
string category = attr.Name;
//檢查category是否已存在
bool countersExist = PerformanceCounterCategory.Exists(category);
//如果不存在,需要建立
if (countersExist == false)
{
//建立一個計數器集合
CounterCreationDataCollection list = new CounterCreationDataCollection();
foreach (FieldInfo prop in typeof(T).GetFields())
{
attribs = prop.GetCustomAttributes(typeof(CounterUnitAttribute), false);
foreach (CounterUnitAttribute fieldAttrib in attribs)
{
//建立計數器
CounterCreationData data = new CounterCreationData();
data.CounterName = fieldAttrib.Name;
data.CounterHelp = fieldAttrib.Help;
data.CounterType = fieldAttrib.Type;
//加入計數器集合
list.Add(data);
}
}
//建立category和計數器集合
PerformanceCounterCategory.Create(category, "", PerformanceCounterCategoryType.SingleInstance, list);
}
//建立並綁定計數器執行個體
T instance = new T();
foreach (FieldInfo prop in typeof(T).GetFields())
{
attribs = prop.GetCustomAttributes(typeof(CounterUnitAttribute), false);
foreach (CounterUnitAttribute fieldAttrib in attribs)
{
PerformanceCounter pc = new PerformanceCounter(category, fieldAttrib.Name, "",false);
pc.RawValue = 0;
prop.SetValue(instance, pc);
}
}
//存入hash表中,供Resolve函數讀取
_cntList.Add(typeof(T),instance);
return true;
}
通過這樣的封裝,大部分的重複代碼都被包起來了,使用起來會方便很多。具體的代碼我附在參考資料裡,供大家學習研究,望多提寶貴意見:)
本文轉載自:http://it.dianping.com/using_attribute_wrapping_performance_counter.htm
參考資料下載: http://it.dianping.com/using_attribute_wrapping_performance_counter.htm