More cleanup - zipkin exporter removed span related code (#823)

This commit is contained in:
Cijo Thomas 2020-07-14 22:54:23 -07:00 committed by GitHub
parent 59f0a9d06a
commit 2712d4b29b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 7 additions and 309 deletions

View File

@ -1,224 +0,0 @@
// <copyright file="ZipkinConversionExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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.
// </copyright>
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using OpenTelemetry.Trace.Export;
namespace OpenTelemetry.Exporter.Zipkin.Implementation
{
internal static class ZipkinConversionExtensions
{
private static readonly Dictionary<string, int> RemoteEndpointServiceNameKeyResolutionDictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
{
[SpanAttributeConstants.PeerServiceKey] = 0, // priority 0 (highest).
[SpanAttributeConstants.NetPeerName] = 1,
[SpanAttributeConstants.NetPeerIp] = 2,
["peer.hostname"] = 2,
["peer.address"] = 2,
["http.host"] = 3, // RemoteEndpoint.ServiceName for Http.
["db.instance"] = 3, // RemoteEndpoint.ServiceName for Redis.
};
private static readonly ConcurrentDictionary<string, ZipkinEndpoint> LocalEndpointCache = new ConcurrentDictionary<string, ZipkinEndpoint>();
private static readonly ConcurrentDictionary<string, ZipkinEndpoint> RemoteEndpointCache = new ConcurrentDictionary<string, ZipkinEndpoint>();
private static readonly DictionaryEnumerator<string, object, AttributeEnumerationState>.ForEachDelegate ProcessAttributesRef = ProcessAttributes;
private static readonly DictionaryEnumerator<string, object, AttributeEnumerationState>.ForEachDelegate ProcessLibraryResourcesRef = ProcessLibraryResources;
private static readonly ListEnumerator<Event, PooledList<ZipkinAnnotation>>.ForEachDelegate ProcessEventsRef = ProcessEvents;
internal static ZipkinSpan ToZipkinSpan(this SpanData otelSpan, ZipkinEndpoint defaultLocalEndpoint, bool useShortTraceIds = false)
{
var context = otelSpan.Context;
var startTimestamp = ToEpochMicroseconds(otelSpan.StartTimestamp);
var endTimestamp = ToEpochMicroseconds(otelSpan.EndTimestamp);
string parentId = null;
if (otelSpan.ParentSpanId != default)
{
parentId = EncodeSpanId(otelSpan.ParentSpanId);
}
var attributeEnumerationState = new AttributeEnumerationState
{
Tags = PooledList<KeyValuePair<string, string>>.Create(),
};
DictionaryEnumerator<string, object, AttributeEnumerationState>.AllocationFreeForEach(otelSpan.Attributes, ref attributeEnumerationState, ProcessAttributesRef);
DictionaryEnumerator<string, object, AttributeEnumerationState>.AllocationFreeForEach(otelSpan.LibraryResource.Attributes, ref attributeEnumerationState, ProcessLibraryResourcesRef);
var localEndpoint = defaultLocalEndpoint;
var serviceName = attributeEnumerationState.ServiceName;
// override default service name
if (!string.IsNullOrWhiteSpace(serviceName))
{
if (!string.IsNullOrWhiteSpace(attributeEnumerationState.ServiceNamespace))
{
serviceName = attributeEnumerationState.ServiceNamespace + "." + serviceName;
}
if (!LocalEndpointCache.TryGetValue(serviceName, out localEndpoint))
{
localEndpoint = defaultLocalEndpoint.Clone(serviceName);
LocalEndpointCache.TryAdd(serviceName, localEndpoint);
}
}
ZipkinEndpoint remoteEndpoint = null;
if ((otelSpan.Kind == SpanKind.Client || otelSpan.Kind == SpanKind.Producer) && attributeEnumerationState.RemoteEndpointServiceName != null)
{
remoteEndpoint = RemoteEndpointCache.GetOrAdd(attributeEnumerationState.RemoteEndpointServiceName, ZipkinEndpoint.Create);
}
var status = otelSpan.Status;
if (status.IsValid)
{
PooledList<KeyValuePair<string, string>>.Add(ref attributeEnumerationState.Tags, new KeyValuePair<string, string>(SpanAttributeConstants.StatusCodeKey, SpanHelper.GetCachedCanonicalCodeString(status.CanonicalCode)));
if (status.Description != null)
{
PooledList<KeyValuePair<string, string>>.Add(ref attributeEnumerationState.Tags, new KeyValuePair<string, string>(SpanAttributeConstants.StatusDescriptionKey, status.Description));
}
}
var annotations = PooledList<ZipkinAnnotation>.Create();
ListEnumerator<Event, PooledList<ZipkinAnnotation>>.AllocationFreeForEach(otelSpan.Events, ref annotations, ProcessEventsRef);
return new ZipkinSpan(
EncodeTraceId(context.TraceId, useShortTraceIds),
parentId,
EncodeSpanId(context.SpanId),
ToSpanKind(otelSpan),
otelSpan.Name,
ToEpochMicroseconds(otelSpan.StartTimestamp),
duration: endTimestamp - startTimestamp,
localEndpoint,
remoteEndpoint,
annotations,
attributeEnumerationState.Tags,
null,
null);
}
internal static string EncodeSpanId(ActivitySpanId spanId)
{
return spanId.ToHexString();
}
internal static long ToEpochMicroseconds(DateTimeOffset timestamp)
{
return timestamp.ToUnixTimeMilliseconds() * 1000;
}
private static string EncodeTraceId(ActivityTraceId traceId, bool useShortTraceIds)
{
var id = traceId.ToHexString();
if (id.Length > 16 && useShortTraceIds)
{
id = id.Substring(id.Length - 16, 16);
}
return id;
}
private static string ToSpanKind(SpanData otelSpan)
{
switch (otelSpan.Kind)
{
case SpanKind.Server:
return "SERVER";
case SpanKind.Producer:
return "PRODUCER";
case SpanKind.Consumer:
return "CONSUMER";
default:
return "CLIENT";
}
}
private static bool ProcessEvents(ref PooledList<ZipkinAnnotation> annotations, Event @event)
{
PooledList<ZipkinAnnotation>.Add(ref annotations, new ZipkinAnnotation(ToEpochMicroseconds(@event.Timestamp), @event.Name));
return true;
}
private static bool ProcessAttributes(ref AttributeEnumerationState state, KeyValuePair<string, object> attribute)
{
string key = attribute.Key;
if (!(attribute.Value is string strVal))
{
strVal = attribute.Value?.ToString();
}
if (strVal != null
&& RemoteEndpointServiceNameKeyResolutionDictionary.TryGetValue(key, out int priority)
&& (state.RemoteEndpointServiceName == null || priority < state.RemoteEndpointServiceNamePriority))
{
state.RemoteEndpointServiceName = strVal;
state.RemoteEndpointServiceNamePriority = priority;
}
PooledList<KeyValuePair<string, string>>.Add(ref state.Tags, new KeyValuePair<string, string>(key, strVal));
return true;
}
private static bool ProcessLibraryResources(ref AttributeEnumerationState state, KeyValuePair<string, object> label)
{
// See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-resource-semantic-conventions.md
string key = label.Key;
object val = label.Value;
string strVal = val as string;
if (key == Resource.ServiceNameKey && strVal != null)
{
state.ServiceName = strVal;
}
else if (key == Resource.ServiceNamespaceKey && strVal != null)
{
state.ServiceNamespace = strVal;
}
else
{
PooledList<KeyValuePair<string, string>>.Add(ref state.Tags, new KeyValuePair<string, string>(key, strVal ?? val?.ToString()));
}
return true;
}
private struct AttributeEnumerationState
{
public PooledList<KeyValuePair<string, string>> Tags;
public string RemoteEndpointServiceName;
public int RemoteEndpointServiceNamePriority;
public string ServiceName;
public string ServiceNamespace;
}
}
}

View File

@ -13,12 +13,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using OpenTelemetry.Exporter.Zipkin.Implementation;
using OpenTelemetry.Trace;
using OpenTelemetry.Trace.Export;
using Xunit;
namespace OpenTelemetry.Exporter.Zipkin.Tests.Implementation
@ -31,10 +27,10 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests.Implementation
public void ZipkinSpanConverterTest_GenerateSpan_RemoteEndpointOmittedByDefault()
{
// Arrange
var span = CreateTestSpan();
var activity = ZipkinExporterTests.CreateTestActivity();
// Act & Assert
var zipkinSpan = ZipkinConversionExtensions.ToZipkinSpan(span, DefaultZipkinEndpoint);
var zipkinSpan = ZipkinActivityConversionExtensions.ToZipkinSpan(activity, DefaultZipkinEndpoint);
Assert.Null(zipkinSpan.RemoteEndpoint);
}
@ -43,14 +39,14 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests.Implementation
public void ZipkinSpanConverterTest_GenerateSpan_RemoteEndpointResolution()
{
// Arrange
var span = CreateTestSpan(
var activity = ZipkinExporterTests.CreateTestActivity(
additionalAttributes: new Dictionary<string, object>
{
["net.peer.name"] = "RemoteServiceName",
});
// Act & Assert
var zipkinSpan = ZipkinConversionExtensions.ToZipkinSpan(span, DefaultZipkinEndpoint);
var zipkinSpan = ZipkinActivityConversionExtensions.ToZipkinSpan(activity, DefaultZipkinEndpoint);
Assert.NotNull(zipkinSpan.RemoteEndpoint);
Assert.Equal("RemoteServiceName", zipkinSpan.RemoteEndpoint.ServiceName);
@ -60,7 +56,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests.Implementation
public void ZipkinSpanConverterTest_GenerateSpan_RemoteEndpointResolutionPriority()
{
// Arrange
var span = CreateTestSpan(
var activity = ZipkinExporterTests.CreateTestActivity(
additionalAttributes: new Dictionary<string, object>
{
["http.host"] = "DiscardedRemoteServiceName",
@ -69,83 +65,10 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests.Implementation
});
// Act & Assert
var zipkinSpan = ZipkinConversionExtensions.ToZipkinSpan(span, DefaultZipkinEndpoint);
var zipkinSpan = ZipkinActivityConversionExtensions.ToZipkinSpan(activity, DefaultZipkinEndpoint);
Assert.NotNull(zipkinSpan.RemoteEndpoint);
Assert.Equal("RemoteServiceName", zipkinSpan.RemoteEndpoint.ServiceName);
}
internal static SpanData CreateTestSpan(
bool setAttributes = true,
Dictionary<string, object> additionalAttributes = null,
bool addEvents = true,
bool addLinks = true)
{
var startTimestamp = DateTime.UtcNow;
var endTimestamp = startTimestamp.AddSeconds(60);
var eventTimestamp = startTimestamp;
var traceId = ActivityTraceId.CreateFromString("e8ea7e9ac72de94e91fabc613f9686b2".AsSpan());
var spanId = ActivitySpanId.CreateRandom();
var parentSpanId = ActivitySpanId.CreateFromBytes(new byte[] { 12, 23, 34, 45, 56, 67, 78, 89 });
var attributes = new Dictionary<string, object>
{
{ "stringKey", "value" },
{ "longKey", 1L },
{ "longKey2", 1 },
{ "doubleKey", 1D },
{ "doubleKey2", 1F },
{ "boolKey", true },
};
if (additionalAttributes != null)
{
foreach (var attribute in additionalAttributes)
{
attributes.Add(attribute.Key, attribute.Value);
}
}
var events = new List<Event>
{
new Event(
"Event1",
eventTimestamp,
new Dictionary<string, object>
{
{ "key", "value" },
}),
new Event(
"Event2",
eventTimestamp,
new Dictionary<string, object>
{
{ "key", "value" },
}),
};
var linkedSpanId = ActivitySpanId.CreateFromString("888915b6286b9c41".AsSpan());
var links = addLinks
? new[]
{
new Link(new SpanContext(
traceId,
linkedSpanId,
ActivityTraceFlags.Recorded)),
}
: null;
return new SpanData(
"Name",
new SpanContext(traceId, spanId, ActivityTraceFlags.Recorded),
parentSpanId,
SpanKind.Client,
startTimestamp,
setAttributes ? attributes : null,
addEvents ? events : null,
links,
null,
Status.Ok,
endTimestamp);
}
}
}

View File

@ -28,7 +28,6 @@ using OpenTelemetry.Exporter.Zipkin.Implementation;
using OpenTelemetry.Internal.Test;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace.Configuration;
using OpenTelemetry.Trace.Export;
using Xunit;
namespace OpenTelemetry.Exporter.Zipkin.Tests
@ -125,7 +124,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests
var traceId = useShortTraceIds ? TraceId.Substring(TraceId.Length - 16, 16) : TraceId;
Assert.Equal(
$@"[{{""traceId"":""{traceId}"",""name"":""Name"",""parentId"":""{ZipkinConversionExtensions.EncodeSpanId(activity.ParentSpanId)}"",""id"":""{ZipkinActivityConversionExtensions.EncodeSpanId(context.SpanId)}"",""kind"":""CLIENT"",""timestamp"":{timestamp},""duration"":60000000,""localEndpoint"":{{""serviceName"":""Open Telemetry Exporter""{ipInformation}}},""annotations"":[{{""timestamp"":{eventTimestamp},""value"":""Event1""}},{{""timestamp"":{eventTimestamp},""value"":""Event2""}}],""tags"":{{""stringKey"":""value"",""longKey"":""1"",""longKey2"":""1"",""doubleKey"":""1"",""doubleKey2"":""1"",""boolKey"":""True"",""library.name"":""CreateTestActivity""}}}}]",
$@"[{{""traceId"":""{traceId}"",""name"":""Name"",""parentId"":""{ZipkinActivityConversionExtensions.EncodeSpanId(activity.ParentSpanId)}"",""id"":""{ZipkinActivityConversionExtensions.EncodeSpanId(context.SpanId)}"",""kind"":""CLIENT"",""timestamp"":{timestamp},""duration"":60000000,""localEndpoint"":{{""serviceName"":""Open Telemetry Exporter""{ipInformation}}},""annotations"":[{{""timestamp"":{eventTimestamp},""value"":""Event1""}},{{""timestamp"":{eventTimestamp},""value"":""Event2""}}],""tags"":{{""stringKey"":""value"",""longKey"":""1"",""longKey2"":""1"",""doubleKey"":""1"",""doubleKey2"":""1"",""boolKey"":""True"",""library.name"":""CreateTestActivity""}}}}]",
Responses[requestId]);
}