public IRequestSpan AddEvent(string name, DateTimeOffset?timestamp = null)
        {
            var activityEvent = new ActivityEvent(name, timestamp ?? default);

            _activity?.AddEvent(activityEvent);
            return(this);
        }
Example #2
0
        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));
            }
        }
Example #3
0
        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());
            }
        }
Example #4
0
        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();
        }
Example #5
0
        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();
        }