| File: System\ServiceModel\Diagnostics\ServiceModelActivity.cs | Web Access |
| Project: src\src\System.ServiceModel.Primitives\src\System.ServiceModel.Primitives.csproj (System.ServiceModel.Primitives) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Diagnostics; using System.Threading; namespace System.ServiceModel.Diagnostics { internal class ServiceModelActivity : IDisposable { [ThreadStatic] private static ServiceModelActivity s_currentActivity; private static string[] s_activityTypeNames = new string[(int)ActivityType.NumItems]; private bool _autoStop = false; private bool _autoResume = false; private bool _disposed = false; private bool _isAsync = false; private int _stopCount = 0; private const int AsyncStopCount = 2; private TransferActivity _activity = null; static ServiceModelActivity() { s_activityTypeNames[(int)ActivityType.Unknown] = "Unknown"; s_activityTypeNames[(int)ActivityType.Close] = "Close"; s_activityTypeNames[(int)ActivityType.Construct] = "Construct"; s_activityTypeNames[(int)ActivityType.ExecuteUserCode] = "ExecuteUserCode"; s_activityTypeNames[(int)ActivityType.ListenAt] = "ListenAt"; s_activityTypeNames[(int)ActivityType.Open] = "Open"; s_activityTypeNames[(int)ActivityType.OpenClient] = "Open"; s_activityTypeNames[(int)ActivityType.ProcessMessage] = "ProcessMessage"; s_activityTypeNames[(int)ActivityType.ProcessAction] = "ProcessAction"; s_activityTypeNames[(int)ActivityType.ReceiveBytes] = "ReceiveBytes"; s_activityTypeNames[(int)ActivityType.SecuritySetup] = "SecuritySetup"; s_activityTypeNames[(int)ActivityType.TransferToComPlus] = "TransferToComPlus"; s_activityTypeNames[(int)ActivityType.WmiGetObject] = "WmiGetObject"; s_activityTypeNames[(int)ActivityType.WmiPutInstance] = "WmiPutInstance"; } private ServiceModelActivity(Guid activityId) { Id = activityId; PreviousActivity = ServiceModelActivity.Current; } internal ActivityType ActivityType { get; private set; } = ActivityType.Unknown; internal ServiceModelActivity PreviousActivity { get; } = null; internal static Activity BoundOperation(ServiceModelActivity activity) { if (!DiagnosticUtility.ShouldUseActivity) { return null; } return ServiceModelActivity.BoundOperation(activity, false); } static internal Activity BoundOperation(ServiceModelActivity activity, bool addTransfer) { return activity == null ? null : ServiceModelActivity.BoundOperationCore(activity, addTransfer); } private static Activity BoundOperationCore(ServiceModelActivity activity, bool addTransfer) { if (!DiagnosticUtility.ShouldUseActivity) { return null; } TransferActivity retval = null; if (activity != null) { retval = TransferActivity.CreateActivity(activity.Id, addTransfer); if (retval != null) { retval.SetPreviousServiceModelActivity(ServiceModelActivity.Current); } ServiceModelActivity.Current = activity; } return retval; } internal static ServiceModelActivity CreateActivity() { if (!DiagnosticUtility.ShouldUseActivity) { return null; } return ServiceModelActivity.CreateActivity(Guid.NewGuid(), true); } internal static ServiceModelActivity CreateActivity(bool autoStop) { if (!DiagnosticUtility.ShouldUseActivity) { return null; } ServiceModelActivity activity = ServiceModelActivity.CreateActivity(Guid.NewGuid(), true); if (activity != null) { activity._autoStop = autoStop; } return activity; } internal static ServiceModelActivity CreateActivity(bool autoStop, string activityName, ActivityType activityType) { if (!DiagnosticUtility.ShouldUseActivity) { return null; } ServiceModelActivity activity = ServiceModelActivity.CreateActivity(autoStop); ServiceModelActivity.Start(activity, activityName, activityType); return activity; } internal static ServiceModelActivity CreateAsyncActivity() { if (!DiagnosticUtility.ShouldUseActivity) { return null; } ServiceModelActivity activity = ServiceModelActivity.CreateActivity(true); if (activity != null) { activity._isAsync = true; } return activity; } internal static ServiceModelActivity CreateBoundedActivity() { return ServiceModelActivity.CreateBoundedActivity(false); } internal static ServiceModelActivity CreateBoundedActivity(bool suspendCurrent) { if (!DiagnosticUtility.ShouldUseActivity) { return null; } ServiceModelActivity activityToSuspend = ServiceModelActivity.Current; ServiceModelActivity retval = ServiceModelActivity.CreateActivity(true); if (retval != null) { retval._activity = (TransferActivity)ServiceModelActivity.BoundOperation(retval, true); retval._activity.SetPreviousServiceModelActivity(activityToSuspend); if (suspendCurrent) { retval._autoResume = true; } } if (suspendCurrent && activityToSuspend != null) { activityToSuspend.Suspend(); } return retval; } internal static ServiceModelActivity CreateBoundedActivity(Guid activityId) { if (!DiagnosticUtility.ShouldUseActivity) { return null; } ServiceModelActivity retval = ServiceModelActivity.CreateActivity(activityId, true); if (retval != null) { retval._activity = (TransferActivity)ServiceModelActivity.BoundOperation(retval, true); } return retval; } internal static ServiceModelActivity CreateBoundedActivityWithTransferInOnly(Guid activityId) { if (!DiagnosticUtility.ShouldUseActivity) { return null; } ServiceModelActivity retval = ServiceModelActivity.CreateActivity(activityId, true); if (retval != null) { if (null != FxTrace.Trace) { FxTrace.Trace.TraceTransfer(activityId); } retval._activity = (TransferActivity)ServiceModelActivity.BoundOperation(retval); } return retval; } internal static ServiceModelActivity CreateLightWeightAsyncActivity(Guid activityId) { return new ServiceModelActivity(activityId); } internal static ServiceModelActivity CreateActivity(Guid activityId) { if (!DiagnosticUtility.ShouldUseActivity) { return null; } ServiceModelActivity retval = null; if (activityId != Guid.Empty) { retval = new ServiceModelActivity(activityId); } if (retval != null) { ServiceModelActivity.Current = retval; } return retval; } internal static ServiceModelActivity CreateActivity(Guid activityId, bool autoStop) { if (!DiagnosticUtility.ShouldUseActivity) { return null; } ServiceModelActivity retval = ServiceModelActivity.CreateActivity(activityId); if (retval != null) { retval._autoStop = autoStop; } return retval; } internal static ServiceModelActivity Current { get { return ServiceModelActivity.s_currentActivity; } private set { ServiceModelActivity.s_currentActivity = value; } } public void Dispose() { if (!_disposed) { _disposed = true; try { if (_activity != null) { _activity.Dispose(); } if (_autoStop) { Stop(); } if (_autoResume && ServiceModelActivity.Current != null) { ServiceModelActivity.Current.Resume(); } } finally { ServiceModelActivity.Current = PreviousActivity; GC.SuppressFinalize(this); } } } internal Guid Id { get; } private ActivityState LastState { get; set; } = ActivityState.Unknown; internal string Name { get; set; } = null; internal void Resume() { if (LastState == ActivityState.Suspend) { LastState = ActivityState.Resume; } } internal void Resume(string activityName) { if (string.IsNullOrEmpty(Name)) { Name = activityName; } Resume(); } static internal void Start(ServiceModelActivity activity, string activityName, ActivityType activityType) { if (activity != null && activity.LastState == ActivityState.Unknown) { activity.LastState = ActivityState.Start; activity.Name = activityName; activity.ActivityType = activityType; } } internal void Stop() { int newStopCount = 0; if (_isAsync) { newStopCount = Interlocked.Increment(ref _stopCount); } if (LastState != ActivityState.Stop && (!_isAsync || (_isAsync && newStopCount >= ServiceModelActivity.AsyncStopCount))) { LastState = ActivityState.Stop; } } static internal void Stop(ServiceModelActivity activity) { if (activity != null) { activity.Stop(); } } internal void Suspend() { if (LastState != ActivityState.Stop) { LastState = ActivityState.Suspend; } } public override string ToString() { return Id.ToString(); } private enum ActivityState { Unknown, Start, Suspend, Resume, Stop, } internal class TransferActivity : Activity { private bool _addTransfer = false; private bool _changeCurrentServiceModelActivity = false; private ServiceModelActivity _previousActivity = null; private TransferActivity(Guid activityId, Guid parentId) : base(activityId, parentId) { } internal static TransferActivity CreateActivity(Guid activityId, bool addTransfer) { if (!DiagnosticUtility.ShouldUseActivity) { return null; } TransferActivity retval = null; return retval; } internal void SetPreviousServiceModelActivity(ServiceModelActivity previous) { _previousActivity = previous; _changeCurrentServiceModelActivity = true; } public override void Dispose() { try { if (_addTransfer) { // Make sure that we are transferring from our AID to the // parent. It is possible for someone else to change the ambient // in user code (MB 49318). using (Activity.CreateActivity(Id)) { if (null != FxTrace.Trace) { FxTrace.Trace.TraceTransfer(parentId); } } } } finally { if (_changeCurrentServiceModelActivity) { ServiceModelActivity.Current = _previousActivity; } base.Dispose(); } } } } }