var tracer = GlobalTracer.Instance;
const string operationName = "RootDialog-MessageReceivedAsync";
var spanBuilder = tracer.BuildSpan(operationName);
if (tracer.ActiveSpan != null)
spanBuilder.AsChildOf(tracer.ActiveSpan);
using (var scope = spanBuilder.StartActive(true))
{
// 其他的程式碼 ...
}
這些程式碼跟 Exception Handle 類似,所以我們可以透過 Dynamic Proxy 的方式來包裝起來,讓程式開發人員專注在程式的邏輯之中,不用去理會這煩雜的程式碼。public class OpenTracingInterceptor : IInterceptor
{
IAsyncInterceptor _asyncInterceptor;
public OpenTracingInterceptor(IAsyncInterceptor asyncInterceptor)
{
_asyncInterceptor = asyncInterceptor;
}
public void Intercept(IInvocation invocation)
{
_asyncInterceptor.ToInterceptor().Intercept(invocation);
}
}
public class OpenTracingInterceptorAsync : IAsyncInterceptor
{
public void InterceptAsynchronous(IInvocation invocation)
{
invocation.ReturnValue = InternalInterceptAsynchronous(invocation);
}
private async Task InternalInterceptAsynchronous(IInvocation invocation)
{
var tracer = GlobalTracer.Instance;
string operationName = invocation.Method.Name;
var spanBuilder = tracer.BuildSpan(operationName);
if (tracer.ActiveSpan != null)
{
spanBuilder.AsChildOf(tracer.ActiveSpan);
}
using (var scope = spanBuilder.StartActive(true))
{
// Step 1. Do something prior to invocation.
invocation.Proceed();
var task = (Task)invocation.ReturnValue;
await task;
// Step 2. Do something after invocation.
}
}
public void InterceptAsynchronous<TResult>(IInvocation invocation)
{
invocation.ReturnValue = InternalInterceptAsynchronous<TResult>(invocation);
}
private async Task<TResult> InternalInterceptAsynchronous<TResult>(IInvocation invocation)
{
var tracer = GlobalTracer.Instance;
string operationName = invocation.Method.Name;
var spanBuilder = tracer.BuildSpan(operationName);
if (tracer.ActiveSpan != null)
{
spanBuilder.AsChildOf(tracer.ActiveSpan);
}
TResult result;
using (var scope = spanBuilder.StartActive(true))
{
// Step 1. Do something prior to invocation.
invocation.Proceed();
var task = (Task<TResult>)invocation.ReturnValue;
result = await task;
// Step 2. Do something after invocation.
}
return result;
}
public void InterceptSynchronous(IInvocation invocation)
{
var tracer = GlobalTracer.Instance;
string operationName = invocation.Method.Name;
var spanBuilder = tracer.BuildSpan(operationName);
if (tracer.ActiveSpan != null)
{
spanBuilder.AsChildOf(tracer.ActiveSpan);
}
using (var scope = spanBuilder.StartActive(true))
{
// Step 1. Do something prior to invocation.
invocation.Proceed();
// Step 2. Do something after invocation.
}
}
}
//autofac codes...
builder.RegisterType<OpenTracingInterceptor>();
builder.RegisterType<OpenTracingInterceptorAsync>().As<IAsyncInterceptor>();
builder.RegisterType<RootDialog>()
.AsSelf()
.EnableClassInterceptors()
.InterceptedBy(typeof(OpenTracingInterceptor));
builder
.RegisterType<ShowMenuActionStrategy>()
.Named<IActionStrategy>(ActionTypes.ShowMenuAction.ToString())
.InstancePerLifetimeScope()
.EnableClassInterceptors()
.InterceptedBy(typeof(OpenTracingInterceptor));
//autofac codes...