public void NoEventsRecordedAfterEnd() { ISpan span = Span.StartSpan( spanContext, recordSpanOptions, SPAN_NAME, SpanKind.Internal, parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); span.End(); // Check that adding trace events after Span#End() does not throw any exception and are not // recorded. foreach (var attribute in attributes) { span.SetAttribute(attribute.Key, attribute.Value); } span.SetAttribute( "MySingleStringAttributeKey", AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); span.AddEvent(Event.Create(EVENT_DESCRIPTION)); span.AddEvent(EVENT_DESCRIPTION, attributes); span.AddLink(Link.FromSpanContext(spanContext)); SpanData spanData = ((Span)span).ToSpanData(); Assert.Equal(timestamp, spanData.StartTimestamp); Assert.Empty(spanData.Attributes.AttributeMap); Assert.Empty(spanData.Events.Events); Assert.Empty(spanData.Links.Links); Assert.Equal(Status.Ok, spanData.Status); Assert.Equal(timestamp, spanData.EndTimestamp); }
public void ToSpanData_ActiveSpan() { ISpan span = Span.StartSpan( spanContext, recordSpanOptions, SPAN_NAME, SpanKind.Internal, parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); span.SetAttribute( "MySingleStringAttributeKey", AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); foreach (var attribute in attributes) { span.SetAttribute(attribute.Key, attribute.Value); } interval = TimeSpan.FromMilliseconds(100); span.AddEvent(Event.Create(EVENT_DESCRIPTION)); interval = TimeSpan.FromMilliseconds(200); span.AddEvent(EVENT_DESCRIPTION, attributes); interval = TimeSpan.FromMilliseconds(300); interval = TimeSpan.FromMilliseconds(400); ILink link = Link.FromSpanContext(spanContext); span.AddLink(link); SpanData spanData = ((Span)span).ToSpanData(); Assert.Equal(spanContext, spanData.Context); Assert.Equal(SPAN_NAME, spanData.Name); Assert.Equal(parentSpanId, spanData.ParentSpanId); Assert.Equal(0, spanData.Attributes.DroppedAttributesCount); Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); Assert.Equal(0, spanData.Events.DroppedEventsCount); Assert.Equal(2, spanData.Events.Events.Count()); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), spanData.Events.Events.ToList()[0].Timestamp); Assert.Equal(Event.Create(EVENT_DESCRIPTION), spanData.Events.Events.ToList()[0].Event); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(200))), spanData.Events.Events.ToList()[1].Timestamp); Assert.Equal(Event.Create(EVENT_DESCRIPTION, attributes), spanData.Events.Events.ToList()[1].Event); Assert.Equal(0, spanData.Links.DroppedLinksCount); Assert.Single(spanData.Links.Links); Assert.Equal(link, spanData.Links.Links.First()); Assert.Equal(timestamp, spanData.StartTimestamp); Assert.Null(spanData.Status); Assert.Null(spanData.EndTimestamp); var startEndMock = Mock.Get <IStartEndHandler>(startEndHandler); var spanBase = span as SpanBase; startEndMock.Verify(s => s.OnStart(spanBase), Times.Once); }
public void GoSpanData_EndedSpan() { ISpan span = Span.StartSpan( spanContext, recordSpanOptions, SPAN_NAME, parentSpanId, false, TraceParams.Default, startEndHandler, timestampConverter); span.SetAttribute( "MySingleStringAttributeKey", AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); span.SetAttributes(attributes); interval = TimeSpan.FromMilliseconds(100); span.AddEvent(Event.Create(EVENT_DESCRIPTION)); interval = TimeSpan.FromMilliseconds(200); span.AddEvent(EVENT_DESCRIPTION, attributes); interval = TimeSpan.FromMilliseconds(300); ILink link = Link.FromSpanContext(spanContext, LinkType.ChildLinkedSpan); span.AddLink(link); interval = TimeSpan.FromMilliseconds(400); span.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); ISpanData spanData = ((Span)span).ToSpanData(); Assert.Equal(spanContext, spanData.Context); Assert.Equal(SPAN_NAME, spanData.Name); Assert.Equal(parentSpanId, spanData.ParentSpanId); Assert.False(spanData.HasRemoteParent); Assert.Equal(0, spanData.Attributes.DroppedAttributesCount); Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); Assert.Equal(0, spanData.Events.DroppedEventsCount); Assert.Equal(2, spanData.Events.Events.Count()); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), spanData.Events.Events.ToList()[0].Timestamp); Assert.Equal(Event.Create(EVENT_DESCRIPTION), spanData.Events.Events.ToList()[0].Event); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(200))), spanData.Events.Events.ToList()[1].Timestamp); Assert.Equal(Event.Create(EVENT_DESCRIPTION, attributes), spanData.Events.Events.ToList()[1].Event); Assert.Equal(0, spanData.Links.DroppedLinksCount); Assert.Single(spanData.Links.Links); Assert.Equal(link, spanData.Links.Links.First()); Assert.Equal(timestamp, spanData.StartTimestamp); Assert.Equal(Status.Cancelled, spanData.Status); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(400))), spanData.EndTimestamp); var startEndMock = Mock.Get <IStartEndHandler>(startEndHandler); var spanBase = span as SpanBase; startEndMock.Verify(s => s.OnStart(spanBase), Times.Once); startEndMock.Verify(s => s.OnEnd(spanBase), Times.Once); }
private static void DoWork(int i) { // 6. Get the global singleton Tracer object ITracer tracer = Tracing.Tracer; // 7. Start another span. If another span was already started, it'll use that span as the parent span. // In this example, the main method already started a span, so that'll be the parent span, and this will be // a child span. using (OpenTelemetry.Common.IScope scope = tracer.SpanBuilder("DoWork").StartScopedSpan()) { // Simulate some work. ISpan span = tracer.CurrentSpan; try { Console.WriteLine("Doing busy work"); Thread.Sleep(1000); } catch (ArgumentOutOfRangeException e) { // 6. Set status upon error span.Status = Status.Internal.WithDescription(e.ToString()); } // 7. Annotate our span to capture metadata about our operation var attributes = new Dictionary <string, IAttributeValue>(); attributes.Add("use", AttributeValue.StringAttributeValue("demo")); attributes.Add("hoge", AttributeValue.LongAttributeValue(256 * i)); span.AddEvent("Invoking DoWork", attributes); } }
public void ToSpanData_NoRecordEvents() { ISpan span = Span.StartSpan( spanContext, noRecordSpanOptions, SPAN_NAME, parentSpanId, false, TraceParams.Default, startEndHandler, timestampConverter); // Check that adding trace events after Span#End() does not throw any exception. span.SetAttributes(attributes); span.AddEvent(Event.Create(EVENT_DESCRIPTION)); span.AddEvent(EVENT_DESCRIPTION, attributes); span.AddLink(Link.FromSpanContext(spanContext, LinkType.ChildLinkedSpan)); span.End(); // exception.expect(IllegalStateException); Assert.Throws <InvalidOperationException>(() => ((Span)span).ToSpanData()); }
public void DroppingEvents() { int maxNumberOfEvents = 8; TraceParams traceParams = TraceParams.Default.ToBuilder().SetMaxNumberOfEvents(maxNumberOfEvents).Build(); ISpan span = Span.StartSpan( spanContext, recordSpanOptions, SPAN_NAME, SpanKind.Internal, parentSpanId, traceParams, startEndHandler, timestampConverter); IEvent testEvent = Event.Create(EVENT_DESCRIPTION); int i = 0; for (i = 0; i < 2 * maxNumberOfEvents; i++) { span.AddEvent(testEvent); interval += TimeSpan.FromMilliseconds(100); } SpanData spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfEvents, spanData.Events.DroppedEventsCount); Assert.Equal(maxNumberOfEvents, spanData.Events.Events.Count()); i = 0; foreach (var te in spanData.Events.Events) { Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100 * (maxNumberOfEvents + i)))), te.Timestamp); Assert.Equal(testEvent, te.Event); i++; } span.End(); spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfEvents, spanData.Events.DroppedEventsCount); Assert.Equal(maxNumberOfEvents, spanData.Events.Events.Count()); i = 0; foreach (var te in spanData.Events.Events) { Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100 * (maxNumberOfEvents + i)))), te.Timestamp); Assert.Equal(testEvent, te.Event); i++; } }
private async Task ProcessWebQueueMessageAsync(object sender, BasicDeliverEventArgs @event) { // ExtractActivity creates the Activity setting the parent based on the RabbitMQ "traceparent" header var activity = @event.ExtractActivity("Process single RabbitMQ message"); ISpan span = null; IOperationHolder <DependencyTelemetry> operation = null; var processingSucceeded = false; string source = string.Empty; IDisposable loggingScope = null; try { if (tracer != null) { // OpenTelemetry seems to require the Activity to have started, unlike AI SDK activity.Start(); tracer.StartActiveSpanFromActivity(activity.OperationName, activity, SpanKind.Consumer, out span); span.SetAttribute("queue", Constants.WebQueueName); } using (operation = telemetryClient?.StartOperation <DependencyTelemetry>(activity)) { if (operation != null) { operation.Telemetry.Properties.Add("queue", Constants.WebQueueName); operation.Telemetry.Type = ApplicationInformation.Name; operation.Telemetry.Target = this.rabbitMQHostName; } loggingScope = logger.BeginScope("Starting message processing"); // Get the payload var message = JsonSerializer.Deserialize <EnqueuedMessage>(@event.Body, jsonSerializerOptions); if (logger.IsEnabled(LogLevel.Information)) { logger.LogInformation("Processing message from {source}: {message}", message.Source, Encoding.UTF8.GetString(@event.Body)); } source = message.Source; if ("error".Equals(message.EventName, StringComparison.OrdinalIgnoreCase)) { throw new InvalidEventNameException("Invalid event name"); } var apiFullUrl = $"{timeApiURL}/api/time/dbtime"; var time = await httpClientFactory.CreateClient().GetStringAsync(apiFullUrl); if (!string.IsNullOrEmpty(message.EventName)) { span?.AddEvent(message.EventName); telemetryClient?.TrackEvent(message.EventName); } } processingSucceeded = true; } catch (Exception ex) { if (span != null) { span.SetAttribute("error", true); span.Status = Status.Internal.WithDescription(ex.ToString()); } if (operation != null) { operation.Telemetry.Success = false; operation.Telemetry.ResultCode = "500"; // Track exception, adding the connection to the current activity var exOperation = new ExceptionTelemetry(ex); exOperation.Context.Operation.Id = operation.Telemetry.Context.Operation.Id; exOperation.Context.Operation.ParentId = operation.Telemetry.Context.Operation.ParentId; telemetryClient.TrackException(exOperation); } logger.LogError(ex, "Failed to process message from {source}", source); } finally { span?.End(); metrics.TrackItemProcessed(1, source, processingSucceeded); loggingScope?.Dispose(); } }
private async Task ProcessWebQueueMessageAsync(object sender, BasicDeliverEventArgs @event) { //var correlationId = @event.BasicProperties.CorrelationId; TraceParent traceParent = null; if (@event.BasicProperties.Headers.TryGetValue(TraceParent.HeaderKey, out var rawTraceParent) && rawTraceParent is byte[] binRawTraceParent) { traceParent = TraceParent.CreateFromString(Encoding.UTF8.GetString(binRawTraceParent)); } ISpan span = null; IOperationHolder <RequestTelemetry> operation = null; try { if (traceParent == null) { throw new Exception("Trace information not found in message"); } if (tracer != null) { var traceId = ActivityTraceId.CreateFromString(traceParent.TraceId); var parentId = ActivitySpanId.CreateFromString(traceParent.SpanId); var parentContext = new SpanContext(traceId, parentId, ActivityTraceFlags.Recorded, isRemote: true); tracer.StartActiveSpan("Process single RabbitMQ message", parentContext, SpanKind.Consumer, out span); span.SetAttribute("queue", Constants.WebQueueName); } using (operation = telemetryClient?.StartOperation <RequestTelemetry>("Process single RabbitMQ message", traceParent.TraceId, traceParent.SpanId)) { if (operation != null) { operation.Telemetry.Properties.Add("queue", Constants.WebQueueName); } using (logger.BeginScope("processing message {correlationId}", traceParent.TraceId)) { var apiFullUrl = $"{apiUrl}/api/time/dbtime"; var time = await httpClientFactory.CreateClient().GetStringAsync(apiFullUrl); // Get the payload var message = JsonSerializer.Deserialize <EnqueuedMessage>(@event.Body, jsonSerializerOptions); if (!string.IsNullOrEmpty(message.EventName)) { span?.AddEvent(message.EventName); telemetryClient?.TrackEvent(message.EventName); } if (logger.IsEnabled(LogLevel.Debug)) { logger.LogDebug("Processed message: {message}", Encoding.UTF8.GetString(@event.Body)); } } } } catch (Exception ex) { if (span != null) { span.Status = Status.Internal.WithDescription(ex.ToString()); } if (operation != null) { operation.Telemetry.Success = false; telemetryClient.TrackException(ex); } } finally { span?.End(); } }