private void RabbitMqConsumer_Received(object sender, BasicDeliverEventArgs e) { // ExtractActivity creates the Activity setting the parent based on the RabbitMQ "traceparent" header var activity = e.ExtractActivity("Process single RabbitMQ message"); TelemetrySpan span = null; 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(Telemetry.Constants.RoutingKeyTagName, e.RoutingKey); } try { string message = DeserializeMessage(e.Body, e.RoutingKey); string fullTypeName = e.BasicProperties.GetCustomProperty <string>(TypeNameHeader); OnMessagedReceived(new MessageReceivedEventArgs(message, fullTypeName)); } catch (Exception ex) { logger.LogError(ex, "Unable to proccess message. Routing key: {RoutingKey}", e.RoutingKey); } finally { span?.End(); } }
public static void ApplyContext(this TelemetrySpan span, ReadOnlySettings settings, IReadOnlyDictionary <string, string> contextHeaders) { var transportDefinition = settings.Get <TransportDefinition>(); span.SetAttribute("messaging.system", transportDefinition.GetType().Name.Replace("Transport", null).ToLowerInvariant()); span.SetAttribute("messaging.destination", settings.LogicalAddress().ToString()); if (contextHeaders.TryGetValue(Headers.ConversationId, out var conversationId)) { span.SetAttribute("messaging.conversation_id", conversationId); } if (contextHeaders.TryGetValue(Headers.MessageIntent, out var intent) && Enum.TryParse <MessageIntentEnum>(intent, out var intentValue)) { var routingPolicy = settings.Get <TransportInfrastructure>().OutboundRoutingPolicy; var kind = GetDestinationKind(intentValue, routingPolicy); if (kind != null) { span.SetAttribute("messaging.destination_kind", kind); } } foreach (var header in contextHeaders.Where(header => header.Key.StartsWith("NServiceBus."))) { span.SetAttribute($"messaging.{header.Key.ToLowerInvariant()}", header.Value); } }
protected internal void InjectTraceContext(HttpWebRequest message, TelemetrySpan parentSpan) { // Expects the currentspan to be the span to inject into var headers = message.Headers; TextFormat.Inject(Tracer.CurrentSpan.Context, headers, (c, k, v) => { if (k == B3Constants.XB3TraceId && v.Length > 16 && Options.UseShortTraceIds) { v = v.Substring(v.Length - 16, 16); } if (c.Get(k) != null) { c.Remove(k); } c.Add(k, v); }); if (parentSpan != null) { headers.Add(B3Constants.XB3ParentSpanId, parentSpan.Context.SpanId.ToHexString()); } }
public LoggingScope(TelemetrySpan span, bool endSpan = true) { this.span = span; this.endSpan = endSpan; this.origContext = CurrentSpanUtils.asyncLocalContext.Value; CurrentSpanUtils.asyncLocalContext.Value = span; }
private static void PutHeadersAttribute(TelemetrySpan span, string key, List <KeyValuePair <string, IEnumerable <string> > > headers) { foreach (var header in headers) { span.SetAttribute(key + header.Key, string.Join(",", header.Value)); } }
public static void DrainSession(Tracer tracer, TelemetrySpan parentSpan, IEnumerable <IProfiledCommand> sessionCommands) { foreach (var command in sessionCommands) { ProfilerCommandToSpan(tracer, parentSpan, command); } }
/// <inheritdoc /> public override TelemetrySpan StartSpan(string operationName, TelemetrySpan parent, SpanKind kind, SpanCreationOptions options) { Logger.Log( $"{prefix}.StartSpan({operationName}, {parent.GetType().Name}, {kind}, {options.StartTimestamp:o}, {options.LinksFactory}, {options.Links})"); return(new LoggingSpan(operationName, kind)); }
public LoggingScope(TelemetrySpan span, bool endSpan = true) { this.span = span; this.endSpan = endSpan; origContext = AsyncLocalContext.Value; AsyncLocalContext.Value = span; }
/// <inheritdoc/> public ISpan Start() { TelemetrySpan span = null; SpanCreationOptions options = null; if (this.explicitStartTime != null || this.links != null) { options = new SpanCreationOptions { StartTimestamp = this.explicitStartTime ?? default, Links = this.links, }; } // If specified, this takes precedence. if (this.ignoreActiveSpan) { span = this.tracer.StartRootSpan(this.spanName, this.spanKind, options); } else if (this.parentSpan != null) { span = this.tracer.StartSpan(this.spanName, this.parentSpan, this.spanKind, options); } else if (this.parentSpanContext.IsValid) { span = this.tracer.StartSpan(this.spanName, this.parentSpanContext, this.spanKind, options); } else if (this.parentSpan == null && !this.parentSpanContext.IsValid && (this.tracer.CurrentSpan == null || !this.tracer.CurrentSpan.Context.IsValid)) { // We need to know if we should inherit an existing Activity-based context or start a new one. if (System.Diagnostics.Activity.Current != null && System.Diagnostics.Activity.Current.IdFormat == System.Diagnostics.ActivityIdFormat.W3C) { var currentActivity = System.Diagnostics.Activity.Current; if (this.rootOperationNamesForActivityBasedAutoAdapters.Contains(currentActivity.OperationName)) { this.tracer.StartSpanFromActivity(this.spanName, currentActivity, this.spanKind, this.links); span = this.tracer.CurrentSpan; } } } if (span == null) { span = this.tracer.StartSpan(this.spanName, null, this.spanKind, options); } foreach (var kvp in this.attributes) { span.SetAttribute(kvp.Key, kvp.Value); } if (this.error) { span.Status = Trace.Status.Unknown; } return(new SpanShim(span)); }
public void ParentIds() { using var parentActivity = new Activity("parentOperation"); parentActivity.Start(); // can't generate the Id until the operation is started using var parentSpan = new TelemetrySpan(parentActivity); // ParentId should be unset Assert.Equal(default, parentSpan.ParentSpanId);
private static void PutHeadersAttribute(TelemetrySpan span, string key, NameValueCollection headers) { foreach (var header in headers.AllKeys) { var val = string.Join(",", headers.GetValues(header)); span.SetAttribute(key + header, val); } }
/// <inheritdoc/> public ISpan Start() { TelemetrySpan span = null; // If specified, this takes precedence. if (this.ignoreActiveSpan) { span = this.tracer.StartRootSpan(this.spanName, this.spanKind, default, this.links, this.explicitStartTime ?? default);
/// <summary> /// Helper method that populates span properties from http status code according /// to https://github.com/open-telemetry/opentelemetry-specification/blob/2316771e7e0ca3bfe9b2286d13e3a41ded6b8858/specification/data-http.md. /// </summary> /// <param name="span">Span to fill out.</param> /// <param name="statusCode">Http status code.</param> /// <param name="reasonPhrase">Http reason phrase.</param> /// <returns>Span with populated properties.</returns> public static TelemetrySpan PutHttpStatusCode(this TelemetrySpan span, int statusCode, string reasonPhrase) { span.PutHttpStatusCodeAttribute(statusCode); span.Status = SpanHelper.ResolveSpanStatusForHttpStatusCode(statusCode).WithDescription(reasonPhrase); return(span); }
/// <summary> /// Helper method that populates span properties from route /// to https://github.com/open-telemetry/opentelemetry-specification/blob/2316771e7e0ca3bfe9b2286d13e3a41ded6b8858/specification/data-http.md. /// </summary> /// <param name="span">Span to fill out.</param> /// <param name="route">Route used to resolve url to controller.</param> /// <returns>Span with populated route properties.</returns> public static TelemetrySpan PutHttpRouteAttribute(this TelemetrySpan span, string route) { if (!string.IsNullOrEmpty(route)) { span.SetAttribute(SpanAttributeConstants.HttpRouteKey, route); } return(span); }
/// <summary> /// Helper method that populates span properties from host and port /// to https://github.com/open-telemetry/opentelemetry-specification/blob/2316771e7e0ca3bfe9b2286d13e3a41ded6b8858/specification/data-http.md. /// </summary> /// <param name="span">Span to fill out.</param> /// <param name="rawUrl">Raw url.</param> /// <returns>Span with populated url properties.</returns> public static TelemetrySpan PutHttpRawUrlAttribute(this TelemetrySpan span, string rawUrl) { if (!string.IsNullOrEmpty(rawUrl)) { span.SetAttribute(SpanAttributeConstants.HttpUrlKey, rawUrl); } return(span); }
/// <summary> /// Helper method that populates span properties from http user agent according /// to https://github.com/open-telemetry/opentelemetry-specification/blob/2316771e7e0ca3bfe9b2286d13e3a41ded6b8858/specification/data-http.md. /// </summary> /// <param name="span">Span to fill out.</param> /// <param name="userAgent">Http status code.</param> /// <returns>Span with populated user agent code properties.</returns> public static TelemetrySpan PutHttpUserAgentAttribute(this TelemetrySpan span, string userAgent) { if (!string.IsNullOrWhiteSpace(userAgent)) { span.SetAttribute(SpanAttributeConstants.HttpUserAgentKey, userAgent); } return(span); }
/// <summary> /// Helper method that populates span properties from host and port /// to https://github.com/open-telemetry/opentelemetry-specification/blob/2316771e7e0ca3bfe9b2286d13e3a41ded6b8858/specification/data-http.md. /// </summary> /// <param name="span">Span to fill out.</param> /// <param name="hostAndPort">Host and port value.</param> /// <returns>Span with populated host properties.</returns> public static TelemetrySpan PutHttpHostAttribute(this TelemetrySpan span, string hostAndPort) { if (!string.IsNullOrEmpty(hostAndPort)) { span.SetAttribute(SpanAttributeConstants.HttpHostKey, hostAndPort); } return(span); }
public void CheckRecordExceptionEmpty() { using Activity activity = new Activity("exception-test"); using TelemetrySpan telemetrySpan = new TelemetrySpan(activity); telemetrySpan.RecordException(string.Empty, string.Empty, string.Empty); Assert.Empty(activity.Events); telemetrySpan.RecordException(null); Assert.Empty(activity.Events); }
/// <summary> /// Helper method that populates span properties from http status code according /// to https://github.com/open-telemetry/opentelemetry-specification/blob/2316771e7e0ca3bfe9b2286d13e3a41ded6b8858/specification/data-http.md. /// </summary> /// <param name="span">Span to fill out.</param> /// <param name="statusCode">Http status code.</param> /// <param name="reasonPhrase">Http reason phrase.</param> /// <returns>Span with populated properties.</returns> public static TelemetrySpan PutHttpStatusCode(this TelemetrySpan span, int statusCode, string reasonPhrase) { span.PutHttpStatusCodeAttribute(statusCode); var newStatus = Status.Ok; if ((int)statusCode < 200) { newStatus = Status.Unknown; } else if ((int)statusCode >= 200 && (int)statusCode <= 399) { newStatus = Status.Ok; } else if ((int)statusCode == 400) { newStatus = Status.InvalidArgument; } else if ((int)statusCode == 401) { newStatus = Status.Unauthenticated; } else if ((int)statusCode == 403) { newStatus = Status.PermissionDenied; } else if ((int)statusCode == 404) { newStatus = Status.NotFound; } else if ((int)statusCode == 429) { newStatus = Status.ResourceExhausted; } else if ((int)statusCode == 501) { newStatus = Status.Unimplemented; } else if ((int)statusCode == 503) { newStatus = Status.Unavailable; } else if ((int)statusCode == 504) { newStatus = Status.DeadlineExceeded; } else { newStatus = Status.Unknown; } span.Status = newStatus.WithDescription(reasonPhrase); return(span); }
public SpanShim(TelemetrySpan span) { this.Span = span ?? throw new ArgumentNullException(nameof(span), "Parameter cannot be null"); if (!this.Span.Context.IsValid) { throw new ArgumentException("Passed span's context is not valid", nameof(this.Span.Context)); } this.spanContextShim = new SpanContextShim(this.Span.Context); }
public SpanShim(TelemetrySpan span) { Guard.Null(span, nameof(span)); if (!span.Context.IsValid) { throw new ArgumentException($"Invalid '{nameof(SpanContext)}'", nameof(span.Context)); } this.Span = span; this.spanContextShim = new SpanContextShim(this.Span.Context); }
public SpanShim(TelemetrySpan span) { this.Span = span ?? throw new ArgumentNullException(nameof(span)); if (!this.Span.Context.IsValid) { throw new ArgumentException(nameof(this.Span.Context)); } this.spanContextShim = new SpanContextShim(this.Span.Context); }
internal static object Run() { var zpagesOptions = new ZPagesExporterOptions() { Url = "http://localhost:7284/rpcz/" }; var zpagesExporter = new ZPagesExporter(zpagesOptions); var spanProcessor = new ZPagesSpanProcessor(zpagesExporter); ZPagesSpans.RetentionTime = 3600000; var httpServer = new ZPagesExporterStatsHttpServer(zpagesExporter, spanProcessor); // Start the server httpServer.Start(); // Configure exporter using (var tracerFactory = TracerFactory.Create(builder => builder .AddProcessorPipeline(b => b .SetExporter(zpagesExporter) .SetExportingProcessor(e => spanProcessor)))) { var tracer = tracerFactory.GetTracer("zpages-test"); while (true) { // Create a scoped span. TelemetrySpan telemetrySpan = tracer.StartSpan("Main"); telemetrySpan.Status = Status.Unavailable; using (tracer.WithSpan(telemetrySpan)) { Console.WriteLine("Starting Span"); } Thread.Sleep(3000); telemetrySpan.End(); // Create a scoped span. TelemetrySpan telemetrySpan2 = tracer.StartSpan("TestSpan"); telemetrySpan2.Status = Status.Ok; using (tracer.WithSpan(telemetrySpan2)) { Console.WriteLine("Starting Span2"); } Thread.Sleep(5000); telemetrySpan2.End(); } } }
/// <inheritdoc /> public IKafkaMessage <TKey, TValue> Consume(CancellationToken cancellationToken = default) { TelemetrySpan span = null; Activity consumingActivity = null; try { var consumeResult = _consumer.Consume(cancellationToken); consumingActivity = new Activity(Constants.ConsumeActivityName); consumingActivity.Start(); var kafkaMessage = (KafkaMessage <TKey, TValue>)consumeResult; if (kafkaMessage.Headers?.Any() ?? false) { kafkaMessage.Headers.TryGetValue(AbstractionConstants.CorrelationIdHeaderName, out var parentActivityId); if (!string.IsNullOrEmpty(parentActivityId)) { consumingActivity.SetParentId(parentActivityId); } foreach (var baggageItem in kafkaMessage.Headers) { if (baggageItem.Key != AbstractionConstants.CorrelationIdHeaderName) { consumingActivity.AddBaggage(baggageItem.Key, baggageItem.Value); } } } span = _tracer?.StartSpanFromActivity(Constants.SpanConsumeOperationNamePrefix, consumingActivity, SpanKind.Consumer); _logger.LogDebug("Consumed message 'key {key} ' at: '{partitionOffset}'.", consumeResult.Key, consumeResult.TopicPartitionOffset); return(kafkaMessage); } catch (ConsumeException e) { _logger.LogError(e, "ConsumeException occurred: {reason}", e.Error.Reason); throw; } catch (KafkaException e) { _logger.LogError(e, "KafkaException occurred: {reason}", e.Error.Reason); throw; } finally { consumingActivity?.Stop(); span?.End(); } }
/// <summary> /// Helper method that populates span properties from host and port /// to https://github.com/open-telemetry/opentelemetry-specification/blob/2316771e7e0ca3bfe9b2286d13e3a41ded6b8858/specification/data-http.md. /// </summary> /// <param name="span">Span to fill out.</param> /// <param name="hostName">Hostr name.</param> /// <param name="port">Port number.</param> /// <returns>Span with populated host properties.</returns> public static TelemetrySpan PutHttpHostAttribute(this TelemetrySpan span, string hostName, int port) { if (port == 80 || port == 443) { span.SetAttribute(SpanAttributeConstants.HttpHostKey, hostName); } else { span.SetAttribute(SpanAttributeConstants.HttpHostKey, hostName + ":" + port); } return(span); }
public void CheckRecordExceptionData() { string message = "message"; using Activity activity = new Activity("exception-test"); using TelemetrySpan telemetrySpan = new TelemetrySpan(activity); telemetrySpan.RecordException(new ArgumentNullException(message, new Exception("new-exception"))); Assert.Single(activity.Events); var @event = telemetrySpan.Activity.Events.FirstOrDefault(q => q.Name == SemanticConventions.AttributeExceptionEventName); Assert.Equal(message, @event.Tags.FirstOrDefault(t => t.Key == SemanticConventions.AttributeExceptionMessage).Value); Assert.Equal(typeof(ArgumentNullException).Name, @event.Tags.FirstOrDefault(t => t.Key == SemanticConventions.AttributeExceptionType).Value); }
/// <inheritdoc/> public ISpan Start() { TelemetrySpan span = null; // If specified, this takes precedence. if (this.ignoreActiveSpan) { span = this.tracer.StartSpan(this.spanName, this.spanKind, default(SpanContext), null, this.links, this.explicitStartTime ?? default); } else if (this.parentSpan != null) { span = this.tracer.StartSpan(this.spanName, this.spanKind, this.parentSpan, null, this.links, this.explicitStartTime ?? default); } else if (this.parentSpanContext.IsValid) { span = this.tracer.StartSpan(this.spanName, this.spanKind, this.parentSpanContext, null, this.links, this.explicitStartTime ?? default); } else if (this.parentSpan == null && !this.parentSpanContext.IsValid && (this.tracer.CurrentSpan == null || !this.tracer.CurrentSpan.Context.IsValid)) { // TODO: We need to know if we should inherit an existing Activity-based context or start a new one. /* * if (System.Diagnostics.Activity.Current != null && System.Diagnostics.Activity.Current.IdFormat == System.Diagnostics.ActivityIdFormat.W3C) * { * var currentActivity = System.Diagnostics.Activity.Current; * if (this.rootOperationNamesForActivityBasedAutoInstrumentations.Contains(currentActivity.OperationName)) * { * this.tracer.StartSpanFromActivity(this.spanName, currentActivity, this.spanKind, this.links); * span = this.tracer.CurrentSpan; * } * }*/ } if (span == null) { span = this.tracer.StartSpan(this.spanName, this.spanKind, default(SpanContext), null, null, this.explicitStartTime ?? default); } foreach (var kvp in this.attributes) { span.SetAttribute(kvp.Key, kvp.Value.ToString()); } if (this.error) { span.Status = Trace.Status.Unknown; } return(new SpanShim(span)); }
/// <inheritdoc/> public ISpanBuilder AsChildOf(ISpan parent) { if (parent == null) { return(this); } if (!this.ParentSet) { this.parentSpan = GetOpenTelemetrySpan(parent); return(this); } return(this.AsChildOf(parent.Context)); }
public async Task Map(string supplier, Tracer tracer, TelemetrySpan parentSpan, CancellationToken cancellationToken) { using var localityMappingSpan = tracer.StartActiveSpan("Map Localities", SpanKind.Internal, parentSpan); _logger.LogMappingLocalitiesStart(supplier); var countries = await _locationMapperDataRetrieveService.GetCountries(cancellationToken); foreach (var country in countries) { await MapCountryLocalities(supplier, country.Id, country.Code, country.Name, localityMappingSpan, cancellationToken); } _logger.LogMappingLocalitiesFinish(supplier); }
public void CheckRecordExceptionData2() { string type = "ArgumentNullException"; string message = "message"; string stack = "stack"; using Activity activity = new Activity("exception-test"); using TelemetrySpan telemetrySpan = new TelemetrySpan(activity); telemetrySpan.RecordException(type, message, stack); Assert.Single(activity.Events); var @event = telemetrySpan.Activity.Events.FirstOrDefault(q => q.Name == SemanticConventions.AttributeExceptionEventName); Assert.Equal(message, @event.Tags.FirstOrDefault(t => t.Key == SemanticConventions.AttributeExceptionMessage).Value); Assert.Equal(type, @event.Tags.FirstOrDefault(t => t.Key == SemanticConventions.AttributeExceptionType).Value); Assert.Equal(stack, @event.Tags.FirstOrDefault(t => t.Key == SemanticConventions.AttributeExceptionStacktrace).Value); }