internal static async Task Receive(MessageEnvelope envelope, SpanSetup receiveSpanSetup, ITracer tracer, Func <Task> receive) { var message = envelope.Message; var parentSpanCtx = envelope.Header != null ? tracer.Extract(BuiltinFormats.TextMap, new TextMapExtractAdapter(envelope.Header.ToDictionary())) : null; using (var scope = tracer.BuildStartedScope(parentSpanCtx, nameof(Receive), message, receiveSpanSetup)) { try { var span = scope.Span; if (envelope.Sender != null) { ProtoTags.SenderPID.Set(span, envelope.Sender.ToShortString()); } receiveSpanSetup?.Invoke(span, message); await receive().ConfigureAwait(false); } catch (Exception ex) { ex.SetupSpan(scope.Span); throw; } } }
/// <summary> /// Setup open tracing send middleware & decorator. /// </summary> /// <param name="props">props.</param> /// <param name="sendSpanSetup">provide a way inject send span constumisation according to the message.</param> /// <param name="receiveSpanSetup">provide a way inject receive span constumisation according to the message.</param> /// <param name="tracer">OpenTracing, if nul : GlobalTracer.Instance will be used.</param> /// <returns>props</returns> public static Props WithOpenTracing( this Props props, SpanSetup sendSpanSetup = null, SpanSetup receiveSpanSetup = null, ITracer tracer = null ) => props .WithContextDecorator(ctx => ctx.WithOpenTracing(sendSpanSetup, receiveSpanSetup, tracer)) .WithOpenTracingSender(tracer);
static void Main(string[] args) { var tracer = new Trace.Builder("Proto.Chat.Server") .WithSampler(new ConstSampler(true)) .Build(); GlobalTracer.Register(tracer); SpanSetup spanSetup = (span, message) => span.Log(message?.ToString()); var context = new RootContext(); Serialization.RegisterFileDescriptor(ChatReflection.Descriptor); Remote.Start("127.0.0.1", 8000); var clients = new HashSet <PID>(); var props = Actor.FromFunc(ctx => { switch (ctx.Message) { case Connect connect: Console.WriteLine($"Client {connect.Sender} connected"); clients.Add(connect.Sender); ctx.Send(connect.Sender, new Connected { Message = "Welcome!" }); break; case SayRequest sayRequest: foreach (var client in clients) { ctx.Send(client, new SayResponse { UserName = sayRequest.UserName, Message = sayRequest.Message }); } break; case NickRequest nickRequest: foreach (var client in clients) { ctx.Send(client, new NickResponse { OldUserName = nickRequest.OldUserName, NewUserName = nickRequest.NewUserName }); } break; } return(Actor.Done); }) .WithOpenTracing(spanSetup, spanSetup); context.SpawnNamed(props, "chatserver"); Console.ReadLine(); }
public OpenTracingRootContextDecorator(IRootContext context, SpanSetup sendSpanSetup, ITracer tracer) : base(context) { _sendSpanSetup = (span, message) => { ProtoTags.ActorType.Set(span, "<None>"); sendSpanSetup(span, message); }; _tracer = tracer; }
static void Main(string[] args) { var tracer = new Tracer.Builder("Proto.Chat.Client") .WithSampler(new ConstSampler(true)) .Build(); SpanSetup spanSetup = (span, message) => span.Log(message?.ToString()); var openTracingMiddleware = OpenTracingExtensions.OpenTracingSenderMiddleware(tracer); Serialization.RegisterFileDescriptor(ChatReflection.Descriptor); Remote.Start("127.0.0.1", 0); var server = new PID("127.0.0.1:8000", "chatserver"); var context = new RootContext(default, openTracingMiddleware);
internal static void Request(PID target, object message, SpanSetup sendSpanSetup, ITracer tracer, Action request) { using var scope = tracer.BuildStartedScope(tracer.ActiveSpan?.Context, nameof(Request), message, sendSpanSetup); try { ProtoTags.TargetPID.Set(scope.Span, target.ToString()); request(); } catch (Exception ex) { ex.SetupSpan(scope.Span); throw; } }
public OpenTracingActorContextDecorator(IContext context, SpanSetup sendSpanSetup, SpanSetup receiveSpanSetup, ITracer tracer) : base(context) { _sendSpanSetup = (span, message) => { ProtoTags.ActorType.Set(span, context.Actor.GetType().Name); ProtoTags.SenderPID.Set(span, context.Self.ToString()); sendSpanSetup(span, message); }; _receiveSpanSetup = (span, message) => { ProtoTags.ActorType.Set(span, context.Actor.GetType().Name); ProtoTags.TargetPID.Set(span, context.Self.ToString()); receiveSpanSetup(span, message); }; _tracer = tracer; }
internal static async Task <T> RequestAsync <T>(PID target, object message, SpanSetup sendSpanSetup, ITracer tracer, Func <Task <T> > requestAsync) { using var scope = tracer.BuildStartedScope(tracer.ActiveSpan?.Context, nameof(Request), message, sendSpanSetup); try { ProtoTags.TargetPID.Set(scope.Span, target.ToString()); return(await requestAsync().ConfigureAwait(false)); } catch (Exception ex) { ex.SetupSpan(scope.Span); throw; } }
public static void Send(PID target, object message, SpanSetup sendSpanSetup, ITracer tracer, Action send) { using var scope = tracer.BuildStartedScope(tracer.ActiveSpan?.Context, nameof(Send), message, sendSpanSetup); try { ProtoTags.TargetPID.Set(scope.Span, target.ToShortString()); send(); } catch (Exception ex) { ex.SetupSpan(scope.Span); throw; } }
public static IScope BuildStartedScope(this ITracer tracer, ISpanContext parentSpan, string verb, object message, SpanSetup spanSetup) { var messageType = message?.GetType().Name ?? "Unknown"; var scope = tracer .BuildSpan($"{verb} {messageType}") // <= perhaps is not good to have the operation name mentioning the message type .AsChildOf(parentSpan) .StartActive(true); ProtoTags.MessageType.Set(scope.Span, messageType); spanSetup?.Invoke(scope.Span, message); return(scope); }