Advertisement
Guest User

Untitled

a guest
Sep 20th, 2017
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.09 KB | None | 0 0
  1. using System;
  2. using System.Data;
  3. using System.Data.SqlClient;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Xml.Linq;
  7. using System.Threading;
  8. using System.Linq;
  9.  
  10. //Delegate definition for the real method responsible for logging
  11. internal delegate void LogIt(string message, string type, string componentName);
  12.  
  13. internal delegate void LogIt2(string userId, string machineName, string details1, string details2, string machineName2, string moduleName, string dateLastLogin, string calssName, string methodName, string ErorMassage);
  14.  
  15. // Delegate for DBTraceFailed event
  16. public delegate void DBTraceFailedHandler(string exceptionText);
  17.  
  18. public class DBTraceListener : TraceListener
  19. {
  20. public event DBTraceFailedHandler DBTraceFailed;
  21. #region Constants
  22.  
  23. private const string STORED_PROC_NAME = "AddUserLog";
  24.  
  25. private const string STORED_PROC_PARAM_UserId = "@PI_UserId";
  26. private const string STORED_PROC_PARAM_IP = "@PI_IP";
  27. private const string STORED_PROC_PARAM_PcName = "@PI_PcName";
  28. private const string STORED_PROC_PARAM_Actions = "@PI_Actions";
  29. private const string STORED_PROC_PARAM_Details = "@PI_Details";
  30. private const string STORED_PROC_PARAM_Module = "@PI_Module";
  31. private const string STORED_PROC_PARAM_LastLogin = "@PI_LastLogin";
  32. private const string STORED_PROC_PARAM_ClassName = "@PI_Class";
  33. private const string STORED_PROC_PARAM_Method = "@PI_Method";
  34. private const string STORED_PROC_PARAM_Message = "@PI_Message";
  35.  
  36.  
  37. private const string TRACE_SWITCH_NAME = "DBTraceSwitch";//?
  38. private const string TRACE_SWITCH_DESCRIPTION = "Trace switch defined in config file for configuring trace output to database";
  39.  
  40. // Not defining it as readonly string so that in future it could come
  41. // from an external source and we can provide initializer for it
  42. private static readonly string DEFAULT_TRACE_TYPE = "Verbose";//all
  43.  
  44. #endregion
  45.  
  46. #region Class Data
  47.  
  48. // Database connection object
  49. private SqlConnection _cn;// the connection
  50.  
  51. // Database command object
  52. private SqlCommand _cm;
  53.  
  54. // Connection string for database
  55. private string _connectionString;
  56.  
  57. // Flag for DBTraceListener object disposal status
  58. private bool _disposed = false;
  59.  
  60. // Trace Switch object for controlling trace output, defaulting to Verbose
  61. private TraceSwitch TraceSwitch = new TraceSwitch(TRACE_SWITCH_NAME, TRACE_SWITCH_DESCRIPTION, DEFAULT_TRACE_TYPE);
  62.  
  63. // Delegate to point to the method which would do actual operation of logging
  64. private LogIt workerMethod;
  65. private LogIt2 workerMethod2;
  66.  
  67. // Component Name
  68. private string _componentName;
  69.  
  70. // Lock object
  71. private object _traceLockObject = new object();
  72. private object _fileLockObject = new object();
  73.  
  74. // Timer to refresh trace configuration information
  75. private Timer _traceSwitchTimer;
  76.  
  77. // Flag to indicate whether trace configuration data needs to be refreshed
  78. private bool _refreshTraceConfig = false;
  79.  
  80. #endregion
  81.  
  82. #region Properties
  83.  
  84. public override bool IsThreadSafe
  85. {
  86. get { return false; }
  87. }
  88.  
  89. public string ConnectionString
  90. {
  91. get
  92. {
  93. if (string.IsNullOrEmpty(this._connectionString))
  94. {
  95. this.LoadAttributes();
  96. }
  97. return this._connectionString;
  98. }
  99. set { this._connectionString = value; }
  100. }
  101.  
  102. public string ComponentName
  103. {
  104. get
  105. {
  106. if (string.IsNullOrEmpty(this._componentName))
  107. {
  108. this.LoadAttributes();
  109. }
  110. return this._componentName;
  111. }
  112. set { this._componentName = value; }
  113. }
  114.  
  115. public bool RefreshTraceConfig
  116. {
  117. get
  118. {
  119. this.LoadAttributes();
  120. return this._refreshTraceConfig;
  121. }
  122. set
  123. {
  124. if (value)
  125. {
  126. // Refresh trace section every 15 minutes
  127. if (!this._refreshTraceConfig)
  128. {
  129. // i.e. If timer is not already active
  130. this._refreshTraceConfig = true;
  131. this._traceSwitchTimer = new Timer(new TimerCallback(RefreshSwitch), null, new TimeSpan(0, 15, 0), new TimeSpan(0, 15, 0));
  132. }
  133. }
  134. else
  135. {
  136. // If timer is active, stop it
  137. this._refreshTraceConfig = false;
  138. this._traceSwitchTimer.Dispose();
  139. this._traceSwitchTimer = null;
  140. }
  141. }
  142. }
  143.  
  144. #endregion
  145.  
  146.  
  147. #region Constructors
  148.  
  149. public DBTraceListener() : this(string.Empty) { }
  150.  
  151. public DBTraceListener(string initializeData)
  152. : base(initializeData)
  153. {
  154. // Initialize connection object
  155. this._cn = new SqlConnection();
  156. this._cn.ConnectionString = initializeData;
  157. this.ConnectionString = initializeData;
  158.  
  159. try
  160. {
  161. this._cn.Open();
  162. }
  163. catch (Exception ex)
  164. {
  165. // Write to internal
  166. this.WriteEntryToInternalLog(string.Format("Could not connect to database from the provided connection string. Exception: {0}", ex.ToString()));
  167.  
  168. // Let the caller know that this listener object cannot do its
  169. // work because it cannot establish connection to database
  170. //
  171. // Since Tracing framework is initialized by CLR, you would
  172. // in all likelihood get Could not create type... error
  173. throw;
  174. }
  175.  
  176. // Setup command object
  177. this._cm = this._cn.CreateCommand();
  178. this._cm.CommandText = STORED_PROC_NAME;
  179. this._cm.CommandType = CommandType.StoredProcedure;
  180. this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_UserId, DBNull.Value));
  181. this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_IP, DBNull.Value));
  182. this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_PcName, DBNull.Value));
  183. this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Actions, DBNull.Value));
  184. this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Details, DBNull.Value));
  185. this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Module, DBNull.Value));
  186. this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_LastLogin, DBNull.Value));
  187. this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_ClassName, DBNull.Value));
  188. this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Method, DBNull.Value));
  189. this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Message, DBNull.Value));
  190.  
  191. }
  192. #endregion
  193.  
  194. #region Methods
  195.  
  196. private void LoadAttributes()
  197. {
  198. if (Attributes.ContainsKey("connectionString"))
  199. {
  200. this.ConnectionString = this.Attributes["connectionString"];
  201. }
  202.  
  203. if (Attributes.ContainsKey("componentName"))
  204. {
  205. this.ComponentName = this.Attributes["componentName"];
  206. }
  207.  
  208. if (Attributes.ContainsKey("refreshTraceConfig"))
  209. {
  210. bool val;
  211. bool.TryParse(this.Attributes["refreshTraceConfig"], out val);
  212. this.RefreshTraceConfig = val;
  213. }
  214. }
  215.  
  216. void RefreshSwitch(object o)
  217. {
  218. // Trace.Refresh call is not expected to throw any exception, but if it DOES
  219. // catch the exception and do nothing
  220. try
  221. {
  222. if (this.RefreshTraceConfig)
  223. {
  224. Trace.Refresh();
  225. }
  226. }
  227. catch (Exception ex)
  228. {
  229. this.WriteLine(
  230. string.Format("DBTraceListener.Trace.RefreshSwitch failed with following exception: {0}, ", ex.ToString()),
  231. "Error"
  232. );
  233.  
  234. this.WriteEntryToInternalLog(string.Format("Trace.RefreshSwitch failed with following exception: {0}, ", ex.ToString()));
  235. }
  236. }
  237.  
  238. private void WriteEntryToInternalLog(string msg)
  239. {
  240. lock (this._fileLockObject)
  241. {
  242. try
  243. {
  244. File.AppendAllText(@"C:DBTraceListener.log",//AppDomain.CurrentDomain.BaseDirectory+
  245. string.Format("{0}{1}: {2}", Environment.NewLine, DateTime.Now.ToString(), msg));
  246. }
  247. catch
  248. {
  249. // Do nothing
  250. }
  251. }
  252. }
  253.  
  254. /// <summary>
  255. /// Another method useful for testing if DBTraceListener is
  256. /// able to establish connection to database
  257. /// </summary>
  258. /// <returns>void</returns>
  259. public bool TestDBConnection()
  260. {
  261. try
  262. {
  263. using (SqlConnection cn = new SqlConnection(this.ConnectionString))
  264. {
  265. cn.Open();
  266. }
  267. return true;
  268. }
  269. catch
  270. {
  271. // In case of any exception just return false
  272. return false;
  273. }
  274. }
  275.  
  276. internal bool ShouldLogTrace(TraceEventType eventType)
  277. {
  278. bool shouldLog = true;
  279.  
  280. switch (eventType)
  281. {
  282. case TraceEventType.Critical:
  283. case TraceEventType.Error:
  284. shouldLog = this.TraceSwitch.TraceError;
  285. break;
  286.  
  287. case TraceEventType.Warning:
  288. shouldLog = this.TraceSwitch.TraceWarning;
  289. break;
  290.  
  291. case TraceEventType.Information:
  292. shouldLog = this.TraceSwitch.TraceInfo;
  293. break;
  294.  
  295. case TraceEventType.Start:
  296. case TraceEventType.Stop:
  297. case TraceEventType.Suspend:
  298. case TraceEventType.Resume:
  299. case TraceEventType.Transfer:
  300. case TraceEventType.Verbose:
  301. shouldLog = this.TraceSwitch.TraceVerbose;
  302. break;
  303. }
  304.  
  305. return shouldLog;
  306. }
  307.  
  308. #region TraceData
  309.  
  310. // TODO: Need to check whether it serves any purpose to override TraceData methods in this listener class
  311.  
  312. public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
  313. {
  314. this.TraceData(eventCache, source, eventType, id, data);
  315. }
  316.  
  317. public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data)
  318. {
  319. //TODO: The values of data array needs to be extracted for Message placeholder
  320.  
  321. if (this.ShouldLogTrace(eventType))
  322. {
  323. this.WriteLine(string.Format(
  324. "Source:{0} nId:{1} nMessage:{2}",
  325. source,
  326. id,
  327. data.ToString()),
  328. eventType.ToString());
  329. }
  330. }
  331.  
  332. #endregion
  333.  
  334. #region TraceEvent
  335.  
  336. public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id)
  337. {
  338. this.TraceEvent(eventCache, source, eventType, id, string.Empty);
  339. }
  340.  
  341. public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
  342. {
  343. //?????
  344. }
  345.  
  346. public virtual void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
  347. {
  348. //?????
  349. }
  350.  
  351. #endregion
  352.  
  353. #region TraceTransfer
  354.  
  355. public override void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
  356. {
  357. try
  358. {
  359. if (this.ShouldLogTrace(TraceEventType.Transfer))
  360. {
  361. XElement msg = new XElement("TraceLog",
  362. new XElement("Message", message),
  363. new XElement("Source", source),
  364. new XElement("Id", id),
  365. new XElement("RelatedActivityId", relatedActivityId.ToString()),
  366. new XElement("CallStack", eventCache.Callstack.ToString()),
  367. new XElement("ThreadId", eventCache.ThreadId),
  368. new XElement("ProcessId", eventCache.ProcessId));
  369.  
  370. this.WriteLine(msg.ToString(), TraceEventType.Verbose.ToString());
  371. }
  372. }
  373. catch (Exception ex)
  374. {
  375. this.WriteLine(
  376. string.Format("DBTraceListener - Trace.TraceTransfer failed with following exception: {0}, for message {1} ", ex.ToString(), message),
  377. "Error"
  378. );
  379.  
  380. this.WriteEntryToInternalLog(string.Format("Trace.TraceTransfer failed with following exception: {0}", ex.ToString()));
  381. }
  382. }
  383.  
  384. #endregion
  385.  
  386.  
  387. #region Write Methods
  388.  
  389. public override void Write(object o)
  390. {
  391. if (o != null)
  392. {
  393. this.WriteLine(o.ToString(), null);
  394. }
  395. }
  396.  
  397. public override void Write(string message)
  398. {
  399. this.WriteLine(message, null);
  400. }
  401.  
  402. public override void Write(object o, string category)
  403. {
  404. if (o != null)
  405. {
  406. this.WriteLine(o.ToString(), category);
  407. }
  408. }
  409.  
  410. public override void Write(string message, string category)
  411. {
  412. this.WriteLine(message, category);
  413. }
  414.  
  415. #endregion
  416.  
  417. #region WriteLine Methods
  418.  
  419. public override void WriteLine(object o)
  420. {
  421. if (o != null)
  422. {
  423. this.WriteLine(o.ToString(), null);
  424. }
  425. }
  426.  
  427. public override void WriteLine(string message)
  428. {
  429. this.WriteLine(message, null);
  430. }
  431.  
  432. public override void WriteLine(object o, string category)
  433. {
  434. if (o != null)
  435. {
  436. this.WriteLine(o.ToString(), category);
  437. }
  438. }
  439.  
  440. public override void WriteLine(string message, string category)
  441. {
  442. WriteLineInternal( message, category);
  443. }
  444.  
  445. #endregion
  446.  
  447. #region WriteLineInternal
  448.  
  449. private void WriteLineInternal(string message, string category)
  450. {
  451. try
  452. {
  453. if (!this.ShouldLogTrace(TraceEventType.Verbose))
  454. {
  455. this.WriteEntryToInternalLog(string.Format("WriteLineInternal: log is not going to write, TraceEventType.Verbose: {0} Message: {1}", TraceEventType.Verbose,message));
  456. return;
  457. }
  458.  
  459. System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
  460. 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;
  461.  
  462. try
  463. {
  464. xmlDoc.LoadXml(message);
  465. userId = xmlDoc.SelectSingleNode("/LogInfo/Record/UserId").InnerText;
  466. ip = xmlDoc.SelectSingleNode("/LogInfo/Record/IP").InnerText;
  467. pcName = xmlDoc.SelectSingleNode("/LogInfo/Record/PcName").InnerText;
  468. actions = xmlDoc.SelectSingleNode("/LogInfo/Record/Actions").InnerText;
  469. details = xmlDoc.SelectSingleNode("/LogInfo/Record/Details").InnerText;
  470. moduleName = xmlDoc.SelectSingleNode("/LogInfo/Record/Module").InnerText;
  471. dateLastLogin = xmlDoc.SelectSingleNode("/LogInfo/Record/LastLogin").InnerText;
  472. calssName = xmlDoc.SelectSingleNode("/LogInfo/Record/ClassName").InnerText;
  473. methodName = xmlDoc.SelectSingleNode("/LogInfo/Record/Method").InnerText;
  474. ErrorMassage = xmlDoc.SelectSingleNode("/LogInfo/Record/Message").InnerText;
  475. }
  476. catch (Exception exp)
  477. {
  478.  
  479. }
  480.  
  481. workerMethod2 = SaveLogEntry;
  482. workerMethod2.BeginInvoke(userId, ip, actions, details, pcName, moduleName, dateLastLogin, calssName,methodName,ErrorMassage,null,null);
  483. }
  484. catch(Exception ex)
  485. {
  486. this.WriteEntryToInternalLog(string.Format("WriteLine failed with following exception: {0}", ex.ToString()));
  487. }
  488. }
  489.  
  490. #endregion
  491.  
  492. private void SaveLogEntry(string userId, string ip, string actions, string details, string pcName, string moduleName, string dateLastLogin, string calssName, string methodName, string ErorMassage)
  493. {
  494. // IMPORTANT!!!!
  495. // DO NOT WRITE ANY Debug.WriteLine or Trace.WriteLine statements in this method
  496. try
  497. {
  498. this.WriteEntryToInternalLog(string.Format("SaveLogEntry Before Lock"));
  499. }
  500. catch { }
  501. lock (_traceLockObject)
  502. {
  503. try
  504. {
  505. // save trace message to database
  506. if (this._cn.State == ConnectionState.Broken || this._cn.State == ConnectionState.Closed)
  507. {
  508. this._cn.ConnectionString = this.ConnectionString;
  509. this._cn.Open();
  510. }
  511.  
  512. this._cm.Parameters[STORED_PROC_PARAM_UserId].Value = userId;//string.IsNullOrEmpty(userId)? DBNull.Value:
  513. this._cm.Parameters[STORED_PROC_PARAM_IP].Value = ip;
  514. this._cm.Parameters[STORED_PROC_PARAM_PcName].Value = pcName;
  515. this._cm.Parameters[STORED_PROC_PARAM_Actions].Value = actions;
  516. this._cm.Parameters[STORED_PROC_PARAM_Details].Value = details;
  517. this._cm.Parameters[STORED_PROC_PARAM_Module].Value = moduleName;
  518. this._cm.Parameters[STORED_PROC_PARAM_LastLogin].Value = dateLastLogin;
  519. this._cm.Parameters[STORED_PROC_PARAM_ClassName].Value = calssName;
  520. this._cm.Parameters[STORED_PROC_PARAM_Method].Value = methodName;
  521. this._cm.Parameters[STORED_PROC_PARAM_Message].Value = ErorMassage;
  522.  
  523. this._cm.ExecuteNonQuery();
  524. try
  525. {
  526. this.WriteEntryToInternalLog(string.Format("SaveLogEntry after ExecuteNonQuery"));
  527. }
  528. catch { }
  529. }
  530. catch (Exception ex)
  531. {
  532. // Raise event to let others know, just in case
  533. // someone interested
  534. if (this.DBTraceFailed != null)
  535. {
  536. DBTraceFailed(ex.ToString());
  537. }
  538.  
  539. // Write entry to internal log file
  540. this.WriteEntryToInternalLog(ex.ToString());
  541. }
  542. finally
  543. {
  544. // Nothing to dispose in case of exception
  545. }
  546. }
  547. }
  548.  
  549. protected override string[] GetSupportedAttributes()
  550. {
  551. return new string[] { "connectionString", "componentName", "refreshTraceConfig" };
  552. }
  553.  
  554. protected override void Dispose(bool disposing)
  555. {
  556. if (!this._disposed)
  557. {
  558. if (disposing)
  559. {
  560. if (this._cn != null)
  561. this._cn.Dispose();
  562.  
  563. if (this._cm != null)
  564. this._cm.Dispose();
  565.  
  566. if (this._traceSwitchTimer != null)
  567. this._traceSwitchTimer.Dispose();
  568. }
  569.  
  570. this._disposed = true;
  571. }
  572.  
  573. this._cm = null;
  574. this._cn = null;
  575.  
  576. base.Dispose(disposing);
  577. }
  578.  
  579. #endregion
  580.  
  581. }
  582.  
  583. Debug.Listeners.Add(new DBTraceListener(System.Configuration.ConfigurationManager.ConnectionStrings["connectionString"].ToString()));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement