ServiceModelActivity.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Diagnostics
  5. {
  6. using System;
  7. using System.Diagnostics;
  8. using System.Runtime.Remoting.Messaging;
  9. using System.Threading;
  10. using System.Globalization;
  11. using System.Collections.Generic;
  12. using System.ServiceModel.Diagnostics.Application;
  13. using System.Runtime.Diagnostics;
  14. class ServiceModelActivity : IDisposable
  15. {
  16. [ThreadStatic]
  17. static ServiceModelActivity currentActivity;
  18. static string[] ActivityTypeNames = new string[(int)ActivityType.NumItems];
  19. ServiceModelActivity previousActivity = null;
  20. static string activityBoundaryDescription = null;
  21. ActivityState lastState = ActivityState.Unknown;
  22. string name = null;
  23. bool autoStop = false;
  24. bool autoResume = false;
  25. Guid activityId;
  26. bool disposed = false;
  27. bool isAsync = false;
  28. int stopCount = 0;
  29. const int AsyncStopCount = 2;
  30. TransferActivity activity = null;
  31. ActivityType activityType = ActivityType.Unknown;
  32. static ServiceModelActivity()
  33. {
  34. ActivityTypeNames[(int)ActivityType.Unknown] = "Unknown";
  35. ActivityTypeNames[(int)ActivityType.Close] = "Close";
  36. ActivityTypeNames[(int)ActivityType.Construct] = "Construct";
  37. ActivityTypeNames[(int)ActivityType.ExecuteUserCode] = "ExecuteUserCode";
  38. ActivityTypeNames[(int)ActivityType.ListenAt] = "ListenAt";
  39. ActivityTypeNames[(int)ActivityType.Open] = "Open";
  40. ActivityTypeNames[(int)ActivityType.OpenClient] = "Open";
  41. ActivityTypeNames[(int)ActivityType.ProcessMessage] = "ProcessMessage";
  42. ActivityTypeNames[(int)ActivityType.ProcessAction] = "ProcessAction";
  43. ActivityTypeNames[(int)ActivityType.ReceiveBytes] = "ReceiveBytes";
  44. ActivityTypeNames[(int)ActivityType.SecuritySetup] = "SecuritySetup";
  45. ActivityTypeNames[(int)ActivityType.TransferToComPlus] = "TransferToComPlus";
  46. ActivityTypeNames[(int)ActivityType.WmiGetObject] = "WmiGetObject";
  47. ActivityTypeNames[(int)ActivityType.WmiPutInstance] = "WmiPutInstance";
  48. }
  49. ServiceModelActivity(Guid activityId)
  50. {
  51. this.activityId = activityId;
  52. this.previousActivity = ServiceModelActivity.Current;
  53. }
  54. static string ActivityBoundaryDescription
  55. {
  56. get
  57. {
  58. if (ServiceModelActivity.activityBoundaryDescription == null)
  59. {
  60. ServiceModelActivity.activityBoundaryDescription = TraceSR.GetString(TraceSR.ActivityBoundary);
  61. }
  62. return ServiceModelActivity.activityBoundaryDescription;
  63. }
  64. }
  65. internal ActivityType ActivityType
  66. {
  67. get { return this.activityType; }
  68. }
  69. internal ServiceModelActivity PreviousActivity
  70. {
  71. get { return this.previousActivity; }
  72. }
  73. static internal Activity BoundOperation(ServiceModelActivity activity)
  74. {
  75. if (!DiagnosticUtility.ShouldUseActivity)
  76. {
  77. return null;
  78. }
  79. return ServiceModelActivity.BoundOperation(activity, false);
  80. }
  81. static internal Activity BoundOperation(ServiceModelActivity activity, bool addTransfer)
  82. {
  83. return activity == null ? null : ServiceModelActivity.BoundOperationCore(activity, addTransfer);
  84. }
  85. static Activity BoundOperationCore(ServiceModelActivity activity, bool addTransfer)
  86. {
  87. if (!DiagnosticUtility.ShouldUseActivity)
  88. {
  89. return null;
  90. }
  91. TransferActivity retval = null;
  92. if (activity != null)
  93. {
  94. retval = TransferActivity.CreateActivity(activity.activityId, addTransfer);
  95. if (retval != null)
  96. {
  97. retval.SetPreviousServiceModelActivity(ServiceModelActivity.Current);
  98. }
  99. ServiceModelActivity.Current = activity;
  100. }
  101. return retval;
  102. }
  103. internal static ServiceModelActivity CreateActivity()
  104. {
  105. if (!DiagnosticUtility.ShouldUseActivity)
  106. {
  107. return null;
  108. }
  109. return ServiceModelActivity.CreateActivity(Guid.NewGuid(), true);
  110. }
  111. internal static ServiceModelActivity CreateActivity(bool autoStop)
  112. {
  113. if (!DiagnosticUtility.ShouldUseActivity)
  114. {
  115. return null;
  116. }
  117. ServiceModelActivity activity = ServiceModelActivity.CreateActivity(Guid.NewGuid(), true);
  118. if (activity != null)
  119. {
  120. activity.autoStop = autoStop;
  121. }
  122. return activity;
  123. }
  124. internal static ServiceModelActivity CreateActivity(bool autoStop, string activityName, ActivityType activityType)
  125. {
  126. if (!DiagnosticUtility.ShouldUseActivity)
  127. {
  128. return null;
  129. }
  130. ServiceModelActivity activity = ServiceModelActivity.CreateActivity(autoStop);
  131. ServiceModelActivity.Start(activity, activityName, activityType);
  132. return activity;
  133. }
  134. internal static ServiceModelActivity CreateAsyncActivity()
  135. {
  136. if (!DiagnosticUtility.ShouldUseActivity)
  137. {
  138. return null;
  139. }
  140. ServiceModelActivity activity = ServiceModelActivity.CreateActivity(true);
  141. if (activity != null)
  142. {
  143. activity.isAsync = true;
  144. }
  145. return activity;
  146. }
  147. internal static ServiceModelActivity CreateBoundedActivity()
  148. {
  149. return ServiceModelActivity.CreateBoundedActivity(false);
  150. }
  151. internal static ServiceModelActivity CreateBoundedActivity(bool suspendCurrent)
  152. {
  153. if (!DiagnosticUtility.ShouldUseActivity)
  154. {
  155. return null;
  156. }
  157. ServiceModelActivity activityToSuspend = ServiceModelActivity.Current;
  158. ServiceModelActivity retval = ServiceModelActivity.CreateActivity(true);
  159. if (retval != null)
  160. {
  161. retval.activity = (TransferActivity)ServiceModelActivity.BoundOperation(retval, true);
  162. retval.activity.SetPreviousServiceModelActivity(activityToSuspend);
  163. if (suspendCurrent)
  164. {
  165. retval.autoResume = true;
  166. }
  167. }
  168. if (suspendCurrent && activityToSuspend != null)
  169. {
  170. activityToSuspend.Suspend();
  171. }
  172. return retval;
  173. }
  174. internal static ServiceModelActivity CreateBoundedActivity(Guid activityId)
  175. {
  176. if (!DiagnosticUtility.ShouldUseActivity)
  177. {
  178. return null;
  179. }
  180. ServiceModelActivity retval = ServiceModelActivity.CreateActivity(activityId, true);
  181. if (retval != null)
  182. {
  183. retval.activity = (TransferActivity)ServiceModelActivity.BoundOperation(retval, true);
  184. }
  185. return retval;
  186. }
  187. internal static ServiceModelActivity CreateBoundedActivityWithTransferInOnly(Guid activityId)
  188. {
  189. if (!DiagnosticUtility.ShouldUseActivity)
  190. {
  191. return null;
  192. }
  193. ServiceModelActivity retval = ServiceModelActivity.CreateActivity(activityId, true);
  194. if (retval != null)
  195. {
  196. if (null != FxTrace.Trace)
  197. {
  198. FxTrace.Trace.TraceTransfer(activityId);
  199. }
  200. retval.activity = (TransferActivity)ServiceModelActivity.BoundOperation(retval);
  201. }
  202. return retval;
  203. }
  204. internal static ServiceModelActivity CreateLightWeightAsyncActivity(Guid activityId)
  205. {
  206. return new ServiceModelActivity(activityId);
  207. }
  208. internal static ServiceModelActivity CreateActivity(Guid activityId)
  209. {
  210. if (!DiagnosticUtility.ShouldUseActivity)
  211. {
  212. return null;
  213. }
  214. ServiceModelActivity retval = null;
  215. if (activityId != Guid.Empty)
  216. {
  217. retval = new ServiceModelActivity(activityId);
  218. }
  219. if (retval != null)
  220. {
  221. ServiceModelActivity.Current = retval;
  222. }
  223. return retval;
  224. }
  225. internal static ServiceModelActivity CreateActivity(Guid activityId, bool autoStop)
  226. {
  227. if (!DiagnosticUtility.ShouldUseActivity)
  228. {
  229. return null;
  230. }
  231. ServiceModelActivity retval = ServiceModelActivity.CreateActivity(activityId);
  232. if (retval != null)
  233. {
  234. retval.autoStop = autoStop;
  235. }
  236. return retval;
  237. }
  238. internal static ServiceModelActivity Current
  239. {
  240. get { return ServiceModelActivity.currentActivity; }
  241. private set { ServiceModelActivity.currentActivity = value; }
  242. }
  243. public void Dispose()
  244. {
  245. if (!this.disposed)
  246. {
  247. this.disposed = true;
  248. try
  249. {
  250. if (this.activity != null)
  251. {
  252. this.activity.Dispose();
  253. }
  254. if (this.autoStop)
  255. {
  256. this.Stop();
  257. }
  258. if (this.autoResume &&
  259. ServiceModelActivity.Current != null)
  260. {
  261. ServiceModelActivity.Current.Resume();
  262. }
  263. }
  264. finally
  265. {
  266. ServiceModelActivity.Current = this.previousActivity;
  267. GC.SuppressFinalize(this);
  268. }
  269. }
  270. }
  271. internal Guid Id
  272. {
  273. get { return this.activityId; }
  274. }
  275. ActivityState LastState
  276. {
  277. get { return this.lastState; }
  278. set { this.lastState = value; }
  279. }
  280. internal string Name
  281. {
  282. get { return this.name; }
  283. set { this.name = value; }
  284. }
  285. internal void Resume()
  286. {
  287. if (this.LastState == ActivityState.Suspend)
  288. {
  289. this.LastState = ActivityState.Resume;
  290. this.TraceMilestone(TraceEventType.Resume);
  291. }
  292. }
  293. internal void Resume(string activityName)
  294. {
  295. if (string.IsNullOrEmpty(this.Name))
  296. {
  297. this.name = activityName;
  298. }
  299. this.Resume();
  300. }
  301. static internal void Start(ServiceModelActivity activity, string activityName, ActivityType activityType)
  302. {
  303. if (activity != null && activity.LastState == ActivityState.Unknown)
  304. {
  305. activity.LastState = ActivityState.Start;
  306. activity.name = activityName;
  307. activity.activityType = activityType;
  308. activity.TraceMilestone(TraceEventType.Start);
  309. }
  310. }
  311. internal void Stop()
  312. {
  313. int newStopCount = 0;
  314. if (this.isAsync)
  315. {
  316. newStopCount = Interlocked.Increment(ref this.stopCount);
  317. }
  318. if (this.LastState != ActivityState.Stop &&
  319. (!this.isAsync || (this.isAsync && newStopCount >= ServiceModelActivity.AsyncStopCount)))
  320. {
  321. this.LastState = ActivityState.Stop;
  322. this.TraceMilestone(TraceEventType.Stop);
  323. }
  324. }
  325. static internal void Stop(ServiceModelActivity activity)
  326. {
  327. if (activity != null)
  328. {
  329. activity.Stop();
  330. }
  331. }
  332. internal void Suspend()
  333. {
  334. if (this.LastState != ActivityState.Stop)
  335. {
  336. this.LastState = ActivityState.Suspend;
  337. this.TraceMilestone(TraceEventType.Suspend);
  338. }
  339. }
  340. public override string ToString()
  341. {
  342. return this.Id.ToString();
  343. }
  344. void TraceMilestone(TraceEventType type)
  345. {
  346. if (string.IsNullOrEmpty(this.Name))
  347. {
  348. if (null != FxTrace.Trace)
  349. {
  350. CallEtwMileStoneEvent(type, null);
  351. }
  352. if (null != DiagnosticUtility.DiagnosticTrace)
  353. {
  354. TraceUtility.TraceEventNoCheck(type, TraceCode.ActivityBoundary, ServiceModelActivity.ActivityBoundaryDescription, null, ServiceModelActivity.ActivityBoundaryDescription, (Exception)null);
  355. }
  356. }
  357. else
  358. {
  359. if (null != FxTrace.Trace)
  360. {
  361. Dictionary<string, string> values = new Dictionary<string, string>(2);
  362. values["ActivityName"] = this.Name;
  363. values["ActivityType"] = ServiceModelActivity.ActivityTypeNames[(int)this.activityType];
  364. using (DiagnosticUtility.ShouldUseActivity && Guid.Empty == activityId ? null : Activity.CreateActivity(this.Id))
  365. {
  366. CallEtwMileStoneEvent(type, new DictionaryTraceRecord(values));
  367. }
  368. }
  369. if (null != DiagnosticUtility.DiagnosticTrace)
  370. {
  371. Dictionary<string, string> values = new Dictionary<string, string>(2);
  372. values["ActivityName"] = this.Name;
  373. values["ActivityType"] = ServiceModelActivity.ActivityTypeNames[(int)this.activityType];
  374. TraceUtility.TraceEventNoCheck(type, TraceCode.ActivityBoundary, ServiceModelActivity.ActivityBoundaryDescription, new DictionaryTraceRecord(values), null, null, this.Id);
  375. }
  376. }
  377. }
  378. void CallEtwMileStoneEvent(TraceEventType type, DictionaryTraceRecord record)
  379. {
  380. switch (type)
  381. {
  382. case TraceEventType.Start:
  383. if (TD.StartSignpostEventIsEnabled())
  384. {
  385. TD.StartSignpostEvent(record);
  386. }
  387. break;
  388. case TraceEventType.Stop:
  389. if (TD.StopSignpostEventIsEnabled())
  390. {
  391. TD.StopSignpostEvent(record);
  392. }
  393. break;
  394. case TraceEventType.Suspend:
  395. if (TD.SuspendSignpostEventIsEnabled())
  396. {
  397. TD.SuspendSignpostEvent(record);
  398. }
  399. break;
  400. case TraceEventType.Resume:
  401. if (TD.ResumeSignpostEventIsEnabled())
  402. {
  403. TD.ResumeSignpostEvent(record);
  404. }
  405. break;
  406. }
  407. }
  408. enum ActivityState
  409. {
  410. Unknown,
  411. Start,
  412. Suspend,
  413. Resume,
  414. Stop,
  415. }
  416. class TransferActivity : Activity
  417. {
  418. bool addTransfer = false;
  419. bool changeCurrentServiceModelActivity = false;
  420. ServiceModelActivity previousActivity = null;
  421. TransferActivity(Guid activityId, Guid parentId)
  422. : base(activityId, parentId)
  423. {
  424. }
  425. internal static TransferActivity CreateActivity(Guid activityId, bool addTransfer)
  426. {
  427. if (!DiagnosticUtility.ShouldUseActivity)
  428. {
  429. return null;
  430. }
  431. TransferActivity retval = null;
  432. if (DiagnosticUtility.TracingEnabled && activityId != Guid.Empty)
  433. {
  434. Guid currentActivityId = DiagnosticTraceBase.ActivityId;
  435. if (activityId != currentActivityId)
  436. {
  437. if (addTransfer)
  438. {
  439. if (null != FxTrace.Trace)
  440. {
  441. FxTrace.Trace.TraceTransfer(activityId);
  442. }
  443. }
  444. TransferActivity activity = new TransferActivity(activityId, currentActivityId);
  445. activity.addTransfer = addTransfer;
  446. retval = activity;
  447. }
  448. }
  449. return retval;
  450. }
  451. internal void SetPreviousServiceModelActivity(ServiceModelActivity previous)
  452. {
  453. this.previousActivity = previous;
  454. this.changeCurrentServiceModelActivity = true;
  455. }
  456. public override void Dispose()
  457. {
  458. try
  459. {
  460. if (addTransfer)
  461. {
  462. // Make sure that we are transferring from our AID to the
  463. // parent. It is possible for someone else to change the ambient
  464. // in user code (MB 49318).
  465. using (Activity.CreateActivity(this.Id))
  466. {
  467. if (null != FxTrace.Trace)
  468. {
  469. FxTrace.Trace.TraceTransfer(this.parentId);
  470. }
  471. }
  472. }
  473. }
  474. finally
  475. {
  476. if (this.changeCurrentServiceModelActivity)
  477. {
  478. ServiceModelActivity.Current = this.previousActivity;
  479. }
  480. base.Dispose();
  481. }
  482. }
  483. }
  484. }
  485. }