internal static Scope CreateProducerScope(Tracer tracer, ITopicPartition topicPartition, bool isTombstone, bool finishOnClose) { Scope scope = null; try { var settings = tracer.Settings; if (!settings.IsIntegrationEnabled(KafkaConstants.IntegrationId)) { // integration disabled, don't create a scope/span, skip this trace return(null); } var parent = tracer.ActiveScope?.Span; if (parent is not null && parent.OperationName == KafkaConstants.ProduceOperationName && parent.GetTag(Tags.InstrumentationName) != null) { return(null); } string serviceName = settings.GetServiceName(tracer, KafkaConstants.ServiceName); var tags = new KafkaTags(SpanKinds.Producer); scope = tracer.StartActiveInternal( KafkaConstants.ProduceOperationName, tags: tags, serviceName: serviceName, finishOnClose: finishOnClose); string resourceName = $"Produce Topic {(string.IsNullOrEmpty(topicPartition?.Topic) ? "kafka" : topicPartition?.Topic)}"; var span = scope.Span; span.Type = SpanTypes.Queue; span.ResourceName = resourceName; if (topicPartition?.Partition is not null && !topicPartition.Partition.IsSpecial) { tags.Partition = (topicPartition?.Partition).ToString(); } if (isTombstone) { tags.Tombstone = "true"; } // Producer spans should always be measured span.SetTag(Tags.Measured, "1"); tags.SetAnalyticsSampleRate(KafkaConstants.IntegrationId, settings, enabledWithGlobalSetting: false); tracer.TracerManager.Telemetry.IntegrationGeneratedSpan(KafkaConstants.IntegrationId); } catch (Exception ex) { Log.Error(ex, "Error creating or populating scope."); } return(scope); }
internal static ISpan CreateProducerSpan(IApmAgent agent, ITopicPartition topicPartition, bool isTombstone, bool finishOnClose) { ISpan span = null; try { // no current transaction, don't create a span var currentTransaction = agent.Tracer.CurrentTransaction; if (currentTransaction is null) { return(span); } var topic = topicPartition?.Topic; var matcher = WildcardMatcher.AnyMatch(currentTransaction.Configuration.IgnoreMessageQueues, topic); if (matcher != null) { agent.Logger.Trace() ?.Log( "Not tracing message from {Queue} because it matched IgnoreMessageQueues pattern {Matcher}", topic, matcher.GetMatcher()); return(span); } var spanName = string.IsNullOrEmpty(topic) ? "Kafka SEND" : $"Kafka SEND to {topic}"; span = agent.GetCurrentExecutionSegment().StartSpan( spanName, ApiConstants.TypeMessaging, Subtype, isExitSpan: true); if (!string.IsNullOrEmpty(topic)) { span.Context.Message = new Message { Queue = new Queue { Name = topic } } } ; if (topicPartition?.Partition is not null && !topicPartition.Partition.IsSpecial) { span.SetLabel("partition", topicPartition.Partition.ToString()); } if (isTombstone) { span.SetLabel("tombstone", "true"); } } catch (Exception ex) { agent.Logger.Error()?.LogException(ex, "Error creating or populating kafka span."); } return(span); }