Actor方法启动/停止日志|添加其他信息

时间:2016-09-14 15:51:00

标签: azure-service-fabric

对于azure actor服务,Actor Method Start Stop在Diagnostics窗口中登录,如下所示。

如何在每次调用方法时添加一些其他详细信息,例如关联ID?

{
  "Timestamp": "2016-09-14T19:46:40.9955448+05:30",
  "ProviderName": "Microsoft-ServiceFabric-Actors",
  "Id": 7,
  "Message": "Actor method is being invoked. Method name: IStore.GetStoreById, actor type: Backend.Actor.Store.Store, actor ID: STORE_6.",
  "ProcessId": 30736,
  "Level": "Verbose",
  "Keywords": "0x0000F00000000002",
  "EventName": "ActorMethod/Start",
  "Payload": {
    "methodName": "IStore.GetStoreById",
    "methodSignature": "System.Threading.Tasks.Task`1[Backend.Models.Store.StoreView] GetStoreById(System.String)",
    "actorType": "Backend.Actor.Store.Store",
    "actorId": "STORE_6",
    "actorIdKind": 2,
    "replicaOrInstanceId": 131183360004211655,
    "partitionId": "8af1c125-3666-40d0-b630-e3570c41833b",
    "serviceName": "fabric:/MultiBannerBackend/StoreActorService",
    "applicationName": "fabric:/MultiBannerBackend",
    "serviceTypeName": "StoreActorServiceType",
    "applicationTypeName": "MultiBannerBackendType",
    "nodeName": "_Node_4"
  }
}

1 个答案:

答案 0 :(得分:0)

为了记录每个Actor操作的自定义数据,您可以使用以下方法:

protected override Task OnPreActorMethodAsync(ActorMethodContext c)
protected override Task OnPostActorMethodAsync(ActorMethodContext c)

为了获得调用上下文,我发现CallContext.LogicalGetData在这种情况下不起作用。幸运的是,Actor确实知道它的上下文。你可以使用一些反思来获得它。

例如:

protected override Task OnPreActorMethodAsync(ActorMethodContext c)
        {
            var correlationID = this.GetActorContext() ?? Guid.Empty.ToString("N");
            string message = $"Actor method is being invoked. Method name: {c.MethodName}, actor type: {GetType().FullName}, actor ID: {Id}, CorrelationID:{correlationID}";
            ActorEventSource.Current.ActorMessage(this, message);
            return Task.FromResult(true);
        }

        protected override Task OnPostActorMethodAsync(ActorMethodContext c)
        {
            var correlationID = this.GetActorContext() ?? Guid.Empty.ToString("N");
            string message = $"Actor method has completed. Method name: {c.MethodName}, actor type: {GetType().FullName}, actor ID: {Id}, CorrelationID:{correlationID}";
            ActorEventSource.Current.ActorMessage(this, message);
            return Task.FromResult(true);
        }

结合:

public static class ActorContextExtensions
    {
        public static string GetActorContext(this Actor actor)
        {
            var concurrencyLockProperty = GetPropertyInfo("ConcurrencyLock", typeof(ActorBase));
            var concurrencyLockPropertyValue = concurrencyLockProperty.GetValue(actor);

            var currentContextProperty = GetPropertyInfo("Test_CurrentContext", concurrencyLockPropertyValue.GetType());
            string currentContextPropertyValue = (string)currentContextProperty.GetValue(concurrencyLockPropertyValue);
            return currentContextPropertyValue;
        }

        private static PropertyInfo GetPropertyInfo(string propertyName, IReflect owner)
        {
            var property = owner.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance);
            if (property == null) throw new InvalidOperationException($"Failed to find property '{propertyName}' on '{owner}'.");
            return property;
        }
    }

明显的缺点是,只要ActorBase的内部发生变化,您就需要相应地更改反射代码。