diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..24d319c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,184 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+x64/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
+!packages/*/build/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+#NUNIT
+*.VisualState.xml
+TestResult.xml
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+*.log
+*.orig
+
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding addin-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+*.ncrunch*
+_NCrunch_*
+.*crunch*.local.xml
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.Publish.xml
+*.azurePubxml
+
+# NuGet Packages Directory
+## TODO: If you have NuGet Package Restore enabled, uncomment the next line
+packages/
+## TODO: If the tool you use requires repositories.config, also uncomment the next line
+#!packages/repositories.config
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.[Pp]ublish.xml
+*.pfx
+*.publishsettings
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+App_Data/*.mdf
+App_Data/*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# =========================
+# Windows detritus
+# =========================
+
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
\ No newline at end of file
diff --git a/Cat.Net.csproj b/Cat.Net.csproj
index a8b32cd..8d038f9 100644
--- a/Cat.Net.csproj
+++ b/Cat.Net.csproj
@@ -1,94 +1,100 @@
-
-
-
- Debug
- x86
- 10.0.0
- 2.0
- {7B5F7994-F1D1-494D-85B9-935A478591AD}
- Library
- Com.Dianping.Cat
- Cat
- 0.1.1
- false
- Cat .Net Client
- v4.0
-
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;
- prompt
- 4
- AnyCPU
- true
-
-
- none
- true
- bin\Release\
- prompt
- 4
- AnyCPU
- true
-
-
-
-
-
-
-
-
-
- Code
-
-
-
-
-
-
-
-
-
- Code
-
-
-
- Code
-
-
-
-
- Code
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Code
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ Debug
+ x86
+ 10.0.0
+ 2.0
+ {7B5F7994-F1D1-494D-85B9-935A478591AD}
+ Library
+ Com.Dianping.Cat
+ Cat
+ 0.1.1
+ false
+ Cat .Net Client
+ v4.0
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;
+ prompt
+ 4
+ AnyCPU
+ true
+
+
+ none
+ true
+ bin\Release\
+ prompt
+ 4
+ AnyCPU
+ true
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+ Code
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cat.Net.csproj.user b/Cat.Net.csproj.user
deleted file mode 100644
index 55f44b9..0000000
--- a/Cat.Net.csproj.user
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
- ShowAllFiles
-
-
\ No newline at end of file
diff --git a/Cat.Net.sln.DotSettings.user b/Cat.Net.sln.DotSettings.user
deleted file mode 100644
index 8641e71..0000000
--- a/Cat.Net.sln.DotSettings.user
+++ /dev/null
@@ -1,2 +0,0 @@
-
- False
\ No newline at end of file
diff --git a/Cat.Net.suo b/Cat.Net.suo
deleted file mode 100644
index 2667299..0000000
Binary files a/Cat.Net.suo and /dev/null differ
diff --git a/Cat.cs b/Cat.cs
index dbd6510..28bc714 100644
--- a/Cat.cs
+++ b/Cat.cs
@@ -1,193 +1,258 @@
-using Com.Dianping.Cat.Configuration;
-using Com.Dianping.Cat.Message.Spi;
-using System.Collections.Generic;
-using System.IO;
-using System.Xml;
-using System.Linq;
-using Com.Dianping.Cat.Message.Spi.Internals;
-using Com.Dianping.Cat.Util;
-
-namespace Com.Dianping.Cat
-{
- public class Cat
- {
- private static readonly Cat Instance = new Cat();
-
- private bool _mInitialized;
-
- private IMessageManager _mManager;
-
- private IMessageProducer _mProducer;
-
- private Cat()
- {
- }
-
- public static IMessageManager GetManager()
- {
- return Instance._mManager;
- }
-
- public static IMessageProducer GetProducer()
- {
- return Instance._mProducer;
- }
-
- public static void Initialize(string configFile)
- {
- if (Instance._mInitialized)
- {
- Logger.Warn("Cat can't initialize again with config file(%s), IGNORED!", configFile);
- return;
- }
-
- Logger.Info("Initializing Cat .Net Client ...");
-
- DefaultMessageManager manager = new DefaultMessageManager();
- ClientConfig clientConfig = LoadClientConfig(configFile);
-
- manager.InitializeClient(clientConfig);
- Instance._mProducer = new DefaultMessageProducer(manager);
- Instance._mManager = manager;
- Instance._mInitialized = true;
-
- Logger.Info("Cat .Net Client initialized.");
- }
-
- public static bool IsInitialized()
- {
- return Instance._mInitialized;
- }
-
- private static ClientConfig LoadClientConfig(string configFile)
- {
- ClientConfig config = new ClientConfig();
-
- if (File.Exists(configFile))
- {
- Logger.Info("Use config file({0}).", configFile);
-
- XmlDocument doc = new XmlDocument();
-
- doc.Load(configFile);
-
- XmlElement root = doc.DocumentElement;
-
- if (root != null)
- {
- config.Domain = BuildDomain(root.GetElementsByTagName("domain"));
-
- IEnumerable servers = BuildServers(root.GetElementsByTagName("servers"));
-
- //NOTE: 只添加Enabled的
- foreach (Server server in servers.Where(server => server.Enabled))
- {
- config.Servers.Add(server);
- Logger.Info("CAT server configured: {0}:{1}", server.Ip, server.Port);
- }
- }
- }
- else
- {
- Logger.Warn("Config file({0}) not found, using localhost:2280 instead.", configFile);
-
- config.Domain = BuildDomain(null);
- config.Servers.Add(new Server("localhost", 2280));
- }
-
- return config;
- }
-
- private static Domain BuildDomain(XmlNodeList nodes)
- {
- if (nodes == null || nodes.Count == 0)
- {
- return new Domain();
- }
-
- XmlElement node = (XmlElement) nodes[0];
- return new Domain
- {
- Id = GetStringProperty(node, "id", "Unknown"),
- //Ip = GetStringProperty(node, "ip", null),
- Enabled = GetBooleanProperty(node, "enabled", true)
- };
- }
-
- private static IEnumerable BuildServers(XmlNodeList nodes)
- {
- List servers = new List();
-
- if (nodes != null && nodes.Count > 0)
- {
- XmlElement first = (XmlElement) nodes[0];
- XmlNodeList serverNodes = first.GetElementsByTagName("server");
-
- foreach (XmlNode node in serverNodes)
- {
- XmlElement serverNode = (XmlElement) node;
- string ip = GetStringProperty(serverNode, "ip", "localhost");
- int port = GetIntProperty(serverNode, "port", 2280);
- Server server = new Server(ip, port) {Enabled = GetBooleanProperty(serverNode, "enabled", true)};
-
- servers.Add(server);
- }
- }
-
- if (servers.Count == 0)
- {
- Logger.Warn("No server configured, use localhost:2280 instead.");
- servers.Add(new Server("localhost", 2280));
- }
-
- return servers;
- }
-
- private static string GetStringProperty(XmlElement element, string name, string defaultValue)
- {
- if (element != null)
- {
- string value = element.GetAttribute(name);
-
- if (value.Length > 0)
- {
- return value;
- }
- }
-
- return defaultValue;
- }
-
- private static bool GetBooleanProperty(XmlElement element, string name, bool defaultValue)
- {
- if (element != null)
- {
- string value = element.GetAttribute(name);
-
- if (value.Length > 0)
- {
- return "true".Equals(value);
- }
- }
-
- return defaultValue;
- }
-
- private static int GetIntProperty(XmlElement element, string name, int defaultValue)
- {
- if (element != null)
- {
- string value = element.GetAttribute(name);
-
- if (value.Length > 0)
- {
- int tmpRet;
- if (int.TryParse(value, out tmpRet))
- return tmpRet;
- }
- }
-
- return defaultValue;
- }
- }
+using Com.Dianping.Cat.Configuration;
+using Com.Dianping.Cat.Message;
+using Com.Dianping.Cat.Message.Spi;
+using Com.Dianping.Cat.Message.Spi.Internals;
+using Com.Dianping.Cat.Util;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Xml;
+
+namespace Com.Dianping.Cat
+{
+ public class Cat
+ {
+ private static readonly Cat Instance = new Cat();
+
+ private bool _mInitialized;
+
+ private IMessageManager _mManager;
+
+ private IMessageProducer _mProducer;
+
+ private Cat()
+ {
+ }
+
+ public static IMessageManager GetManager()
+ {
+ return Instance._mManager;
+ }
+
+ public static IMessageProducer GetProducer()
+ {
+ return Instance._mProducer;
+ }
+
+ public static void Initialize(string configFile = null)
+ {
+ if (string.IsNullOrWhiteSpace(configFile))
+ configFile = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "App_Data\\TCConfig\\CatConfig.xml");
+ if (Instance._mInitialized)
+ {
+ Logger.Warn("Cat can't initialize again with config file(%s), IGNORED!", configFile);
+ return;
+ }
+
+ Logger.Info("Initializing Cat .Net Client ...");
+
+ DefaultMessageManager manager = new DefaultMessageManager();
+ ClientConfig clientConfig = LoadClientConfig(configFile);
+
+ manager.InitializeClient(clientConfig);
+ Instance._mProducer = new DefaultMessageProducer(manager);
+ Instance._mManager = manager;
+ Instance._mInitialized = true;
+ Logger.Info("Cat .Net Client initialized.");
+ }
+
+ public static bool IsInitialized()
+ {
+ bool isInitialized = Instance._mInitialized;
+ if (isInitialized && !Instance._mManager.HasContext())
+ {
+ Instance._mManager.Setup();
+ }
+ return isInitialized;
+ }
+
+ #region Log
+
+ public static void LogError(Exception ex)
+ {
+ Cat.GetProducer().LogError(ex);
+ }
+
+ public static void LogEvent(string type, string name, string status = "0", string nameValuePairs = null)
+ {
+ Cat.GetProducer().LogEvent(type, name, status, nameValuePairs);
+ }
+
+ public static void LogHeartbeat(string type, string name, string status = "0", string nameValuePairs = null)
+ {
+ Cat.GetProducer().LogHeartbeat(type, name, status, nameValuePairs);
+ }
+
+ public static void LogMetricForCount(string name, int quantity = 1)
+ {
+ LogMetricInternal(name, "C", quantity.ToString());
+ }
+
+ public static void LogMetricForDuration(string name, double value)
+ {
+ LogMetricInternal(name, "T", String.Format("{0:F}", value));
+ }
+
+ public static void LogMetricForSum(string name, double sum, int quantity)
+ {
+ LogMetricInternal(name, "S,C", String.Format("{0},{1:F}", quantity, sum));
+ }
+
+ private static void LogMetricInternal(string name, string status, string keyValuePairs = null)
+ {
+ Cat.GetProducer().LogMetric(name, status, keyValuePairs);
+ }
+
+ #endregion
+
+ #region New message
+
+ public static IEvent NewEvent(string type, string name)
+ {
+ return Cat.GetProducer().NewEvent(type, name);
+ }
+
+ public static ITransaction NewTransaction(string type, string name)
+ {
+ return Cat.GetProducer().NewTransaction(type, name);
+ }
+ #endregion
+
+ #region 配置文件属性获取
+
+ private static ClientConfig LoadClientConfig(string configFile)
+ {
+ ClientConfig config = new ClientConfig();
+
+ if (File.Exists(configFile))
+ {
+ Logger.Info("Use config file({0}).", configFile);
+
+ XmlDocument doc = new XmlDocument();
+
+ doc.Load(configFile);
+
+ XmlElement root = doc.DocumentElement;
+
+ if (root != null)
+ {
+ config.Domain = BuildDomain(root.GetElementsByTagName("domain"));
+
+ IEnumerable servers = BuildServers(root.GetElementsByTagName("servers"));
+
+ //NOTE: 只添加Enabled的
+ foreach (Server server in servers.Where(server => server.Enabled))
+ {
+ config.Servers.Add(server);
+ Logger.Info("CAT server configured: {0}:{1}", server.Ip, server.Port);
+ }
+ }
+ }
+ else
+ {
+ Logger.Warn("Config file({0}) not found.", configFile);
+ //Logger.Warn("Config file({0}) not found, using localhost:2280 instead.", configFile);
+
+ //config.Domain = BuildDomain(null);
+ //config.Servers.Add(new Server("localhost", 2280));
+ }
+
+ return config;
+ }
+
+ private static Domain BuildDomain(XmlNodeList nodes)
+ {
+ if (nodes == null || nodes.Count == 0)
+ {
+ return new Domain();
+ }
+
+ XmlElement node = (XmlElement)nodes[0];
+ return new Domain
+ {
+ Id = GetStringProperty(node, "id", "Unknown"),
+ //Ip = GetStringProperty(node, "ip", null),
+ Enabled = GetBooleanProperty(node, "enabled", false)
+ };
+ }
+
+ private static IEnumerable BuildServers(XmlNodeList nodes)
+ {
+ List servers = new List();
+
+ if (nodes != null && nodes.Count > 0)
+ {
+ XmlElement first = (XmlElement)nodes[0];
+ XmlNodeList serverNodes = first.GetElementsByTagName("server");
+
+ foreach (XmlNode node in serverNodes)
+ {
+ XmlElement serverNode = (XmlElement)node;
+ string ip = GetStringProperty(serverNode, "ip", "localhost");
+ int port = GetIntProperty(serverNode, "port", 2280);
+ Server server = new Server(ip, port) { Enabled = GetBooleanProperty(serverNode, "enabled", true) };
+
+ servers.Add(server);
+ }
+ }
+
+ if (servers.Count == 0)
+ {
+ Logger.Warn("No server configured, use localhost:2280 instead.");
+ servers.Add(new Server("localhost", 2280));
+ }
+
+ return servers;
+ }
+
+ private static string GetStringProperty(XmlElement element, string name, string defaultValue)
+ {
+ if (element != null)
+ {
+ string value = element.GetAttribute(name);
+
+ if (value.Length > 0)
+ {
+ return value;
+ }
+ }
+
+ return defaultValue;
+ }
+
+ private static bool GetBooleanProperty(XmlElement element, string name, bool defaultValue)
+ {
+ if (element != null)
+ {
+ string value = element.GetAttribute(name);
+
+ if (value.Length > 0)
+ {
+ return "true".Equals(value);
+ }
+ }
+
+ return defaultValue;
+ }
+
+ private static int GetIntProperty(XmlElement element, string name, int defaultValue)
+ {
+ if (element != null)
+ {
+ string value = element.GetAttribute(name);
+
+ if (value.Length > 0)
+ {
+ int tmpRet;
+ if (int.TryParse(value, out tmpRet))
+ return tmpRet;
+ }
+ }
+
+ return defaultValue;
+ }
+ #endregion
+
+ }
}
\ No newline at end of file
diff --git a/Configuration/ClientConfig.cs b/Configuration/ClientConfig.cs
index 86e7bf3..4131072 100644
--- a/Configuration/ClientConfig.cs
+++ b/Configuration/ClientConfig.cs
@@ -1,38 +1,38 @@
-using System.Collections.Generic;
-
-namespace Com.Dianping.Cat.Configuration
-{
- ///
- /// Cat客户端配置
- ///
- public class ClientConfig
- {
- private readonly IList _mServers;
- private Domain _mDomain;
-
- public ClientConfig()
- {
- _mServers = new List();
- }
-
- ///
- /// 是否是开发模式
- ///
- public bool DevMode { get; set; }
-
- public Domain Domain
- {
- get { return _mDomain ?? (_mDomain = new Domain()); }
-
- set { _mDomain = value; }
- }
-
- ///
- /// Cat日志服务器,可以有多个
- ///
- public IList Servers
- {
- get { return _mServers; }
- }
- }
+using System.Collections.Generic;
+
+namespace Com.Dianping.Cat.Configuration
+{
+ ///
+ /// Cat客户端配置
+ ///
+ public class ClientConfig
+ {
+ private readonly IList _mServers;
+ private Domain _mDomain;
+
+ public ClientConfig()
+ {
+ _mServers = new List();
+ }
+
+ ///
+ /// 是否是开发模式
+ ///
+ public bool DevMode { get; set; }
+
+ public Domain Domain
+ {
+ get { return _mDomain ?? (_mDomain = new Domain()); }
+
+ set { _mDomain = value; }
+ }
+
+ ///
+ /// Cat日志服务器,可以有多个
+ ///
+ public IList Servers
+ {
+ get { return _mServers; }
+ }
+ }
}
\ No newline at end of file
diff --git a/Configuration/Domain.cs b/Configuration/Domain.cs
index 63368ae..8c13f63 100644
--- a/Configuration/Domain.cs
+++ b/Configuration/Domain.cs
@@ -1,34 +1,34 @@
-namespace Com.Dianping.Cat.Configuration
-{
- ///
- /// 描述当前系统的情况
- ///
- public class Domain
- {
- private string _id = "Unknown";
- private bool _mEnabled = true;
-
- ///
- /// 当前系统的标识
- ///
- public string Id
- {
- get { return _id; }
- set { _id = value; }
- }
-
- /////
- ///// 当前系统的IP
- /////
- //public string Ip { get; set; }
-
- ///
- /// Cat日志是否开启,默认开启
- ///
- public bool Enabled
- {
- get { return _mEnabled; }
- set { _mEnabled = value; }
- }
- }
+namespace Com.Dianping.Cat.Configuration
+{
+ ///
+ /// 描述当前系统的情况
+ ///
+ public class Domain
+ {
+ private string _id = "Unknown";
+ private bool _mEnabled = false;
+
+ ///
+ /// 当前系统的标识
+ ///
+ public string Id
+ {
+ get { return _id; }
+ set { _id = value; }
+ }
+
+ /////
+ ///// 当前系统的IP
+ /////
+ //public string Ip { get; set; }
+
+ ///
+ /// Cat日志是否开启,默认关闭
+ ///
+ public bool Enabled
+ {
+ get { return _mEnabled; }
+ set { _mEnabled = value; }
+ }
+ }
}
\ No newline at end of file
diff --git a/Configuration/Server.cs b/Configuration/Server.cs
index 5dfebf5..3c01809 100644
--- a/Configuration/Server.cs
+++ b/Configuration/Server.cs
@@ -1,40 +1,40 @@
-namespace Com.Dianping.Cat.Configuration
-{
- ///
- /// 描述记录当前系统日志的目标Cat服务器
- ///
- public class Server
- {
- private readonly string _mIp;
-
- private readonly int _mPort;
-
- public Server(string ip, int port)
- {
- _mIp = ip;
- _mPort = port;
- Enabled = true;
- }
-
- ///
- /// Cat服务器IP
- ///
- public string Ip
- {
- get { return _mIp; }
- }
-
- ///
- /// Cat服务器端口
- ///
- public int Port
- {
- get { return _mPort; }
- }
-
- ///
- /// Cat服务器是否有效,默认有效
- ///
- public bool Enabled { get; set; }
- }
+namespace Com.Dianping.Cat.Configuration
+{
+ ///
+ /// 描述记录当前系统日志的目标Cat服务器
+ ///
+ public class Server
+ {
+ private readonly string _mIp;
+
+ private readonly int _mPort;
+
+ public Server(string ip, int port)
+ {
+ _mIp = ip;
+ _mPort = port;
+ Enabled = true;
+ }
+
+ ///
+ /// Cat服务器IP
+ ///
+ public string Ip
+ {
+ get { return _mIp; }
+ }
+
+ ///
+ /// Cat服务器端口
+ ///
+ public int Port
+ {
+ get { return _mPort; }
+ }
+
+ ///
+ /// Cat服务器是否有效,默认有效
+ ///
+ public bool Enabled { get; set; }
+ }
}
\ No newline at end of file
diff --git a/Message/IEvent.cs b/Message/IEvent.cs
index 21f006c..e8577fe 100644
--- a/Message/IEvent.cs
+++ b/Message/IEvent.cs
@@ -1,21 +1,21 @@
-namespace Com.Dianping.Cat.Message
-{
- ///
- ///
- /// Event
- /// is used to log anything interesting happens at a specific
- /// time. Such as an exception thrown, a review added by user, a new user
- /// registered, an user logged into the system etc.
However, if it could be failure, or last for a long time, such as a remote
- /// API call, database call or search engine call etc. It should be logged as a
- /// Transaction
- ///
All CAT message will be constructed as a message tree and send to back-end
- /// for further analysis, and for monitoring. Only
- /// Transaction
- /// can
- /// be a tree node, all other message will be the tree leaf.?The transaction
- /// without other messages nested is an atomic transaction.
- ///
- public interface IEvent : IMessage
- {
- }
+namespace Com.Dianping.Cat.Message
+{
+ ///
+ ///
+ /// Event
+ /// is used to log anything interesting happens at a specific
+ /// time. Such as an exception thrown, a review added by user, a new user
+ /// registered, an user logged into the system etc.
However, if it could be failure, or last for a long time, such as a remote
+ /// API call, database call or search engine call etc. It should be logged as a
+ /// Transaction
+ ///
All CAT message will be constructed as a message tree and send to back-end
+ /// for further analysis, and for monitoring. Only
+ /// Transaction
+ /// can
+ /// be a tree node, all other message will be the tree leaf.?The transaction
+ /// without other messages nested is an atomic transaction.
+ ///
+ public interface IEvent : IMessage
+ {
+ }
}
\ No newline at end of file
diff --git a/Message/IHeartbeat.cs b/Message/IHeartbeat.cs
index 290c473..addae00 100644
--- a/Message/IHeartbeat.cs
+++ b/Message/IHeartbeat.cs
@@ -1,27 +1,27 @@
-namespace Com.Dianping.Cat.Message
-{
- ///
- ///
- /// Heartbeat
- /// is used to log data that happens in a regular
- /// intervals, for example once per second, such as system load, CPU percentage,
- /// memory usage, thread pool statistics, cache hit/miss rate, service manifest
- /// etc., and even some configuration could be carried by
- /// Heartbeat
- /// .
- /// There could be some good use cases, for example health checker and load
- /// balancer, that make good use of it.
- /// Heartbeat
- /// should never be used per request since the request is
- /// not regular predictable, instead it could be logged in a daemon background
- /// thread, or something like a Timer.
All CAT message will be constructed as a message tree and send to back-end
- /// for further analysis, and for monitoring. Only
- /// Transaction
- /// can
- /// be a tree node, all other message will be the tree leaf.?The transaction
- /// without other messages nested is an atomic transaction.
- ///
- public interface IHeartbeat : IMessage
- {
- }
+namespace Com.Dianping.Cat.Message
+{
+ ///
+ ///
+ /// Heartbeat
+ /// is used to log data that happens in a regular
+ /// intervals, for example once per second, such as system load, CPU percentage,
+ /// memory usage, thread pool statistics, cache hit/miss rate, service manifest
+ /// etc., and even some configuration could be carried by
+ /// Heartbeat
+ /// .
+ /// There could be some good use cases, for example health checker and load
+ /// balancer, that make good use of it.
+ /// Heartbeat
+ /// should never be used per request since the request is
+ /// not regular predictable, instead it could be logged in a daemon background
+ /// thread, or something like a Timer.
All CAT message will be constructed as a message tree and send to back-end
+ /// for further analysis, and for monitoring. Only
+ /// Transaction
+ /// can
+ /// be a tree node, all other message will be the tree leaf.?The transaction
+ /// without other messages nested is an atomic transaction.
+ ///
+ public interface IHeartbeat : IMessage
+ {
+ }
}
\ No newline at end of file
diff --git a/Message/IMessage.cs b/Message/IMessage.cs
index 4deae9f..cb06003 100644
--- a/Message/IMessage.cs
+++ b/Message/IMessage.cs
@@ -1,108 +1,108 @@
-using System;
-
-namespace Com.Dianping.Cat.Message
-{
- /**
- *
- * Message represents data collected during application runtime. It will be sent
- * to back-end system asynchronous for further processing.
- *
- *
- *
- * Super interface of Event, Heartbeat and
- * Transaction.
- *
- *
- * @see Event, Heartbeat, Transaction
- * @author Frankie Wu
- */
-
- public interface IMessage
- {
- /**
- * @return key value pairs data
- */
- string Data { get; }
-
- /**
- * Message name.
- *
- * @return message name
- */
- string Name { get; }
-
- /**
- * Get the message status.
- *
- * @return message status. "0" means success, otherwise error code.
- */
- string Status { get; set; }
-
- /**
- * The time stamp the message was created.
- *
- * @return message creation time stamp in milliseconds
- */
- long Timestamp { get; set; }
-
- /**
- * Message type.
- *
- *
- * Typical message types are:
- *
- * - URL: maps to one method of an action
- * - Service: maps to one method of service call
- * - Search: maps to one method of search call
- * - SQL: maps to one SQL statement
- * - Cache: maps to one cache access
- * - Error: maps to java.lang.Throwable (java.lang.Exception and java.lang.Error)
- *
- *
- *
- * @return message type
- */
- string Type { get; }
-
- /**
- * add one or multiple key-value pairs to the message.
- *
- * @param keyValuePairs
- * key-value pairs like 'a=1&b=2&...'
- */
- void AddData(String keyValuePairs);
-
- /**
- * add one key-value pair to the message.
- *
- * @param key
- * @param value
- */
- void AddData(String key, Object value);
-
- /**
- * Complete the message construction.
- */
- void Complete();
-
- /**
- * If the complete() method was called or not.
- *
- * @return true means the complete() method was called, false otherwise.
- */
- bool IsCompleted();
-
- /**
- * @return
- */
- bool IsSuccess();
-
- /**
- * Set the message status with exception class name.
- *
- * @param e
- * exception.
- */
- void SetStatus(Exception e);
- }
+using System;
+
+namespace Com.Dianping.Cat.Message
+{
+ /**
+ *
+ * Message represents data collected during application runtime. It will be sent
+ * to back-end system asynchronous for further processing.
+ *
+ *
+ *
+ * Super interface of Event, Heartbeat and
+ * Transaction.
+ *
+ *
+ * @see Event, Heartbeat, Transaction
+ * @author Frankie Wu
+ */
+
+ public interface IMessage
+ {
+ /**
+ * @return key value pairs data
+ */
+ string Data { get; }
+
+ /**
+ * Message name.
+ *
+ * @return message name
+ */
+ string Name { get; }
+
+ /**
+ * Get the message status.
+ *
+ * @return message status. "0" means success, otherwise error code.
+ */
+ string Status { get; set; }
+
+ /**
+ * The time stamp the message was created.
+ *
+ * @return message creation time stamp in milliseconds
+ */
+ long Timestamp { get; set; }
+
+ /**
+ * Message type.
+ *
+ *
+ * Typical message types are:
+ *
+ * - URL: maps to one method of an action
+ * - Service: maps to one method of service call
+ * - Search: maps to one method of search call
+ * - SQL: maps to one SQL statement
+ * - Cache: maps to one cache access
+ * - Error: maps to java.lang.Throwable (java.lang.Exception and java.lang.Error)
+ *
+ *
+ *
+ * @return message type
+ */
+ string Type { get; }
+
+ /**
+ * add one or multiple key-value pairs to the message.
+ *
+ * @param keyValuePairs
+ * key-value pairs like 'a=1&b=2&...'
+ */
+ void AddData(String keyValuePairs);
+
+ /**
+ * add one key-value pair to the message.
+ *
+ * @param key
+ * @param value
+ */
+ void AddData(String key, Object value);
+
+ /**
+ * Complete the message construction.
+ */
+ void Complete();
+
+ /**
+ * If the complete() method was called or not.
+ *
+ * @return true means the complete() method was called, false otherwise.
+ */
+ bool IsCompleted();
+
+ /**
+ * @return
+ */
+ bool IsSuccess();
+
+ /**
+ * Set the message status with exception class name.
+ *
+ * @param e
+ * exception.
+ */
+ void SetStatus(Exception e);
+ }
}
\ No newline at end of file
diff --git a/Message/IMessageTree.cs b/Message/IMessageTree.cs
index 78f8f2f..b9a75e7 100644
--- a/Message/IMessageTree.cs
+++ b/Message/IMessageTree.cs
@@ -1,41 +1,41 @@
-using System;
-
-namespace Com.Dianping.Cat.Message
-{
- public interface IMessageTree
- {
- String Domain { get; set; }
-
-
- String HostName { get; set; }
-
-
- String IpAddress { get; set; }
-
-
- IMessage Message { get; set; }
-
-
- String MessageId { get; set; }
-
-
- String ParentMessageId { get; set; }
-
-
- String RootMessageId { get; set; }
-
-
- String SessionToken { get; set; }
-
-
- String ThreadGroupName { get; set; }
-
-
- String ThreadId { get; set; }
-
-
- String ThreadName { get; set; }
-
- IMessageTree Copy();
- }
+using System;
+
+namespace Com.Dianping.Cat.Message
+{
+ public interface IMessageTree
+ {
+ String Domain { get; set; }
+
+
+ String HostName { get; set; }
+
+
+ String IpAddress { get; set; }
+
+
+ IMessage Message { get; set; }
+
+
+ String MessageId { get; set; }
+
+
+ String ParentMessageId { get; set; }
+
+
+ String RootMessageId { get; set; }
+
+
+ String SessionToken { get; set; }
+
+
+ String ThreadGroupName { get; set; }
+
+
+ String ThreadId { get; set; }
+
+
+ String ThreadName { get; set; }
+
+ IMessageTree Copy();
+ }
}
\ No newline at end of file
diff --git a/Message/IMetric.cs b/Message/IMetric.cs
new file mode 100644
index 0000000..3ef0947
--- /dev/null
+++ b/Message/IMetric.cs
@@ -0,0 +1,6 @@
+namespace Com.Dianping.Cat.Message
+{
+ public interface IMetric : IMessage
+ {
+ }
+}
diff --git a/Message/ITransaction.cs b/Message/ITransaction.cs
index 21973e4..ac8813c 100644
--- a/Message/ITransaction.cs
+++ b/Message/ITransaction.cs
@@ -1,94 +1,94 @@
-using System.Collections.Generic;
-
-namespace Com.Dianping.Cat.Message
-{
- /**
- *
- * Transaction is any interesting unit of work that takes time to
- * complete and may fail.
- *
- *
- *
- * Basically, all data access across the boundary needs to be logged as a
- * Transaction since it may fail and time consuming. For example,
- * URL request, disk IO, JDBC query, search query, HTTP request, 3rd party API
- * call etc.
- *
- *
- *
- * Sometime if A needs call B which is owned by another team, although A and B
- * are deployed together without any physical boundary. To make the ownership
- * clear, there could be some Transaction logged when A calls B.
- *
- *
- *
- * Most of Transaction should be logged in the infrastructure level
- * or framework level, which is transparent to the application.
- *
- *
- *
- * All CAT message will be constructed as a message tree and send to back-end
- * for further analysis, and for monitoring. Only Transaction can
- * be a tree node, all other message will be the tree leaf. The transaction
- * without other messages nested is an atomic transaction.
- *
- *
- * @author Frankie Wu
- */
-
- public interface ITransaction : IMessage
- {
- /**
- * Get all children message within current transaction.
- *
- *
- * Typically, a Transaction can nest other
- * Transactions, Events and Heartbeat
- * s, while an Event or Heartbeat can't nest other
- * messages.
- *
- *
- * @return all children messages, empty if there is no nested children.
- */
- IList Children { get; }
-
- /**
- * How long the transaction took from construction to complete. Time unit is
- * microsecond.
- *
- * @return duration time in microsecond
- */
- long DurationInMicros { get; set; }
-
- /**
- * How long the transaction took from construction to complete. Time unit is
- * millisecond.
- *
- * @return duration time in millisecond
- */
- long DurationInMillis { get; set; }
-
- /**
- * Check if the transaction is stand-alone or belongs to another one.
- *
- * @return true if it's an root transaction.
- */
- bool Standalone { get; set; }
-
- /**
- * Add one nested child message to current transaction.
- *
- * @param message
- * to be added
- */
- ITransaction AddChild(IMessage message);
-
- /**
- * Has children or not. An atomic transaction does not have any children
- * message.
- *
- * @return true if child exists, else false.
- */
- bool HasChildren();
- }
+using System.Collections.Generic;
+
+namespace Com.Dianping.Cat.Message
+{
+ /**
+ *
+ * Transaction is any interesting unit of work that takes time to
+ * complete and may fail.
+ *
+ *
+ *
+ * Basically, all data access across the boundary needs to be logged as a
+ * Transaction since it may fail and time consuming. For example,
+ * URL request, disk IO, JDBC query, search query, HTTP request, 3rd party API
+ * call etc.
+ *
+ *
+ *
+ * Sometime if A needs call B which is owned by another team, although A and B
+ * are deployed together without any physical boundary. To make the ownership
+ * clear, there could be some Transaction logged when A calls B.
+ *
+ *
+ *
+ * Most of Transaction should be logged in the infrastructure level
+ * or framework level, which is transparent to the application.
+ *
+ *
+ *
+ * All CAT message will be constructed as a message tree and send to back-end
+ * for further analysis, and for monitoring. Only Transaction can
+ * be a tree node, all other message will be the tree leaf. The transaction
+ * without other messages nested is an atomic transaction.
+ *
+ *
+ * @author Frankie Wu
+ */
+
+ public interface ITransaction : IMessage
+ {
+ /**
+ * Get all children message within current transaction.
+ *
+ *
+ * Typically, a Transaction can nest other
+ * Transactions, Events and Heartbeat
+ * s, while an Event or Heartbeat can't nest other
+ * messages.
+ *
+ *
+ * @return all children messages, empty if there is no nested children.
+ */
+ IList Children { get; }
+
+ /**
+ * How long the transaction took from construction to complete. Time unit is
+ * microsecond.
+ *
+ * @return duration time in microsecond
+ */
+ long DurationInMicros { get; set; }
+
+ /**
+ * How long the transaction took from construction to complete. Time unit is
+ * millisecond.
+ *
+ * @return duration time in millisecond
+ */
+ long DurationInMillis { get; set; }
+
+ /**
+ * Check if the transaction is stand-alone or belongs to another one.
+ *
+ * @return true if it's an root transaction.
+ */
+ bool Standalone { get; set; }
+
+ /**
+ * Add one nested child message to current transaction.
+ *
+ * @param message
+ * to be added
+ */
+ ITransaction AddChild(IMessage message);
+
+ /**
+ * Has children or not. An atomic transaction does not have any children
+ * message.
+ *
+ * @return true if child exists, else false.
+ */
+ bool HasChildren();
+ }
}
\ No newline at end of file
diff --git a/Message/Internals/AbstractMessage.cs b/Message/Internals/AbstractMessage.cs
index 5d5345a..ba15fa2 100644
--- a/Message/Internals/AbstractMessage.cs
+++ b/Message/Internals/AbstractMessage.cs
@@ -1,126 +1,127 @@
-using System;
-using System.Text;
-using Com.Dianping.Cat.Message.Spi.Codec;
-using Com.Dianping.Cat.Util;
-
-namespace Com.Dianping.Cat.Message.Internals
-{
- public abstract class AbstractMessage : IMessage
- {
- private readonly String _mName;
- private readonly String _mType;
- private bool _mCompleted;
- private StringBuilder _mData;
-
- private String _mStatus = "unset";
-
- protected AbstractMessage(String type, String name)
- {
- _mType = type;
- _mName = name;
- TimestampInMicros = MilliSecondTimer.CurrentTimeMicros();
- }
-
- ///
- /// 其实是Ticks除以10
- ///
- protected long TimestampInMicros { get; private set; }
-
- #region IMessage Members
-
- public String Data
- {
- get { return _mData == null ? "" : _mData.ToString(); }
- }
-
- public String Name
- {
- get { return _mName; }
- }
-
- public String Status
- {
- get { return _mStatus; }
-
- set { _mStatus = value; }
- }
-
- ///
- /// 其实是Ticks除以10000
- ///
- public long Timestamp
- {
- get { return TimestampInMicros/1000L; }
- set { TimestampInMicros = value*1000L; }
- }
-
- public String Type
- {
- get { return _mType; }
- }
-
- public void AddData(String keyValuePairs)
- {
- if (_mData == null)
- {
- _mData = new StringBuilder(keyValuePairs);
- }
- else
- {
- _mData.Append(keyValuePairs);
- }
- }
-
- public void AddData(String key, Object value)
- {
- if (_mData == null)
- {
- _mData = new StringBuilder();
- }
- else if (_mData.Length > 0)
- {
- _mData.Append('&');
- }
-
- _mData.Append(key).Append('=').Append(value);
- }
-
- public virtual void Complete()
- {
- SetCompleted(true);
- }
-
- public bool IsCompleted()
- {
- return _mCompleted;
- }
-
- public bool IsSuccess()
- {
- return "0".Equals(_mStatus);
- }
-
- public void SetStatus(Exception e)
- {
- _mStatus = e.GetType().FullName;
- }
-
- #endregion
-
- protected void SetCompleted(bool completed)
- {
- _mCompleted = completed;
- }
-
- public override String ToString()
- {
- PlainTextMessageCodec codec = new PlainTextMessageCodec();
- ChannelBuffer buf = new ChannelBuffer(8192);
-
- codec.EncodeMessage(this, buf);
- buf.Reset();
-
- return buf.ToString();
- }
- }
+using System;
+using System.Text;
+using Com.Dianping.Cat.Message.Spi.Codec;
+using Com.Dianping.Cat.Util;
+
+namespace Com.Dianping.Cat.Message.Internals
+{
+ [Serializable]
+ public abstract class AbstractMessage : IMessage
+ {
+ private readonly String _mName;
+ private readonly String _mType;
+ private bool _mCompleted;
+ private StringBuilder _mData;
+
+ private String _mStatus = "unset";
+
+ protected AbstractMessage(String type, String name)
+ {
+ _mType = type;
+ _mName = name;
+ TimestampInMicros = MilliSecondTimer.CurrentTimeMicros();
+ }
+
+ ///
+ /// 其实是Ticks除以10
+ ///
+ protected long TimestampInMicros { get; private set; }
+
+ #region IMessage Members
+
+ public String Data
+ {
+ get { return _mData == null || _mData.Length == 0 ? string.Empty : _mData.ToString(); }
+ }
+
+ public String Name
+ {
+ get { return _mName; }
+ }
+
+ public String Status
+ {
+ get { return _mStatus; }
+
+ set { _mStatus = value; }
+ }
+
+ ///
+ /// 其实是Ticks除以10000
+ ///
+ public long Timestamp
+ {
+ get { return TimestampInMicros / 1000L; }
+ set { TimestampInMicros = value * 1000L; }
+ }
+
+ public String Type
+ {
+ get { return _mType; }
+ }
+
+ public void AddData(String keyValuePairs)
+ {
+ if (_mData == null)
+ {
+ _mData = new StringBuilder(keyValuePairs);
+ }
+ else
+ {
+ _mData.Append(keyValuePairs);
+ }
+ }
+
+ public void AddData(String key, Object value)
+ {
+ if (_mData == null)
+ {
+ _mData = new StringBuilder();
+ }
+ else if (_mData.Length > 0)
+ {
+ _mData.Append('&');
+ }
+
+ _mData.Append(key).Append('=').Append(value);
+ }
+
+ public virtual void Complete()
+ {
+ SetCompleted(true);
+ }
+
+ public bool IsCompleted()
+ {
+ return _mCompleted;
+ }
+
+ public bool IsSuccess()
+ {
+ return "0".Equals(_mStatus);
+ }
+
+ public void SetStatus(Exception e)
+ {
+ _mStatus = e.GetType().FullName;
+ }
+
+ #endregion
+
+ protected void SetCompleted(bool completed)
+ {
+ _mCompleted = completed;
+ }
+
+ public override String ToString()
+ {
+ PlainTextMessageCodec codec = new PlainTextMessageCodec();
+ ChannelBuffer buf = new ChannelBuffer(8192);
+
+ codec.EncodeMessage(this, buf);
+ buf.Reset();
+
+ return buf.ToString();
+ }
+ }
}
\ No newline at end of file
diff --git a/Message/Internals/DefaultEvent.cs b/Message/Internals/DefaultEvent.cs
index 450cf8d..3336aae 100644
--- a/Message/Internals/DefaultEvent.cs
+++ b/Message/Internals/DefaultEvent.cs
@@ -1,11 +1,12 @@
-using System;
-
-namespace Com.Dianping.Cat.Message.Internals
-{
- public class DefaultEvent : AbstractMessage, IEvent
- {
- public DefaultEvent(String type, String name) : base(type, name)
- {
- }
- }
+using System;
+
+namespace Com.Dianping.Cat.Message.Internals
+{
+ public class DefaultEvent : AbstractMessage, IEvent
+ {
+ public DefaultEvent(String type, String name)
+ : base(type, name)
+ {
+ }
+ }
}
\ No newline at end of file
diff --git a/Message/Internals/DefaultHeartbeat.cs b/Message/Internals/DefaultHeartbeat.cs
index 9725603..cffe0fe 100644
--- a/Message/Internals/DefaultHeartbeat.cs
+++ b/Message/Internals/DefaultHeartbeat.cs
@@ -1,11 +1,12 @@
-using System;
-
-namespace Com.Dianping.Cat.Message.Internals
-{
- public class DefaultHeartbeat : AbstractMessage, IHeartbeat
- {
- public DefaultHeartbeat(String type, String name) : base(type, name)
- {
- }
- }
+using System;
+
+namespace Com.Dianping.Cat.Message.Internals
+{
+ public class DefaultHeartbeat : AbstractMessage, IHeartbeat
+ {
+ public DefaultHeartbeat(String type, String name)
+ : base(type, name)
+ {
+ }
+ }
}
\ No newline at end of file
diff --git a/Message/Internals/DefaultMessageTree.cs b/Message/Internals/DefaultMessageTree.cs
index 047ea7c..b75a433 100644
--- a/Message/Internals/DefaultMessageTree.cs
+++ b/Message/Internals/DefaultMessageTree.cs
@@ -1,102 +1,102 @@
-using Com.Dianping.Cat.Message.Spi.Codec;
-using System;
-
-namespace Com.Dianping.Cat.Message.Internals
-{
- public class DefaultMessageTree : IMessageTree
- {
- private String _mMessageId;
-
- private String _mParentMessageId;
-
- private String _mRootMessageId;
-
- #region IMessageTree Members
-
- public IMessageTree Copy()
- {
- DefaultMessageTree tree = new DefaultMessageTree();
-
- tree.Domain = Domain;
- tree.HostName = HostName;
- tree.IpAddress = IpAddress;
- tree.MessageId = _mMessageId;
- tree.ParentMessageId = _mParentMessageId;
- tree.RootMessageId = _mRootMessageId;
- tree.SessionToken = SessionToken;
- tree.ThreadGroupName = ThreadGroupName;
- tree.ThreadId = ThreadId;
- tree.ThreadName = ThreadName;
- tree.Message = Message;
-
- return tree;
- }
-
- public string Domain { get; set; }
-
- public string HostName { get; set; }
-
- public string IpAddress { get; set; }
-
- public IMessage Message { get; set; }
-
- public String MessageId
- {
- get { return _mMessageId; }
- set
- {
- if (!string.IsNullOrEmpty(value))
- {
- _mMessageId = value;
- }
- }
- }
-
- public String ParentMessageId
- {
- get { return _mParentMessageId; }
- set
- {
- if (!string.IsNullOrEmpty(value))
- {
- _mParentMessageId = value;
- }
- }
- }
-
- public String RootMessageId
- {
- get { return _mRootMessageId; }
- set
- {
- if (!string.IsNullOrEmpty(value))
- {
- _mRootMessageId = value;
- }
- }
- }
-
- public string SessionToken { get; set; }
-
- public string ThreadGroupName { get; set; }
-
- public string ThreadId { get; set; }
-
- public string ThreadName { get; set; }
-
- #endregion
-
- public override String ToString()
- {
- PlainTextMessageCodec codec = new PlainTextMessageCodec();
- ChannelBuffer buf = new ChannelBuffer(8192);
-
- codec.Encode(this, buf);
-
- buf.Reset();
- buf.Skip(4); // get rid of length
-
- return buf.ToString();
- }
- }
+using Com.Dianping.Cat.Message.Spi.Codec;
+using System;
+
+namespace Com.Dianping.Cat.Message.Internals
+{
+ public class DefaultMessageTree : IMessageTree
+ {
+ private String _mMessageId;
+
+ private String _mParentMessageId;
+
+ private String _mRootMessageId;
+
+ #region IMessageTree Members
+
+ public IMessageTree Copy()
+ {
+ DefaultMessageTree tree = new DefaultMessageTree();
+
+ tree.Domain = Domain;
+ tree.HostName = HostName;
+ tree.IpAddress = IpAddress;
+ tree.MessageId = _mMessageId;
+ tree.ParentMessageId = _mParentMessageId;
+ tree.RootMessageId = _mRootMessageId;
+ tree.SessionToken = SessionToken;
+ tree.ThreadGroupName = ThreadGroupName;
+ tree.ThreadId = ThreadId;
+ tree.ThreadName = ThreadName;
+ tree.Message = Message;
+
+ return tree;
+ }
+
+ public string Domain { get; set; }
+
+ public string HostName { get; set; }
+
+ public string IpAddress { get; set; }
+
+ public IMessage Message { get; set; }
+
+ public String MessageId
+ {
+ get { return _mMessageId; }
+ set
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ _mMessageId = value;
+ }
+ }
+ }
+
+ public String ParentMessageId
+ {
+ get { return _mParentMessageId; }
+ set
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ _mParentMessageId = value;
+ }
+ }
+ }
+
+ public String RootMessageId
+ {
+ get { return _mRootMessageId; }
+ set
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ _mRootMessageId = value;
+ }
+ }
+ }
+
+ public string SessionToken { get; set; }
+
+ public string ThreadGroupName { get; set; }
+
+ public string ThreadId { get; set; }
+
+ public string ThreadName { get; set; }
+
+ #endregion
+
+ public override String ToString()
+ {
+ PlainTextMessageCodec codec = new PlainTextMessageCodec();
+ ChannelBuffer buf = new ChannelBuffer(8192);
+
+ codec.Encode(this, buf);
+
+ buf.Reset();
+ buf.Skip(4); // get rid of length
+
+ return buf.ToString();
+ }
+ }
}
\ No newline at end of file
diff --git a/Message/Internals/DefaultMetric.cs b/Message/Internals/DefaultMetric.cs
new file mode 100644
index 0000000..74ed63a
--- /dev/null
+++ b/Message/Internals/DefaultMetric.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Com.Dianping.Cat.Message.Internals
+{
+ public class DefaultMetric : AbstractMessage, IMetric
+ {
+ public DefaultMetric(String type, String name)
+ : base(type, name)
+ {
+ }
+ }
+}
diff --git a/Message/Internals/DefaultTransaction.cs b/Message/Internals/DefaultTransaction.cs
index b71f4ed..d08d0c3 100644
--- a/Message/Internals/DefaultTransaction.cs
+++ b/Message/Internals/DefaultTransaction.cs
@@ -1,113 +1,116 @@
-using Com.Dianping.Cat.Util;
-using System;
-using System.Collections.Generic;
-
-namespace Com.Dianping.Cat.Message.Internals
-{
- public class DefaultTransaction : AbstractMessage, ITransaction
- {
- private readonly Action _endCallBack;
- private IList _mChildren;
- private long _mDurationInMicro; // must be less than 0
-
- public DefaultTransaction(String type, String name, Action endCallBack)
- : base(type, name)
- {
- _mDurationInMicro = -1;
- _endCallBack = endCallBack;
- Standalone = true;
- }
-
- #region ITransaction Members
-
- public IList Children
- {
- get { return _mChildren ?? (_mChildren = new List()); }
- }
-
- public long DurationInMicros
- {
- get
- {
- if (_mDurationInMicro >= 0)
- {
- return _mDurationInMicro;
- }
- // if it's not completed explicitly
- long duration = 0;
- int len = (_mChildren == null) ? 0 : _mChildren.Count;
-
- if (len > 0)
- {
- if (_mChildren != null)
- {
- IMessage lastChild = _mChildren[len - 1];
-
- if (lastChild is ITransaction)
- {
- ITransaction trx = lastChild as ITransaction;
-
- duration = trx.Timestamp*1000L + trx.DurationInMicros - TimestampInMicros;
- }
- else
- {
- duration = lastChild.Timestamp*1000L - TimestampInMicros;
- }
- }
- }
-
- return duration;
- }
- set { _mDurationInMicro = value; }
- }
-
- public long DurationInMillis
- {
- get { return DurationInMicros/1000L; }
- set { _mDurationInMicro = value*1000L; }
- }
-
- public bool Standalone { get; set; }
-
- public ITransaction AddChild(IMessage message)
- {
- if (_mChildren == null)
- {
- _mChildren = new List();
- }
-
- _mChildren.Add(message);
- return this;
- }
-
- public override void Complete()
- {
- if (IsCompleted())
- {
- // complete() was called more than once
- IMessage evt0 = new DefaultEvent("CAT", "BadInstrument") {Status = "TransactionAlreadyCompleted"};
-
- evt0.Complete();
- AddChild(evt0);
- }
- else
- {
- _mDurationInMicro = MilliSecondTimer.CurrentTimeMicros() - TimestampInMicros;
-
- SetCompleted(true);
-
- if (_endCallBack != null)
- {
- _endCallBack(this);
- }
- }
- }
-
- public bool HasChildren()
- {
- return _mChildren != null && _mChildren.Count > 0;
- }
-
- #endregion
- }
+using Com.Dianping.Cat.Util;
+//using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+
+namespace Com.Dianping.Cat.Message.Internals
+{
+ [Serializable]
+ public class DefaultTransaction : AbstractMessage, ITransaction
+ {
+ private readonly Action _endCallBack;
+ private IList _mChildren;
+ private long _mDurationInMicro; // must be less than 0
+
+ public DefaultTransaction(String type, String name, Action endCallBack)
+ : base(type, name)
+ {
+ _mDurationInMicro = -1;
+ _endCallBack = endCallBack;
+ Standalone = true;
+ }
+
+ #region ITransaction Members
+
+ //[JsonConverter(typeof(List))]
+ public IList Children
+ {
+ get { return _mChildren ?? (_mChildren = new List()); }
+ }
+
+ public long DurationInMicros
+ {
+ get
+ {
+ if (_mDurationInMicro >= 0)
+ {
+ return _mDurationInMicro;
+ }
+ // if it's not completed explicitly
+ long duration = 0;
+ int len = (_mChildren == null) ? 0 : _mChildren.Count;
+
+ if (len > 0)
+ {
+ if (_mChildren != null)
+ {
+ IMessage lastChild = _mChildren[len - 1];
+
+ if (lastChild is ITransaction)
+ {
+ ITransaction trx = lastChild as ITransaction;
+
+ duration = trx.Timestamp * 1000L + trx.DurationInMicros - TimestampInMicros;
+ }
+ else
+ {
+ duration = lastChild.Timestamp * 1000L - TimestampInMicros;
+ }
+ }
+ }
+
+ return duration;
+ }
+ set { _mDurationInMicro = value; }
+ }
+
+ public long DurationInMillis
+ {
+ get { return DurationInMicros / 1000L; }
+ set { _mDurationInMicro = value * 1000L; }
+ }
+
+ public bool Standalone { get; set; }
+
+ public ITransaction AddChild(IMessage message)
+ {
+ if (_mChildren == null)
+ {
+ _mChildren = new List();
+ }
+
+ _mChildren.Add(message);
+ return this;
+ }
+
+ public override void Complete()
+ {
+ if (IsCompleted())
+ {
+ // complete() was called more than once
+ IMessage evt0 = new DefaultEvent("CAT", "BadInstrument") { Status = "TransactionAlreadyCompleted" };
+
+ evt0.Complete();
+ AddChild(evt0);
+ }
+ else
+ {
+ _mDurationInMicro = MilliSecondTimer.CurrentTimeMicros() - TimestampInMicros;
+
+ SetCompleted(true);
+
+ if (_endCallBack != null)
+ {
+ _endCallBack(this);
+ }
+ }
+ }
+
+ public bool HasChildren()
+ {
+ return _mChildren != null && _mChildren.Count > 0;
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Message/Internals/MessageId.cs b/Message/Internals/MessageId.cs
index e1a501b..9f263fe 100644
--- a/Message/Internals/MessageId.cs
+++ b/Message/Internals/MessageId.cs
@@ -1,102 +1,102 @@
-using System.Globalization;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Com.Dianping.Cat.Message.Internals
-{
- [Obsolete]
- public class MessageId
- {
- private readonly String _mDomain;
-
- private readonly int _mIndex;
-
- private readonly String _mIpAddressInHex;
-
- private readonly long _mTimestamp;
-
- internal MessageId(String domain, String ipAddressInHex, long timestamp, int index)
- {
- _mDomain = domain;
- _mIpAddressInHex = ipAddressInHex;
- _mTimestamp = timestamp;
- _mIndex = index;
- }
-
- public String Domain
- {
- get { return _mDomain; }
- }
-
- public int Index
- {
- get { return _mIndex; }
- }
-
- public String IpAddressInHex
- {
- get { return _mIpAddressInHex; }
- }
-
- public long Timestamp
- {
- get { return _mTimestamp; }
- }
-
- public static MessageId Parse(String messageId)
- {
- IList list = messageId.Split('-');
- int len = list.Count;
-
- if (len >= 4)
- {
- String ipAddressInHex = list[len - 3];
- long timestamp = (Int64.Parse(list[len - 2], NumberStyles.Integer));
- int index = Int32.Parse(list[len - 1]);
- String domain;
-
- if (len > 4)
- {
- // allow domain contains '-'
- StringBuilder sb = new StringBuilder();
-
- for (int i = 0; i < len - 3; i++)
- {
- if (i > 0)
- {
- sb.Append('-');
- }
-
- sb.Append(list[i]);
- }
-
- domain = sb.ToString();
- }
- else
- {
- domain = list[0];
- }
-
- return new MessageId(domain, ipAddressInHex, timestamp, index);
- }
-
- throw new Exception("Invalid message id format: " + messageId);
- }
-
- public override String ToString()
- {
- StringBuilder sb = new StringBuilder(_mDomain.Length + 32);
-
- sb.Append(_mDomain);
- sb.Append('-');
- sb.Append(_mIpAddressInHex);
- sb.Append('-');
- sb.Append(_mTimestamp);
- sb.Append('-');
- sb.Append(_mIndex);
-
- return sb.ToString();
- }
- }
+using System.Globalization;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Com.Dianping.Cat.Message.Internals
+{
+ [Obsolete]
+ public class MessageId
+ {
+ private readonly String _mDomain;
+
+ private readonly int _mIndex;
+
+ private readonly String _mIpAddressInHex;
+
+ private readonly long _mTimestamp;
+
+ internal MessageId(String domain, String ipAddressInHex, long timestamp, int index)
+ {
+ _mDomain = domain;
+ _mIpAddressInHex = ipAddressInHex;
+ _mTimestamp = timestamp;
+ _mIndex = index;
+ }
+
+ public String Domain
+ {
+ get { return _mDomain; }
+ }
+
+ public int Index
+ {
+ get { return _mIndex; }
+ }
+
+ public String IpAddressInHex
+ {
+ get { return _mIpAddressInHex; }
+ }
+
+ public long Timestamp
+ {
+ get { return _mTimestamp; }
+ }
+
+ public static MessageId Parse(String messageId)
+ {
+ IList list = messageId.Split('-');
+ int len = list.Count;
+
+ if (len >= 4)
+ {
+ String ipAddressInHex = list[len - 3];
+ long timestamp = (Int64.Parse(list[len - 2], NumberStyles.Integer));
+ int index = Int32.Parse(list[len - 1]);
+ String domain;
+
+ if (len > 4)
+ {
+ // allow domain contains '-'
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < len - 3; i++)
+ {
+ if (i > 0)
+ {
+ sb.Append('-');
+ }
+
+ sb.Append(list[i]);
+ }
+
+ domain = sb.ToString();
+ }
+ else
+ {
+ domain = list[0];
+ }
+
+ return new MessageId(domain, ipAddressInHex, timestamp, index);
+ }
+
+ throw new Exception("Invalid message id format: " + messageId);
+ }
+
+ public override String ToString()
+ {
+ StringBuilder sb = new StringBuilder(_mDomain.Length + 32);
+
+ sb.Append(_mDomain);
+ sb.Append('-');
+ sb.Append(_mIpAddressInHex);
+ sb.Append('-');
+ sb.Append(_mTimestamp);
+ sb.Append('-');
+ sb.Append(_mIndex);
+
+ return sb.ToString();
+ }
+ }
}
\ No newline at end of file
diff --git a/Message/Internals/NullEvent.cs b/Message/Internals/NullEvent.cs
index a37d544..a631d46 100644
--- a/Message/Internals/NullEvent.cs
+++ b/Message/Internals/NullEvent.cs
@@ -1,9 +1,10 @@
-namespace Com.Dianping.Cat.Message.Internals
-{
- public class NullEvent : AbstractMessage, IEvent
- {
- public NullEvent() : base(null, null)
- {
- }
- }
+namespace Com.Dianping.Cat.Message.Internals
+{
+ public class NullEvent : AbstractMessage, IEvent
+ {
+ public NullEvent()
+ : base(null, null)
+ {
+ }
+ }
}
\ No newline at end of file
diff --git a/Message/Internals/NullHeartbeat.cs b/Message/Internals/NullHeartbeat.cs
index ea39e40..f273d14 100644
--- a/Message/Internals/NullHeartbeat.cs
+++ b/Message/Internals/NullHeartbeat.cs
@@ -1,9 +1,10 @@
-namespace Com.Dianping.Cat.Message.Internals
-{
- public class NullHeartbeat : AbstractMessage, IHeartbeat
- {
- public NullHeartbeat() : base(null, null)
- {
- }
- }
+namespace Com.Dianping.Cat.Message.Internals
+{
+ public class NullHeartbeat : AbstractMessage, IHeartbeat
+ {
+ public NullHeartbeat()
+ : base(null, null)
+ {
+ }
+ }
}
\ No newline at end of file
diff --git a/Message/Internals/NullMetric.cs b/Message/Internals/NullMetric.cs
new file mode 100644
index 0000000..4d5bf52
--- /dev/null
+++ b/Message/Internals/NullMetric.cs
@@ -0,0 +1,11 @@
+
+namespace Com.Dianping.Cat.Message.Internals
+{
+ public class NullMetric : AbstractMessage, IMetric
+ {
+ public NullMetric()
+ : base(null, null)
+ {
+ }
+ }
+}
diff --git a/Message/Internals/NullTransaction.cs b/Message/Internals/NullTransaction.cs
index 920ce9e..aa73f89 100644
--- a/Message/Internals/NullTransaction.cs
+++ b/Message/Internals/NullTransaction.cs
@@ -1,65 +1,66 @@
-using System.Collections.Generic;
-
-namespace Com.Dianping.Cat.Message.Internals
-{
- public class NullTransaction : AbstractMessage, ITransaction
- {
- private IList _mChildren;
-
- public NullTransaction() : base(null, null)
- {
- }
-
- #region ITransaction Members
-
- public IList Children
- {
- get { return _mChildren ?? (_mChildren = new List()); }
- }
-
- public long DurationInMicros
- {
- get { return 0; }
- set
- {
- //do nothing here
- }
- }
-
- public long DurationInMillis
- {
- get { return 0; }
- set
- {
- //do nothing here
- }
- }
-
- public bool Standalone
- {
- get { return true; }
- set
- {
- //do nothing here
- }
- }
-
- public ITransaction AddChild(IMessage message)
- {
- // do nothing here
- return this;
- }
-
- public override void Complete()
- {
- // do nothing here
- }
-
- public bool HasChildren()
- {
- return false;
- }
-
- #endregion
- }
+using System.Collections.Generic;
+
+namespace Com.Dianping.Cat.Message.Internals
+{
+ public class NullTransaction : AbstractMessage, ITransaction
+ {
+ private IList _mChildren;
+
+ public NullTransaction()
+ : base(null, null)
+ {
+ }
+
+ #region ITransaction Members
+
+ public IList Children
+ {
+ get { return _mChildren ?? (_mChildren = new List()); }
+ }
+
+ public long DurationInMicros
+ {
+ get { return 0; }
+ set
+ {
+ //do nothing here
+ }
+ }
+
+ public long DurationInMillis
+ {
+ get { return 0; }
+ set
+ {
+ //do nothing here
+ }
+ }
+
+ public bool Standalone
+ {
+ get { return true; }
+ set
+ {
+ //do nothing here
+ }
+ }
+
+ public ITransaction AddChild(IMessage message)
+ {
+ // do nothing here
+ return this;
+ }
+
+ public override void Complete()
+ {
+ // do nothing here
+ }
+
+ public bool HasChildren()
+ {
+ return false;
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/Codec/ChannelBuffer.cs b/Message/Spi/Codec/ChannelBuffer.cs
index 6e99b4d..408fcc3 100644
--- a/Message/Spi/Codec/ChannelBuffer.cs
+++ b/Message/Spi/Codec/ChannelBuffer.cs
@@ -1,142 +1,142 @@
-using System.Text;
-using System.IO;
-
-namespace Com.Dianping.Cat.Message.Spi.Codec
-{
- public class ChannelBuffer
- {
- private readonly MemoryStream _mBuf;
-
- private readonly BinaryWriter _mWriter;
-
- public ChannelBuffer(int capacity)
- {
- _mBuf = new MemoryStream(capacity);
- _mWriter = new BinaryWriter(_mBuf, Encoding.UTF8);
- }
-
- ///
- /// 从当前位置到目标字符第一次出现的位置有多少字节?
- ///
- ///
- ///
- public int BytesBefore(byte separator)
- {
- int count = 0;
- long oldPosition = _mBuf.Position;
-
- while (_mBuf.Position < _mBuf.Length)
- {
- int b = _mBuf.ReadByte();
-
- if (b == -1)
- {
- return -1;
- }
- if ((byte) b == separator)
- {
- _mBuf.Position = oldPosition;
- return count;
- }
-
- count++;
- }
-
- _mBuf.Position = oldPosition;
- return 0;
- }
-
- public void Skip(int bytes)
- {
- _mBuf.Position += bytes;
- }
-
- public int ReadableBytes()
- {
- return (int) (_mBuf.Length - _mBuf.Position);
- }
-
- public int ReadBytes(byte[] data)
- {
- return _mBuf.Read(data, 0, data.Length);
- }
-
- public byte ReadByte()
- {
- return (byte) (_mBuf.ReadByte() & 0xFF);
- }
-
- public void WriteByte(byte b)
- {
- _mWriter.Write(b);
- }
-
- public void WriteByte(char c)
- {
- _mWriter.Write((byte) (c & 0xFF));
- }
-
- public void WriteInt(int i)
- {
- _mWriter.Write(ToBytes(i));
- }
-
- public void WriteBytes(byte[] data)
- {
- _mWriter.Write(data);
- }
-
- public void WriteBytes(byte[] data, int offset, int len)
- {
- _mWriter.Write(data, offset, len);
- }
-
- // for test purpose
- public void Reset()
- {
- _mBuf.Seek(0, SeekOrigin.Begin);
- }
-
- ///
- /// 在流的相应位置插入一个整数的字节(覆盖?)
- ///
- ///
- ///
- public void SetInt(int index, int i)
- {
- _mWriter.Seek(index, SeekOrigin.Begin);
- _mWriter.Write(ToBytes(i));
- }
-
- private static byte[] ToBytes(int value)
- {
- byte[] bytes = new byte[4];
-
- bytes[3] = (byte) value;
- bytes[2] = (byte) (value >> 8);
- bytes[1] = (byte) (value >> 16);
- bytes[0] = (byte) (value >> 24);
- return bytes;
- }
-
- public byte[] ToArray()
- {
- return _mBuf.ToArray();
- }
-
- ///
- /// 从当前位置到结尾的字节数组的字符串表示
- ///
- ///
- public override string ToString()
- {
- byte[] data = _mBuf.ToArray();
- int offset = (int) _mBuf.Position;
- string str = Encoding.UTF8.GetString(data, offset, data.Length - offset);
-
- //ToArray本身就不为该Position,所以下一行代码多余
- //_mBuf.Seek(offset, SeekOrigin.Begin);
- return str;
- }
- }
+using System.Text;
+using System.IO;
+
+namespace Com.Dianping.Cat.Message.Spi.Codec
+{
+ public class ChannelBuffer
+ {
+ private readonly MemoryStream _mBuf;
+
+ private readonly BinaryWriter _mWriter;
+
+ public ChannelBuffer(int capacity)
+ {
+ _mBuf = new MemoryStream(capacity);
+ _mWriter = new BinaryWriter(_mBuf, Encoding.UTF8);
+ }
+
+ ///
+ /// 从当前位置到目标字符第一次出现的位置有多少字节?
+ ///
+ ///
+ ///
+ public int BytesBefore(byte separator)
+ {
+ int count = 0;
+ long oldPosition = _mBuf.Position;
+
+ while (_mBuf.Position < _mBuf.Length)
+ {
+ int b = _mBuf.ReadByte();
+
+ if (b == -1)
+ {
+ return -1;
+ }
+ if ((byte)b == separator)
+ {
+ _mBuf.Position = oldPosition;
+ return count;
+ }
+
+ count++;
+ }
+
+ _mBuf.Position = oldPosition;
+ return 0;
+ }
+
+ public void Skip(int bytes)
+ {
+ _mBuf.Position += bytes;
+ }
+
+ public int ReadableBytes()
+ {
+ return (int)(_mBuf.Length - _mBuf.Position);
+ }
+
+ public int ReadBytes(byte[] data)
+ {
+ return _mBuf.Read(data, 0, data.Length);
+ }
+
+ public byte ReadByte()
+ {
+ return (byte)(_mBuf.ReadByte() & 0xFF);
+ }
+
+ public void WriteByte(byte b)
+ {
+ _mWriter.Write(b);
+ }
+
+ public void WriteByte(char c)
+ {
+ _mWriter.Write((byte)(c & 0xFF));
+ }
+
+ public void WriteInt(int i)
+ {
+ _mWriter.Write(ToBytes(i));
+ }
+
+ public void WriteBytes(byte[] data)
+ {
+ _mWriter.Write(data);
+ }
+
+ public void WriteBytes(byte[] data, int offset, int len)
+ {
+ _mWriter.Write(data, offset, len);
+ }
+
+ // for test purpose
+ public void Reset()
+ {
+ _mBuf.Seek(0, SeekOrigin.Begin);
+ }
+
+ ///
+ /// 在流的相应位置插入一个整数的字节(覆盖?)
+ ///
+ ///
+ ///
+ public void SetInt(int index, int i)
+ {
+ _mWriter.Seek(index, SeekOrigin.Begin);
+ _mWriter.Write(ToBytes(i));
+ }
+
+ private static byte[] ToBytes(int value)
+ {
+ byte[] bytes = new byte[4];
+
+ bytes[3] = (byte)value;
+ bytes[2] = (byte)(value >> 8);
+ bytes[1] = (byte)(value >> 16);
+ bytes[0] = (byte)(value >> 24);
+ return bytes;
+ }
+
+ public byte[] ToArray()
+ {
+ return _mBuf.ToArray();
+ }
+
+ ///
+ /// 从当前位置到结尾的字节数组的字符串表示
+ ///
+ ///
+ public override string ToString()
+ {
+ byte[] data = _mBuf.ToArray();
+ int offset = (int)_mBuf.Position;
+ string str = Encoding.UTF8.GetString(data, offset, data.Length - offset);
+
+ //ToArray本身就不为该Position,所以下一行代码多余
+ //_mBuf.Seek(offset, SeekOrigin.Begin);
+ return str;
+ }
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/Codec/IMessageCodec.cs b/Message/Spi/Codec/IMessageCodec.cs
index 64daa0b..f738695 100644
--- a/Message/Spi/Codec/IMessageCodec.cs
+++ b/Message/Spi/Codec/IMessageCodec.cs
@@ -1,11 +1,11 @@
-namespace Com.Dianping.Cat.Message.Spi.Codec
-{
- public interface IMessageCodec
- {
- IMessageTree Decode(ChannelBuffer buf);
-
- void Decode(ChannelBuffer buf, IMessageTree tree);
-
- void Encode(IMessageTree tree, ChannelBuffer buf);
- }
+namespace Com.Dianping.Cat.Message.Spi.Codec
+{
+ public interface IMessageCodec
+ {
+ IMessageTree Decode(ChannelBuffer buf);
+
+ void Decode(ChannelBuffer buf, IMessageTree tree);
+
+ void Encode(IMessageTree tree, ChannelBuffer buf);
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/Codec/PlainTextMessageCodec.cs b/Message/Spi/Codec/PlainTextMessageCodec.cs
index e9fc980..bfc40d7 100644
--- a/Message/Spi/Codec/PlainTextMessageCodec.cs
+++ b/Message/Spi/Codec/PlainTextMessageCodec.cs
@@ -1,526 +1,539 @@
-using Com.Dianping.Cat.Message.Internals;
-using Com.Dianping.Cat.Util;
-using System;
-using System.Text;
-using System.Globalization;
-using System.Collections.Generic;
-
-namespace Com.Dianping.Cat.Message.Spi.Codec
-{
- public class PlainTextMessageCodec : IMessageCodec
- {
- #region Policy enum
-
- public enum Policy
- {
- DEFAULT,
-
- WITHOUT_STATUS,
-
- WITH_DURATION
- }
-
- #endregion
-
- private const String ID = "PT1"; // plain text version 1
-
- private const byte TAB = (byte) '\t'; // tab character
-
- private const byte LF = (byte) '\n'; // line feed character
-
- private readonly BufferHelper _mBufferHelper;
-
- private readonly DateHelper _mDateHelper;
-
- public PlainTextMessageCodec()
- {
- _mBufferHelper = new BufferHelper();
- _mDateHelper = new DateHelper();
- }
-
- #region IMessageCodec Members
-
- public virtual IMessageTree Decode(ChannelBuffer buf)
- {
- DefaultMessageTree tree = new DefaultMessageTree();
-
- Decode(buf, tree);
- return tree;
- }
-
- public virtual void Decode(ChannelBuffer buf, IMessageTree tree)
- {
- DecodeHeader(buf, tree);
-
- if (buf.ReadableBytes() > 0)
- {
- DecodeMessage(buf, tree);
- }
- }
-
- public virtual void Encode(IMessageTree tree, ChannelBuffer buf)
- {
- int count = 0;
-
- buf.WriteInt(0); // place-holder
- count += EncodeHeader(tree, buf);
-
- if (tree.Message != null)
- {
- count += EncodeMessage(tree.Message, buf);
- }
-
- buf.SetInt(0, count);
- }
-
- #endregion
-
- protected internal void DecodeHeader(ChannelBuffer buf, IMessageTree tree)
- {
- BufferHelper helper = _mBufferHelper;
- String id = helper.Read(buf, TAB);
- String domain = helper.Read(buf, TAB);
- String hostName = helper.Read(buf, TAB);
- String ipAddress = helper.Read(buf, TAB);
- String threadGroupName = helper.Read(buf, TAB);
- String threadId = helper.Read(buf, TAB);
- String threadName = helper.Read(buf, TAB);
- String messageId = helper.Read(buf, TAB);
- String parentMessageId = helper.Read(buf, TAB);
- String rootMessageId = helper.Read(buf, TAB);
- String sessionToken = helper.Read(buf, LF);
-
- if (ID.Equals(id))
- {
- tree.Domain = domain;
- tree.HostName = hostName;
- tree.IpAddress = ipAddress;
- tree.ThreadGroupName = threadGroupName;
- tree.ThreadId = threadId;
- tree.ThreadName = threadName;
- tree.MessageId = messageId;
- tree.ParentMessageId = parentMessageId;
- tree.RootMessageId = rootMessageId;
- tree.SessionToken = sessionToken;
- }
- else
- {
- throw new Exception("Unrecognized id(" + id + ") for plain text message codec!");
- }
- }
-
- protected internal IMessage DecodeLine(ChannelBuffer buf, ITransaction parent,
- Stack stack, IMessageTree tree)
- {
- BufferHelper helper = _mBufferHelper;
- byte identifier = buf.ReadByte();
- String timestamp = helper.Read(buf, TAB);
- String type = helper.Read(buf, TAB);
- String name = helper.Read(buf, TAB);
-
- if (identifier == 'E')
- {
- IMessage evt = new DefaultEvent(type, name);
- String status = helper.Read(buf, TAB);
- String data = helper.ReadRaw(buf, TAB);
-
- helper.Read(buf, LF); // get rid of line feed
- evt.Timestamp = _mDateHelper.Parse(timestamp);
- evt.Status = status;
- evt.AddData(data);
-
- if (parent != null)
- {
- parent.AddChild(evt);
- return parent;
- }
- return evt;
- }
- if (identifier == 'H')
- {
- IMessage heartbeat = new DefaultHeartbeat(type, name);
- String status0 = helper.Read(buf, TAB);
- String data1 = helper.ReadRaw(buf, TAB);
-
- helper.Read(buf, LF); // get rid of line feed
- heartbeat.Timestamp = _mDateHelper.Parse(timestamp);
- heartbeat.Status = status0;
- heartbeat.AddData(data1);
-
- if (parent != null)
- {
- parent.AddChild(heartbeat);
- return parent;
- }
- return heartbeat;
- }
- if (identifier == 't')
- {
- IMessage transaction = new DefaultTransaction(type, name,
- null);
-
- helper.Read(buf, LF); // get rid of line feed
- transaction.Timestamp = _mDateHelper.Parse(timestamp);
-
- if (parent != null)
- {
- parent.AddChild(transaction);
- }
-
- stack.Push(parent);
- return transaction;
- }
- if (identifier == 'A')
- {
- ITransaction transaction2 = new DefaultTransaction(type, name, null);
- String status3 = helper.Read(buf, TAB);
- String duration = helper.Read(buf, TAB);
- String data4 = helper.ReadRaw(buf, TAB);
-
- helper.Read(buf, LF); // get rid of line feed
- transaction2.Timestamp = _mDateHelper.Parse(timestamp);
- transaction2.Status = status3;
- transaction2.AddData(data4);
-
- long d = Int64.Parse(duration.Substring(0, duration.Length - 2), NumberStyles.Integer);
- transaction2.DurationInMicros = d;
-
- if (parent != null)
- {
- parent.AddChild(transaction2);
- return parent;
- }
- return transaction2;
- }
- if (identifier == 'T')
- {
- String status5 = helper.Read(buf, TAB);
- String duration6 = helper.Read(buf, TAB);
- String data7 = helper.ReadRaw(buf, TAB);
-
- helper.Read(buf, LF); // get rid of line feed
- parent.Status = status5;
- parent.AddData(data7);
-
- long d8 = Int64.Parse(
- duration6.Substring(0, duration6.Length - 2),
- NumberStyles.Integer);
- parent.DurationInMicros = d8;
-
- return stack.Pop();
- }
- Logger.Error("Unknown identifier(" + identifier + ") of message: " + buf);
-
- // unknown message, ignore it
- return parent;
- }
-
- protected internal void DecodeMessage(ChannelBuffer buf, IMessageTree tree)
- {
- Stack stack = new Stack();
- IMessage parent = DecodeLine(buf, null, stack, tree);
-
- tree.Message = parent;
-
- while (buf.ReadableBytes() > 0)
- {
- IMessage message = DecodeLine(buf, (ITransaction) parent, stack, tree);
-
- if (message is ITransaction)
- {
- parent = message;
- }
- else
- {
- break;
- }
- }
- }
-
- protected internal int EncodeHeader(IMessageTree tree, ChannelBuffer buf)
- {
- BufferHelper helper = _mBufferHelper;
- int count = 0;
-
- count += helper.Write(buf, ID);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, tree.Domain);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, tree.HostName);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, tree.IpAddress);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, tree.ThreadGroupName);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, tree.ThreadId);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, tree.ThreadName);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, tree.MessageId);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, tree.ParentMessageId);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, tree.RootMessageId);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, tree.SessionToken);
- count += helper.Write(buf, LF);
-
- return count;
- }
-
- protected internal int EncodeLine(IMessage message, ChannelBuffer buf, char type, Policy policy)
- {
- BufferHelper helper = _mBufferHelper;
- int count = 0;
-
- count += helper.Write(buf, (byte) type);
-
- if (type == 'T' && message is ITransaction)
- {
- long duration = ((ITransaction) message).DurationInMillis;
-
- count += helper.Write(buf, _mDateHelper.Format(message.Timestamp + duration));
- }
- else
- {
- count += helper.Write(buf, _mDateHelper.Format(message.Timestamp));
- }
-
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, message.Type);
- count += helper.Write(buf, TAB);
- count += helper.Write(buf, message.Name);
- count += helper.Write(buf, TAB);
-
- if (policy != Policy.WITHOUT_STATUS)
- {
- count += helper.Write(buf, message.Status);
- count += helper.Write(buf, TAB);
-
- Object data = message.Data;
-
- if (policy == Policy.WITH_DURATION && message is ITransaction)
- {
- long duration0 = ((ITransaction) message).DurationInMicros;
-
- count += helper.Write(buf, duration0.ToString(CultureInfo.InvariantCulture));
- //以微秒为单位
- count += helper.Write(buf, "us");
- count += helper.Write(buf, TAB);
- }
-
- count += helper.WriteRaw(buf, data.ToString());
- count += helper.Write(buf, TAB);
- }
-
- count += helper.Write(buf, LF);
-
- return count;
- }
-
- public int EncodeMessage(IMessage message, ChannelBuffer buf)
- {
- if (message is IEvent)
- {
- return EncodeLine(message, buf, 'E', Policy.DEFAULT);
- }
- var transaction = message as ITransaction;
- if (transaction != null)
- {
- IList children = transaction.Children;
-
- if ((children.Count == 0))
- {
- return EncodeLine(transaction, buf, 'A', Policy.WITH_DURATION);
- }
- int count = 0;
- int len = children.Count;
-
- count += EncodeLine(transaction, buf, 't', Policy.WITHOUT_STATUS);
-
- for (int i = 0; i < len; i++)
- {
- IMessage child = children[i];
-
- count += EncodeMessage(child, buf);
- }
-
- count += EncodeLine(transaction, buf, 'T', Policy.WITH_DURATION);
-
- return count;
- }
- if (message is IHeartbeat)
- {
- return EncodeLine(message, buf, 'H', Policy.DEFAULT);
- }
- throw new Exception("Unsupported message type: " + message.Type + ".");
- }
-
- #region Nested type: BufferHelper
-
- protected internal class BufferHelper
- {
- private readonly UTF8Encoding _mEncoding = new UTF8Encoding();
-
- public String Read(ChannelBuffer buf, byte separator)
- {
- int count = buf.BytesBefore(separator);
-
- if (count < 0)
- {
- return null;
- }
- byte[] data = new byte[count];
-
- buf.ReadBytes(data);
- buf.ReadByte(); // get rid of separator
-
- return Encoding.UTF8.GetString(data);
- }
-
- public String ReadRaw(ChannelBuffer buf, byte separator)
- {
- int count = buf.BytesBefore(separator);
-
- if (count < 0)
- {
- return null;
- }
- byte[] data = new byte[count];
-
- buf.ReadBytes(data);
- buf.ReadByte(); // get rid of separator
-
- int length = data.Length;
-
- for (int i = 0; i < length; i++)
- {
- if (data[i] == '\\')
- {
- if (i + 1 < length)
- {
- byte b = data[i + 1];
-
- if (b == 't')
- {
- data[i] = (byte) '\t';
- }
- else if (b == 'r')
- {
- data[i] = (byte) '\r';
- }
- else if (b == 'n')
- {
- data[i] = (byte) '\n';
- }
- else
- {
- data[i] = b;
- }
-
- Array.Copy(data, i + 2, data, i + 1, length - i - 2);
- length--;
- }
- }
- }
-
- return Encoding.UTF8.GetString(data, 0, length);
- }
-
- public int Write(ChannelBuffer buf, byte b)
- {
- buf.WriteByte(b);
- return 1;
- }
-
- public int Write(ChannelBuffer buf, String str)
- {
- if (str == null)
- {
- str = "null";
- }
-
- byte[] data = _mEncoding.GetBytes(str);
-
- buf.WriteBytes(data);
- return data.Length;
- }
-
- public int WriteRaw(ChannelBuffer buf, String str)
- {
- if (str == null)
- {
- str = "null";
- }
-
- byte[] data = _mEncoding.GetBytes(str);
-
- int len = data.Length;
- int count = len;
- int offset = 0;
-
- for (int i = 0; i < len; i++)
- {
- byte b = data[i];
-
- if (b == '\t' || b == '\r' || b == '\n' || b == '\\')
- {
- buf.WriteBytes(data, offset, i - offset);
- buf.WriteByte('\\');
-
- if (b == '\t')
- {
- buf.WriteByte('t');
- }
- else if (b == '\r')
- {
- buf.WriteByte('r');
- }
- else if (b == '\n')
- {
- buf.WriteByte('n');
- }
- else
- {
- buf.WriteByte(b);
- }
-
- count++;
- offset = i + 1;
- }
- }
-
- if (len > offset)
- {
- buf.WriteBytes(data, offset, len - offset);
- }
-
- return count;
- }
- }
-
- #endregion
-
- #region Nested type: DateHelper
-
- ///
- /// Thread safe date helper class. DateFormat is NOT thread safe.
- ///
- protected internal class DateHelper
- {
- public String Format(long timestamp)
- {
- return new DateTime(timestamp*10000L).ToString("yyyy-MM-dd HH:mm:ss.fff");
- }
-
- public long Parse(String str)
- {
- DateTime dateTime = DateTime.ParseExact(str, "yyyy-MM-dd HH:mm:ss.fff", CultureInfo.CurrentCulture);
-
- return dateTime.Ticks/10000L;
- }
- }
-
- #endregion
- }
+using Com.Dianping.Cat.Message.Internals;
+using Com.Dianping.Cat.Util;
+using System;
+using System.Text;
+using System.Globalization;
+using System.Collections.Generic;
+
+namespace Com.Dianping.Cat.Message.Spi.Codec
+{
+ public class PlainTextMessageCodec : IMessageCodec
+ {
+ #region Policy enum
+
+ public enum Policy
+ {
+ DEFAULT,
+
+ WITHOUT_STATUS,
+
+ WITH_DURATION
+ }
+
+ #endregion
+
+ private const String ID = "PT1"; // plain text version 1
+
+ private const byte TAB = (byte)'\t'; // tab character
+
+ private const byte LF = (byte)'\n'; // line feed character
+
+ private readonly BufferHelper _mBufferHelper;
+
+ private readonly DateHelper _mDateHelper;
+
+ public PlainTextMessageCodec()
+ {
+ _mBufferHelper = new BufferHelper();
+ _mDateHelper = new DateHelper();
+ }
+
+ #region IMessageCodec Members
+
+ public virtual IMessageTree Decode(ChannelBuffer buf)
+ {
+ DefaultMessageTree tree = new DefaultMessageTree();
+
+ Decode(buf, tree);
+ return tree;
+ }
+
+ public virtual void Decode(ChannelBuffer buf, IMessageTree tree)
+ {
+ DecodeHeader(buf, tree);
+
+ if (buf.ReadableBytes() > 0)
+ {
+ DecodeMessage(buf, tree);
+ }
+ }
+
+ public virtual void Encode(IMessageTree tree, ChannelBuffer buf)
+ {
+ int count = 0;
+
+ buf.WriteInt(0); // place-holder
+ count += EncodeHeader(tree, buf);
+
+ if (tree.Message != null)
+ {
+ count += EncodeMessage(tree.Message, buf);
+ }
+
+ buf.SetInt(0, count);
+ }
+
+ #endregion
+
+ protected internal void DecodeHeader(ChannelBuffer buf, IMessageTree tree)
+ {
+ BufferHelper helper = _mBufferHelper;
+ String id = helper.Read(buf, TAB);
+ String domain = helper.Read(buf, TAB);
+ String hostName = helper.Read(buf, TAB);
+ String ipAddress = helper.Read(buf, TAB);
+ String threadGroupName = helper.Read(buf, TAB);
+ String threadId = helper.Read(buf, TAB);
+ String threadName = helper.Read(buf, TAB);
+ String messageId = helper.Read(buf, TAB);
+ String parentMessageId = helper.Read(buf, TAB);
+ String rootMessageId = helper.Read(buf, TAB);
+ String sessionToken = helper.Read(buf, LF);
+
+ if (ID.Equals(id))
+ {
+ tree.Domain = domain;
+ tree.HostName = hostName;
+ tree.IpAddress = ipAddress;
+ tree.ThreadGroupName = threadGroupName;
+ tree.ThreadId = threadId;
+ tree.ThreadName = threadName;
+ tree.MessageId = messageId;
+ tree.ParentMessageId = parentMessageId;
+ tree.RootMessageId = rootMessageId;
+ tree.SessionToken = sessionToken;
+ }
+ else
+ {
+ throw new Exception("Unrecognized id(" + id + ") for plain text message codec!");
+ }
+ }
+
+ protected internal IMessage DecodeLine(ChannelBuffer buf, ITransaction parent,
+ Stack stack, IMessageTree tree)
+ {
+ BufferHelper helper = _mBufferHelper;
+ char identifier = (char)buf.ReadByte();
+ String timestamp = helper.Read(buf, TAB);
+ String type = helper.Read(buf, TAB);
+ String name = helper.Read(buf, TAB);
+ switch (identifier)
+ {
+ case 't':
+ IMessage transaction = new DefaultTransaction(type, name, null);
+
+ helper.Read(buf, LF); // get rid of line feed
+ transaction.Timestamp = _mDateHelper.Parse(timestamp);
+
+ if (parent != null)
+ {
+ parent.AddChild(transaction);
+ }
+
+ stack.Push(parent);
+ return transaction;
+ case 'A':
+ DefaultTransaction tran = new DefaultTransaction(type, name, null);
+ String status = helper.Read(buf, TAB);
+ String duration = helper.Read(buf, TAB);
+ String data = helper.ReadRaw(buf, TAB);
+
+ helper.Read(buf, LF); // get rid of line feed
+ tran.Timestamp = _mDateHelper.Parse(timestamp);
+ tran.Status = status;
+ tran.AddData(data);
+
+ long d = Int64.Parse(duration.Substring(0, duration.Length - 2), NumberStyles.Integer);
+
+ tran.DurationInMicros = d;
+
+ if (parent != null)
+ {
+ parent.AddChild(tran);
+ return parent;
+ }
+ return tran;
+ case 'T':
+ String transactionStatus = helper.Read(buf, TAB);
+ String transactionDuration = helper.Read(buf, TAB);
+ String transactionData = helper.ReadRaw(buf, TAB);
+
+ helper.Read(buf, LF); // get rid of line feed
+ parent.Status = transactionStatus;
+ parent.AddData(transactionData);
+
+ long transactionD = Int64.Parse(transactionDuration.Substring(0, transactionDuration.Length - 2), NumberStyles.Integer);
+
+ parent.DurationInMicros = transactionD;
+
+ return stack.Pop();
+ case 'E':
+ DefaultEvent evt = new DefaultEvent(type, name);
+ String eventStatus = helper.Read(buf, TAB);
+ String eventData = helper.ReadRaw(buf, TAB);
+
+ helper.Read(buf, LF); // get rid of line feed
+ evt.Timestamp = _mDateHelper.Parse(timestamp);
+ evt.Status = eventStatus;
+ evt.AddData(eventData);
+
+ if (parent != null)
+ {
+ parent.AddChild(evt);
+ return parent;
+ }
+ return evt;
+ case 'M':
+ DefaultMetric metric = new DefaultMetric(type, name);
+ String metricStatus = helper.Read(buf, TAB);
+ String metricData = helper.ReadRaw(buf, TAB);
+
+ helper.Read(buf, LF);
+ metric.Timestamp = _mDateHelper.Parse(timestamp);
+ metric.Status = metricStatus;
+ metric.AddData(metricData);
+
+ if (parent != null)
+ {
+ parent.AddChild(metric);
+ return parent;
+ }
+ return metric;
+ case 'H':
+ DefaultHeartbeat heartbeat = new DefaultHeartbeat(type, name);
+ String heartbeatStatus = helper.Read(buf, TAB);
+ String heartbeatData = helper.ReadRaw(buf, TAB);
+
+ helper.Read(buf, LF); // get rid of line feed
+ heartbeat.Timestamp = _mDateHelper.Parse(timestamp);
+ heartbeat.Status = heartbeatStatus;
+ heartbeat.AddData(heartbeatData);
+
+ if (parent != null)
+ {
+ parent.AddChild(heartbeat);
+ return parent;
+ }
+ return heartbeat;
+ }
+
+ Logger.Error("Unknown identifier(" + identifier + ") of message: " + buf);
+ //throw new Exception("Unknown identifier int name"); //java版的抛出异常
+
+ // unknown message, ignore it
+ return parent;
+ }
+
+ protected internal void DecodeMessage(ChannelBuffer buf, IMessageTree tree)
+ {
+ Stack stack = new Stack();
+ IMessage parent = DecodeLine(buf, null, stack, tree);
+
+ tree.Message = parent;
+
+ while (buf.ReadableBytes() > 0)
+ {
+ IMessage message = DecodeLine(buf, (ITransaction)parent, stack, tree);
+
+ if (message is ITransaction)
+ {
+ parent = message;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ protected internal int EncodeHeader(IMessageTree tree, ChannelBuffer buf)
+ {
+ BufferHelper helper = _mBufferHelper;
+ int count = 0;
+
+ count += helper.Write(buf, ID);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, tree.Domain);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, tree.HostName);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, tree.IpAddress);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, tree.ThreadGroupName);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, tree.ThreadId);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, tree.ThreadName);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, tree.MessageId);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, tree.ParentMessageId);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, tree.RootMessageId);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, tree.SessionToken);
+ count += helper.Write(buf, LF);
+
+ return count;
+ }
+
+ protected internal int EncodeLine(IMessage message, ChannelBuffer buf, char type, Policy policy)
+ {
+ BufferHelper helper = _mBufferHelper;
+ int count = 0;
+
+ count += helper.Write(buf, (byte)type);
+
+ if (type == 'T' && message is ITransaction)
+ {
+ long duration = ((ITransaction)message).DurationInMillis;
+
+ count += helper.Write(buf, _mDateHelper.Format(message.Timestamp + duration));
+ }
+ else
+ {
+ count += helper.Write(buf, _mDateHelper.Format(message.Timestamp));
+ }
+
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, message.Type);
+ count += helper.Write(buf, TAB);
+ count += helper.Write(buf, message.Name);
+ count += helper.Write(buf, TAB);
+
+ if (policy != Policy.WITHOUT_STATUS)
+ {
+ count += helper.Write(buf, message.Status);
+ count += helper.Write(buf, TAB);
+
+ Object data = message.Data;
+
+ if (policy == Policy.WITH_DURATION && message is ITransaction)
+ {
+ long duration0 = ((ITransaction)message).DurationInMicros;
+
+ count += helper.Write(buf, duration0.ToString(CultureInfo.InvariantCulture));
+ //以微秒为单位
+ count += helper.Write(buf, "us");
+ count += helper.Write(buf, TAB);
+ }
+
+ count += helper.WriteRaw(buf, data.ToString());
+ count += helper.Write(buf, TAB);
+ }
+
+ count += helper.Write(buf, LF);
+
+ return count;
+ }
+
+ public int EncodeMessage(IMessage message, ChannelBuffer buf)
+ {
+ if (message is ITransaction)
+ {
+ var transaction = message as ITransaction;
+ IList children = transaction.Children;
+
+ if (children.Count == 0)
+ {
+ return EncodeLine(transaction, buf, 'A', Policy.WITH_DURATION);
+ }
+ int count = 0;
+ int len = children.Count;
+
+ count += EncodeLine(transaction, buf, 't', Policy.WITHOUT_STATUS);
+
+ for (int i = 0; i < len; i++)
+ {
+ IMessage child = children[i];
+
+ count += EncodeMessage(child, buf);
+ }
+
+ count += EncodeLine(transaction, buf, 'T', Policy.WITH_DURATION);
+
+ return count;
+ }
+ if (message is IEvent)
+ {
+ return EncodeLine(message, buf, 'E', Policy.DEFAULT);
+ }
+ if (message is IHeartbeat)
+ {
+ return EncodeLine(message, buf, 'H', Policy.DEFAULT);
+ }
+ if (message is IMetric)
+ {
+ return EncodeLine(message, buf, 'M', Policy.DEFAULT);
+ }
+ throw new Exception(string.Format("Unsupported message type: {0}.", message.Type));
+ }
+
+ #region Nested type: BufferHelper
+
+ protected internal class BufferHelper
+ {
+ private readonly UTF8Encoding _mEncoding = new UTF8Encoding();
+
+ public String Read(ChannelBuffer buf, byte separator)
+ {
+ int count = buf.BytesBefore(separator);
+
+ if (count < 0)
+ {
+ return null;
+ }
+ byte[] data = new byte[count];
+
+ buf.ReadBytes(data);
+ buf.ReadByte(); // get rid of separator
+
+ return Encoding.UTF8.GetString(data);
+ }
+
+ public String ReadRaw(ChannelBuffer buf, byte separator)
+ {
+ int count = buf.BytesBefore(separator);
+
+ if (count < 0)
+ {
+ return null;
+ }
+ byte[] data = new byte[count];
+
+ buf.ReadBytes(data);
+ buf.ReadByte(); // get rid of separator
+
+ int length = data.Length;
+
+ for (int i = 0; i < length; i++)
+ {
+ if (data[i] == '\\')
+ {
+ if (i + 1 < length)
+ {
+ byte b = data[i + 1];
+
+ if (b == 't')
+ {
+ data[i] = (byte)'\t';
+ }
+ else if (b == 'r')
+ {
+ data[i] = (byte)'\r';
+ }
+ else if (b == 'n')
+ {
+ data[i] = (byte)'\n';
+ }
+ else
+ {
+ data[i] = b;
+ }
+
+ Array.Copy(data, i + 2, data, i + 1, length - i - 2);
+ length--;
+ }
+ }
+ }
+
+ return Encoding.UTF8.GetString(data, 0, length);
+ }
+
+ public int Write(ChannelBuffer buf, byte b)
+ {
+ buf.WriteByte(b);
+ return 1;
+ }
+
+ public int Write(ChannelBuffer buf, String str)
+ {
+ if (str == null)
+ {
+ str = "null";
+ }
+
+ byte[] data = _mEncoding.GetBytes(str);
+
+ buf.WriteBytes(data);
+ return data.Length;
+ }
+
+ public int WriteRaw(ChannelBuffer buf, String str)
+ {
+ if (str == null)
+ {
+ str = "null";
+ }
+
+ byte[] data = _mEncoding.GetBytes(str);
+
+ int len = data.Length;
+ int count = len;
+ int offset = 0;
+
+ for (int i = 0; i < len; i++)
+ {
+ byte b = data[i];
+
+ if (b == '\t' || b == '\r' || b == '\n' || b == '\\')
+ {
+ buf.WriteBytes(data, offset, i - offset);
+ buf.WriteByte('\\');
+
+ if (b == '\t')
+ {
+ buf.WriteByte('t');
+ }
+ else if (b == '\r')
+ {
+ buf.WriteByte('r');
+ }
+ else if (b == '\n')
+ {
+ buf.WriteByte('n');
+ }
+ else
+ {
+ buf.WriteByte(b);
+ }
+
+ count++;
+ offset = i + 1;
+ }
+ }
+
+ if (len > offset)
+ {
+ buf.WriteBytes(data, offset, len - offset);
+ }
+
+ return count;
+ }
+ }
+
+ #endregion
+
+ #region Nested type: DateHelper
+
+ ///
+ /// Thread safe date helper class. DateFormat is NOT thread safe.
+ ///
+ protected internal class DateHelper
+ {
+ public String Format(long timestamp)
+ {
+ return new DateTime(timestamp * 10000L).ToString("yyyy-MM-dd HH:mm:ss.fff");
+ }
+
+ public long Parse(String str)
+ {
+ DateTime dateTime = DateTime.ParseExact(str, "yyyy-MM-dd HH:mm:ss.fff", CultureInfo.CurrentCulture);
+
+ return dateTime.Ticks / 10000L;
+ }
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/IMessageManager.cs b/Message/Spi/IMessageManager.cs
index 4973ddb..3e39120 100644
--- a/Message/Spi/IMessageManager.cs
+++ b/Message/Spi/IMessageManager.cs
@@ -1,77 +1,80 @@
-using Com.Dianping.Cat.Configuration;
-
-namespace Com.Dianping.Cat.Message.Spi
-{
- ///
- /// Message manager to help build CAT message. Notes: This method is reserved for internal usage only. Application developer
- /// should never call this method directly.
- ///
- public interface IMessageManager
- {
- ///
- /// Return configuration for CAT client.
- ///
- /// CAT configuration
- ClientConfig ClientConfig { get; }
-
- //TransportManager TransportManager { get; }
-
- ///
- /// Get peek transaction for current thread.
- ///
- /// peek transaction for current thread, null if no transaction there.
- ITransaction PeekTransaction { get; }
-
- ///
- /// Get thread local message information.
- ///
- /// message tree, null means current thread is not setup correctly.
- IMessageTree ThreadLocalMessageTree { get; }
-
- ///
- /// Check if CAT logging is enabled or disabled.
- ///
- /// true if CAT is enabled
- bool CatEnabled { get; }
-
- ///
- /// 用于添加Event或者Heartbeat到peek transaction或者到根 如果是添加到根,建议直接使用IMessageProducer中的LogError、LogEvent或LogHeartbeat方法
- ///
- ///
- void Add(IMessage message);
-
- ///
- /// Initialize CAT client with given CAT configuration.
- ///
- /// CAT configuration
- void InitializeClient(ClientConfig config);
-
- ///
- /// Do cleanup for current thread environment in order to release resources in thread local objects.
- ///
- void Reset();
-
- ///
- /// Check if the thread context is setup or not.
- ///
- /// true if the thread context is setup, false otherwise
- bool HasContext();
-
- ///
- /// Do setup for current thread environment in order to prepare thread local objects.
- ///
- void Setup();
-
- ///
- /// Be triggered when a new transaction starts, whatever it's the root transaction or nested transaction.
- ///
- ///
- void Start(ITransaction transaction);
-
- ///
- /// Be triggered when a transaction ends, whatever it's the root transaction or nested transaction. However, if it's the root transaction then it will be flushed to back-end CAT server asynchronously.
- ///
- ///
- void End(ITransaction transaction);
- }
+using Com.Dianping.Cat.Configuration;
+using Com.Dianping.Cat.Message.Spi.Internals;
+
+namespace Com.Dianping.Cat.Message.Spi
+{
+ ///
+ /// Message manager to help build CAT message. Notes: This method is reserved for internal usage only. Application developer
+ /// should never call this method directly.
+ ///
+ public interface IMessageManager
+ {
+ ///
+ /// Return configuration for CAT client.
+ ///
+ /// CAT configuration
+ ClientConfig ClientConfig { get; }
+
+ //TransportManager TransportManager { get; }
+
+ ///
+ /// Get peek transaction for current thread.
+ ///
+ /// peek transaction for current thread, null if no transaction there.
+ ITransaction PeekTransaction { get; }
+
+ ///
+ /// Get thread local message information.
+ ///
+ /// message tree, null means current thread is not setup correctly.
+ IMessageTree ThreadLocalMessageTree { get; }
+
+ ///
+ /// Check if CAT logging is enabled or disabled.
+ ///
+ /// true if CAT is enabled
+ bool CatEnabled { get; }
+
+ ///
+ /// 用于添加Event或者Heartbeat到peek transaction或者到根 如果是添加到根,建议直接使用IMessageProducer中的LogError、LogEvent或LogHeartbeat方法
+ ///
+ ///
+ void Add(IMessage message);
+
+ ///
+ /// Initialize CAT client with given CAT configuration.
+ ///
+ /// CAT configuration
+ void InitializeClient(ClientConfig config);
+
+ ///
+ /// Do cleanup for current thread environment in order to release resources in thread local objects.
+ ///
+ void Reset();
+
+ ///
+ /// Check if the thread context is setup or not.
+ ///
+ /// true if the thread context is setup, false otherwise
+ bool HasContext();
+
+ ///
+ /// Do setup for current thread environment in order to prepare thread local objects.
+ ///
+ void Setup();
+
+ ///
+ /// Be triggered when a new transaction starts, whatever it's the root transaction or nested transaction.
+ ///
+ ///
+ void Start(ITransaction transaction);
+
+ ///
+ /// Be triggered when a transaction ends, whatever it's the root transaction or nested transaction. However, if it's the root transaction then it will be flushed to back-end CAT server asynchronously.
+ ///
+ ///
+ void End(ITransaction transaction);
+
+ MessageIdFactory GetMessageIdFactory();
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/IMessageProducer.cs b/Message/Spi/IMessageProducer.cs
index bdb51ea..655756c 100644
--- a/Message/Spi/IMessageProducer.cs
+++ b/Message/Spi/IMessageProducer.cs
@@ -1,131 +1,149 @@
-using System;
-
-namespace Com.Dianping.Cat.Message.Spi
-{
- ///
- /// Message factory is used to create new transaction,event and/or heartbeat.
Normally, application code logs message in following ways, for example:
- ///
- /// - Event
- ///
public class MyClass {
- /// public static MessageFactory CAT = Cat.getFactory();
- /// public void bizMethod() {
- /// Event event = CAT.newEvent("Review", "New");
- /// event.addData("id", 12345);
- /// event.addData("user", "john");
- /// ...
- /// event.setStatus("0");
- /// event.complete();
- /// }
- /// ...
- /// }
- ///
- /// - Heartbeat
- ///
public class MyClass {
- /// public static MessageFactory CAT = Cat.getFactory();
- /// public void bizMethod() {
- /// Heartbeat event = CAT.newHeartbeat("System", "Status");
- /// event.addData("ip", "192.168.10.111");
- /// event.addData("host", "host-1");
- /// event.addData("load", "2.1");
- /// event.addData("cpu", "0.12,0.10");
- /// event.addData("memory.total", "2G");
- /// event.addData("memory.free", "456M");
- /// event.setStatus("0");
- /// event.complete();
- /// }
- /// ...
- /// }
- ///
- /// - Transaction
- ///
public class MyClass {
- /// public static MessageFactory CAT = Cat.getFactory();
- /// public void bizMethod() {
- /// Transaction t = CAT.newTransaction("URL", "MyPage");
- /// try {
- /// // do your business here
- /// t.addData("k1", "v1");
- /// t.addData("k2", "v2");
- /// t.addData("k3", "v3");
- /// Thread.sleep(30);
- /// t.setStatus("0");
- /// } catch (Exception e) {
- /// t.setStatus(e);
- /// } finally {
- /// t.complete();
- /// }
- /// }
- /// ...
- /// }
- ///
- ///
- /// or logs event or heartbeat in one shot, for example:
- ///
- /// - Event
- ///
public class MyClass {
- /// public static MessageFactory CAT = Cat.getFactory();
- /// public void bizMethod() {
- /// CAT.logEvent("Review", "New", "0", "id=12345&user=john");
- /// }
- /// ...
- /// }
- ///
- /// - Heartbeat
- ///
public class MyClass {
- /// public static MessageFactory CAT = Cat.getFactory();
- /// public void bizMethod() {
- /// CAT.logHeartbeat("System", "Status", "0", "ip=192.168.10.111&host=host-1&load=2.1&cpu=0.12,0.10&memory.total=2G&memory.free=456M");
- /// }
- /// ...
- /// }
- ///
- ///
- ///
- ///
- public interface IMessageProducer
- {
- ///
- /// Log an error.
- ///
- /// root cause exception
- void LogError(Exception cause);
-
- ///
- /// Log an event in one shot.
- ///
- /// event type
- /// event name
- /// "0" means success, otherwise means error code
- /// name value pairs in the format of "a=1&b=2&..."
- void LogEvent(String type, String name, String status, String nameValuePairs);
-
- ///
- /// Log a heartbeat in one shot.
- ///
- /// heartbeat type
- /// heartbeat name
- /// "0" means success, otherwise means error code
- /// name value pairs in the format of "a=1&b=2&..."
- void LogHeartbeat(String type, String name, String status, String nameValuePairs);
-
- ///
- /// Create a new event with given type and name.
- ///
- /// event type
- /// event name
- IEvent NewEvent(String type, String name);
-
- ///
- /// Create a new heartbeat with given type and name.
- ///
- /// heartbeat type
- /// heartbeat name
- IHeartbeat NewHeartbeat(String type, String name);
-
- ///
- /// Create a new transaction with given type and name.
- ///
- /// transaction type
- /// transaction name
- ITransaction NewTransaction(String type, String name);
- }
+using System;
+
+namespace Com.Dianping.Cat.Message.Spi
+{
+ ///
+ /// Message factory is used to create new transaction,event and/or heartbeat.
Normally, application code logs message in following ways, for example:
+ ///
+ /// - Event
+ ///
public class MyClass {
+ /// public static MessageFactory CAT = Cat.getFactory();
+ /// public void bizMethod() {
+ /// Event event = CAT.newEvent("Review", "New");
+ /// event.addData("id", 12345);
+ /// event.addData("user", "john");
+ /// ...
+ /// event.setStatus("0");
+ /// event.complete();
+ /// }
+ /// ...
+ /// }
+ ///
+ /// - Heartbeat
+ ///
public class MyClass {
+ /// public static MessageFactory CAT = Cat.getFactory();
+ /// public void bizMethod() {
+ /// Heartbeat event = CAT.newHeartbeat("System", "Status");
+ /// event.addData("ip", "192.168.10.111");
+ /// event.addData("host", "host-1");
+ /// event.addData("load", "2.1");
+ /// event.addData("cpu", "0.12,0.10");
+ /// event.addData("memory.total", "2G");
+ /// event.addData("memory.free", "456M");
+ /// event.setStatus("0");
+ /// event.complete();
+ /// }
+ /// ...
+ /// }
+ ///
+ /// - Transaction
+ ///
public class MyClass {
+ /// public static MessageFactory CAT = Cat.getFactory();
+ /// public void bizMethod() {
+ /// Transaction t = CAT.newTransaction("URL", "MyPage");
+ /// try {
+ /// // do your business here
+ /// t.addData("k1", "v1");
+ /// t.addData("k2", "v2");
+ /// t.addData("k3", "v3");
+ /// Thread.sleep(30);
+ /// t.setStatus("0");
+ /// } catch (Exception e) {
+ /// t.setStatus(e);
+ /// } finally {
+ /// t.complete();
+ /// }
+ /// }
+ /// ...
+ /// }
+ ///
+ ///
+ /// or logs event or heartbeat in one shot, for example:
+ ///
+ /// - Event
+ ///
public class MyClass {
+ /// public static MessageFactory CAT = Cat.getFactory();
+ /// public void bizMethod() {
+ /// CAT.logEvent("Review", "New", "0", "id=12345&user=john");
+ /// }
+ /// ...
+ /// }
+ ///
+ /// - Heartbeat
+ ///
public class MyClass {
+ /// public static MessageFactory CAT = Cat.getFactory();
+ /// public void bizMethod() {
+ /// CAT.logHeartbeat("System", "Status", "0", "ip=192.168.10.111&host=host-1&load=2.1&cpu=0.12,0.10&memory.total=2G&memory.free=456M");
+ /// }
+ /// ...
+ /// }
+ ///
+ ///
+ ///
+ ///
+ public interface IMessageProducer
+ {
+ String CreateMessageId();
+
+ ///
+ /// Log an error.
+ ///
+ /// root cause exception
+ void LogError(Exception cause);
+
+ ///
+ /// Log an event in one shot.
+ ///
+ /// event type
+ /// event name
+ /// "0" means success, otherwise means error code
+ /// name value pairs in the format of "a=1&b=2&..."
+ void LogEvent(String type, String name, String status, String nameValuePairs);
+
+ ///
+ /// Log a heartbeat in one shot.
+ ///
+ /// heartbeat type
+ /// heartbeat name
+ /// "0" means success, otherwise means error code
+ /// name value pairs in the format of "a=1&b=2&..."
+ void LogHeartbeat(String type, String name, String status, String nameValuePairs);
+
+ ///
+ /// Log a metric in one shot.
+ ///
+ /// metric name
+ /// "0" means success, otherwise means error code
+ /// name value pairs in the format of "a=1&b=2&..."
+ void LogMetric(String name, String status, String nameValuePairs);
+
+ ///
+ /// Create a new event with given type and name.
+ ///
+ /// event type
+ /// event name
+ IEvent NewEvent(String type, String name);
+
+ ///
+ /// Create a new heartbeat with given type and name.
+ ///
+ /// heartbeat type
+ /// heartbeat name
+ IHeartbeat NewHeartbeat(String type, String name);
+
+ ///
+ /// Create a new transaction with given type and name.
+ ///
+ /// transaction type
+ /// transaction name
+ ITransaction NewTransaction(String type, String name);
+
+ ///
+ /// Create a new metric with given type and name.
+ ///
+ /// metric type
+ /// metric name
+ IMetric NewMetric(String type, String name);
+
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/IMessageStatistics.cs b/Message/Spi/IMessageStatistics.cs
index e289cf0..c3a3fb0 100644
--- a/Message/Spi/IMessageStatistics.cs
+++ b/Message/Spi/IMessageStatistics.cs
@@ -1,17 +1,17 @@
-namespace Com.Dianping.Cat.Message.Spi
-{
- public interface IMessageStatistics
- {
- long Produced { get; set; }
-
- long Overflowed { get; set; }
-
- long Bytes { get; set; }
-
- void OnSending(IMessageTree tree);
-
- void OnOverflowed(IMessageTree tree);
-
- void OnBytes(int size);
- }
+namespace Com.Dianping.Cat.Message.Spi
+{
+ public interface IMessageStatistics
+ {
+ long Produced { get; set; }
+
+ long Overflowed { get; set; }
+
+ long Bytes { get; set; }
+
+ void OnSending(IMessageTree tree);
+
+ void OnOverflowed(IMessageTree tree);
+
+ void OnBytes(int size);
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/IO/IMessageSender.cs b/Message/Spi/IO/IMessageSender.cs
index 7d1c881..09d8f65 100644
--- a/Message/Spi/IO/IMessageSender.cs
+++ b/Message/Spi/IO/IMessageSender.cs
@@ -1,13 +1,13 @@
-namespace Com.Dianping.Cat.Message.Spi.IO
-{
- public interface IMessageSender
- {
- bool HasSendingMessage { get; }
-
- void Initialize();
-
- void Send(IMessageTree tree);
-
- void Shutdown();
- }
+namespace Com.Dianping.Cat.Message.Spi.IO
+{
+ public interface IMessageSender
+ {
+ bool HasSendingMessage { get; }
+
+ void Initialize();
+
+ void Send(IMessageTree tree);
+
+ void Shutdown();
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/IO/TcpMessageSender.cs b/Message/Spi/IO/TcpMessageSender.cs
index 5ee4edc..a64efae 100644
--- a/Message/Spi/IO/TcpMessageSender.cs
+++ b/Message/Spi/IO/TcpMessageSender.cs
@@ -1,263 +1,263 @@
-using System;
-using Com.Dianping.Cat.Configuration;
-using Com.Dianping.Cat.Message.Spi.Codec;
-using Com.Dianping.Cat.Util;
-using System.Collections.Generic;
-using System.Net.Sockets;
-using System.Threading;
-
-namespace Com.Dianping.Cat.Message.Spi.IO
-{
- public class TcpMessageSender : IMessageSender
- {
- private readonly ClientConfig _mClientConfig;
- private readonly IMessageCodec _mCodec;
- private readonly IList _mQueue;
- private readonly IMessageStatistics _mStatistics;
- private bool _mActive;
- private TcpClient _mActiveChannel;
- private int _mActiveIndex;
- private int _mErrors;
- private TcpClient _mLastChannel;
-
- public TcpMessageSender(ClientConfig clientConfig, IMessageStatistics statistics)
- {
- _mClientConfig = clientConfig;
- _mStatistics = statistics;
- _mActive = true;
- _mQueue = new List(100000);
- _mCodec = new PlainTextMessageCodec();
- }
-
- #region IMessageSender Members
-
- public virtual bool HasSendingMessage
- {
- get { return _mQueue.Count > 0; }
- }
-
- public void Initialize()
- {
- int len = _mClientConfig.Servers.Count;
-
- for (int i = 0; i < len; i++)
- {
- TcpClient channel = CreateChannel(i);
-
- if (channel != null)
- {
- _mActiveChannel = channel;
- _mActiveIndex = i;
- break;
- }
- }
-
- ThreadPool.QueueUserWorkItem(ChannelManagementTask);
- ThreadPool.QueueUserWorkItem(AsynchronousSendTask);
-
- Logger.Info("Thread(TcpMessageSender-ChannelManagementTask) started.");
- Logger.Info("Thread(TcpMessageSender-AsynchronousSendTask) started.");
- }
-
- public void Send(IMessageTree tree)
- {
- lock (_mQueue)
- {
- if (_mQueue.Count < 100000)
- {
- _mQueue.Add(tree);
- }
- else
- {
- // throw it away since the queue is full
- _mErrors ++;
-
- if (_mStatistics != null)
- {
- _mStatistics.OnOverflowed(tree);
- }
-
- if (_mErrors%100 == 0)
- {
- Logger.Warn("Can't send message to cat-server due to queue's full! Count: " + _mErrors);
- }
- }
- }
- }
-
- public void Shutdown()
- {
- _mActive = false;
-
- try
- {
- if (_mActiveChannel != null && _mActiveChannel.Connected)
- {
- _mActiveChannel.Close();
- }
- }
- catch
- {
- // ignore it
- }
- }
-
- #endregion
-
- public void ChannelManagementTask(object o)
- {
- while (true)
- {
- if (_mActive)
- {
- if (_mActiveChannel == null || !_mActiveChannel.Connected)
- {
- if (_mActiveChannel != null)
- Logger.Warn("ChannelManagementTask中,Socket关闭");
- _mActiveIndex = _mClientConfig.Servers.Count;
- }
-
- for (int i = 0; i < _mActiveIndex; i++)
- {
- TcpClient channel = CreateChannel(i);
-
- if (channel != null)
- {
- _mLastChannel = _mActiveChannel;
- _mActiveChannel = channel;
- _mActiveIndex = i;
- break;
- }
- }
- }
-
- Thread.Sleep(5*1000); // every 2 seconds
- }
- }
-
- public void AsynchronousSendTask(object o)
- {
- while (true)
- {
- if (_mActive)
- {
- while (_mQueue.Count == 0 || _mActiveChannel == null || !_mActiveChannel.Connected)
- {
- if (_mActiveChannel != null && !_mActiveChannel.Connected)
- Logger.Warn("AsynchronousSendTask中,Socket关闭");
- Thread.Sleep(5*1000);
- }
-
- IMessageTree tree = null;
-
- lock (_mQueue)
- {
- foreach (IMessageTree t in _mQueue)
- {
- tree = t;
- break;
- }
-
- _mQueue.RemoveAt(0);
- }
-
- try
- {
- SendInternal(tree);
- if (tree != null) tree.Message = null;
- }
- catch (Exception t)
- {
- Logger.Error("Error when sending message over TCP socket! Error: {0}", t);
- }
- }
- else
- {
- Thread.Sleep(5*1000);
- }
- }
- }
-
- private void SendInternal(IMessageTree tree)
- {
- if (_mLastChannel != null)
- {
- try
- {
- Logger.Warn("SendInternal中,_mLastChannel关闭");
- _mLastChannel.Close();
- }
- catch
- {
- // ignore it
- }
-
- _mLastChannel = null;
- }
-
- if (_mActiveChannel != null && _mActiveChannel.Connected)
- {
- ChannelBuffer buf = new ChannelBuffer(8192);
-
- _mCodec.Encode(tree, buf);
-
- byte[] data = buf.ToArray();
-
- _mActiveChannel.Client.Send(data);
-
- if (_mStatistics != null)
- {
- _mStatistics.OnBytes(data.Length);
- }
- }
- else
- {
- Logger.Warn("SendInternal中,Socket关闭");
- }
- }
-
- private TcpClient CreateChannel(int index)
- {
- Server server = _mClientConfig.Servers[index];
-
- if (!server.Enabled)
- {
- return null;
- }
-
- TcpClient socket = new TcpClient();
-
- socket.NoDelay = true;
- socket.ReceiveTimeout = 2*1000; // 2 seconds
-
- string ip = server.Ip;
- int port = server.Port;
-
- Logger.Info("Connecting to server({0}:{1}) ...", ip, port);
-
- try
- {
- socket.Connect(ip, port);
-
- if (socket.Connected)
- {
- Logger.Info("Connected to server({0}:{1}).", ip, port);
-
- return socket;
- }
- Logger.Error("Failed to connect to server({0}:{1}).", ip, port);
- }
- catch (Exception e)
- {
- Logger.Error(
- "Failed to connect to server({0}:{1}). Error: {2}.",
- ip,
- port,
- e.Message
- );
- }
-
- return null;
- }
- }
+using System;
+using Com.Dianping.Cat.Configuration;
+using Com.Dianping.Cat.Message.Spi.Codec;
+using Com.Dianping.Cat.Util;
+using System.Collections.Generic;
+using System.Net.Sockets;
+using System.Threading;
+
+namespace Com.Dianping.Cat.Message.Spi.IO
+{
+ public class TcpMessageSender : IMessageSender
+ {
+ private readonly ClientConfig _mClientConfig;
+ private readonly IMessageCodec _mCodec;
+ private readonly IList _mQueue;
+ private readonly IMessageStatistics _mStatistics;
+ private bool _mActive;
+ private TcpClient _mActiveChannel;
+ private int _mActiveIndex;
+ private int _mErrors;
+ private TcpClient _mLastChannel;
+
+ public TcpMessageSender(ClientConfig clientConfig, IMessageStatistics statistics)
+ {
+ _mClientConfig = clientConfig;
+ _mStatistics = statistics;
+ _mActive = true;
+ _mQueue = new List(100000);
+ _mCodec = new PlainTextMessageCodec();
+ }
+
+ #region IMessageSender Members
+
+ public virtual bool HasSendingMessage
+ {
+ get { return _mQueue.Count > 0; }
+ }
+
+ public void Initialize()
+ {
+ int len = _mClientConfig.Servers.Count;
+
+ for (int i = 0; i < len; i++)
+ {
+ TcpClient channel = CreateChannel(i);
+
+ if (channel != null)
+ {
+ _mActiveChannel = channel;
+ _mActiveIndex = i;
+ break;
+ }
+ }
+
+ ThreadPool.QueueUserWorkItem(ChannelManagementTask);
+ ThreadPool.QueueUserWorkItem(AsynchronousSendTask);
+
+ Logger.Info("Thread(TcpMessageSender-ChannelManagementTask) started.");
+ Logger.Info("Thread(TcpMessageSender-AsynchronousSendTask) started.");
+ }
+
+ public void Send(IMessageTree tree)
+ {
+ lock (_mQueue)
+ {
+ if (_mQueue.Count < 100000)
+ {
+ _mQueue.Add(tree);
+ }
+ else
+ {
+ // throw it away since the queue is full
+ _mErrors++;
+
+ if (_mStatistics != null)
+ {
+ _mStatistics.OnOverflowed(tree);
+ }
+
+ if (_mErrors % 100 == 0)
+ {
+ Logger.Warn("Can't send message to cat-server due to queue's full! Count: " + _mErrors);
+ }
+ }
+ }
+ }
+
+ public void Shutdown()
+ {
+ _mActive = false;
+
+ try
+ {
+ if (_mActiveChannel != null && _mActiveChannel.Connected)
+ {
+ _mActiveChannel.Close();
+ }
+ }
+ catch
+ {
+ // ignore it
+ }
+ }
+
+ #endregion
+
+ public void ChannelManagementTask(object o)
+ {
+ while (true)
+ {
+ if (_mActive)
+ {
+ if (_mActiveChannel == null || !_mActiveChannel.Connected)
+ {
+ if (_mActiveChannel != null)
+ Logger.Warn("ChannelManagementTask中,Socket关闭");
+ _mActiveIndex = _mClientConfig.Servers.Count;
+ }
+
+ for (int i = 0; i < _mActiveIndex; i++)
+ {
+ TcpClient channel = CreateChannel(i);
+
+ if (channel != null)
+ {
+ _mLastChannel = _mActiveChannel;
+ _mActiveChannel = channel;
+ _mActiveIndex = i;
+ break;
+ }
+ }
+ }
+
+ Thread.Sleep(5 * 1000); // every 2 seconds
+ }
+ }
+
+ public void AsynchronousSendTask(object o)
+ {
+ while (true)
+ {
+ if (_mActive)
+ {
+ while (_mQueue.Count == 0 || _mActiveChannel == null || !_mActiveChannel.Connected)
+ {
+ if (_mActiveChannel != null && !_mActiveChannel.Connected)
+ Logger.Warn("AsynchronousSendTask中,Socket关闭");
+ Thread.Sleep(5 * 1000);
+ }
+
+ IMessageTree tree = null;
+
+ lock (_mQueue)
+ {
+ foreach (IMessageTree t in _mQueue)
+ {
+ tree = t;
+ break;
+ }
+
+ _mQueue.RemoveAt(0);
+ }
+
+ try
+ {
+ SendInternal(tree);
+ if (tree != null) tree.Message = null;
+ }
+ catch (Exception t)
+ {
+ Logger.Error("Error when sending message over TCP socket! Error: {0}", t);
+ }
+ }
+ else
+ {
+ Thread.Sleep(5 * 1000);
+ }
+ }
+ }
+
+ private void SendInternal(IMessageTree tree)
+ {
+ if (_mLastChannel != null)
+ {
+ try
+ {
+ Logger.Warn("SendInternal中,_mLastChannel关闭");
+ _mLastChannel.Close();
+ }
+ catch
+ {
+ // ignore it
+ }
+
+ _mLastChannel = null;
+ }
+
+ if (_mActiveChannel != null && _mActiveChannel.Connected)
+ {
+ ChannelBuffer buf = new ChannelBuffer(8192);
+
+ _mCodec.Encode(tree, buf);
+
+ byte[] data = buf.ToArray();
+
+ _mActiveChannel.Client.Send(data);
+
+ if (_mStatistics != null)
+ {
+ _mStatistics.OnBytes(data.Length);
+ }
+ }
+ else
+ {
+ Logger.Warn("SendInternal中,Socket关闭");
+ }
+ }
+
+ private TcpClient CreateChannel(int index)
+ {
+ Server server = _mClientConfig.Servers[index];
+
+ if (!server.Enabled)
+ {
+ return null;
+ }
+
+ TcpClient socket = new TcpClient();
+
+ socket.NoDelay = true;
+ socket.ReceiveTimeout = 2 * 1000; // 2 seconds
+
+ string ip = server.Ip;
+ int port = server.Port;
+
+ Logger.Info("Connecting to server({0}:{1}) ...", ip, port);
+
+ try
+ {
+ socket.Connect(ip, port);
+
+ if (socket.Connected)
+ {
+ Logger.Info("Connected to server({0}:{1}).", ip, port);
+
+ return socket;
+ }
+ Logger.Error("Failed to connect to server({0}:{1}).", ip, port);
+ }
+ catch (Exception e)
+ {
+ Logger.Error(
+ "Failed to connect to server({0}:{1}). Error: {2}.",
+ ip,
+ port,
+ e.Message
+ );
+ }
+
+ return null;
+ }
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/Internals/DefaultMessageManager.cs b/Message/Spi/Internals/DefaultMessageManager.cs
index 19261b2..1cdad24 100644
--- a/Message/Spi/Internals/DefaultMessageManager.cs
+++ b/Message/Spi/Internals/DefaultMessageManager.cs
@@ -1,343 +1,344 @@
-using System.Globalization;
-using Com.Dianping.Cat.Message.Internals;
-using Com.Dianping.Cat.Message.Spi.IO;
-using Com.Dianping.Cat.Util;
-using Com.Dianping.Cat.Configuration;
-using System;
-using System.Collections.Generic;
-using System.Threading;
-
-namespace Com.Dianping.Cat.Message.Spi.Internals
-{
- public class DefaultMessageManager : IMessageManager
- {
- // we don't use static modifier since MessageManager is a singleton in
- // production actually
- private readonly CatThreadLocal _mContext = new CatThreadLocal();
-
- private ClientConfig _mClientConfig;
-
- private MessageIdFactory _mFactory;
-
- private bool _mFirstMessage = true;
- private String _mHostName;
-
- private IMessageSender _mSender;
-
- private IMessageStatistics _mStatistics;
-
- private StatusUpdateTask _mStatusUpdateTask;
-
- #region IMessageManager Members
-
- public virtual ClientConfig ClientConfig
- {
- get { return _mClientConfig; }
- }
-
- public virtual ITransaction PeekTransaction
- {
- get
- {
- Context ctx = GetContext();
-
- return ctx != null ? ctx.PeekTransaction() : null;
- }
- }
-
- public virtual IMessageTree ThreadLocalMessageTree
- {
- get
- {
- Context ctx = _mContext.Value;
-
- return ctx != null ? ctx.Tree : null;
- }
- }
-
- public virtual void Reset()
- {
- // destroy current thread local data
- _mContext.Dispose();
- }
-
- public virtual void InitializeClient(ClientConfig clientConfig)
- {
- _mClientConfig = clientConfig ?? new ClientConfig();
-
- _mHostName = NetworkInterfaceManager.GetLocalHostName();
-
- _mStatistics = new DefaultMessageStatistics();
- _mSender = new TcpMessageSender(_mClientConfig, _mStatistics);
- _mSender.Initialize();
- _mFactory = new MessageIdFactory();
- _mStatusUpdateTask = new StatusUpdateTask(_mStatistics);
-
- // initialize domain and ip address
- _mFactory.Initialize(_mClientConfig.Domain.Id);
-
- // start status update task
- ThreadPool.QueueUserWorkItem(_mStatusUpdateTask.Run);
-
- Logger.Info("Thread(StatusUpdateTask) started.");
- }
-
- public virtual bool HasContext()
- {
- return _mContext.Value != null;
- }
-
- public virtual bool CatEnabled
- {
- get { return _mClientConfig.Domain.Enabled && _mContext.Value != null; }
- }
-
- public virtual void Add(IMessage message)
- {
- Context ctx = GetContext();
-
- if (ctx != null)
- {
- ctx.Add(this, message);
- }
- else
- Logger.Warn("Context没取到");
- }
-
- public virtual void Setup()
- {
- Context ctx = new Context(_mClientConfig.Domain.Id, _mHostName,
- NetworkInterfaceManager.GetLocalHostAddress());
-
- _mContext.Value = ctx;
- }
-
- public virtual void Start(ITransaction transaction)
- {
- Context ctx = GetContext();
-
- if (ctx != null)
- {
- ctx.Start(this, transaction);
- }
- else if (_mFirstMessage)
- {
- _mFirstMessage = false;
- Logger.Info("CAT client is not enabled because it's not initialized yet");
- }
- else
- Logger.Warn("Context没取到");
- }
-
- public virtual void End(ITransaction transaction)
- {
- Context ctx = GetContext();
-
- if (ctx != null)
- {
- //if (!transaction.Standalone) return;
- if (ctx.End(this, transaction))
- {
- _mContext.Dispose();
- }
- }
- else
- Logger.Warn("Context没取到");
- }
-
- #endregion
-
- public MessageIdFactory GetMessageIdFactory()
- {
- return _mFactory;
- }
-
- internal void Flush(IMessageTree tree)
- {
- if (_mSender != null)
- {
- _mSender.Send(tree);
-
- if (_mStatistics != null)
- {
- _mStatistics.OnSending(tree);
- }
- }
- }
-
- internal Context GetContext()
- {
- if (Cat.IsInitialized())
- {
- Context ctx = _mContext.Value;
-
- if (ctx != null)
- {
- return ctx;
- }
- if (_mClientConfig.DevMode)
- {
- throw new Exception(
- "Cat has not been initialized successfully, please call Cal.setup(...) first for each thread.");
- }
- }
-
- return null;
- }
-
- internal String NextMessageId()
- {
- return _mFactory.GetNextId();
- }
-
- //internal bool ShouldThrottle(IMessageTree tree)
- //{
- // return false;
- //}
-
- #region Nested type: Context
-
- internal class Context
- {
- private readonly Stack _mStack;
- private readonly IMessageTree _mTree;
-
- public Context(String domain, String hostName, String ipAddress)
- {
- _mTree = new DefaultMessageTree();
- _mStack = new Stack();
-
- Thread thread = Thread.CurrentThread;
- String groupName = Thread.GetDomain().FriendlyName;
-
- _mTree.ThreadGroupName = groupName;
- _mTree.ThreadId = thread.ManagedThreadId.ToString(CultureInfo.InvariantCulture);
- _mTree.ThreadName = thread.Name;
-
- _mTree.Domain = domain;
- _mTree.HostName = hostName;
- _mTree.IpAddress = ipAddress;
- }
-
- public IMessageTree Tree
- {
- get { return _mTree; }
- }
-
- ///
- /// 添加Event和Heartbeat
- ///
- ///
- ///
- public void Add(DefaultMessageManager manager, IMessage message)
- {
- if ((_mStack.Count == 0))
- {
- IMessageTree tree = _mTree.Copy();
- tree.MessageId = manager.NextMessageId();
- tree.Message = message;
- manager.Flush(tree);
- }
- else
- {
- ITransaction entry = _mStack.Peek();
- entry.AddChild(message);
- }
- }
-
- ///
- /// return true means the transaction has been flushed.
- ///
- ///
- ///
- /// true if message is flushed, false otherwise
- public bool End(DefaultMessageManager manager, ITransaction transaction)
- {
- if (_mStack.Count != 0)
- {
- ITransaction current = _mStack.Pop();
- while (transaction != current && _mStack.Count != 0)
- {
- current = _mStack.Pop();
- }
- if (transaction != current)
- throw new Exception("没找到对应的Transaction.");
-
- if (_mStack.Count == 0)
- {
- ValidateTransaction(current);
-
- IMessageTree tree = _mTree.Copy();
- _mTree.MessageId = null;
- _mTree.Message = null;
- manager.Flush(tree);
- return true;
- }
- return false;
- }
-
- throw new Exception("Stack为空, 没找到对应的Transaction.");
- }
-
- ///
- /// 返回stack的顶部对象
- ///
- ///
- public ITransaction PeekTransaction()
- {
- return (_mStack.Count == 0) ? null : _mStack.Peek();
- }
-
- ///
- /// 添加transaction
- ///
- ///
- ///
- public void Start(DefaultMessageManager manager, ITransaction transaction)
- {
- if (_mStack.Count != 0)
- {
- transaction.Standalone = false;
- ITransaction entry = _mStack.Peek();
- entry.AddChild(transaction);
- }
- else
- {
- _mTree.MessageId = manager.NextMessageId();
- _mTree.Message = transaction;
- }
-
- _mStack.Push(transaction);
- }
-
- //验证Transaction
- internal void ValidateTransaction(ITransaction transaction)
- {
- IList children = transaction.Children;
- int len = children.Count;
- for (int i = 0; i < len; i++)
- {
- IMessage message = children[i];
- var transaction1 = message as ITransaction;
- if (transaction1 != null)
- {
- ValidateTransaction(transaction1);
- }
- }
-
- if (!transaction.IsCompleted())
- {
- // missing transaction end, log a BadInstrument event so that
- // developer can fix the code
- IMessage notCompleteEvent = new DefaultEvent("CAT", "BadInstrument")
- {Status = "TransactionNotCompleted"};
- notCompleteEvent.Complete();
- transaction.AddChild(notCompleteEvent);
- transaction.Complete();
- }
- }
- }
-
- #endregion
- }
+using System.Globalization;
+using Com.Dianping.Cat.Message.Internals;
+using Com.Dianping.Cat.Message.Spi.IO;
+using Com.Dianping.Cat.Util;
+using Com.Dianping.Cat.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Com.Dianping.Cat.Message.Spi.Internals
+{
+ [Serializable]
+ public class DefaultMessageManager : IMessageManager
+ {
+ // we don't use static modifier since MessageManager is a singleton in
+ // production actually
+ private readonly CatThreadLocal _mContext = new CatThreadLocal();
+
+ private ClientConfig _mClientConfig;
+
+ private MessageIdFactory _mFactory;
+
+ private bool _mFirstMessage = true;
+ private String _mHostName;
+
+ private IMessageSender _mSender;
+
+ private IMessageStatistics _mStatistics;
+
+ private StatusUpdateTask _mStatusUpdateTask;
+
+ #region IMessageManager Members
+
+ public virtual ClientConfig ClientConfig
+ {
+ get { return _mClientConfig; }
+ }
+
+ public virtual ITransaction PeekTransaction
+ {
+ get
+ {
+ Context ctx = GetContext();
+
+ return ctx != null ? ctx.PeekTransaction() : null;
+ }
+ }
+
+ public virtual IMessageTree ThreadLocalMessageTree
+ {
+ get
+ {
+ Context ctx = _mContext.Value;
+
+ return ctx != null ? ctx.Tree : null;
+ }
+ }
+
+ public virtual void Reset()
+ {
+ // destroy current thread local data
+ _mContext.Dispose();
+ }
+
+ public virtual void InitializeClient(ClientConfig clientConfig)
+ {
+ _mClientConfig = clientConfig ?? new ClientConfig();
+
+ _mHostName = NetworkInterfaceManager.GetLocalHostName();
+
+ _mStatistics = new DefaultMessageStatistics();
+ _mSender = new TcpMessageSender(_mClientConfig, _mStatistics);
+ _mSender.Initialize();
+ _mFactory = new MessageIdFactory();
+ _mStatusUpdateTask = new StatusUpdateTask(_mStatistics);
+
+ // initialize domain and ip address
+ _mFactory.Initialize(_mClientConfig.Domain.Id);
+
+ // start status update task
+ // ThreadPool.QueueUserWorkItem(_mStatusUpdateTask.Run);
+
+ Logger.Info("Thread(StatusUpdateTask) started.");
+ }
+
+ public virtual bool HasContext()
+ {
+ return _mContext.Value != null;
+ }
+
+ public virtual bool CatEnabled
+ {
+ get { return _mClientConfig.Domain.Enabled && _mContext.Value != null; }
+ }
+
+ public virtual void Add(IMessage message)
+ {
+ Context ctx = GetContext();
+
+ if (ctx != null)
+ {
+ ctx.Add(this, message);
+ }
+ else
+ Logger.Warn("Context没取到");
+ }
+
+ public virtual void Setup()
+ {
+ Context ctx = new Context(_mClientConfig.Domain.Id, _mHostName,
+ NetworkInterfaceManager.GetLocalHostAddress());
+
+ _mContext.Value = ctx;
+ }
+
+ public virtual void Start(ITransaction transaction)
+ {
+ Context ctx = GetContext();
+
+ if (ctx != null)
+ {
+ ctx.Start(this, transaction);
+ }
+ else if (_mFirstMessage)
+ {
+ _mFirstMessage = false;
+ Logger.Info("CAT client is not enabled because it's not initialized yet");
+ }
+ else
+ Logger.Warn("Context没取到");
+ }
+
+ public virtual void End(ITransaction transaction)
+ {
+ Context ctx = GetContext();
+
+ if (ctx != null)
+ {
+ //if (!transaction.Standalone) return;
+ if (ctx.End(this, transaction))
+ {
+ _mContext.Dispose();
+ }
+ }
+ else
+ Logger.Warn("Context没取到");
+ }
+
+ #endregion
+
+ public MessageIdFactory GetMessageIdFactory()
+ {
+ return _mFactory;
+ }
+
+ internal void Flush(IMessageTree tree)
+ {
+ if (_mSender != null)
+ {
+ _mSender.Send(tree);
+
+ if (_mStatistics != null)
+ {
+ _mStatistics.OnSending(tree);
+ }
+ }
+ }
+
+ internal Context GetContext()
+ {
+ if (Cat.IsInitialized())
+ {
+ Context ctx = _mContext.Value;
+
+ if (ctx != null)
+ {
+ return ctx;
+ }
+ if (_mClientConfig.DevMode)
+ {
+ throw new Exception(
+ "Cat has not been initialized successfully, please call Cal.setup(...) first for each thread.");
+ }
+ }
+
+ return null;
+ }
+
+ public String NextMessageId()
+ {
+ return _mFactory.GetNextId();
+ }
+
+ //internal bool ShouldThrottle(IMessageTree tree)
+ //{
+ // return false;
+ //}
+
+ #region Nested type: Context
+
+ internal class Context
+ {
+ private readonly Stack _mStack;
+ private readonly IMessageTree _mTree;
+
+ public Context(String domain, String hostName, String ipAddress)
+ {
+ _mTree = new DefaultMessageTree();
+ _mStack = new Stack();
+
+ Thread thread = Thread.CurrentThread;
+ String groupName = Thread.GetDomain().FriendlyName;
+
+ _mTree.ThreadGroupName = groupName;
+ _mTree.ThreadId = thread.ManagedThreadId.ToString(CultureInfo.InvariantCulture);
+ _mTree.ThreadName = thread.Name;
+
+ _mTree.Domain = domain;
+ _mTree.HostName = hostName;
+ _mTree.IpAddress = ipAddress;
+ }
+
+ public IMessageTree Tree
+ {
+ get { return _mTree; }
+ }
+
+ ///
+ /// 添加Event和Heartbeat
+ ///
+ ///
+ ///
+ public void Add(DefaultMessageManager manager, IMessage message)
+ {
+ if ((_mStack.Count == 0))
+ {
+ IMessageTree tree = _mTree.Copy();
+ tree.MessageId = manager.NextMessageId();
+ tree.Message = message;
+ manager.Flush(tree);
+ }
+ else
+ {
+ ITransaction entry = _mStack.Peek();
+ entry.AddChild(message);
+ }
+ }
+
+ ///
+ /// return true means the transaction has been flushed.
+ ///
+ ///
+ ///
+ /// true if message is flushed, false otherwise
+ public bool End(DefaultMessageManager manager, ITransaction transaction)
+ {
+ if (_mStack.Count != 0)
+ {
+ ITransaction current = _mStack.Pop();
+ while (transaction != current && _mStack.Count != 0)
+ {
+ current = _mStack.Pop();
+ }
+ if (transaction != current)
+ throw new Exception("没找到对应的Transaction.");
+
+ if (_mStack.Count == 0)
+ {
+ ValidateTransaction(current);
+
+ IMessageTree tree = _mTree.Copy();
+ _mTree.MessageId = null;
+ _mTree.Message = null;
+ manager.Flush(tree);
+ return true;
+ }
+ return false;
+ }
+ throw new Exception("Stack为空, 没找到对应的Transaction.");
+
+
+ }
+
+ ///
+ /// 返回stack的顶部对象
+ ///
+ ///
+ public ITransaction PeekTransaction()
+ {
+ return (_mStack.Count == 0) ? null : _mStack.Peek();
+ }
+
+ ///
+ /// 添加transaction
+ ///
+ ///
+ ///
+ public void Start(DefaultMessageManager manager, ITransaction transaction)
+ {
+ if (_mStack.Count != 0)
+ {
+ transaction.Standalone = false;
+ ITransaction entry = _mStack.Peek();
+ entry.AddChild(transaction);
+ }
+ else
+ {
+ _mTree.MessageId = manager.NextMessageId();
+ _mTree.Message = transaction;
+ }
+
+ _mStack.Push(transaction);
+ }
+
+ //验证Transaction
+ internal void ValidateTransaction(ITransaction transaction)
+ {
+ IList children = transaction.Children;
+ int len = children.Count;
+ for (int i = 0; i < len; i++)
+ {
+ IMessage message = children[i];
+ var transaction1 = message as ITransaction;
+ if (transaction1 != null)
+ {
+ ValidateTransaction(transaction1);
+ }
+ }
+
+ if (!transaction.IsCompleted())
+ {
+ // missing transaction end, log a BadInstrument event so that
+ // developer can fix the code
+ IMessage notCompleteEvent = new DefaultEvent("CAT", "BadInstrument") { Status = "TransactionNotCompleted" };
+ notCompleteEvent.Complete();
+ transaction.AddChild(notCompleteEvent);
+ transaction.Complete();
+ }
+ }
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/Internals/DefaultMessageProducer.cs b/Message/Spi/Internals/DefaultMessageProducer.cs
index cf3afcb..1622f59 100644
--- a/Message/Spi/Internals/DefaultMessageProducer.cs
+++ b/Message/Spi/Internals/DefaultMessageProducer.cs
@@ -1,129 +1,172 @@
-using Com.Dianping.Cat.Message.Internals;
-using System;
-using System.IO;
-
-namespace Com.Dianping.Cat.Message.Spi.Internals
-{
- public class DefaultMessageProducer : IMessageProducer
- {
- private readonly IMessageManager _mManager;
-
- public DefaultMessageProducer(IMessageManager manager)
- {
- _mManager = manager;
- }
-
- #region IMessageProducer Members
-
- public virtual void LogError(Exception cause)
- {
- var ignore = false;
- if (cause.Data.Contains("CatIgnore") && cause.Data["CatIgnore"] is bool)
- ignore = (bool) (cause.Data["CatIgnore"]);
-
- if (ignore) return;
-
- StringWriter writer = new StringWriter();
-
- try
- {
- writer.WriteLine(cause.Message);
- writer.WriteLine(cause.StackTrace);
- var innerException = cause.InnerException;
- while (innerException != null)
- {
- writer.WriteLine("-------------------------------------------------------------------");
- writer.WriteLine(innerException.Message);
- writer.WriteLine(innerException.StackTrace);
-
- innerException = innerException.InnerException;
- }
- }
- catch
- {
- }
-
- LogEvent("Error", cause.GetType().FullName, "ERROR",
- writer.ToString());
- }
-
- public virtual void LogEvent(String type, String name, String status, String nameValuePairs)
- {
- IEvent evt0 = NewEvent(type, name);
-
- if (!string.IsNullOrEmpty(nameValuePairs))
- {
- evt0.AddData(nameValuePairs);
- }
-
- evt0.Status = status;
- evt0.Complete();
- }
-
- public virtual void LogHeartbeat(String type, String name, String status, String nameValuePairs)
- {
- IHeartbeat heartbeat = NewHeartbeat(type, name);
-
- if (!string.IsNullOrEmpty(nameValuePairs))
- {
- heartbeat.AddData(nameValuePairs);
- }
- heartbeat.Status = status;
- heartbeat.Complete();
- }
-
- public virtual IEvent NewEvent(String type, String name)
- {
- if (!_mManager.HasContext())
- {
- _mManager.Setup();
- }
-
- if (_mManager.CatEnabled)
- {
- IEvent evt0 = new DefaultEvent(type, name);
-
- _mManager.Add(evt0);
- return evt0;
- }
- return new NullEvent();
- }
-
- public virtual IHeartbeat NewHeartbeat(String type, String name)
- {
- if (!_mManager.HasContext())
- {
- _mManager.Setup();
- }
-
- if (_mManager.CatEnabled)
- {
- IHeartbeat heartbeat = new DefaultHeartbeat(type, name);
-
- _mManager.Add(heartbeat);
- return heartbeat;
- }
- return new NullHeartbeat();
- }
-
- public virtual ITransaction NewTransaction(String type, String name)
- {
- // this enable CAT client logging cat message without explicit setup
- if (!_mManager.HasContext())
- {
- _mManager.Setup();
- }
-
- if (_mManager.CatEnabled)
- {
- ITransaction transaction = new DefaultTransaction(type, name, _mManager.End);
-
- _mManager.Start(transaction);
- return transaction;
- }
- return new NullTransaction();
- }
-
- #endregion
- }
+using Com.Dianping.Cat.Message.Internals;
+using System;
+using System.IO;
+
+namespace Com.Dianping.Cat.Message.Spi.Internals
+{
+ public class DefaultMessageProducer : IMessageProducer
+ {
+ private readonly IMessageManager _mManager;
+
+ public DefaultMessageProducer(IMessageManager manager)
+ {
+ _mManager = manager;
+ }
+
+ public String CreateMessageId()
+ {
+ return _mManager.GetMessageIdFactory().GetNextId();
+ }
+
+ #region IMessageProducer Members
+
+ public virtual void LogError(Exception cause)
+ {
+ var ignore = false;
+ if (cause.Data.Contains("CatIgnore") && cause.Data["CatIgnore"] is bool)
+ ignore = (bool)(cause.Data["CatIgnore"]);
+
+ if (ignore) return;
+
+ StringWriter writer = new StringWriter();
+
+ try
+ {
+ writer.WriteLine(cause.Message);
+ writer.WriteLine(cause.StackTrace);
+ var innerException = cause.InnerException;
+ while (innerException != null)
+ {
+ writer.WriteLine("-------------------------------------------------------------------");
+ writer.WriteLine(innerException.Message);
+ writer.WriteLine(innerException.StackTrace);
+
+ innerException = innerException.InnerException;
+ }
+ }
+ catch
+ {
+ }
+
+ LogEvent("Error", cause.GetType().FullName, "ERROR",
+ writer.ToString());
+ }
+
+ public virtual void LogEvent(String type, String name, String status, String nameValuePairs)
+ {
+ IEvent evt0 = NewEvent(type, name);
+
+ if (!string.IsNullOrEmpty(nameValuePairs))
+ {
+ evt0.AddData(nameValuePairs);
+ }
+
+ evt0.Status = status;
+ evt0.Complete();
+ }
+
+ public virtual void LogHeartbeat(String type, String name, String status, String nameValuePairs)
+ {
+ IHeartbeat heartbeat = NewHeartbeat(type, name);
+
+ if (!string.IsNullOrEmpty(nameValuePairs))
+ {
+ heartbeat.AddData(nameValuePairs);
+ }
+ heartbeat.Status = status;
+ heartbeat.Complete();
+ }
+
+ public virtual void LogMetric(String name, String status, String nameValuePairs)
+ {
+ String type = string.Empty;
+ IMetric metric = NewMetric(type, name);
+
+ if (!string.IsNullOrWhiteSpace(nameValuePairs))
+ {
+ metric.AddData(nameValuePairs);
+ }
+
+ metric.Status = status;
+ metric.Complete();
+ }
+
+ public virtual IEvent NewEvent(String type, String name)
+ {
+ if (!_mManager.HasContext())
+ {
+ _mManager.Setup();
+ }
+
+ if (_mManager.CatEnabled)
+ {
+ IEvent evt0 = new DefaultEvent(type, name);
+
+ _mManager.Add(evt0);
+ return evt0;
+ }
+ return new NullEvent();
+ }
+
+ public virtual IHeartbeat NewHeartbeat(String type, String name)
+ {
+ if (!_mManager.HasContext())
+ {
+ _mManager.Setup();
+ }
+
+ if (_mManager.CatEnabled)
+ {
+ IHeartbeat heartbeat = new DefaultHeartbeat(type, name);
+
+ _mManager.Add(heartbeat);
+ return heartbeat;
+ }
+ return new NullHeartbeat();
+ }
+
+ public virtual ITransaction NewTransaction(String type, String name)
+ {
+ // this enable CAT client logging cat message without explicit setup
+ if (!_mManager.HasContext())
+ {
+ _mManager.Setup();
+ }
+
+ if (_mManager.CatEnabled)
+ {
+ ITransaction transaction = new DefaultTransaction(type, name, _mManager.End);
+
+ _mManager.Start(transaction);
+ return transaction;
+ }
+ return new NullTransaction();
+ }
+
+ ///
+ /// new metric
+ ///
+ /// group
+ /// key
+ public virtual IMetric NewMetric(String type, String name)
+ {
+ // this enable CAT client logging cat message without explicit setup
+ if (!_mManager.HasContext())
+ {
+ _mManager.Setup();
+ }
+
+ if (_mManager.CatEnabled)
+ {
+ IMetric metric = new DefaultMetric(string.IsNullOrWhiteSpace(type) ? string.Empty : type, name);
+
+ _mManager.Add(metric);
+ return metric;
+ }
+ return new NullMetric();
+ }
+
+ #endregion
+
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/Internals/DefaultMessageStatistics.cs b/Message/Spi/Internals/DefaultMessageStatistics.cs
index 9ddc50c..a7990bc 100644
--- a/Message/Spi/Internals/DefaultMessageStatistics.cs
+++ b/Message/Spi/Internals/DefaultMessageStatistics.cs
@@ -1,30 +1,30 @@
-namespace Com.Dianping.Cat.Message.Spi.Internals
-{
- public class DefaultMessageStatistics : IMessageStatistics
- {
- #region IMessageStatistics Members
-
- public long Produced { get; set; }
-
- public long Overflowed { get; set; }
-
- public long Bytes { get; set; }
-
- public void OnSending(IMessageTree tree)
- {
- Produced++;
- }
-
- public void OnOverflowed(IMessageTree tree)
- {
- Overflowed++;
- }
-
- public void OnBytes(int size)
- {
- Bytes += size;
- }
-
- #endregion
- }
+namespace Com.Dianping.Cat.Message.Spi.Internals
+{
+ public class DefaultMessageStatistics : IMessageStatistics
+ {
+ #region IMessageStatistics Members
+
+ public long Produced { get; set; }
+
+ public long Overflowed { get; set; }
+
+ public long Bytes { get; set; }
+
+ public void OnSending(IMessageTree tree)
+ {
+ Produced++;
+ }
+
+ public void OnOverflowed(IMessageTree tree)
+ {
+ Overflowed++;
+ }
+
+ public void OnBytes(int size)
+ {
+ Bytes += size;
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/Internals/MessageIdFactory.cs b/Message/Spi/Internals/MessageIdFactory.cs
index f45e874..d1d7411 100644
--- a/Message/Spi/Internals/MessageIdFactory.cs
+++ b/Message/Spi/Internals/MessageIdFactory.cs
@@ -1,86 +1,86 @@
-using Com.Dianping.Cat.Util;
-using System;
-using System.Text;
-
-namespace Com.Dianping.Cat.Message.Spi.Internals
-{
- ///
- /// 根据域名(配置指定的),系统IP(自动解析的,16进制字符串),时间戳(1970年到当前的小时数)和自增编号组成
- ///
- public class MessageIdFactory
- {
- private String _mDomain;
- private volatile int _mIndex;
-
- private String _mIpAddress;
- private long _mLastTimestamp;
-
- public MessageIdFactory()
- {
- _mLastTimestamp = Timestamp;
- }
-
- protected internal long Timestamp
- {
- get { return MilliSecondTimer.CurrentTimeHoursForJava(); }
- }
-
- public String Domain
- {
- set { _mDomain = value; }
- }
-
- public String IpAddress
- {
- set { _mIpAddress = value; }
- }
-
- public String GetNextId()
- {
- long timestamp = Timestamp;
- int index;
-
- lock (this)
- {
- if (timestamp != _mLastTimestamp)
- {
- _mIndex = 0;
- _mLastTimestamp = timestamp;
- }
-
- index = _mIndex++;
- }
-
- StringBuilder sb = new StringBuilder(_mDomain.Length + 32);
-
- sb.Append(_mDomain);
- sb.Append('-');
- sb.Append(_mIpAddress);
- sb.Append('-');
- sb.Append(timestamp);
- sb.Append('-');
- sb.Append(index);
-
- return sb.ToString();
- }
-
- public void Initialize(String domain)
- {
- _mDomain = domain;
-
- if (_mIpAddress != null) return;
-
- byte[] bytes = NetworkInterfaceManager.GetAddressBytes();
-
- StringBuilder sb = new StringBuilder();
-
- foreach (byte b in bytes)
- {
- sb.Append(((b >> 4) & 0x0F).ToString("x"));
- sb.Append((b & 0x0F).ToString("x"));
- }
-
- _mIpAddress = sb.ToString();
- }
- }
+using Com.Dianping.Cat.Util;
+using System;
+using System.Text;
+
+namespace Com.Dianping.Cat.Message.Spi.Internals
+{
+ ///
+ /// 根据域名(配置指定的),系统IP(自动解析的,16进制字符串),时间戳(1970年到当前的小时数)和自增编号组成
+ ///
+ public class MessageIdFactory
+ {
+ private String _mDomain;
+ private volatile int _mIndex;
+
+ private String _mIpAddress;
+ private long _mLastTimestamp;
+
+ public MessageIdFactory()
+ {
+ _mLastTimestamp = Timestamp;
+ }
+
+ protected internal long Timestamp
+ {
+ get { return MilliSecondTimer.CurrentTimeHoursForJava(); }
+ }
+
+ public String Domain
+ {
+ set { _mDomain = value; }
+ }
+
+ public String IpAddress
+ {
+ set { _mIpAddress = value; }
+ }
+
+ public String GetNextId()
+ {
+ long timestamp = Timestamp;
+ int index;
+
+ lock (this)
+ {
+ if (timestamp != _mLastTimestamp)
+ {
+ _mIndex = 0;
+ _mLastTimestamp = timestamp;
+ }
+
+ index = _mIndex++;
+ }
+
+ StringBuilder sb = new StringBuilder(_mDomain.Length + 32);
+
+ sb.Append(_mDomain);
+ sb.Append('-');
+ sb.Append(_mIpAddress);
+ sb.Append('-');
+ sb.Append(timestamp);
+ sb.Append('-');
+ sb.Append(index);
+
+ return sb.ToString();
+ }
+
+ public void Initialize(String domain)
+ {
+ _mDomain = domain;
+
+ if (_mIpAddress != null) return;
+
+ byte[] bytes = NetworkInterfaceManager.GetAddressBytes();
+
+ StringBuilder sb = new StringBuilder();
+
+ foreach (byte b in bytes)
+ {
+ sb.Append(((b >> 4) & 0x0F).ToString("x"));
+ sb.Append((b & 0x0F).ToString("x"));
+ }
+
+ _mIpAddress = sb.ToString();
+ }
+ }
}
\ No newline at end of file
diff --git a/Message/Spi/Internals/StatusUpdateTask.cs b/Message/Spi/Internals/StatusUpdateTask.cs
index 649d44a..61f001a 100644
--- a/Message/Spi/Internals/StatusUpdateTask.cs
+++ b/Message/Spi/Internals/StatusUpdateTask.cs
@@ -1,192 +1,192 @@
-using System;
-using System.Diagnostics;
-using System.Globalization;
-using System.Management;
-using System.Threading;
-using System.Text;
-using Com.Dianping.Cat.Util;
-
-namespace Com.Dianping.Cat.Message.Spi.Internals
-{
- public class StatusUpdateTask
- {
- private readonly IMessageStatistics _mStatistics;
-
- public StatusUpdateTask(IMessageStatistics mStatistics)
- {
- _mStatistics = mStatistics;
- }
-
- ///
- /// 获取系统内存大小
- ///
- /// 内存大小(单位M)
- private static int GetPhisicalMemory()
- {
- ManagementObjectSearcher searcher = new ManagementObjectSearcher(); //用于查询一些如系统信息的管理对象
- searcher.Query = new SelectQuery("Win32_PhysicalMemory ", "", new[] {"Capacity"}); //设置查询条件
- ManagementObjectCollection collection = searcher.Get(); //获取内存容量
- ManagementObjectCollection.ManagementObjectEnumerator em = collection.GetEnumerator();
-
- long capacity = 0;
- while (em.MoveNext())
- {
- ManagementBaseObject baseObj = em.Current;
- if (baseObj.Properties["Capacity"].Value != null)
- {
- try
- {
- capacity += long.Parse(baseObj.Properties["Capacity"].Value.ToString());
- }
- catch
- {
- return 0;
- }
- }
- }
- return (int) (capacity/1024/1024);
- }
-
- public void Run(object o)
- {
- while (true)
- {
- var sb = new StringBuilder();
- sb.AppendLine("StatusUpdateTask:");
- sb.AppendLine("Bytes=" + _mStatistics.Bytes);
- sb.AppendLine("Overflowed=" + _mStatistics.Overflowed);
- sb.AppendLine("Produced=" + _mStatistics.Produced);
-
- //机器的CPU内核数
- var processorCount = Environment.ProcessorCount;
- sb.AppendLine("机器的CPU内核数=" + processorCount);
-
- //获取当前进程
- Process currentProcess = Process.GetCurrentProcess();
- //var processId = CurrentProcess.Id;//PID
- //获取当前进程CPU利用率
- var tmpRate =
- Math.Round(
- currentProcess.UserProcessorTime.TotalMilliseconds*100/
- currentProcess.TotalProcessorTime.TotalMilliseconds, 2);
- var cpuUsage = tmpRate + "%"; //CPU
- //获取当前进程内存占用
- var memoryUsage = (currentProcess.WorkingSet64/1024/1024).ToString(CultureInfo.InvariantCulture) + "M (" +
- (currentProcess.WorkingSet64/1024).ToString(CultureInfo.InvariantCulture) + "KB)";
- //占用内存
- //获取当前进程的线程数
- var threadCount = currentProcess.Threads.Count; //线程
-
- //获取当前进程的线程池大小
- int maxThread, maxThread2;
- ThreadPool.GetMaxThreads(out maxThread, out maxThread2); //线程
- int avThread, avThread2;
- ThreadPool.GetAvailableThreads(out avThread, out avThread2);
- int mThread, mThread2;
- ThreadPool.GetMinThreads(out mThread, out mThread2);
-
- var threadPoolInfo = string.Format("线程池大小={0}/{1}, 线程池可用线程数={2}/{3}, 线程池最小线程数={4}/{5}", maxThread2,
- maxThread, avThread2, avThread, mThread2,
- mThread);
-
- sb.AppendLine("当前进程CPU利用率=" + cpuUsage);
- sb.AppendLine("当前进程内存占用=" + memoryUsage);
- sb.AppendLine("当前进程的线程数=" + threadCount);
- sb.AppendLine(threadPoolInfo);
-
- var bestThreadInfo = string.Empty;
- //最佳线程数为
- var bestThreadCountTmp = currentProcess.TotalProcessorTime.TotalMilliseconds/
- (currentProcess.UserProcessorTime.TotalMilliseconds/threadCount);
- bestThreadInfo += "最佳线程数=" + bestThreadCountTmp + ",";
-
- //如果需要增加线程
- if (Math.Abs(bestThreadCountTmp - maxThread) > 1)
- {
- if (tmpRate < 90 && bestThreadCountTmp > 400)
- {
- int bestThreadCount = (int) Math.Floor(bestThreadCountTmp);
- //ThreadPool.SetMinThreads(bestThreadCount, bestThreadCount);
- ThreadPool.SetMaxThreads(bestThreadCount, bestThreadCount);
- bestThreadInfo += "重设线程池的MaxThreads=" + bestThreadCount + ",";
- }
- }
- sb.AppendLine(bestThreadInfo);
-
- var phisicalMemory = GetPhisicalMemory();
- sb.AppendLine("MemoryCapacity=" + phisicalMemory + "M");
-
- PerformanceCounter ramCounter = new PerformanceCounter("Memory", "Available MBytes");
- double available = ramCounter.NextValue();
-
- ////获取内存可用大小
- //ManagementClass cimobject2 = new ManagementClass("Win32_PerfFormattedData_PerfOS_Memory");
- //ManagementObjectCollection moc2 = cimobject2.GetInstances();
- //foreach (ManagementObject mo2 in moc2)
- //{
- // available += int.Parse(mo2.Properties["AvailableMBytes"].Value.ToString();
- //}
- //moc2.Dispose();
- //cimobject2.Dispose();
-
- sb.AppendLine("MemoryAvailable=" + available + "M");
- sb.AppendLine("MemoryUsed=" + (phisicalMemory - available) + "M," +
- Math.Round(((phisicalMemory - available)/phisicalMemory*100), 2) + "%");
-
- PerformanceCounter cpuCounter = new PerformanceCounter
- {
- CategoryName = "Processor",
- CounterName = "% Processor Time",
- InstanceName = "_Total"
- };
- sb.AppendLine("总CPU利用率=" + cpuCounter.NextValue() + "%");
-
- //// Get the WMI class
- //ManagementClass cc = new ManagementClass(new ManagementPath("Win32_Processor"));
- //// Get the properties in the class
- //ManagementObjectCollection moc = cc.GetInstances();
- //foreach (ManagementObject mo in moc)
- //{
- // PropertyDataCollection properties = mo.Properties; //获取内核数代码
- // Console.WriteLine("物理内核数:" + properties["NumberOfCores"].Value);
- // Console.WriteLine("逻辑内核数:" + properties["NumberOfLogicalProcessors"].Value);
- // //其他属性获取代码
- // foreach (PropertyData property in properties)
- // {
- // Console.WriteLine(property.Name + ":" + property.Value);
- // }
- //}
- //moc.Dispose();
- //cc.Dispose();
-
- Logger.Info(sb.ToString());
-
- var sb2 = new StringBuilder();
- sb2.Append("Bytes=" + _mStatistics.Bytes);
- sb2.Append("&Overflowed=" + _mStatistics.Overflowed);
- sb2.Append("&Produced=" + _mStatistics.Produced);
-
- sb2.AppendLine("&机器的CPU内核数=" + processorCount);
- sb2.AppendLine("&当前进程CPU利用率=" + cpuUsage);
- sb2.AppendLine("&当前进程内存占用=" + memoryUsage);
- sb2.AppendLine("&当前进程的线程数=" + threadCount);
- sb2.AppendLine("&" + threadPoolInfo);
- sb2.AppendLine("&" + bestThreadInfo);
- sb2.AppendLine("&MemoryCapacity=" + phisicalMemory + "M");
- sb2.AppendLine("&MemoryAvailable=" + available + "M");
- sb2.AppendLine("&MemoryUsed=" + (phisicalMemory - available) + "M," +
- Math.Round(((phisicalMemory - available)/phisicalMemory*100), 2) + "%");
- sb2.AppendLine("&总CPU利用率=" + cpuCounter.NextValue() + "%");
-
- Cat.GetProducer().LogHeartbeat("Cat", "Heartbeat", "0", sb2.ToString());
- Cat.GetProducer().LogEvent("Cat", "Heartbeat" + DateTime.Now.Minute, "0", sb2.ToString());
-
- _mStatistics.Bytes = 0;
- _mStatistics.Overflowed = 0;
- _mStatistics.Produced = 0;
-
- Thread.Sleep(60000);
- }
- }
- }
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Management;
+using System.Threading;
+using System.Text;
+using Com.Dianping.Cat.Util;
+
+namespace Com.Dianping.Cat.Message.Spi.Internals
+{
+ public class StatusUpdateTask
+ {
+ private readonly IMessageStatistics _mStatistics;
+
+ public StatusUpdateTask(IMessageStatistics mStatistics)
+ {
+ _mStatistics = mStatistics;
+ }
+
+ ///
+ /// 获取系统内存大小
+ ///
+ /// 内存大小(单位M)
+ private static int GetPhisicalMemory()
+ {
+ ManagementObjectSearcher searcher = new ManagementObjectSearcher(); //用于查询一些如系统信息的管理对象
+ searcher.Query = new SelectQuery("Win32_PhysicalMemory ", "", new[] { "Capacity" }); //设置查询条件
+ ManagementObjectCollection collection = searcher.Get(); //获取内存容量
+ ManagementObjectCollection.ManagementObjectEnumerator em = collection.GetEnumerator();
+
+ long capacity = 0;
+ while (em.MoveNext())
+ {
+ ManagementBaseObject baseObj = em.Current;
+ if (baseObj.Properties["Capacity"].Value != null)
+ {
+ try
+ {
+ capacity += long.Parse(baseObj.Properties["Capacity"].Value.ToString());
+ }
+ catch
+ {
+ return 0;
+ }
+ }
+ }
+ return (int)(capacity / 1024 / 1024);
+ }
+
+ public void Run(object o)
+ {
+ while (true)
+ {
+ var sb = new StringBuilder();
+ sb.AppendLine("StatusUpdateTask:");
+ sb.AppendLine("Bytes=" + _mStatistics.Bytes);
+ sb.AppendLine("Overflowed=" + _mStatistics.Overflowed);
+ sb.AppendLine("Produced=" + _mStatistics.Produced);
+
+ //机器的CPU内核数
+ var processorCount = Environment.ProcessorCount;
+ sb.AppendLine("机器的CPU内核数=" + processorCount);
+
+ //获取当前进程
+ Process currentProcess = Process.GetCurrentProcess();
+ //var processId = CurrentProcess.Id;//PID
+ //获取当前进程CPU利用率
+ var tmpRate =
+ Math.Round(
+ currentProcess.UserProcessorTime.TotalMilliseconds * 100 /
+ currentProcess.TotalProcessorTime.TotalMilliseconds, 2);
+ var cpuUsage = tmpRate + "%"; //CPU
+ //获取当前进程内存占用
+ var memoryUsage = (currentProcess.WorkingSet64 / 1024 / 1024).ToString(CultureInfo.InvariantCulture) + "M (" +
+ (currentProcess.WorkingSet64 / 1024).ToString(CultureInfo.InvariantCulture) + "KB)";
+ //占用内存
+ //获取当前进程的线程数
+ var threadCount = currentProcess.Threads.Count; //线程
+
+ //获取当前进程的线程池大小
+ int maxThread, maxThread2;
+ ThreadPool.GetMaxThreads(out maxThread, out maxThread2); //线程
+ int avThread, avThread2;
+ ThreadPool.GetAvailableThreads(out avThread, out avThread2);
+ int mThread, mThread2;
+ ThreadPool.GetMinThreads(out mThread, out mThread2);
+
+ var threadPoolInfo = string.Format("线程池大小={0}/{1}, 线程池可用线程数={2}/{3}, 线程池最小线程数={4}/{5}", maxThread2,
+ maxThread, avThread2, avThread, mThread2,
+ mThread);
+
+ sb.AppendLine("当前进程CPU利用率=" + cpuUsage);
+ sb.AppendLine("当前进程内存占用=" + memoryUsage);
+ sb.AppendLine("当前进程的线程数=" + threadCount);
+ sb.AppendLine(threadPoolInfo);
+
+ var bestThreadInfo = string.Empty;
+ //最佳线程数为
+ var bestThreadCountTmp = currentProcess.TotalProcessorTime.TotalMilliseconds /
+ (currentProcess.UserProcessorTime.TotalMilliseconds / threadCount);
+ bestThreadInfo += "最佳线程数=" + bestThreadCountTmp + ",";
+
+ //如果需要增加线程
+ if (Math.Abs(bestThreadCountTmp - maxThread) > 1)
+ {
+ if (tmpRate < 90 && bestThreadCountTmp > 400)
+ {
+ int bestThreadCount = (int)Math.Floor(bestThreadCountTmp);
+ //ThreadPool.SetMinThreads(bestThreadCount, bestThreadCount);
+ ThreadPool.SetMaxThreads(bestThreadCount, bestThreadCount);
+ bestThreadInfo += "重设线程池的MaxThreads=" + bestThreadCount + ",";
+ }
+ }
+ sb.AppendLine(bestThreadInfo);
+
+ var phisicalMemory = GetPhisicalMemory();
+ sb.AppendLine("MemoryCapacity=" + phisicalMemory + "M");
+
+ PerformanceCounter ramCounter = new PerformanceCounter("Memory", "Available MBytes");
+ double available = ramCounter.NextValue();
+
+ ////获取内存可用大小
+ //ManagementClass cimobject2 = new ManagementClass("Win32_PerfFormattedData_PerfOS_Memory");
+ //ManagementObjectCollection moc2 = cimobject2.GetInstances();
+ //foreach (ManagementObject mo2 in moc2)
+ //{
+ // available += int.Parse(mo2.Properties["AvailableMBytes"].Value.ToString();
+ //}
+ //moc2.Dispose();
+ //cimobject2.Dispose();
+
+ sb.AppendLine("MemoryAvailable=" + available + "M");
+ sb.AppendLine("MemoryUsed=" + (phisicalMemory - available) + "M," +
+ Math.Round(((phisicalMemory - available) / phisicalMemory * 100), 2) + "%");
+
+ PerformanceCounter cpuCounter = new PerformanceCounter
+ {
+ CategoryName = "Processor",
+ CounterName = "% Processor Time",
+ InstanceName = "_Total"
+ };
+ sb.AppendLine("总CPU利用率=" + cpuCounter.NextValue() + "%");
+
+ //// Get the WMI class
+ //ManagementClass cc = new ManagementClass(new ManagementPath("Win32_Processor"));
+ //// Get the properties in the class
+ //ManagementObjectCollection moc = cc.GetInstances();
+ //foreach (ManagementObject mo in moc)
+ //{
+ // PropertyDataCollection properties = mo.Properties; //获取内核数代码
+ // Console.WriteLine("物理内核数:" + properties["NumberOfCores"].Value);
+ // Console.WriteLine("逻辑内核数:" + properties["NumberOfLogicalProcessors"].Value);
+ // //其他属性获取代码
+ // foreach (PropertyData property in properties)
+ // {
+ // Console.WriteLine(property.Name + ":" + property.Value);
+ // }
+ //}
+ //moc.Dispose();
+ //cc.Dispose();
+
+ Logger.Info(sb.ToString());
+
+ var sb2 = new StringBuilder();
+ sb2.Append("Bytes=" + _mStatistics.Bytes);
+ sb2.Append("&Overflowed=" + _mStatistics.Overflowed);
+ sb2.Append("&Produced=" + _mStatistics.Produced);
+
+ sb2.AppendLine("&机器的CPU内核数=" + processorCount);
+ sb2.AppendLine("&当前进程CPU利用率=" + cpuUsage);
+ sb2.AppendLine("&当前进程内存占用=" + memoryUsage);
+ sb2.AppendLine("&当前进程的线程数=" + threadCount);
+ sb2.AppendLine("&" + threadPoolInfo);
+ sb2.AppendLine("&" + bestThreadInfo);
+ sb2.AppendLine("&MemoryCapacity=" + phisicalMemory + "M");
+ sb2.AppendLine("&MemoryAvailable=" + available + "M");
+ sb2.AppendLine("&MemoryUsed=" + (phisicalMemory - available) + "M," +
+ Math.Round(((phisicalMemory - available) / phisicalMemory * 100), 2) + "%");
+ sb2.AppendLine("&总CPU利用率=" + cpuCounter.NextValue() + "%");
+
+ Cat.GetProducer().LogHeartbeat("Cat", "Heartbeat", "0", sb2.ToString());
+ Cat.GetProducer().LogEvent("Cat", "Heartbeat" + DateTime.Now.Minute, "0", sb2.ToString());
+
+ _mStatistics.Bytes = 0;
+ _mStatistics.Overflowed = 0;
+ _mStatistics.Produced = 0;
+
+ Thread.Sleep(60000);
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index abb13d7..4c3509b 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -1,4 +1,5 @@
-using System.Reflection;
+using System.Reflection;
+using System.Web;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
@@ -10,13 +11,13 @@
[assembly: AssemblyProduct("Cat")]
[assembly: AssemblyCopyright("Copyright © Dianping.com 2013")]
[assembly: AssemblyTrademark("Dianping.com")]
-[assembly: AssemblyCulture("")]
-
+[assembly: AssemblyCulture("")]
+[assembly: PreApplicationStartMethod(typeof(Com.Dianping.Cat.Cat), "RegisterHttpModule")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-[assembly: AssemblyVersion("0.1.0")]
+[assembly: AssemblyVersion("0.3.1.0")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
diff --git a/Util/AppEnv.cs b/Util/AppEnv.cs
new file mode 100644
index 0000000..40a6fae
--- /dev/null
+++ b/Util/AppEnv.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Web;
+
+namespace Com.Dianping.Cat.Util
+{
+ public static class AppEnv
+ {
+ public static string IP { get { return getLocalIP(); } }
+
+ private static string getLocalIP()
+ {
+ try
+ {
+ return NetworkInterfaceManager.GetLocalHostAddress();
+ }
+ catch
+ {
+ return string.Empty;
+ }
+ }
+
+ public static string GetClientIp(HttpRequest request)
+ {
+ if (request == null)
+ {
+ return string.Empty;
+ }
+ var serverVariables = request.ServerVariables["HTTP_X_FORWARDED_FOR"];
+ if (!string.IsNullOrEmpty(serverVariables))
+ {
+ var items = serverVariables.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+ if (items.Length > 0)
+ {
+ return items[0];
+ }
+ }
+ return request.ServerVariables["REMOTE_ADDR"];
+ }
+
+ public static string GetRemoteIp(HttpRequest request)
+ {
+ if (request == null)
+ {
+ return string.Empty;
+ }
+ return request.ServerVariables["REMOTE_ADDR"];
+ }
+ }
+}
diff --git a/Util/CatThreadLocal.cs b/Util/CatThreadLocal.cs
index 3d92ce8..68f9922 100644
--- a/Util/CatThreadLocal.cs
+++ b/Util/CatThreadLocal.cs
@@ -1,34 +1,34 @@
-using System.Collections;
-using System.Threading;
-
-namespace Com.Dianping.Cat.Util
-{
- public class CatThreadLocal
- {
- private readonly Hashtable _mValues = new Hashtable(1024);
-
- public T Value
- {
- get
- {
- int threadId = Thread.CurrentThread.ManagedThreadId;
- object value = _mValues[threadId];
-
- return (T) value;
- }
- set
- {
- int threadId = Thread.CurrentThread.ManagedThreadId;
-
- _mValues[threadId] = value;
- }
- }
-
- public void Dispose()
- {
- int threadId = Thread.CurrentThread.ManagedThreadId;
-
- _mValues.Remove(threadId);
- }
- }
+using System.Collections;
+using System.Threading;
+
+namespace Com.Dianping.Cat.Util
+{
+ public class CatThreadLocal
+ {
+ private readonly Hashtable _mValues = new Hashtable(1024);
+
+ public T Value
+ {
+ get
+ {
+ int threadId = Thread.CurrentThread.ManagedThreadId;
+ object value = _mValues[threadId];
+
+ return (T)value;
+ }
+ set
+ {
+ int threadId = Thread.CurrentThread.ManagedThreadId;
+
+ _mValues[threadId] = value;
+ }
+ }
+
+ public void Dispose()
+ {
+ int threadId = Thread.CurrentThread.ManagedThreadId;
+
+ _mValues.Remove(threadId);
+ }
+ }
}
\ No newline at end of file
diff --git a/Util/Logger.cs b/Util/Logger.cs
index 5cb4494..e40b5cd 100644
--- a/Util/Logger.cs
+++ b/Util/Logger.cs
@@ -1,67 +1,67 @@
-using System;
-using System.IO;
-
-namespace Com.Dianping.Cat.Util
-{
- ///
- /// 简单记录Cat客户端的启动日志
- ///
- public class Logger
- {
- private static StreamWriter _mWriter;
-
- public static void Info(string pattern, params object[] args)
- {
- Log("INFO", pattern, args);
- }
-
- public static void Warn(string pattern, params object[] args)
- {
- Log("WARN", pattern, args);
- }
-
- public static void Error(string pattern, params object[] args)
- {
- Log("ERROR", pattern, args);
- }
-
- private static void Log(string severity, string pattern, params object[] args)
- {
- string timestamp = new DateTime(MilliSecondTimer.CurrentTimeMicros()*10L).ToString("yyyy-MM-dd HH:mm:ss.fff");
- string message = string.Format(pattern, args);
- string line = "[" + timestamp + "] [" + severity + "] " + message;
-
- if (_mWriter != null)
- {
- _mWriter.WriteLine(line);
- _mWriter.Flush();
- }
- else
- {
- Console.WriteLine(line);
- }
- }
-
- ///
- /// 初始化
- ///
- ///
- public static void Initialize(string logFile)
- {
- try
- {
- if (!File.Exists(logFile))
- {
- var directoryInfo = new FileInfo(logFile).Directory;
- if (directoryInfo != null) directoryInfo.Create();
- }
-
- _mWriter = new StreamWriter(logFile, true);
- }
- catch (Exception e)
- {
- Console.WriteLine("Error when openning log file: " + e.Message + " " + e.StackTrace + ".");
- }
- }
- }
+using System;
+using System.IO;
+
+namespace Com.Dianping.Cat.Util
+{
+ ///
+ /// 简单记录Cat客户端的启动日志
+ ///
+ public class Logger
+ {
+ private static StreamWriter _mWriter;
+
+ public static void Info(string pattern, params object[] args)
+ {
+ Log("INFO", pattern, args);
+ }
+
+ public static void Warn(string pattern, params object[] args)
+ {
+ Log("WARN", pattern, args);
+ }
+
+ public static void Error(string pattern, params object[] args)
+ {
+ Log("ERROR", pattern, args);
+ }
+
+ private static void Log(string severity, string pattern, params object[] args)
+ {
+ string timestamp = new DateTime(MilliSecondTimer.CurrentTimeMicros() * 10L).ToString("yyyy-MM-dd HH:mm:ss.fff");
+ string message = string.Format(pattern, args);
+ string line = "[" + timestamp + "] [" + severity + "] " + message;
+
+ if (_mWriter != null)
+ {
+ _mWriter.WriteLine(line);
+ _mWriter.Flush();
+ }
+ else
+ {
+ Console.WriteLine(line);
+ }
+ }
+
+ ///
+ /// 初始化
+ ///
+ ///
+ public static void Initialize(string logFile)
+ {
+ try
+ {
+ if (!File.Exists(logFile))
+ {
+ var directoryInfo = new FileInfo(logFile).Directory;
+ if (directoryInfo != null) directoryInfo.Create();
+ }
+
+ _mWriter = new StreamWriter(logFile, true);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error when openning log file: " + e.Message + " " + e.StackTrace + ".");
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/Util/MilliSecondTimer.cs b/Util/MilliSecondTimer.cs
index c19d959..95df7dc 100644
--- a/Util/MilliSecondTimer.cs
+++ b/Util/MilliSecondTimer.cs
@@ -1,68 +1,68 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace Com.Dianping.Cat.Util
-{
- ///
- /// This timer provides milli-second precise system time.
- ///
- public class MilliSecondTimer
- {
- public static long CurrentTimeMicros()
- {
- //return HighResTicksProvider.GetTickCount () / 10L; // it's microsecond precise
- return DateTime.Now.Ticks/10L; // it's millisecond precise
- }
-
- public static long CurrentTimeHoursForJava()
- {
- DateTime baseline = new DateTime(1970, 1, 1, 0, 0, 0);
- TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - baseline.Ticks);
-
- return ((long) ts.TotalMilliseconds/3600000L);
- }
- }
-
- public class HighResTicksProvider
- {
- private static long _f;
-
- [DllImport("kernel32.dll")]
- private static extern bool QueryPerformanceCounter([In, Out] ref long lpPerformanceCount);
-
- [DllImport("kernel32.dll")]
- private static extern bool QueryPerformanceFrequency([In, Out] ref long lpFrequency);
-
- ///
- /// 获得当前时间戳,十分之一微秒(100纳秒,和 DateTime.Now.Ticks 刻度一样)
- ///
- ///
- public static long GetTickCount()
- {
- long f = _f;
-
- if (f == 0)
- {
- if (QueryPerformanceFrequency(ref f))
- {
- _f = f;
- }
- else
- {
- _f = -1;
- }
- }
-
- if (_f == -1)
- {
- // fallback
- return DateTime.Now.Ticks;
- }
-
- long c = 0;
- QueryPerformanceCounter(ref c);
-
- return (long) (((double) c)*1000*10000/(f));
- }
- }
+using System;
+using System.Runtime.InteropServices;
+
+namespace Com.Dianping.Cat.Util
+{
+ ///
+ /// This timer provides milli-second precise system time.
+ ///
+ public class MilliSecondTimer
+ {
+ public static long CurrentTimeMicros()
+ {
+ //return HighResTicksProvider.GetTickCount () / 10L; // it's microsecond precise
+ return DateTime.Now.Ticks / 10L; // it's millisecond precise
+ }
+
+ public static long CurrentTimeHoursForJava()
+ {
+ DateTime baseline = new DateTime(1970, 1, 1, 0, 0, 0);
+ TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - baseline.Ticks);
+
+ return ((long)ts.TotalMilliseconds / 3600000L);
+ }
+ }
+
+ public class HighResTicksProvider
+ {
+ private static long _f;
+
+ [DllImport("kernel32.dll")]
+ private static extern bool QueryPerformanceCounter([In, Out] ref long lpPerformanceCount);
+
+ [DllImport("kernel32.dll")]
+ private static extern bool QueryPerformanceFrequency([In, Out] ref long lpFrequency);
+
+ ///
+ /// 获得当前时间戳,十分之一微秒(100纳秒,和 DateTime.Now.Ticks 刻度一样)
+ ///
+ ///
+ public static long GetTickCount()
+ {
+ long f = _f;
+
+ if (f == 0)
+ {
+ if (QueryPerformanceFrequency(ref f))
+ {
+ _f = f;
+ }
+ else
+ {
+ _f = -1;
+ }
+ }
+
+ if (_f == -1)
+ {
+ // fallback
+ return DateTime.Now.Ticks;
+ }
+
+ long c = 0;
+ QueryPerformanceCounter(ref c);
+
+ return (long)(((double)c) * 1000 * 10000 / (f));
+ }
+ }
}
\ No newline at end of file
diff --git a/Util/NetworkInterfaceManager.cs b/Util/NetworkInterfaceManager.cs
index 19b8e4c..0349f38 100644
--- a/Util/NetworkInterfaceManager.cs
+++ b/Util/NetworkInterfaceManager.cs
@@ -1,39 +1,39 @@
-using System;
-using System.Linq;
-using System.Net.Sockets;
-using System.Net;
-
-namespace Com.Dianping.Cat.Util
-{
- public class NetworkInterfaceManager
- {
- public static string GetLocalHostName()
- {
- return Dns.GetHostName();
- }
-
- public static string GetLocalHostAddress()
- {
- IPHostEntry host = Dns.GetHostEntry(GetLocalHostName());
-
- foreach (IPAddress ip in host.AddressList.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork))
- {
- return ip.ToString();
- }
-
- throw new NotSupportedException("No IP address found");
- }
-
- public static byte[] GetAddressBytes()
- {
- IPHostEntry host = Dns.GetHostEntry(GetLocalHostName());
-
- foreach (IPAddress ip in host.AddressList.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork))
- {
- return ip.GetAddressBytes();
- }
-
- throw new NotSupportedException("No IP address found");
- }
- }
+using System;
+using System.Linq;
+using System.Net.Sockets;
+using System.Net;
+
+namespace Com.Dianping.Cat.Util
+{
+ public class NetworkInterfaceManager
+ {
+ public static string GetLocalHostName()
+ {
+ return Dns.GetHostName();
+ }
+
+ public static string GetLocalHostAddress()
+ {
+ IPHostEntry host = Dns.GetHostEntry(GetLocalHostName());
+
+ foreach (IPAddress ip in host.AddressList.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork))
+ {
+ return ip.ToString();
+ }
+
+ throw new NotSupportedException("No IP address found");
+ }
+
+ public static byte[] GetAddressBytes()
+ {
+ IPHostEntry host = Dns.GetHostEntry(GetLocalHostName());
+
+ foreach (IPAddress ip in host.AddressList.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork))
+ {
+ return ip.GetAddressBytes();
+ }
+
+ throw new NotSupportedException("No IP address found");
+ }
+ }
}
\ No newline at end of file
diff --git a/bin/Debug/Cat.dll b/bin/Debug/Cat.dll
deleted file mode 100644
index e871f06..0000000
Binary files a/bin/Debug/Cat.dll and /dev/null differ
diff --git a/bin/Debug/Cat.pdb b/bin/Debug/Cat.pdb
deleted file mode 100644
index c534f03..0000000
Binary files a/bin/Debug/Cat.pdb and /dev/null differ
diff --git a/obj/x86/Debug/Cat.Net.csproj.FileListAbsolute.txt b/obj/x86/Debug/Cat.Net.csproj.FileListAbsolute.txt
deleted file mode 100644
index 53b7d06..0000000
--- a/obj/x86/Debug/Cat.Net.csproj.FileListAbsolute.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-E:\work\csharp\Cat.Net\bin\Debug\Cat.dll
-E:\work\csharp\Cat.Net\bin\Debug\Cat.pdb
-E:\work\csharp\Cat.Net\obj\x86\Debug\ResolveAssemblyReference.cache
-E:\work\csharp\Cat.Net\obj\x86\Debug\Cat.dll
-E:\work\csharp\Cat.Net\obj\x86\Debug\Cat.pdb
diff --git a/obj/x86/Debug/Cat.dll b/obj/x86/Debug/Cat.dll
deleted file mode 100644
index e871f06..0000000
Binary files a/obj/x86/Debug/Cat.dll and /dev/null differ
diff --git a/obj/x86/Debug/Cat.pdb b/obj/x86/Debug/Cat.pdb
deleted file mode 100644
index c534f03..0000000
Binary files a/obj/x86/Debug/Cat.pdb and /dev/null differ
diff --git a/obj/x86/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/obj/x86/Debug/DesignTimeResolveAssemblyReferencesInput.cache
deleted file mode 100644
index 9f12ff5..0000000
Binary files a/obj/x86/Debug/DesignTimeResolveAssemblyReferencesInput.cache and /dev/null differ