Skip to content

Commit

Permalink
Auto-infer destination.service.resource and adapt public API (#1520)
Browse files Browse the repository at this point in the history
* Update Destination.cs

* Remove usage of DestinationService.Name and Type

* Handle exit spans according to spec

- Introduces the concept of exit spans
- Calculate Span.Context.Destination.Service.Resource only for exit spans based on the spec
- Adapt all instrumentation to set the isExitSpan flag
- Remove usage of the obsolete fields Destination.Service.Name and Destination.Service.Type

* Update GrpcTests.cs

* Add IsExitSpan to ISpan and use it in HttpDiagnosticListenerImplBase

* Update ApiTests.cs

* Adapt SqlEventListener + Test to exit spans

* Update Span.cs

* Update ExecutionSegmentCommon.cs

* Adapt tests

* Update AzureFileShareStorageDiagnosticListener.cs

* Update Span.cs

* Update Span.cs

* Update Span.cs

* Update GrpcTests.cs
  • Loading branch information
gregkalapos authored Oct 20, 2021
1 parent 64c27a8 commit f2a2b9a
Show file tree
Hide file tree
Showing 33 changed files with 265 additions and 202 deletions.
2 changes: 1 addition & 1 deletion src/Elastic.Apm.Azure.CosmosDb/AzureCosmosDbTracer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public ISpan StartSpan(IApmAgent agent, string method, Uri requestUrl, Func<stri
? $"Cosmos DB {operationName}"
: "Cosmos DB";

var span = ExecutionSegmentCommon.StartSpanOnCurrentExecutionSegment(agent, spanName, ApiConstants.TypeDb, ApiConstants.SubTypeCosmosDb);
var span = ExecutionSegmentCommon.StartSpanOnCurrentExecutionSegment(agent, spanName, ApiConstants.TypeDb, ApiConstants.SubTypeCosmosDb, isExitSpan: true);

if (span != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,11 @@ private void OnReceiveStart(KeyValuePair<string, object> kv, string action)
}
else
{
var span = ApmAgent.GetCurrentExecutionSegment().StartSpan(transactionName, ApiConstants.TypeMessaging, ServiceBus.SubType, action);
var span = ApmAgent.GetCurrentExecutionSegment().StartSpan(transactionName, ApiConstants.TypeMessaging, ServiceBus.SubType, action, isExitSpan: true);

if (queueName != null)
span.Context.Message = new Message { Queue = new Queue { Name = queueName } };

segment = span;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace Elastic.Apm.Azure.ServiceBus
/// <summary>
/// Creates spans for diagnostic events from Microsoft.Azure.ServiceBus
/// </summary>
internal class MicrosoftAzureServiceBusDiagnosticListener: DiagnosticListenerBase
internal class MicrosoftAzureServiceBusDiagnosticListener : DiagnosticListenerBase
{
private readonly ApmAgent _realAgent;
private readonly ConcurrentDictionary<string, IExecutionSegment> _processingSegments = new ConcurrentDictionary<string, IExecutionSegment>();
Expand Down Expand Up @@ -105,7 +105,7 @@ private void OnProcessStart(KeyValuePair<string, object> kv, string action, Prop
return;
}

var queueName = cachedProperties.Fetch(kv.Value,"Entity") as string;
var queueName = cachedProperties.Fetch(kv.Value, "Entity") as string;
if (MatchesIgnoreMessageQueues(queueName))
return;

Expand All @@ -124,11 +124,12 @@ private void OnProcessStart(KeyValuePair<string, object> kv, string action, Prop

if (!_processingSegments.TryAdd(activityId, transaction))
{
Logger.Trace()?.Log(
"Could not add {Action} transaction {TransactionId} for activity {ActivityId} to tracked segments",
action,
transaction.Id,
activityId);
Logger.Trace()
?.Log(
"Could not add {Action} transaction {TransactionId} for activity {ActivityId} to tracked segments",
action,
transaction.Id,
activityId);
}
}

Expand All @@ -140,7 +141,7 @@ private void OnReceiveStart(KeyValuePair<string, object> kv, string action, Prop
return;
}

var queueName = cachedProperties.Fetch(kv.Value,"Entity") as string;
var queueName = cachedProperties.Fetch(kv.Value, "Entity") as string;
if (MatchesIgnoreMessageQueues(queueName))
return;

Expand All @@ -159,9 +160,12 @@ private void OnReceiveStart(KeyValuePair<string, object> kv, string action, Prop
}
else
{
var span = ApmAgent.GetCurrentExecutionSegment().StartSpan(transactionName, ApiConstants.TypeMessaging, ServiceBus.SubType, action);
var span = ApmAgent.GetCurrentExecutionSegment()
.StartSpan(transactionName, ApiConstants.TypeMessaging, ServiceBus.SubType, action, true);

if (queueName != null)
span.Context.Message = new Message { Queue = new Queue { Name = queueName } };

segment = span;
}

Expand All @@ -170,12 +174,13 @@ private void OnReceiveStart(KeyValuePair<string, object> kv, string action, Prop

if (!_processingSegments.TryAdd(activityId, segment))
{
Logger.Trace()?.Log(
"Could not add {Action} {SegmentName} {TransactionId} for activity {ActivityId} to tracked segments",
action,
segment is ITransaction ? "transaction" : "span",
segment.Id,
activityId);
Logger.Trace()
?.Log(
"Could not add {Action} {SegmentName} {TransactionId} for activity {ActivityId} to tracked segments",
action,
segment is ITransaction ? "transaction" : "span",
segment.Id,
activityId);
}
}

Expand All @@ -186,10 +191,11 @@ private bool MatchesIgnoreMessageQueues(string name)
var matcher = WildcardMatcher.AnyMatch(_realAgent.ConfigurationStore.CurrentSnapshot.IgnoreMessageQueues, name);
if (matcher != null)
{
Logger.Debug()?.Log(
"Not tracing message from {QueueName} because it matched IgnoreMessageQueues pattern {Matcher}",
name,
matcher.GetMatcher());
Logger.Debug()
?.Log(
"Not tracing message from {QueueName} because it matched IgnoreMessageQueues pattern {Matcher}",
name,
matcher.GetMatcher());
return true;
}
}
Expand All @@ -213,7 +219,7 @@ private void OnSendStart(KeyValuePair<string, object> kv, string action, Propert
}

var activity = Activity.Current;
var queueName = cachedProperties.Fetch(kv.Value,"Entity") as string;
var queueName = cachedProperties.Fetch(kv.Value, "Entity") as string;
var destinationAddress = cachedProperties.Fetch(kv.Value, "Endpoint") as Uri;

if (MatchesIgnoreMessageQueues(queueName))
Expand Down Expand Up @@ -241,11 +247,12 @@ private void OnSendStart(KeyValuePair<string, object> kv, string action, Propert

if (!_processingSegments.TryAdd(activity.Id, span))
{
Logger.Trace()?.Log(
"Could not add {Action} span {SpanId} for activity {ActivityId} to tracked segments",
action,
span.Id,
activity.Id);
Logger.Trace()
?.Log(
"Could not add {Action} span {SpanId} for activity {ActivityId} to tracked segments",
action,
span.Id,
activity.Id);
}
}

Expand All @@ -260,9 +267,10 @@ private void OnStop(KeyValuePair<string, object> kv, PropertyFetcherCollection c

if (!_processingSegments.TryRemove(activity.Id, out var segment))
{
Logger.Trace()?.Log(
"Could not find segment for activity {ActivityId} in tracked segments",
activity.Id);
Logger.Trace()
?.Log(
"Could not find segment for activity {ActivityId} in tracked segments",
activity.Id);
return;
}

Expand Down Expand Up @@ -290,9 +298,10 @@ private void OnException(KeyValuePair<string, object> kv)

if (!_processingSegments.TryRemove(activity.Id, out var segment))
{
Logger.Trace()?.Log(
"Could not find segment for activity {ActivityId} in tracked segments",
activity.Id);
Logger.Trace()
?.Log(
"Could not find segment for activity {ActivityId} in tracked segments",
activity.Id);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ private void OnStart(KeyValuePair<string, object> kv, string action)
? $"{AzureBlobStorage.SpanName} {action} {blobUrl.ResourceName}"
: $"{AzureBlobStorage.SpanName} {action}";

var span = currentSegment.StartSpan(spanName, ApiConstants.TypeStorage, AzureBlobStorage.SubType, action);
var span = currentSegment.StartSpan(spanName, ApiConstants.TypeStorage, AzureBlobStorage.SubType, action, true);
if (span is Span realSpan)
realSpan.InstrumentationFlag = InstrumentationFlag.Azure;

Expand All @@ -227,9 +227,7 @@ private static void SetDestination(ISpan span, BlobUrl blobUrl) =>
Address = blobUrl.FullyQualifiedNamespace,
Service = new Destination.DestinationService
{
Name = AzureBlobStorage.SubType,
Resource = $"{AzureBlobStorage.SubType}/{blobUrl.StorageAccountName}",
Type = ApiConstants.TypeStorage
Resource = $"{AzureBlobStorage.SubType}/{blobUrl.StorageAccountName}"
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ private void OnStart(KeyValuePair<string, object> kv, string action)
? $"{AzureFileStorage.SpanName} {action} {fileShareUrl.ResourceName}"
: $"{AzureFileStorage.SpanName} {action}";

var span = currentSegment.StartSpan(spanName, ApiConstants.TypeStorage, AzureFileStorage.SubType, action);
var span = currentSegment.StartSpan(spanName, ApiConstants.TypeStorage, AzureFileStorage.SubType, action, true);
if (span is Span realSpan)
realSpan.InstrumentationFlag = InstrumentationFlag.Azure;

Expand All @@ -125,12 +125,7 @@ private static void SetDestination(ISpan span, FileShareUrl fileShareUrl) =>
span.Context.Destination = new Destination
{
Address = fileShareUrl.FullyQualifiedNamespace,
Service = new Destination.DestinationService
{
Name = AzureFileStorage.SubType,
Resource = $"{AzureFileStorage.SubType}/{fileShareUrl.StorageAccountName}",
Type = ApiConstants.TypeStorage
}
Service = new Destination.DestinationService { Resource = $"{AzureFileStorage.SubType}/{fileShareUrl.StorageAccountName}" }
};

private void OnStop()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ private void OnSendStart(KeyValuePair<string, object> kv)
? $"{AzureQueueStorage.SpanName} SEND"
: $"{AzureQueueStorage.SpanName} SEND to {queueName}";

var span = currentSegment.StartSpan(spanName, ApiConstants.TypeMessaging, AzureQueueStorage.SubType, "send");
var span = currentSegment.StartSpan(spanName, ApiConstants.TypeMessaging, AzureQueueStorage.SubType, "send", true);
if (span is Span realSpan)
realSpan.InstrumentationFlag = InstrumentationFlag.Azure;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,14 @@ public ISpan StartSpan(IApmAgent agent, string method, Uri requestUrl, Func<stri

var name = $"{AzureBlobStorage.SpanName} {action} {blobUrl.ResourceName}";
var span = ExecutionSegmentCommon.StartSpanOnCurrentExecutionSegment(agent, name,
ApiConstants.TypeStorage, AzureBlobStorage.SubType, InstrumentationFlag.Azure, true);
ApiConstants.TypeStorage, AzureBlobStorage.SubType, InstrumentationFlag.Azure, true, true);
span.Action = action;
span.Context.Destination = new Destination
{
Address = blobUrl.FullyQualifiedNamespace,
Service = new Destination.DestinationService
{
Name = AzureBlobStorage.SubType,
Resource = $"{AzureBlobStorage.SubType}/{blobUrl.StorageAccountName}",
Type = ApiConstants.TypeStorage
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ internal bool TryStartElasticsearchSpan(string name, out Span span, Uri instance
.StartSpan(
name,
ApiConstants.TypeDb,
ApiConstants.SubtypeElasticsearch);
ApiConstants.SubtypeElasticsearch, isExitSpan: true);

span.InstrumentationFlag = InstrumentationFlag.Elasticsearch;
span.Action = name;
Expand Down
2 changes: 1 addition & 1 deletion src/Elastic.Apm.GrpcClient/GrpcClientDiagnosticListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ protected override void HandleOnNext(KeyValuePair<string, object> kv)
grpcMethodName = "unknown";

Logger.Trace()?.Log("Starting span for gRPC call, method:{methodName}", grpcMethodName);
var newSpan = currentTransaction.StartSpan(grpcMethodName, ApiConstants.TypeExternal, ApiConstants.SubTypeGrpc);
var newSpan = currentTransaction.StartSpan(grpcMethodName, ApiConstants.TypeExternal, ApiConstants.SubTypeGrpc, isExitSpan: true);
ProcessingRequests.TryAdd(requestObject, newSpan);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ private void HandleCommandStartEvent(CommandStartedEvent @event)
var span = currentExecutionSegment.StartSpan(
@event.CommandName,
ApiConstants.TypeDb,
"mongo");
"mongo", isExitSpan: true);

if (!_processingQueries.TryAdd(@event.RequestId, span))
{
Expand Down
3 changes: 1 addition & 2 deletions src/Elastic.Apm.MongoDb/LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,7 @@ Apache License
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.



==========
Elastic.Apm.MongoDb
----------
Expand Down
2 changes: 1 addition & 1 deletion src/Elastic.Apm.SqlClient/SqlEventListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ private void ProcessBeginExecute(IReadOnlyList<object> payload)
: database;

var span = ExecutionSegmentCommon.StartSpanOnCurrentExecutionSegment(_apmAgent, spanName, ApiConstants.TypeDb, ApiConstants.SubtypeMssql,
InstrumentationFlag.SqlClient);
InstrumentationFlag.SqlClient, isExitSpan: true);

if (span == null) return;

Expand Down
2 changes: 1 addition & 1 deletion src/Elastic.Apm.StackExchange.Redis/ElasticApmProfiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ private static void ProcessCommand(IProfiledCommand profiledCommand, IExecutionS

// TODO: clear the raw stacktrace as it won't be representative of the call stack at
// the point at which the call to redis happens, and therefore misleading to include
}, ApiConstants.SubTypeRedis, "query");
}, ApiConstants.SubTypeRedis, "query", true);
}

private static string GetCommand(IProfiledCommand profiledCommand) =>
Expand Down
3 changes: 3 additions & 0 deletions src/Elastic.Apm/Api/Destination.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using System;
using Elastic.Apm.Api.Constraints;

namespace Elastic.Apm.Api
Expand Down Expand Up @@ -72,6 +73,7 @@ public class DestinationService
/// Identifier for the destination service (e.g. 'http://elastic.co', 'elasticsearch', 'rabbitmq')"
/// </summary>
[MaxLength]
[Obsolete("This field will be removed in future versions")]
public string Name { get; set; }

/// <summary>
Expand All @@ -85,6 +87,7 @@ public class DestinationService
/// Type of the destination service (e.g. 'db', 'elasticsearch'). Should typically be the same as span.type.
/// </summary>
[MaxLength]
[Obsolete("This field will be removed in future versions")]
public string Type { get; set; }
}

Expand Down
Loading

0 comments on commit f2a2b9a

Please sign in to comment.