Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Data;
- using System.Data.SqlClient;
- using System.Diagnostics;
- using System.IO;
- using System.Xml.Linq;
- using System.Threading;
- using System.Linq;
- //Delegate definition for the real method responsible for logging
- internal delegate void LogIt(string message, string type, string componentName);
- internal delegate void LogIt2(string userId, string machineName, string details1, string details2, string machineName2, string moduleName, string dateLastLogin, string calssName, string methodName, string ErorMassage);
- // Delegate for DBTraceFailed event
- public delegate void DBTraceFailedHandler(string exceptionText);
- public class DBTraceListener : TraceListener
- {
- public event DBTraceFailedHandler DBTraceFailed;
- #region Constants
- private const string STORED_PROC_NAME = "AddUserLog";
- private const string STORED_PROC_PARAM_UserId = "@PI_UserId";
- private const string STORED_PROC_PARAM_IP = "@PI_IP";
- private const string STORED_PROC_PARAM_PcName = "@PI_PcName";
- private const string STORED_PROC_PARAM_Actions = "@PI_Actions";
- private const string STORED_PROC_PARAM_Details = "@PI_Details";
- private const string STORED_PROC_PARAM_Module = "@PI_Module";
- private const string STORED_PROC_PARAM_LastLogin = "@PI_LastLogin";
- private const string STORED_PROC_PARAM_ClassName = "@PI_Class";
- private const string STORED_PROC_PARAM_Method = "@PI_Method";
- private const string STORED_PROC_PARAM_Message = "@PI_Message";
- private const string TRACE_SWITCH_NAME = "DBTraceSwitch";//?
- private const string TRACE_SWITCH_DESCRIPTION = "Trace switch defined in config file for configuring trace output to database";
- // Not defining it as readonly string so that in future it could come
- // from an external source and we can provide initializer for it
- private static readonly string DEFAULT_TRACE_TYPE = "Verbose";//all
- #endregion
- #region Class Data
- // Database connection object
- private SqlConnection _cn;// the connection
- // Database command object
- private SqlCommand _cm;
- // Connection string for database
- private string _connectionString;
- // Flag for DBTraceListener object disposal status
- private bool _disposed = false;
- // Trace Switch object for controlling trace output, defaulting to Verbose
- private TraceSwitch TraceSwitch = new TraceSwitch(TRACE_SWITCH_NAME, TRACE_SWITCH_DESCRIPTION, DEFAULT_TRACE_TYPE);
- // Delegate to point to the method which would do actual operation of logging
- private LogIt workerMethod;
- private LogIt2 workerMethod2;
- // Component Name
- private string _componentName;
- // Lock object
- private object _traceLockObject = new object();
- private object _fileLockObject = new object();
- // Timer to refresh trace configuration information
- private Timer _traceSwitchTimer;
- // Flag to indicate whether trace configuration data needs to be refreshed
- private bool _refreshTraceConfig = false;
- #endregion
- #region Properties
- public override bool IsThreadSafe
- {
- get { return false; }
- }
- public string ConnectionString
- {
- get
- {
- if (string.IsNullOrEmpty(this._connectionString))
- {
- this.LoadAttributes();
- }
- return this._connectionString;
- }
- set { this._connectionString = value; }
- }
- public string ComponentName
- {
- get
- {
- if (string.IsNullOrEmpty(this._componentName))
- {
- this.LoadAttributes();
- }
- return this._componentName;
- }
- set { this._componentName = value; }
- }
- public bool RefreshTraceConfig
- {
- get
- {
- this.LoadAttributes();
- return this._refreshTraceConfig;
- }
- set
- {
- if (value)
- {
- // Refresh trace section every 15 minutes
- if (!this._refreshTraceConfig)
- {
- // i.e. If timer is not already active
- this._refreshTraceConfig = true;
- this._traceSwitchTimer = new Timer(new TimerCallback(RefreshSwitch), null, new TimeSpan(0, 15, 0), new TimeSpan(0, 15, 0));
- }
- }
- else
- {
- // If timer is active, stop it
- this._refreshTraceConfig = false;
- this._traceSwitchTimer.Dispose();
- this._traceSwitchTimer = null;
- }
- }
- }
- #endregion
- #region Constructors
- public DBTraceListener() : this(string.Empty) { }
- public DBTraceListener(string initializeData)
- : base(initializeData)
- {
- // Initialize connection object
- this._cn = new SqlConnection();
- this._cn.ConnectionString = initializeData;
- this.ConnectionString = initializeData;
- try
- {
- this._cn.Open();
- }
- catch (Exception ex)
- {
- // Write to internal
- this.WriteEntryToInternalLog(string.Format("Could not connect to database from the provided connection string. Exception: {0}", ex.ToString()));
- // Let the caller know that this listener object cannot do its
- // work because it cannot establish connection to database
- //
- // Since Tracing framework is initialized by CLR, you would
- // in all likelihood get Could not create type... error
- throw;
- }
- // Setup command object
- this._cm = this._cn.CreateCommand();
- this._cm.CommandText = STORED_PROC_NAME;
- this._cm.CommandType = CommandType.StoredProcedure;
- this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_UserId, DBNull.Value));
- this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_IP, DBNull.Value));
- this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_PcName, DBNull.Value));
- this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Actions, DBNull.Value));
- this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Details, DBNull.Value));
- this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Module, DBNull.Value));
- this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_LastLogin, DBNull.Value));
- this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_ClassName, DBNull.Value));
- this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Method, DBNull.Value));
- this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Message, DBNull.Value));
- }
- #endregion
- #region Methods
- private void LoadAttributes()
- {
- if (Attributes.ContainsKey("connectionString"))
- {
- this.ConnectionString = this.Attributes["connectionString"];
- }
- if (Attributes.ContainsKey("componentName"))
- {
- this.ComponentName = this.Attributes["componentName"];
- }
- if (Attributes.ContainsKey("refreshTraceConfig"))
- {
- bool val;
- bool.TryParse(this.Attributes["refreshTraceConfig"], out val);
- this.RefreshTraceConfig = val;
- }
- }
- void RefreshSwitch(object o)
- {
- // Trace.Refresh call is not expected to throw any exception, but if it DOES
- // catch the exception and do nothing
- try
- {
- if (this.RefreshTraceConfig)
- {
- Trace.Refresh();
- }
- }
- catch (Exception ex)
- {
- this.WriteLine(
- string.Format("DBTraceListener.Trace.RefreshSwitch failed with following exception: {0}, ", ex.ToString()),
- "Error"
- );
- this.WriteEntryToInternalLog(string.Format("Trace.RefreshSwitch failed with following exception: {0}, ", ex.ToString()));
- }
- }
- private void WriteEntryToInternalLog(string msg)
- {
- lock (this._fileLockObject)
- {
- try
- {
- File.AppendAllText(@"C:DBTraceListener.log",//AppDomain.CurrentDomain.BaseDirectory+
- string.Format("{0}{1}: {2}", Environment.NewLine, DateTime.Now.ToString(), msg));
- }
- catch
- {
- // Do nothing
- }
- }
- }
- /// <summary>
- /// Another method useful for testing if DBTraceListener is
- /// able to establish connection to database
- /// </summary>
- /// <returns>void</returns>
- public bool TestDBConnection()
- {
- try
- {
- using (SqlConnection cn = new SqlConnection(this.ConnectionString))
- {
- cn.Open();
- }
- return true;
- }
- catch
- {
- // In case of any exception just return false
- return false;
- }
- }
- internal bool ShouldLogTrace(TraceEventType eventType)
- {
- bool shouldLog = true;
- switch (eventType)
- {
- case TraceEventType.Critical:
- case TraceEventType.Error:
- shouldLog = this.TraceSwitch.TraceError;
- break;
- case TraceEventType.Warning:
- shouldLog = this.TraceSwitch.TraceWarning;
- break;
- case TraceEventType.Information:
- shouldLog = this.TraceSwitch.TraceInfo;
- break;
- case TraceEventType.Start:
- case TraceEventType.Stop:
- case TraceEventType.Suspend:
- case TraceEventType.Resume:
- case TraceEventType.Transfer:
- case TraceEventType.Verbose:
- shouldLog = this.TraceSwitch.TraceVerbose;
- break;
- }
- return shouldLog;
- }
- #region TraceData
- // TODO: Need to check whether it serves any purpose to override TraceData methods in this listener class
- public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
- {
- this.TraceData(eventCache, source, eventType, id, data);
- }
- public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data)
- {
- //TODO: The values of data array needs to be extracted for Message placeholder
- if (this.ShouldLogTrace(eventType))
- {
- this.WriteLine(string.Format(
- "Source:{0} nId:{1} nMessage:{2}",
- source,
- id,
- data.ToString()),
- eventType.ToString());
- }
- }
- #endregion
- #region TraceEvent
- public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id)
- {
- this.TraceEvent(eventCache, source, eventType, id, string.Empty);
- }
- public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
- {
- //?????
- }
- public virtual void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
- {
- //?????
- }
- #endregion
- #region TraceTransfer
- public override void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
- {
- try
- {
- if (this.ShouldLogTrace(TraceEventType.Transfer))
- {
- XElement msg = new XElement("TraceLog",
- new XElement("Message", message),
- new XElement("Source", source),
- new XElement("Id", id),
- new XElement("RelatedActivityId", relatedActivityId.ToString()),
- new XElement("CallStack", eventCache.Callstack.ToString()),
- new XElement("ThreadId", eventCache.ThreadId),
- new XElement("ProcessId", eventCache.ProcessId));
- this.WriteLine(msg.ToString(), TraceEventType.Verbose.ToString());
- }
- }
- catch (Exception ex)
- {
- this.WriteLine(
- string.Format("DBTraceListener - Trace.TraceTransfer failed with following exception: {0}, for message {1} ", ex.ToString(), message),
- "Error"
- );
- this.WriteEntryToInternalLog(string.Format("Trace.TraceTransfer failed with following exception: {0}", ex.ToString()));
- }
- }
- #endregion
- #region Write Methods
- public override void Write(object o)
- {
- if (o != null)
- {
- this.WriteLine(o.ToString(), null);
- }
- }
- public override void Write(string message)
- {
- this.WriteLine(message, null);
- }
- public override void Write(object o, string category)
- {
- if (o != null)
- {
- this.WriteLine(o.ToString(), category);
- }
- }
- public override void Write(string message, string category)
- {
- this.WriteLine(message, category);
- }
- #endregion
- #region WriteLine Methods
- public override void WriteLine(object o)
- {
- if (o != null)
- {
- this.WriteLine(o.ToString(), null);
- }
- }
- public override void WriteLine(string message)
- {
- this.WriteLine(message, null);
- }
- public override void WriteLine(object o, string category)
- {
- if (o != null)
- {
- this.WriteLine(o.ToString(), category);
- }
- }
- public override void WriteLine(string message, string category)
- {
- WriteLineInternal( message, category);
- }
- #endregion
- #region WriteLineInternal
- private void WriteLineInternal(string message, string category)
- {
- try
- {
- if (!this.ShouldLogTrace(TraceEventType.Verbose))
- {
- this.WriteEntryToInternalLog(string.Format("WriteLineInternal: log is not going to write, TraceEventType.Verbose: {0} Message: {1}", TraceEventType.Verbose,message));
- return;
- }
- System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
- string userId = String.Empty, ip = String.Empty, actions = String.Empty, details = String.Empty, pcName = String.Empty, moduleName = String.Empty, dateLastLogin = String.Empty, calssName = String.Empty, methodName = String.Empty, ErrorMassage = String.Empty;
- try
- {
- xmlDoc.LoadXml(message);
- userId = xmlDoc.SelectSingleNode("/LogInfo/Record/UserId").InnerText;
- ip = xmlDoc.SelectSingleNode("/LogInfo/Record/IP").InnerText;
- pcName = xmlDoc.SelectSingleNode("/LogInfo/Record/PcName").InnerText;
- actions = xmlDoc.SelectSingleNode("/LogInfo/Record/Actions").InnerText;
- details = xmlDoc.SelectSingleNode("/LogInfo/Record/Details").InnerText;
- moduleName = xmlDoc.SelectSingleNode("/LogInfo/Record/Module").InnerText;
- dateLastLogin = xmlDoc.SelectSingleNode("/LogInfo/Record/LastLogin").InnerText;
- calssName = xmlDoc.SelectSingleNode("/LogInfo/Record/ClassName").InnerText;
- methodName = xmlDoc.SelectSingleNode("/LogInfo/Record/Method").InnerText;
- ErrorMassage = xmlDoc.SelectSingleNode("/LogInfo/Record/Message").InnerText;
- }
- catch (Exception exp)
- {
- }
- workerMethod2 = SaveLogEntry;
- workerMethod2.BeginInvoke(userId, ip, actions, details, pcName, moduleName, dateLastLogin, calssName,methodName,ErrorMassage,null,null);
- }
- catch(Exception ex)
- {
- this.WriteEntryToInternalLog(string.Format("WriteLine failed with following exception: {0}", ex.ToString()));
- }
- }
- #endregion
- private void SaveLogEntry(string userId, string ip, string actions, string details, string pcName, string moduleName, string dateLastLogin, string calssName, string methodName, string ErorMassage)
- {
- // IMPORTANT!!!!
- // DO NOT WRITE ANY Debug.WriteLine or Trace.WriteLine statements in this method
- try
- {
- this.WriteEntryToInternalLog(string.Format("SaveLogEntry Before Lock"));
- }
- catch { }
- lock (_traceLockObject)
- {
- try
- {
- // save trace message to database
- if (this._cn.State == ConnectionState.Broken || this._cn.State == ConnectionState.Closed)
- {
- this._cn.ConnectionString = this.ConnectionString;
- this._cn.Open();
- }
- this._cm.Parameters[STORED_PROC_PARAM_UserId].Value = userId;//string.IsNullOrEmpty(userId)? DBNull.Value:
- this._cm.Parameters[STORED_PROC_PARAM_IP].Value = ip;
- this._cm.Parameters[STORED_PROC_PARAM_PcName].Value = pcName;
- this._cm.Parameters[STORED_PROC_PARAM_Actions].Value = actions;
- this._cm.Parameters[STORED_PROC_PARAM_Details].Value = details;
- this._cm.Parameters[STORED_PROC_PARAM_Module].Value = moduleName;
- this._cm.Parameters[STORED_PROC_PARAM_LastLogin].Value = dateLastLogin;
- this._cm.Parameters[STORED_PROC_PARAM_ClassName].Value = calssName;
- this._cm.Parameters[STORED_PROC_PARAM_Method].Value = methodName;
- this._cm.Parameters[STORED_PROC_PARAM_Message].Value = ErorMassage;
- this._cm.ExecuteNonQuery();
- try
- {
- this.WriteEntryToInternalLog(string.Format("SaveLogEntry after ExecuteNonQuery"));
- }
- catch { }
- }
- catch (Exception ex)
- {
- // Raise event to let others know, just in case
- // someone interested
- if (this.DBTraceFailed != null)
- {
- DBTraceFailed(ex.ToString());
- }
- // Write entry to internal log file
- this.WriteEntryToInternalLog(ex.ToString());
- }
- finally
- {
- // Nothing to dispose in case of exception
- }
- }
- }
- protected override string[] GetSupportedAttributes()
- {
- return new string[] { "connectionString", "componentName", "refreshTraceConfig" };
- }
- protected override void Dispose(bool disposing)
- {
- if (!this._disposed)
- {
- if (disposing)
- {
- if (this._cn != null)
- this._cn.Dispose();
- if (this._cm != null)
- this._cm.Dispose();
- if (this._traceSwitchTimer != null)
- this._traceSwitchTimer.Dispose();
- }
- this._disposed = true;
- }
- this._cm = null;
- this._cn = null;
- base.Dispose(disposing);
- }
- #endregion
- }
- Debug.Listeners.Add(new DBTraceListener(System.Configuration.ConfigurationManager.ConnectionStrings["connectionString"].ToString()));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement