public IRequestSpan AddEvent(string name, DateTimeOffset?timestamp = null) { var activityEvent = new ActivityEvent(name, timestamp ?? default); _activity?.AddEvent(activityEvent); return(this); }
private static void DoWork(IDatabase db, ActivitySource activitySource) { // Start another activity. If another activity was already started, it'll use that activity as the parent activity. // In this example, the main method already started a activity, so that'll be the parent activity, and this will be // a child activity. using (Activity activity = activitySource.StartActivity("DoWork")) { try { db.StringSet("key", "value " + DateTime.Now.ToLongDateString()); System.Console.WriteLine("Doing busy work"); Thread.Sleep(1000); // run a command, in this case a GET var myVal = db.StringGet("key"); System.Console.WriteLine(myVal); } catch (ArgumentOutOfRangeException e) { // Set status upon error activity.AddTag(SpanAttributeConstants.StatusCodeKey, SpanHelper.GetCachedCanonicalCodeString(Status.Internal.CanonicalCode)); activity.AddTag(SpanAttributeConstants.StatusDescriptionKey, e.ToString()); } // Annotate our activity to capture metadata about our operation var attributes = new Dictionary <string, object> { { "use", "demo" }, }; activity.AddEvent(new ActivityEvent("Invoking DoWork", attributes)); } }
public async Task <IActionResult> Post([FromBody] GreetingIn input) { _logger.LogTrace("Request Input: {@Input}", input); // this silly logic is so we can show a trace that never went past this point if (input.Name == "string") { _logger.LogWarning("Tricksy hackerses, we hates them!"); // add a tag to the current activity, so we know why the request died Activity.Current?.AddTag("illegal.input", input.Name); // I realize this is mixing movie quotes return(Ok( new GreetingOut { Message = "You're trying to trick me into giving something away... It won't work!" } )); } // start a new child activity since we're about to call the service (for request/reply capture) using Activity callRpcActivity = _activitySource.StartActivity("Call-Grpc-Service"); try { // capture rpc request parameters var rpcRequest = new HelloRequest { Name = input.Name }; callRpcActivity?.AddTag("rpc.request", rpcRequest.ToString()); // send greeting via gRPC HelloReply reply = await _greeterClient.SayHelloAsync( request : rpcRequest, deadline : DateTime.UtcNow.AddSeconds(8) ); _logger.LogDebug("Service replied with {@reply}", reply); // capture reply - not usually appropriate in production callRpcActivity?.AddTag("rpc.reply", reply.ToString()); // all good return(Ok( new GreetingOut { Message = reply.Message } )); } catch (RpcException ex) { // record error information in the trace callRpcActivity?.AddTag("error.status", ex.StatusCode.ToString()); callRpcActivity?.AddEvent(new ActivityEvent(ex.Message)); // not really the right thing to do, but fine for this sample return(BadRequest()); } }
public void TestActivityWithListenerActivityCreateAndAllDataRequested() { RemoteExecutor.Invoke(() => { using (ActivitySource aSource = new ActivitySource("SourceActivityListener")) { int counter = 0; Assert.False(aSource.HasListeners()); using (ActivityListener listener = new ActivityListener { ActivityStarted = activity => counter++, ActivityStopped = activity => counter--, ShouldListenTo = (activitySource) => object.ReferenceEquals(aSource, activitySource), GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> activityOptions) => ActivityDataRequest.AllDataAndRecorded, GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivityDataRequest.AllDataAndRecorded } ) { ActivitySource.AddActivityListener(listener); Assert.True(aSource.HasListeners()); using (Activity activity = aSource.StartActivity("AllDataRequestedActivity")) { Assert.NotNull(activity); Assert.True(activity.IsAllDataRequested); Assert.Equal(1, counter); Assert.Equal(0, activity.Tags.Count()); Assert.Equal(0, activity.Baggage.Count()); Assert.True(object.ReferenceEquals(activity, activity.AddTag("key", "value"))); Assert.True(object.ReferenceEquals(activity, activity.AddBaggage("key", "value"))); Assert.Equal(1, activity.Tags.Count()); Assert.Equal(1, activity.Baggage.Count()); using (Activity activity1 = aSource.StartActivity("AllDataRequestedActivity1")) { Assert.NotNull(activity1); Assert.True(activity1.IsAllDataRequested); Assert.Equal(2, counter); Assert.Equal(0, activity1.Links.Count()); Assert.Equal(0, activity1.Events.Count()); Assert.True(object.ReferenceEquals(activity1, activity1.AddEvent(new ActivityEvent("e1")))); Assert.Equal(1, activity1.Events.Count()); } Assert.Equal(1, counter); } Assert.Equal(0, counter); } } }).Dispose(); }
public static async Task Main(string[] args) { // create the tracer to export the traces CreateTracerProvider(); // attach a listener to generate activities // the listener has callbacks to log at ActivityStart and ActivityEnd ActivitySource.AddActivityListener(GetBatchActivityListener()); // get the metrics api to generate Histograms IMetricsRoot metricsRoot = GetMetricsRoot(); Context context = null; // instrument first activity // sleep for 250ms and add test tag List <KeyValuePair <string, object> > batchAttribute = new List <KeyValuePair <string, object> > { new KeyValuePair <string, object>("batch", "1") }; var worker1 = new InstrumentedWorker("Test activity", ActivityKind.Server, null, batchAttribute, () => Thread.Sleep(250), ActivitySource); Activity firstActivity = worker1.DoWork(); if (firstActivity?.IsAllDataRequested == true) { firstActivity.SetTag("Test tag", "A value for a custom tag"); metricsRoot.Measure.Histogram.Update(SampleHistogram, Convert.ToInt64(firstActivity.Duration.Milliseconds)); context = new Context(firstActivity.Context); } // instrument second activity // sleep for 350 ms batchAttribute[0] = new KeyValuePair <string, object>("batch", "2"); var worker2 = new InstrumentedWorker("Another test activity", ActivityKind.Server, context, batchAttribute, () => Thread.Sleep(350), ActivitySource); Activity secondActivity = worker2.DoWork(); if (secondActivity?.IsAllDataRequested == true) { metricsRoot.Measure.Histogram.Update(SampleHistogram, Convert.ToInt64(secondActivity.Duration.Milliseconds)); context = new Context(secondActivity.Context); } // instrument third activity, keep it opened // sleep for 500 ms and add events batchAttribute[0] = new KeyValuePair <string, object>("batch", "3"); var worker3 = new InstrumentedWorker("Third test activity", ActivityKind.Internal, context, batchAttribute, () => Thread.Sleep(500), ActivitySource); Activity thirdActivity = worker3.StartWork(); if (thirdActivity?.IsAllDataRequested == true) { thirdActivity.AddEvent(new ActivityEvent("An event")); Thread.Sleep(500); thirdActivity.AddEvent(new ActivityEvent("An event 500ms later")); context = new Context(thirdActivity.Context); } // add event using current activity Activity.Current?.AddEvent(new ActivityEvent("An event added to the current activity")); // instrument fourth activity as a nested activity // sleep for 500 ms batchAttribute[0] = new KeyValuePair <string, object>("batch", "4"); var worker4 = new InstrumentedWorker("Nested activity", ActivityKind.Client, context, batchAttribute, () => Thread.Sleep(500), ActivitySource); Activity fourthActivity = worker4.DoWork(); if (fourthActivity?.IsAllDataRequested == true) { metricsRoot.Measure.Histogram.Update(SampleHistogram, Convert.ToInt64(fourthActivity.Duration.Milliseconds)); } // stop 3rd activity thirdActivity = worker3.StopWork(); if (thirdActivity != null) { metricsRoot.Measure.Histogram.Update(SampleHistogram, Convert.ToInt64(thirdActivity.Duration.Milliseconds)); } // export the metrics await Task.WhenAll(metricsRoot.ReportRunner.RunAllAsync()); tracerProvider.Shutdown(); }