Skip to content

Commit

Permalink
Lift and shift Azure instrumentation from main repo
Browse files Browse the repository at this point in the history
  • Loading branch information
cijothomas committed Jun 17, 2020
1 parent 45405e7 commit b8c6a38
Show file tree
Hide file tree
Showing 9 changed files with 423 additions and 8 deletions.
32 changes: 25 additions & 7 deletions opentelemetry-dotnet-contrib.sln
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.30204.135
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{22DF5DC0-1290-4E83-A9D8-6BB7DE3B3E63}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Exporter.Stackdriver", "src\OpenTelemetry.Exporter.Stackdriver\OpenTelemetry.Exporter.Stackdriver.csproj", "{D7F6B622-ED4B-4A3B-BAFD-24FB503666C2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Stackdriver", "src\OpenTelemetry.Exporter.Stackdriver\OpenTelemetry.Exporter.Stackdriver.csproj", "{D7F6B622-ED4B-4A3B-BAFD-24FB503666C2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2097345F-4DD3-477D-BC54-A922F9B2B402}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Exporter.Stackdriver.Tests", "test\OpenTelemetry.Exporter.Stackdriver.Tests\OpenTelemetry.Exporter.Stackdriver.Tests.csproj", "{39EF6946-9909-498D-9181-479DEF6CB4B7}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Stackdriver.Tests", "test\OpenTelemetry.Exporter.Stackdriver.Tests\OpenTelemetry.Exporter.Stackdriver.Tests.csproj", "{39EF6946-9909-498D-9181-479DEF6CB4B7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Instrumentation.Azure", "src\OpenTelemetry.Instrumentation.Azure\OpenTelemetry.Instrumentation.Azure.csproj", "{0E862C3A-89B1-4C3D-A2D5-579E38439C92}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -20,9 +22,6 @@ Global
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D7F6B622-ED4B-4A3B-BAFD-24FB503666C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D7F6B622-ED4B-4A3B-BAFD-24FB503666C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
Expand All @@ -48,9 +47,28 @@ Global
{39EF6946-9909-498D-9181-479DEF6CB4B7}.Release|x64.Build.0 = Release|Any CPU
{39EF6946-9909-498D-9181-479DEF6CB4B7}.Release|x86.ActiveCfg = Release|Any CPU
{39EF6946-9909-498D-9181-479DEF6CB4B7}.Release|x86.Build.0 = Release|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Debug|x64.ActiveCfg = Debug|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Debug|x64.Build.0 = Debug|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Debug|x86.ActiveCfg = Debug|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Debug|x86.Build.0 = Debug|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Release|Any CPU.Build.0 = Release|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Release|x64.ActiveCfg = Release|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Release|x64.Build.0 = Release|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Release|x86.ActiveCfg = Release|Any CPU
{0E862C3A-89B1-4C3D-A2D5-579E38439C92}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{D7F6B622-ED4B-4A3B-BAFD-24FB503666C2} = {22DF5DC0-1290-4E83-A9D8-6BB7DE3B3E63}
{39EF6946-9909-498D-9181-479DEF6CB4B7} = {2097345F-4DD3-477D-BC54-A922F9B2B402}
{0E862C3A-89B1-4C3D-A2D5-579E38439C92} = {22DF5DC0-1290-4E83-A9D8-6BB7DE3B3E63}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B0816796-CDB3-47D7-8C3C-946434DE3B66}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
<Description>Stackdriver .NET Exporter for OpenTelemetry.</Description>
<PackageTags>$(PackageTags);Stackdriver;Google;GCP;distributed-tracing</PackageTags>
<LangVersion>8.0</LangVersion>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// <copyright file="AzureClientsInstrumentation.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 OpenTelemetry.Instrumentation.Azure.Implementation;
using System;

namespace OpenTelemetry.Instrumentation.Azure
{
/// <summary>
/// AzureClients instrumentation.
/// TODO: Azure specific listeners would be moved out of this repo.
/// I believe this was initially put here for quick validation.
/// There were no unit tests covering this feature, so
/// cannot validate after Span is replaced with Activity.
/// </summary>
public class AzureClientsInstrumentation : IDisposable
{
private readonly DiagnosticSourceSubscriber diagnosticSourceSubscriber;

/// <summary>
/// Initializes a new instance of the <see cref="AzureClientsInstrumentation"/> class.
/// </summary>
public AzureClientsInstrumentation()
{
this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(
name => new AzureSdkDiagnosticListener(name),
listener => listener.Name.StartsWith("Azure."),
null);
this.diagnosticSourceSubscriber.Subscribe();
}

/// <inheritdoc/>
public void Dispose()
{
this.diagnosticSourceSubscriber?.Dispose();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// <copyright file="AzurePipelineInstrumentation.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 OpenTelemetry.Instrumentation.Azure.Implementation;
using System;

namespace OpenTelemetry.Instrumentation.Azure
{
/// <summary>
/// AzurePipeline instrumentation.
/// TODO: Azure specific listeners would be moved out of this repo.
/// I believe this was initially put here for quick validation.
/// There were no unit tests covering this feature, so
/// cannot validate after Span is replaced with Activity.
/// </summary>
public class AzurePipelineInstrumentation : IDisposable
{
private readonly DiagnosticSourceSubscriber diagnosticSourceSubscriber;

/// <summary>
/// Initializes a new instance of the <see cref="AzurePipelineInstrumentation"/> class.
/// </summary>
public AzurePipelineInstrumentation()
{
this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new AzureSdkDiagnosticListener("Azure.Pipeline"), null);
this.diagnosticSourceSubscriber.Subscribe();
}

/// <inheritdoc/>
public void Dispose()
{
this.diagnosticSourceSubscriber?.Dispose();
}
}
}
8 changes: 8 additions & 0 deletions src/OpenTelemetry.Instrumentation.Azure/Class1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System;

namespace OpenTelemetry.Instrumentation.Azure
{
public class Class1
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// <copyright file="AzureSdkDiagnosticListener.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.Generic;
using System.Diagnostics;
using System.Linq;
using OpenTelemetry.Trace;

namespace OpenTelemetry.Instrumentation.Azure.Implementation
{
internal class AzureSdkDiagnosticListener : ListenerHandler
{
internal const string ActivitySourceName = "AzureSDK";
internal const string ActivityName = ActivitySourceName + ".HttpRequestOut";
private static readonly Version Version = typeof(AzureSdkDiagnosticListener).Assembly.GetName().Version;
private static readonly ActivitySource AzureSDKActivitySource = new ActivitySource(ActivitySourceName, Version.ToString());

// all fetchers must not be reused between DiagnosticSources.
private readonly PropertyFetcher linksPropertyFetcher = new PropertyFetcher("Links");

public AzureSdkDiagnosticListener(string sourceName)
: base(sourceName, null)
{
}

public void OnCompleted()
{
}

public void OnError(Exception error)
{
}

public override void OnStartActivity(Activity activity, object valueValue)
{
string operationName = null;
var activityKind = ActivityKind.Internal;

foreach (var keyValuePair in activity.Tags)
{
if (keyValuePair.Key == "http.url")
{
operationName = keyValuePair.Value;
activityKind = ActivityKind.Client;
break;
}

if (keyValuePair.Key == "kind")
{
if (Enum.TryParse(keyValuePair.Value, true, out ActivityKind parsedActivityKind))
{
activityKind = parsedActivityKind;
}
}
}

if (operationName == null)
{
operationName = this.GetOperationName(activity);
}

List<ActivityLink> links = null;
if (this.linksPropertyFetcher.Fetch(valueValue) is IEnumerable<Activity> activityLinks)
{
if (activityLinks.Any())
{
links = new List<ActivityLink>();
foreach (var link in activityLinks)
{
if (link != null)
{
links.Add(new ActivityLink(new ActivityContext(link.TraceId, link.ParentSpanId, link.ActivityTraceFlags)));
}
}
}
}

// Ignore the activity and create a new one using ActivitySource.
// The new one will have Sampling decision made using extracted Links as well.
AzureSDKActivitySource.StartActivity(operationName, activityKind, activity.Id, activity.Tags, links);
}

public override void OnStopActivity(Activity current, object valueValue)
{
// nothing to be done.
}

public override void OnException(Activity activity, object valueValue)
{
Status status = Status.Unknown;
activity.AddTag(SpanAttributeConstants.StatusCodeKey, SpanHelper.GetCachedCanonicalCodeString(status.CanonicalCode));
activity.AddTag(SpanAttributeConstants.StatusDescriptionKey, valueValue?.ToString());
}

private string GetOperationName(Activity activity)
{
// activity name looks like 'Azure.<...>.<Class>.<Name>'
// as namespace is too verbose, we'll just take the last two nodes from the activity name as telemetry name
// this will change with https://github.com/Azure/azure-sdk-for-net/issues/9071 ~Feb 2020

string activityName = activity.OperationName;
int methodDotIndex = activityName.LastIndexOf('.');
if (methodDotIndex <= 0)
{
return activityName;
}

int classDotIndex = activityName.LastIndexOf('.', methodDotIndex - 1);

if (classDotIndex == -1)
{
return activityName;
}

return activityName.Substring(classDotIndex + 1, activityName.Length - classDotIndex - 1);
}
}
}
Loading

0 comments on commit b8c6a38

Please sign in to comment.