簡體   English   中英

如何以編程方式跟蹤響應持續時間?

[英]how can I track response duration programmatically?

客戶端調用我的Web WCF服務的方法“ Foo()”,並接收大字節數組作為響應:

public byte[] Foo()
{
    return new byte[10000000];
}

顯然,當客戶端讀取所有數據時,HTTP連接已關閉-如果我知道何時發生,則可以跟蹤“傳輸”的總持續時間。 我知道跟蹤等信息-但是我需要以編程方式獲取此數據,因此可以將其顯示給用戶。 我該如何追蹤?

我有兩種解決方案,性能計數器和自定義行為,但是我不確定它們是否能准確回答您的問題,因為我沒有考慮網絡延遲。

績效櫃台
第一個解決方案使用接近您要求的內置性能計數器 基本上,您想為您的服務啟用PerformanceCounters,然后在您的服務中使用其中之一。 確切的持續時間不可用,但Calls per second是其他計數器之一。

確保將其添加到您的服務配置中:

<system.serviceModel>
    <diagnostics performanceCounters="All" />
</system.serviceModel>

您的服務中有一個靜態類來保存您的PerformanceCounter。 在我的示例中,我將靜態實例添加到服務中,實際上,我將其移至另一個類。

public class Service1 : IService1
{
     // in an ideal world thisd how instancename would look like
    //ServiceName.ContractName.OperationName@first endpoint listener address

    private static PerformanceCounter pc = new PerformanceCounter();

     // our static constructor
    static Service1()
    {
        // naming of the instance is garbeld due to length restrictions...
        var cat = new PerformanceCounterCategory("ServiceModelOperation 4.0.0.0");
        foreach (var instance in cat.GetInstanceNames())
        {
            Trace.WriteLine(instance); // determine the instancename and copy over :-)
        }
        pc.CategoryName = "ServiceModelOperation 4.0.0.0";
        pc.CounterName = "Calls Per Second";
        pc.InstanceName = "Service1.IServ84.GetDataUsingD31@00:||LOCALHOST:2806|SERVICE1.SVC";

    }

    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        // do interesting stuff here

        // here I have the value (in the service call but you can call this from anywhere, 
        // even from another thread. 
        // or use perfmon.exe to obtain or make a graph of the value over time...
        Trace.WriteLine(pc.NextValue().ToString()); 

        return composite;
    }
}

自定義行為
此自定義行為會攔截對服務方法的調用,從而有可能啟動和停止計時器並存儲結果。

添加以下類:

// custom self timing for any wcf operation
    public class Timing :Attribute, IOperationBehavior,  IOperationInvoker 
    { 
        IOperationInvoker innerOperationInvoker;
        private string operName = "";

        public Timing()
        {
        }

        public Timing(IOperationInvoker innerOperationInvoker, string name)
        {
            this.innerOperationInvoker = innerOperationInvoker;
            operName = name;
        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            dispatchOperation.Invoker = new Timing(dispatchOperation.Invoker, operationDescription.Name);
        }

        public object Invoke(object instance, object[] inputs, out object[] outputs)
        {
            object value;

            var sw = new Stopwatch();
            sw.Start();
            value = innerOperationInvoker.Invoke( instance, inputs, out outputs);
            sw.Stop();
            // do what you need with the value...
            Trace.WriteLine(String.Format("{0}: {1} ms", operName,  sw.ElapsedMilliseconds));
            return value;
        }


        // boring required interface stuff

        public object[] AllocateInputs()
        {
            return innerOperationInvoker.AllocateInputs();
        }

        public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
        {
            return innerOperationInvoker.InvokeBegin(instance, inputs, callback, state);
        }

        public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
        {
            return innerOperationInvoker.InvokeEnd(instance, out outputs, result);
        }

        public bool IsSynchronous
        {
            get { return innerOperationInvoker.IsSynchronous; }
        }

        public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            // throw new NotImplementedException();
        }

        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {
            // throw new NotImplementedException();
        }

        public void Validate(OperationDescription operationDescription)
        {
            // throw new NotImplementedException();
        }
    }

現在在您的界面中裝飾您要使用Timing屬性存儲其計時的操作:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [Timing]   // Timing for this Operation!
    CompositeType GetDataUsingDataContract(CompositeType composite);
}

您可以使用StopWatch類找出持續時間,請參考以下msdn鏈接:

http://msdn.microsoft.com/zh-cn/library/system.diagnostics.stopwatch.elapsed.aspx

        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        // your wcf functionalities
        stopWatch.Stop();
        long duration = stopWatch.ElapsedMilliseconds;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM