Skip to content

Commit 69ce526

Browse files
authored
OTel bridge enhancements (#2172)
* Optimise logic for `InferTransactionType` * Simplify dictionary set-up * Optimise access to attributes via Activity.TagObjects * Update tests to latest client version * Remove `ElasticSearchHttpNonTracer`
1 parent cdfc57e commit 69ce526

File tree

4 files changed

+94
-126
lines changed

4 files changed

+94
-126
lines changed

src/Elastic.Apm/OpenTelemetry/ElasticActivityListener.cs

Lines changed: 28 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ namespace Elastic.Apm.OpenTelemetry
2222
{
2323
public class ElasticActivityListener : IDisposable
2424
{
25-
private static readonly string[] ServerPortAttributeKeys = { SemanticConventions.ServerPort, SemanticConventions.NetPeerPort };
26-
private static readonly string[] ServerAddressAttributeKeys = { SemanticConventions.ServerAddress, SemanticConventions.NetPeerName, SemanticConventions.NetPeerIp };
25+
private static readonly string[] ServerPortAttributeKeys = new[] { SemanticConventions.ServerPort, SemanticConventions.NetPeerPort };
26+
private static readonly string[] ServerAddressAttributeKeys = new[] { SemanticConventions.ServerAddress, SemanticConventions.NetPeerName, SemanticConventions.NetPeerIp };
27+
private static readonly string[] HttpAttributeKeys = new[] { SemanticConventions.UrlFull, SemanticConventions.HttpUrl, SemanticConventions.HttpScheme };
28+
private static readonly string[] HttpUrlAttributeKeys = new[] { SemanticConventions.UrlFull, SemanticConventions.HttpUrl };
2729

2830
private readonly ConditionalWeakTable<Activity, Span> _activeSpans = new();
2931
private readonly ConditionalWeakTable<Activity, Transaction> _activeTransactions = new();
@@ -39,17 +41,16 @@ internal ElasticActivityListener(IApmAgent agent, HttpTraceConfiguration httpTra
3941

4042
internal void Start(Tracer tracerInternal)
4143
{
42-
_httpTraceConfiguration?.AddTracer(new ElasticSearchHttpNonTracer());
4344
_tracer = tracerInternal;
4445

45-
4646
Listener = new ActivityListener
4747
{
4848
ActivityStarted = ActivityStarted,
4949
ActivityStopped = ActivityStopped,
5050
ShouldListenTo = _ => true,
5151
Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllData
5252
};
53+
5354
ActivitySource.AddActivityListener(Listener);
5455
}
5556

@@ -73,7 +74,6 @@ internal void Start(Tracer tracerInternal)
7374
var timestamp = TimeUtils.ToTimestamp(activity.StartTimeUtc);
7475
if (!CreateTransactionForActivity(activity, timestamp, spanLinks))
7576
CreateSpanForActivity(activity, timestamp, spanLinks);
76-
7777
};
7878

7979
private bool CreateTransactionForActivity(Activity activity, long timestamp, List<SpanLink> spanLinks)
@@ -153,11 +153,8 @@ private void CreateSpanForActivity(Activity activity, long timestamp, List<SpanL
153153
_activeTransactions.Remove(activity);
154154
transaction.Duration = activity.Duration.TotalMilliseconds;
155155

156-
if (activity.TagObjects.Any())
157-
transaction.Otel.Attributes = new Dictionary<string, object>();
158-
159-
foreach (var tag in activity.TagObjects)
160-
transaction.Otel.Attributes.Add(tag.Key, tag.Value);
156+
if (activity.TagObjects.Any())
157+
transaction.Otel.Attributes = new Dictionary<string, object>(activity.TagObjects);
161158

162159
InferTransactionType(transaction, activity);
163160

@@ -192,10 +189,7 @@ private static void UpdateSpan(Activity activity, Span span)
192189
span.Duration = activity.Duration.TotalMilliseconds;
193190

194191
if (activity.TagObjects.Any())
195-
span.Otel.Attributes = new Dictionary<string, object>();
196-
197-
foreach (var tag in activity.TagObjects)
198-
span.Otel.Attributes.Add(tag.Key, tag.Value);
192+
span.Otel.Attributes = new Dictionary<string, object>(activity.TagObjects);
199193

200194
InferSpanTypeAndSubType(span, activity);
201195

@@ -218,17 +212,17 @@ private static void UpdateSpan(Activity activity, Span span)
218212
span.End();
219213
}
220214

215+
/// <summary>
216+
/// Specifically exposed for benchmarking. This is not intended for any other purpose.
217+
/// </summary>
221218
internal static void UpdateSpanBenchmark(Activity activity, Span span) => UpdateSpan(activity, span);
222219

223220
private static void InferTransactionType(Transaction transaction, Activity activity)
224221
{
225-
var isRpc = activity.Tags.Any(n => n.Key == SemanticConventions.RpcSystem);
226-
var isHttp = activity.Tags.Any(n => n.Key == SemanticConventions.HttpUrl || n.Key == SemanticConventions.UrlFull || n.Key == SemanticConventions.HttpScheme);
227-
var isMessaging = activity.Tags.Any(n => n.Key == SemanticConventions.MessagingSystem);
228-
229-
if (activity.Kind == ActivityKind.Server && (isRpc || isHttp))
222+
if (activity.Kind == ActivityKind.Server && (TryGetStringValue(activity, SemanticConventions.RpcSystem, out _)
223+
|| TryGetStringValue(activity, HttpAttributeKeys, out _)))
230224
transaction.Type = ApiConstants.TypeRequest;
231-
else if (activity.Kind == ActivityKind.Consumer && isMessaging)
225+
else if (activity.Kind == ActivityKind.Consumer && TryGetStringValue(activity, SemanticConventions.MessagingSystem, out _))
232226
transaction.Type = ApiConstants.TypeMessaging;
233227
else
234228
transaction.Type = "unknown";
@@ -284,51 +278,45 @@ static string ToResourceName(string type, string name)
284278
string serviceTargetName = null;
285279
string resource = null;
286280

287-
var isDbSpan = TryGetStringValue(activity, SemanticConventions.DbSystem, out var dbSystem);
288-
289-
if (isDbSpan)
281+
if (TryGetStringValue(activity, SemanticConventions.DbSystem, out var dbSystem))
290282
{
291283
span.Type = ApiConstants.TypeDb;
292284
span.Subtype = dbSystem;
293285
serviceTargetType = span.Subtype;
294286
serviceTargetName = TryGetStringValue(activity, SemanticConventions.DbName, out var dbName) ? dbName : null;
295287
resource = ToResourceName(span.Subtype, serviceTargetName);
296288
}
297-
else if (activity.Tags.Any(n => n.Key == SemanticConventions.MessagingSystem))
289+
else if (TryGetStringValue(activity, SemanticConventions.MessagingSystem, out var messagingSystem))
298290
{
299291
span.Type = ApiConstants.TypeMessaging;
300-
span.Subtype = activity.Tags.First(n => n.Key == SemanticConventions.MessagingSystem).Value;
292+
span.Subtype = messagingSystem;
301293
serviceTargetType = span.Subtype;
302-
serviceTargetName = activity.Tags.FirstOrDefault(n => n.Key == SemanticConventions.MessagingDestination).Value;
294+
serviceTargetName = TryGetStringValue(activity, SemanticConventions.MessagingDestination, out var messagingDestination) ? messagingDestination : null;
303295
resource = ToResourceName(span.Subtype, serviceTargetName);
304296
}
305-
else if (activity.Tags.Any(n => n.Key == SemanticConventions.RpcSystem))
297+
else if (TryGetStringValue(activity, SemanticConventions.RpcSystem, out var rpcSystem))
306298
{
307299
span.Type = ApiConstants.TypeExternal;
308-
span.Subtype = activity.Tags.First(n => n.Key == SemanticConventions.RpcSystem).Value;
300+
span.Subtype = rpcSystem;
309301
serviceTargetType = span.Subtype;
310302
serviceTargetName = !string.IsNullOrEmpty(netName)
311303
? netName
312-
: activity.Tags.FirstOrDefault(n => n.Key == SemanticConventions.RpcService).Value;
304+
: TryGetStringValue(activity, SemanticConventions.RpcService, out var rpcService) ? rpcService : null;
313305
resource = serviceTargetName ?? span.Subtype;
314306
}
315-
else if (activity.Tags.Any(n => n.Key == SemanticConventions.HttpUrl || n.Key == SemanticConventions.UrlFull || n.Key == SemanticConventions.HttpScheme))
307+
else if (activity.TagObjects.Any(n => n.Key == SemanticConventions.HttpUrl || n.Key == SemanticConventions.UrlFull || n.Key == SemanticConventions.HttpScheme))
316308
{
309+
var hasHttpHost = TryGetStringValue(activity, SemanticConventions.HttpHost, out var httpHost);
310+
var hasHttpScheme = TryGetStringValue(activity, SemanticConventions.HttpScheme, out var httpScheme);
317311
span.Type = ApiConstants.TypeExternal;
318312
span.Subtype = ApiConstants.SubtypeHttp;
319313
serviceTargetType = span.Subtype;
320-
if (activity.Tags.Any(n => n.Key == SemanticConventions.HttpHost) && activity.Tags.Any(n => n.Key == SemanticConventions.HttpScheme))
321-
{
322-
serviceTargetName = activity.Tags.FirstOrDefault(n => n.Key == SemanticConventions.HttpHost).Value + ":"
323-
+ HttpPortFromScheme(activity.Tags.FirstOrDefault(n => n.Key == SemanticConventions.HttpScheme).Value);
324-
}
325-
else if (activity.Tags.Any(n => n.Key == SemanticConventions.HttpUrl))
326-
serviceTargetName = ParseNetName(activity.Tags.FirstOrDefault(n => n.Key == SemanticConventions.HttpUrl).Value);
327-
else if (activity.Tags.Any(n => n.Key == SemanticConventions.UrlFull))
328-
serviceTargetName = ParseNetName(activity.Tags.FirstOrDefault(n => n.Key == SemanticConventions.UrlFull).Value);
314+
if (hasHttpHost && hasHttpScheme)
315+
serviceTargetName = $"{httpHost}:{HttpPortFromScheme(httpScheme)}";
316+
else if (TryGetStringValue(activity, HttpUrlAttributeKeys, out var httpUrl))
317+
serviceTargetName = ParseNetName(httpUrl);
329318
else
330319
serviceTargetName = netName;
331-
332320
resource = serviceTargetName;
333321
}
334322

src/Elastic.Apm/OpenTelemetry/ElasticSearchHttpNonTracer.cs

Lines changed: 0 additions & 34 deletions
This file was deleted.

test/instrumentations/Elastic.Clients.Elasticsearch.Tests/Elastic.Clients.Elasticsearch.Tests.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="8.0.1" />
10+
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="8.9.2" />
1111
<PackageReference Include="Testcontainers.Elasticsearch" Version="3.4.0" />
1212
</ItemGroup>
1313

1414
<ItemGroup>
1515
<!--Only adding this for testing: make sure `ElasticsearchDiagnosticsSubscriber` does not cause any issue with the new client -->
1616
<ProjectReference Include="$(SrcInstrumentations)\Elastic.Apm.Elasticsearch\Elastic.Apm.Elasticsearch.csproj" />
17-
1817
<ProjectReference Include="$(SolutionRoot)\src\Elastic.Apm\Elastic.Apm.csproj" />
1918
<ProjectReference Include="$(SolutionRoot)\test\Elastic.Apm.Tests.Utilities\Elastic.Apm.Tests.Utilities.csproj" />
2019
</ItemGroup>

0 commit comments

Comments
 (0)