Remove application insights exporter (#658)
* remove application insights exporter * switch example to use zipkin Co-authored-by: Sergey Kanzhelev <S.Kanzhelev@live.com>
This commit is contained in:
parent
ecb6928bb2
commit
011b21054f
|
|
@ -39,8 +39,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".vsts", ".vsts", "{61188153
|
|||
.vsts\ci-myget-update.yml = .vsts\ci-myget-update.yml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.ApplicationInsights", "src\OpenTelemetry.Exporter.ApplicationInsights\OpenTelemetry.Exporter.ApplicationInsights.csproj", "{4493F5D9-874E-4FBF-B2F3-37890BD910E0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Stackdriver", "src\OpenTelemetry.Exporter.Stackdriver\OpenTelemetry.Exporter.Stackdriver.csproj", "{DE1B4783-C01F-4672-A6EB-695F1717105B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Api", "src\OpenTelemetry.Api\OpenTelemetry.Api.csproj", "{99F8A331-05E9-45A5-89BA-4C54E825E5B2}"
|
||||
|
|
@ -61,8 +59,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp.AspNetCore.3.1", "t
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Stackdriver.Tests", "test\OpenTelemetry.Exporter.Stackdriver.Tests\OpenTelemetry.Exporter.Stackdriver.Tests.csproj", "{6875032B-DFDC-4CDE-A283-37CA7F99926A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.ApplicationInsights.Tests", "test\OpenTelemetry.Exporter.ApplicationInsights.Tests\OpenTelemetry.Exporter.ApplicationInsights.Tests.csproj", "{1FA1F509-7722-48E3-9A35-16CBB6774957}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Adapter.StackExchangeRedis", "src\OpenTelemetry.Adapter.StackExchangeRedis\OpenTelemetry.Adapter.StackExchangeRedis.csproj", "{6B681D72-D68A-44CC-8C75-53B9A322E6EC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Adapter.StackExchangeRedis.Tests", "test\OpenTelemetry.Adapter.StackExchangeRedis.Tests\OpenTelemetry.Adapter.StackExchangeRedis.Tests.csproj", "{CA98AF29-0852-4ADD-A66B-7E96266EE7B7}"
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
<ProjectReference Include="..\..\..\src\OpenTelemetry.Exporter.ZPages\OpenTelemetry.Exporter.ZPages.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\OpenTelemetry\OpenTelemetry.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\OpenTelemetry.Exporter.ApplicationInsights\OpenTelemetry.Exporter.ApplicationInsights.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ namespace Samples
|
|||
///
|
||||
/// dotnet Exporters.dll zipkin -u http://localhost:9411/api/v2/spans
|
||||
/// dotnet Exporters.dll jaeger -h localhost -o 6831
|
||||
/// dotnet Exporters.dll appInsights
|
||||
/// dotnet Exporters.dll prometheus -i 15 -p 9184 -d 2
|
||||
///
|
||||
/// The above must be run from the project bin folder
|
||||
|
|
@ -38,11 +37,10 @@ namespace Samples
|
|||
/// <param name="args">Arguments from command line.</param>
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Parser.Default.ParseArguments<JaegerOptions, ZipkinOptions, ApplicationInsightsOptions, PrometheusOptions, HttpClientOptions, StackdriverOptions, LightStepOptions, ZPagesOptions, ConsoleOptions, OtlpOptions>(args)
|
||||
Parser.Default.ParseArguments<JaegerOptions, ZipkinOptions, PrometheusOptions, HttpClientOptions, StackdriverOptions, LightStepOptions, ZPagesOptions, ConsoleOptions, OtlpOptions>(args)
|
||||
.MapResult(
|
||||
(JaegerOptions options) => TestJaeger.Run(options.Host, options.Port),
|
||||
(ZipkinOptions options) => TestZipkin.Run(options.Uri),
|
||||
(ApplicationInsightsOptions options) => TestApplicationInsights.Run(),
|
||||
(PrometheusOptions options) => TestPrometheus.RunAsync(options.Port, options.PushIntervalInSecs, options.DurationInMins),
|
||||
(HttpClientOptions options) => TestHttpClient.Run(),
|
||||
(RedisOptions options) => TestRedis.Run(options.Uri),
|
||||
|
|
@ -89,11 +87,6 @@ namespace Samples
|
|||
public string Uri { get; set; }
|
||||
}
|
||||
|
||||
[Verb("appInsights", HelpText = "Specify the options required to test ApplicationInsights")]
|
||||
internal class ApplicationInsightsOptions
|
||||
{
|
||||
}
|
||||
|
||||
[Verb("prometheus", HelpText = "Specify the options required to test Prometheus")]
|
||||
internal class PrometheusOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,56 +0,0 @@
|
|||
// <copyright file="TestApplicationInsights.cs" company="OpenTelemetry Authors">
|
||||
// Copyright 2018, 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.Threading;
|
||||
using OpenTelemetry.Context;
|
||||
using OpenTelemetry.Exporter.ApplicationInsights;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
using OpenTelemetry.Trace.Configuration;
|
||||
|
||||
namespace Samples
|
||||
{
|
||||
internal class TestApplicationInsights
|
||||
{
|
||||
private static readonly string FrontendKey = "my.org/keys/frontend";
|
||||
|
||||
internal static object Run()
|
||||
{
|
||||
DistributedContext.Carrier = AsyncLocalDistributedContextCarrier.Instance; // Enable asynclocal carrier for the context
|
||||
DistributedContext dc = DistributedContextBuilder.CreateContext(FrontendKey, "mobile-ios9.3.5");
|
||||
|
||||
using var tracerFactory = TracerFactory.Create(builder => builder
|
||||
.SetResource(Resources.CreateServiceResource("my-service"))
|
||||
.UseApplicationInsights(config => config.InstrumentationKey = "instrumentation-key"));
|
||||
var tracer = tracerFactory.GetTracer("application-insights-test");
|
||||
|
||||
using (DistributedContext.SetCurrent(dc))
|
||||
using (tracer.StartActiveSpan("incoming request", out var span))
|
||||
{
|
||||
span.AddEvent("Start processing video.");
|
||||
Thread.Sleep(TimeSpan.FromMilliseconds(10));
|
||||
span.AddEvent("Finished processing video.");
|
||||
}
|
||||
|
||||
Thread.Sleep(TimeSpan.FromMilliseconds(5100));
|
||||
|
||||
Console.WriteLine("Done... wait for events to arrive to backend!");
|
||||
Console.ReadLine();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\OpenTelemetry.Adapter.AspNetCore\OpenTelemetry.Adapter.AspNetCore.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\OpenTelemetry.Adapter.Dependencies\OpenTelemetry.Adapter.Dependencies.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\OpenTelemetry.Exporter.ApplicationInsights\OpenTelemetry.Exporter.ApplicationInsights.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\OpenTelemetry.Extensions.Hosting\OpenTelemetry.Extensions.Hosting.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ namespace API
|
|||
{
|
||||
builder
|
||||
//.SetSampler(Samplers.AlwaysSample)
|
||||
.UseApplicationInsights(telemetryConfiguration =>
|
||||
.UseZipkin(options =>
|
||||
{
|
||||
var instrumentationKey = this.Configuration.GetValue<string>("ApplicationInsights:InstrumentationKey");
|
||||
telemetryConfiguration.InstrumentationKey = instrumentationKey;
|
||||
options.ServiceName = "test-zipkin";
|
||||
options.Endpoint = new Uri(this.Configuration.GetValue<string>("Zipkin:Endpoint"));
|
||||
})
|
||||
.AddRequestAdapter()
|
||||
.AddDependencyAdapter();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ApplicationInsights": {
|
||||
"InstrumentationKey": "<Insert your InstrumentationKey here>"
|
||||
"Zipkin": {
|
||||
"Endpoint": "http://localhost:9411/api/v2/spans"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,685 +0,0 @@
|
|||
// <copyright file="ApplicationInsightsTraceExporter.cs" company="OpenTelemetry Authors">
|
||||
// Copyright 2018, 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.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.ApplicationInsights;
|
||||
using Microsoft.ApplicationInsights.DataContracts;
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using Microsoft.ApplicationInsights.Extensibility.Implementation;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
using OpenTelemetry.Trace.Export;
|
||||
|
||||
namespace OpenTelemetry.Exporter.ApplicationInsights
|
||||
{
|
||||
/// <summary>
|
||||
/// Application Insights trace exporter.
|
||||
/// </summary>
|
||||
public class ApplicationInsightsTraceExporter : SpanExporter, IDisposable
|
||||
{
|
||||
private const string InProcDependencyType = "InProc";
|
||||
private const string QueueMessageDependencyType = "Queue Message";
|
||||
private const string EventHubsDependencyType = "Microsoft.EventHub";
|
||||
private const string HttpDependencyType = "Http";
|
||||
private readonly TelemetryClient telemetryClient;
|
||||
private readonly string serviceEndpoint;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ApplicationInsightsTraceExporter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="telemetryConfiguration">Telemetry configuration to use.</param>
|
||||
public ApplicationInsightsTraceExporter(TelemetryConfiguration telemetryConfiguration)
|
||||
{
|
||||
this.telemetryClient = new TelemetryClient(telemetryConfiguration);
|
||||
this.telemetryClient.Context.GetInternalContext().SdkVersion = "ot:" + GetAssemblyVersion();
|
||||
this.serviceEndpoint = telemetryConfiguration.TelemetryChannel.EndpointAddress;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task<ExportResult> ExportAsync(IEnumerable<SpanData> spanDataList, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var span in spanDataList)
|
||||
{
|
||||
bool shouldExport = true;
|
||||
string httpUrlAttr = null;
|
||||
|
||||
foreach (var attr in span.Attributes)
|
||||
{
|
||||
if (attr.Key == "http.url")
|
||||
{
|
||||
httpUrlAttr = attr.Value.ToString();
|
||||
if (httpUrlAttr == this.serviceEndpoint)
|
||||
{
|
||||
shouldExport = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldExport)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
this.ExtractGenericProperties(
|
||||
span,
|
||||
out var name,
|
||||
out var resultCode,
|
||||
out var statusDescription,
|
||||
out var traceId,
|
||||
out var spanId,
|
||||
out var parentId,
|
||||
out var success,
|
||||
out var duration,
|
||||
out var roleName,
|
||||
out var roleInstance,
|
||||
out var version);
|
||||
|
||||
// BUILDING resulting telemetry
|
||||
OperationTelemetry result;
|
||||
if (span.Kind == SpanKind.Client || span.Kind == SpanKind.Internal || span.Kind == SpanKind.Producer)
|
||||
{
|
||||
result = new DependencyTelemetry
|
||||
{
|
||||
Name = name,
|
||||
ResultCode = resultCode,
|
||||
Type = span.Kind == SpanKind.Internal ? InProcDependencyType :
|
||||
span.Kind == SpanKind.Producer ? QueueMessageDependencyType : null,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new RequestTelemetry
|
||||
{
|
||||
Name = name,
|
||||
ResponseCode = resultCode,
|
||||
};
|
||||
|
||||
result.Context.Operation.Name = name;
|
||||
}
|
||||
|
||||
string component = this.GetComponent(span);
|
||||
|
||||
switch (component)
|
||||
{
|
||||
case "http":
|
||||
this.SetHttpProperties(
|
||||
span,
|
||||
result,
|
||||
httpUrlAttr);
|
||||
break;
|
||||
case "eventhubs":
|
||||
case "Microsoft.EventHub":
|
||||
this.SetEventHubsProperties(span, result);
|
||||
break;
|
||||
default:
|
||||
|
||||
if (result is DependencyTelemetry dependency && component != null)
|
||||
{
|
||||
dependency.Type = string.IsNullOrEmpty(dependency.Type) ? component : string.Concat(dependency.Type, " | ", component);
|
||||
}
|
||||
|
||||
foreach (var attribute in span.Attributes)
|
||||
{
|
||||
AddPropertyWithAdjustedName(result.Properties, attribute.Key, attribute.Value.ToString());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (span.Links.Count() != 0)
|
||||
{
|
||||
var linksJson = new StringBuilder();
|
||||
linksJson.Append('[');
|
||||
foreach (var link in span.Links)
|
||||
{
|
||||
var linkTraceId = link.Context.TraceId.ToHexString();
|
||||
|
||||
// avoiding json serializers for now because of extra dependency.
|
||||
// System.Text.Json is starting at 4.6.1 while exporter is 4.6
|
||||
// also serialization is trivial and looks like `links` property with json blob
|
||||
// [{"operation_Id":"5eca8b153632494ba00f619d6877b134","id":"d4c1279b6e7b7c47"},
|
||||
// {"operation_Id":"ff28988d0776b44f9ca93352da126047","id":"bf4fa4855d161141"}]
|
||||
linksJson
|
||||
.Append('{')
|
||||
.Append("\"operation_Id\":")
|
||||
.Append('\"')
|
||||
.Append(linkTraceId)
|
||||
.Append('\"')
|
||||
.Append(',');
|
||||
linksJson
|
||||
.Append("\"id\":")
|
||||
.Append('\"')
|
||||
.Append(link.Context.SpanId.ToHexString())
|
||||
.Append('\"');
|
||||
|
||||
// we explicitly ignore sampling flag, tracestate and attributes at this point.
|
||||
linksJson.Append("},");
|
||||
}
|
||||
|
||||
// trim last comma, json does not support it
|
||||
if (linksJson.Length > 0)
|
||||
{
|
||||
linksJson.Remove(linksJson.Length - 1, 1);
|
||||
}
|
||||
|
||||
linksJson.Append("]");
|
||||
result.Properties["_MS.links"] = linksJson.ToString();
|
||||
}
|
||||
|
||||
foreach (var t in span.Events)
|
||||
{
|
||||
var log = new TraceTelemetry(t.Name);
|
||||
|
||||
if (t.Timestamp != null)
|
||||
{
|
||||
log.Timestamp = t.Timestamp;
|
||||
}
|
||||
|
||||
foreach (var attr in t.Attributes)
|
||||
{
|
||||
var value = attr.Value.ToString();
|
||||
|
||||
AddPropertyWithAdjustedName(log.Properties, attr.Key, value);
|
||||
}
|
||||
|
||||
log.Context.Operation.Id = traceId;
|
||||
log.Context.Operation.ParentId = spanId;
|
||||
log.Context.Cloud.RoleName = roleName;
|
||||
log.Context.Cloud.RoleInstance = roleInstance;
|
||||
log.Context.Component.Version = version;
|
||||
|
||||
this.telemetryClient.Track(log);
|
||||
}
|
||||
|
||||
result.Success = success;
|
||||
if (statusDescription != null)
|
||||
{
|
||||
AddPropertyWithAdjustedName(result.Properties, "statusDescription", statusDescription);
|
||||
}
|
||||
|
||||
result.Timestamp = span.StartTimestamp;
|
||||
result.Context.Operation.Id = traceId;
|
||||
result.Context.Cloud.RoleName = roleName;
|
||||
result.Context.Cloud.RoleInstance = roleInstance;
|
||||
result.Context.Component.Version = version;
|
||||
|
||||
if (parentId != null)
|
||||
{
|
||||
result.Context.Operation.ParentId = parentId;
|
||||
}
|
||||
|
||||
result.Id = spanId;
|
||||
|
||||
foreach (var ts in span.Context.Tracestate)
|
||||
{
|
||||
result.Properties[ts.Key] = ts.Value;
|
||||
}
|
||||
|
||||
result.Duration = duration;
|
||||
|
||||
// TODO: deal with those:
|
||||
// span.ChildSpanCount
|
||||
// span.Context.TraceOptions;
|
||||
|
||||
this.telemetryClient.Track(result);
|
||||
}
|
||||
|
||||
return Task.FromResult(ExportResult.Success);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task ShutdownAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
// TODO cancellation support
|
||||
this.telemetryClient.Flush();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
this.ShutdownAsync(CancellationToken.None).ContinueWith(_ => { }).Wait();
|
||||
}
|
||||
|
||||
private static void AddPropertyWithAdjustedName(IDictionary<string, string> props, string name, string value)
|
||||
{
|
||||
if (name == "component" || name == "az.namespace" || name == "kind")
|
||||
{
|
||||
// these attributes are reflected in telemetry types and should not be populated.
|
||||
return;
|
||||
}
|
||||
|
||||
var n = name;
|
||||
var i = 0;
|
||||
while (props.ContainsKey(n))
|
||||
{
|
||||
n = name + "_" + i;
|
||||
++i;
|
||||
}
|
||||
|
||||
props.Add(n, value);
|
||||
}
|
||||
|
||||
private static string GetAssemblyVersion()
|
||||
{
|
||||
try
|
||||
{
|
||||
return typeof(ApplicationInsightsTraceExporter).GetTypeInfo().Assembly.GetCustomAttributes<AssemblyFileVersionAttribute>()
|
||||
.First()
|
||||
.Version;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return "0.0.0";
|
||||
}
|
||||
}
|
||||
|
||||
private void ExtractGenericProperties(
|
||||
SpanData span,
|
||||
out string name,
|
||||
out string resultCode,
|
||||
out string statusDescription,
|
||||
out string traceId,
|
||||
out string spanId,
|
||||
out string parentId,
|
||||
out bool? success,
|
||||
out TimeSpan duration,
|
||||
out string roleName,
|
||||
out string roleInstance,
|
||||
out string serviceVersion)
|
||||
{
|
||||
name = span.Name;
|
||||
|
||||
roleName = null;
|
||||
statusDescription = null;
|
||||
|
||||
traceId = span.Context.TraceId.ToHexString();
|
||||
spanId = span.Context.SpanId.ToHexString();
|
||||
parentId = null;
|
||||
if (span.ParentSpanId != default)
|
||||
{
|
||||
parentId = span.ParentSpanId.ToHexString();
|
||||
}
|
||||
|
||||
resultCode = null;
|
||||
success = null;
|
||||
if (span.Status.IsValid)
|
||||
{
|
||||
resultCode = span.Status.CanonicalCode.ToString();
|
||||
success = span.Status.IsOk;
|
||||
if (!string.IsNullOrEmpty(span.Status.Description))
|
||||
{
|
||||
statusDescription = span.Status.Description;
|
||||
}
|
||||
}
|
||||
|
||||
duration = span.EndTimestamp - span.StartTimestamp;
|
||||
|
||||
string serviceName = null;
|
||||
string serviceNamespace = null;
|
||||
serviceVersion = null;
|
||||
roleInstance = null;
|
||||
|
||||
foreach (var attribute in span.LibraryResource.Attributes)
|
||||
{
|
||||
if (attribute.Key == Resource.ServiceNameKey && attribute.Value is string)
|
||||
{
|
||||
serviceName = (string)attribute.Value;
|
||||
}
|
||||
else if (attribute.Key == Resource.ServiceNamespaceKey && attribute.Value is string)
|
||||
{
|
||||
serviceNamespace = (string)attribute.Value;
|
||||
}
|
||||
else if (attribute.Key == Resource.ServiceVersionKey && attribute.Value is string)
|
||||
{
|
||||
serviceVersion = (string)attribute.Value;
|
||||
}
|
||||
else if (attribute.Key == Resource.ServiceInstanceIdKey && attribute.Value is string)
|
||||
{
|
||||
roleInstance = (string)attribute.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceName != null && serviceNamespace != null)
|
||||
{
|
||||
roleName = string.Concat(serviceNamespace, ".", serviceName);
|
||||
}
|
||||
else
|
||||
{
|
||||
roleName = serviceName;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetHttpProperties(SpanData span, OperationTelemetry telemetry, string httpUrlAttr)
|
||||
{
|
||||
string httpStatusCodeAttr = null;
|
||||
string httpMethodAttr = null;
|
||||
string httpPathAttr = null;
|
||||
string httpHostAttr = null;
|
||||
|
||||
string httpRouteAttr = null;
|
||||
string httpPortAttr = null;
|
||||
|
||||
foreach (var attr in span.Attributes)
|
||||
{
|
||||
switch (attr.Key)
|
||||
{
|
||||
case "http.method":
|
||||
httpMethodAttr = attr.Value.ToString();
|
||||
break;
|
||||
case "http.path":
|
||||
httpPathAttr = attr.Value.ToString();
|
||||
break;
|
||||
case "http.host":
|
||||
httpHostAttr = attr.Value.ToString();
|
||||
break;
|
||||
case "http.status_code":
|
||||
httpStatusCodeAttr = attr.Value.ToString();
|
||||
break;
|
||||
case "http.user_agent":
|
||||
telemetry.Context.User.UserAgent = attr.Value.ToString();
|
||||
break;
|
||||
case "http.route":
|
||||
httpRouteAttr = attr.Value.ToString();
|
||||
break;
|
||||
case "http.port":
|
||||
httpPortAttr = attr.Value.ToString();
|
||||
break;
|
||||
case "http.url":
|
||||
// break without doing anything - this will prevent adding url to custom property bag.
|
||||
// httpUrlAttr is already populated.
|
||||
break;
|
||||
default:
|
||||
AddPropertyWithAdjustedName(telemetry.Properties, attr.Key, attr.Value.ToString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string resultCode = null;
|
||||
if (httpStatusCodeAttr != null)
|
||||
{
|
||||
resultCode = httpStatusCodeAttr.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
Uri url = null;
|
||||
if (httpUrlAttr != null)
|
||||
{
|
||||
Uri.TryCreate(httpUrlAttr, UriKind.RelativeOrAbsolute, out url);
|
||||
}
|
||||
|
||||
string httpMethod = null;
|
||||
string httpPath = null;
|
||||
string httpHost = null;
|
||||
string httpRoute = null;
|
||||
string httpPort = null;
|
||||
|
||||
if (httpMethodAttr != null)
|
||||
{
|
||||
httpMethod = httpMethodAttr;
|
||||
}
|
||||
|
||||
if (httpPathAttr != null)
|
||||
{
|
||||
httpPath = httpPathAttr;
|
||||
}
|
||||
|
||||
if (httpHostAttr != null)
|
||||
{
|
||||
httpHost = httpHostAttr;
|
||||
}
|
||||
|
||||
if (httpRouteAttr != null)
|
||||
{
|
||||
httpRoute = httpRouteAttr;
|
||||
}
|
||||
|
||||
if (httpRouteAttr != null)
|
||||
{
|
||||
httpRoute = httpRouteAttr;
|
||||
}
|
||||
|
||||
if (httpPortAttr != null)
|
||||
{
|
||||
httpPort = httpPortAttr;
|
||||
}
|
||||
|
||||
// restore optional fields when possible
|
||||
if ((httpPathAttr == null) && (url != null))
|
||||
{
|
||||
if (url.IsAbsoluteUri)
|
||||
{
|
||||
httpPath = url.LocalPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
var idx = url.OriginalString.IndexOf('?');
|
||||
if (idx != -1)
|
||||
{
|
||||
httpPath = url.OriginalString.Substring(0, idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
httpPath = url.OriginalString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (url == null)
|
||||
{
|
||||
var urlString = string.Empty;
|
||||
if (!string.IsNullOrEmpty(httpHost))
|
||||
{
|
||||
urlString += "https://" + httpHost;
|
||||
|
||||
if (!string.IsNullOrEmpty(httpPort))
|
||||
{
|
||||
urlString += ":" + httpPort;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(httpPath))
|
||||
{
|
||||
if (httpPath[0] != '/')
|
||||
{
|
||||
urlString += '/';
|
||||
}
|
||||
|
||||
urlString += httpPath;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(urlString))
|
||||
{
|
||||
Uri.TryCreate(urlString, UriKind.RelativeOrAbsolute, out url);
|
||||
}
|
||||
}
|
||||
|
||||
// overwriting
|
||||
if (httpPath != null || httpMethod != null || httpRoute != null)
|
||||
{
|
||||
if (httpRoute != null)
|
||||
{
|
||||
telemetry.Name = (httpMethod + " " + httpRoute).Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
telemetry.Name = (httpMethod + " " + httpPath).Trim();
|
||||
}
|
||||
}
|
||||
|
||||
if (telemetry is DependencyTelemetry dependency)
|
||||
{
|
||||
if (url != null)
|
||||
{
|
||||
dependency.Data = url.OriginalString;
|
||||
dependency.Target = url.IsAbsoluteUri ? url.Authority : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
dependency.Data = null;
|
||||
dependency.Target = null;
|
||||
}
|
||||
|
||||
dependency.ResultCode = resultCode;
|
||||
|
||||
if (string.IsNullOrEmpty(dependency.Type))
|
||||
{
|
||||
dependency.Type = HttpDependencyType;
|
||||
}
|
||||
}
|
||||
else if (telemetry is RequestTelemetry request)
|
||||
{
|
||||
if (url != null)
|
||||
{
|
||||
request.Url = url;
|
||||
}
|
||||
|
||||
request.ResponseCode = resultCode;
|
||||
request.Context.Operation.Name = request.Name;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetEventHubsProperties(SpanData span, OperationTelemetry telemetry)
|
||||
{
|
||||
string endpoint = null;
|
||||
string queueName = null;
|
||||
|
||||
foreach (var attribute in span.Attributes)
|
||||
{
|
||||
if (attribute.Key == "peer.address" && attribute.Value is string)
|
||||
{
|
||||
endpoint = (string)attribute.Value;
|
||||
}
|
||||
else if (attribute.Key == "message_bus.destination")
|
||||
{
|
||||
queueName = (string)attribute.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPropertyWithAdjustedName(telemetry.Properties, attribute.Key, attribute.Value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
string eventHubsInfo = null;
|
||||
|
||||
// Target/source uniquely identifies the resource, we use both: queueName and endpoint
|
||||
if (endpoint != null && queueName != null)
|
||||
{
|
||||
eventHubsInfo = string.Concat(endpoint, "/", queueName);
|
||||
}
|
||||
|
||||
if (telemetry is DependencyTelemetry dependency)
|
||||
{
|
||||
dependency.Type = dependency.Type == QueueMessageDependencyType ? string.Concat(dependency.Type, " | ", EventHubsDependencyType) : EventHubsDependencyType;
|
||||
if (eventHubsInfo != null)
|
||||
{
|
||||
dependency.Target = eventHubsInfo;
|
||||
}
|
||||
}
|
||||
else if (telemetry is RequestTelemetry request)
|
||||
{
|
||||
if (eventHubsInfo != null)
|
||||
{
|
||||
request.Source = eventHubsInfo;
|
||||
}
|
||||
|
||||
if (this.TryGetAverageTimeInQueueForBatch(span, out long enqueuedTime))
|
||||
{
|
||||
request.Metrics["timeSinceEnqueued"] = enqueuedTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetAverageTimeInQueueForBatch(SpanData span, out long avgTimeInQueue)
|
||||
{
|
||||
avgTimeInQueue = 0;
|
||||
int linksCount = 0;
|
||||
foreach (var link in span.Links)
|
||||
{
|
||||
if (!this.TryGetEnqueuedTime(link, out var msgEnqueuedTime))
|
||||
{
|
||||
// instrumentation does not consistently report enqueued time, ignoring whole span
|
||||
return false;
|
||||
}
|
||||
|
||||
avgTimeInQueue += Math.Max(span.StartTimestamp.ToUnixTimeMilliseconds() - msgEnqueuedTime, 0);
|
||||
linksCount++;
|
||||
}
|
||||
|
||||
if (linksCount == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
avgTimeInQueue /= linksCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetEnqueuedTime(Link link, out long enqueuedTime)
|
||||
{
|
||||
enqueuedTime = 0;
|
||||
foreach (var attribute in link.Attributes)
|
||||
{
|
||||
if (attribute.Key == "enqueuedTime")
|
||||
{
|
||||
if (attribute.Value is string strValue)
|
||||
{
|
||||
return long.TryParse(strValue, out enqueuedTime);
|
||||
}
|
||||
|
||||
// future case
|
||||
if (attribute.Value is long longValue)
|
||||
{
|
||||
enqueuedTime = longValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetComponent(SpanData span)
|
||||
{
|
||||
foreach (var attr in span.Attributes)
|
||||
{
|
||||
if (attr.Key == "component" && attr.Value is string strValue)
|
||||
{
|
||||
return strValue;
|
||||
}
|
||||
|
||||
if (attr.Key == "az.namespace" && attr.Value is string azNamespace)
|
||||
{
|
||||
return azNamespace;
|
||||
}
|
||||
|
||||
if (attr.Key.StartsWith("http."))
|
||||
{
|
||||
return "http";
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net46;netstandard2.0</TargetFrameworks>
|
||||
<Description>Application Insights exporter for Open Telemetry.</Description>
|
||||
<PackageTags>$(PackageTags);application-insights;azure;distributed-tracing</PackageTags>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="Implementation\**" />
|
||||
<EmbeddedResource Remove="Implementation\**" />
|
||||
<None Remove="Implementation\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenTelemetry\OpenTelemetry.csproj" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.11.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
|
||||
// Copyright 2018, 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.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.ApplicationInsights.Tests" + AssemblyInfo.PublicKey)]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)]
|
||||
|
||||
#if SIGNED
|
||||
internal static class AssemblyInfo
|
||||
{
|
||||
public const string PublicKey = ", PublicKey=002400000480000094000000060200000024000052534131000400000100010051C1562A090FB0C9F391012A32198B5E5D9A60E9B80FA2D7B434C9E5CCB7259BD606E66F9660676AFC6692B8CDC6793D190904551D2103B7B22FA636DCBB8208839785BA402EA08FC00C8F1500CCEF28BBF599AA64FFB1E1D5DC1BF3420A3777BADFE697856E9D52070A50C3EA5821C80BEF17CA3ACFFA28F89DD413F096F898";
|
||||
public const string MoqPublicKey = ", PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7";
|
||||
}
|
||||
#else
|
||||
internal static class AssemblyInfo
|
||||
{
|
||||
public const string PublicKey = "";
|
||||
public const string MoqPublicKey = "";
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
# Using OpenTelemetry with Application Insights
|
||||
|
||||
## Create Application Insights resource
|
||||
If you don't have resource yet [create one](https://docs.microsoft.com/en-us/azure/azure-monitor/app/create-new-resource).
|
||||
|
||||
## Setup for applications with dependency injection
|
||||
|
||||
If you have ASP.NET Core web application or worker service, or if you simply use use `Microsoft.Extensions.DependencyInjection`,
|
||||
just call `AddOpenTelemetry` during host builder configuration in `ConfigureServices` (in `Startup` or `Program`).
|
||||
|
||||
1. Install packages (latest version)
|
||||
``` xml
|
||||
<PackageReference Include="OpenTelemetry" Version="0.2.0-alpha.182" />
|
||||
<PackageReference Include="OpenTelemetry.Adapter.AspNetCore" Version="0.2.0-alpha.182" />
|
||||
<PackageReference Include="OpenTelemetry.Adapter.Dependencies" Version="0.2.0-alpha.182" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.ApplicationInsights" Version="0.2.0-alpha.182" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="0.2.0-alpha.182" />
|
||||
```
|
||||
|
||||
2. Set up OpenTelemetry
|
||||
```csharp
|
||||
services.AddOpenTelemetry((sp, builder) =>
|
||||
{
|
||||
builder
|
||||
.SetResource(Resources.CreateServiceResource("my-service")) // set any service name as you would like to appear on the Application Map
|
||||
.UseApplicationInsights(telemetryConfiguration =>
|
||||
{
|
||||
telemetryConfiguration.InstrumentationKey = Configuration.GetValue<string>("ApplicationInsights:InstrumentationKey");
|
||||
})
|
||||
.AddRequestAdapter() // regirsters ASP.NET Core incoming requests tracking
|
||||
.AddDependencyAdapter(); // regirsters outgoing requests tracking
|
||||
});
|
||||
```
|
||||
|
||||
## Applications without dependency injection
|
||||
|
||||
1. Install OpenTelemetry packages (latest version)
|
||||
|
||||
``` xml
|
||||
<PackageReference Include="OpenTelemetry" Version="0.2.0-alpha.182" />
|
||||
<PackageReference Include="OpenTelemetry.Adapter.Dependencies" Version="0.2.0-alpha.182" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.ApplicationInsights" Version="0.2.0-alpha.182" />
|
||||
```
|
||||
|
||||
2. Create `TraceFactory` and make sure to keep it alive during application lifetime.
|
||||
Avoid creating multiple `TracerFactories` and dispose factory before application exits.
|
||||
|
||||
```csharp
|
||||
var tracerFactory = TracerFactory.Create(builder =>
|
||||
builder
|
||||
.SetResource(Resources.CreateServiceResource("my-service")) // set any service name as you would like to appear on the Application Map
|
||||
.UseApplicationInsights(telemetryConfiguration =>
|
||||
{
|
||||
telemetryConfiguration.InstrumentationKey = "your instrumentation key";
|
||||
})
|
||||
.AddDependencyAdapter(); // regirsters outgoing requests tracking
|
||||
|
||||
var tracer = tracerFactory.GetTracer("http-client-test");
|
||||
|
||||
// start root span
|
||||
using (tracer.StartActiveSpan("root span", out _))
|
||||
{
|
||||
// do stuff, start other spans, etc
|
||||
}
|
||||
|
||||
// dispose before exit to flush all spans
|
||||
tracerFactory.Dispose();
|
||||
```
|
||||
|
||||
### Export exception and logs from ILogger
|
||||
|
||||
OpenTelemetry does not support logging yet, but you can export your logs to Application Insights.
|
||||
Here is [more info](https://docs.microsoft.com/en-us/azure/azure-monitor/app/ilogger) on ILogger support with Application Insights.
|
||||
|
||||
Logs will be correlated to the OpenTelemetry spans.
|
||||
|
||||
1. In addition to OpenTelemetry packages, install `Microsoft.Extensions.Logging.ApplicationInsights` (latest).
|
||||
```xml
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.ApplicationInsights" Version="2.12.1" />
|
||||
```
|
||||
|
||||
2. Configure logging per [documentation](https://docs.microsoft.com/en-us/azure/azure-monitor/app/ilogger).
|
||||
|
||||
Here is the full example:
|
||||
|
||||
```csharp
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
//....
|
||||
.ConfigureServices((context, services) =>
|
||||
{
|
||||
var instrumentationKey = context.Configuration.GetValue<string>("ApplicationInsights:InstrumentationKey");
|
||||
|
||||
// set up OpenTelemetry
|
||||
services.AddOpenTelemetry(b => b
|
||||
.SetResource(Resources.CreateServiceResource("line-counter")) // use unique name
|
||||
.UseApplicationInsights(o => o.InstrumentationKey = instrumentationKey)
|
||||
.AddDependencyAdapter()
|
||||
.AddRequestAdapter());
|
||||
|
||||
// set up correlation between spans and logs
|
||||
services.Configure<TelemetryConfiguration>(telemetryConfiguration =>
|
||||
{
|
||||
telemetryConfiguration.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
|
||||
});
|
||||
})
|
||||
.ConfigureLogging((context, builder) =>
|
||||
{
|
||||
var instrumentationKey = context.Configuration.GetValue<string>("ApplicationInsights:InstrumentationKey");
|
||||
|
||||
// configure Application Insights provider for ILogger
|
||||
builder.AddApplicationInsights(instrumentationKey);
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
// <copyright file="TracerBuilderExtensions.cs" company="OpenTelemetry Authors">
|
||||
// Copyright 2018, 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 Microsoft.ApplicationInsights.Extensibility;
|
||||
using OpenTelemetry.Exporter.ApplicationInsights;
|
||||
using OpenTelemetry.Trace.Export;
|
||||
|
||||
namespace OpenTelemetry.Trace.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods to simplify registering of Application Insights exporter.
|
||||
/// </summary>
|
||||
public static class TracerBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables Application Insights exporter.
|
||||
/// </summary>
|
||||
/// <param name="builder">Trace builder to use.</param>
|
||||
/// <param name="configure">Configuration options.</param>
|
||||
/// <returns>The instance of <see cref="TracerBuilder"/> to chain the calls.</returns>
|
||||
public static TracerBuilder UseApplicationInsights(this TracerBuilder builder, Action<TelemetryConfiguration> configure)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(builder));
|
||||
}
|
||||
|
||||
if (configure == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configure));
|
||||
}
|
||||
|
||||
var configuration = new TelemetryConfiguration();
|
||||
configure(configuration);
|
||||
return builder.AddProcessorPipeline(b => b
|
||||
.SetExporter(new ApplicationInsightsTraceExporter(configuration))
|
||||
.SetExportingProcessor(e => new BatchingSpanProcessor(e)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables Application Insights exporter.
|
||||
/// </summary>
|
||||
/// <param name="builder">Trace builder to use.</param>
|
||||
/// <param name="applicationInsightsConfigure">Configuration options.</param>
|
||||
/// <param name="processorConfigure">Span processor configuration.</param>
|
||||
/// <returns>The instance of <see cref="TracerBuilder"/> to chain the calls.</returns>
|
||||
public static TracerBuilder UseApplicationInsights(this TracerBuilder builder, Action<TelemetryConfiguration> applicationInsightsConfigure, Action<
|
||||
SpanProcessorPipelineBuilder> processorConfigure)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(builder));
|
||||
}
|
||||
|
||||
if (applicationInsightsConfigure == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(applicationInsightsConfigure));
|
||||
}
|
||||
|
||||
if (processorConfigure == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(processorConfigure));
|
||||
}
|
||||
|
||||
var options = new TelemetryConfiguration();
|
||||
applicationInsightsConfigure(options);
|
||||
return builder.AddProcessorPipeline(b =>
|
||||
{
|
||||
b.SetExporter(new ApplicationInsightsTraceExporter(options));
|
||||
processorConfigure.Invoke(b);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,34 +11,6 @@ There is also a constructor for specifying path to the service account credentia
|
|||
4. Instantiate a new instance of `StackdriverExporter` with your Google Cloud's ProjectId
|
||||
5. See [sample][stackdriver-sample] for example use.
|
||||
|
||||
### Advanced configuration
|
||||
|
||||
You may want to filter on enrich spans and send them to multiple destinations (e.g. for debugging or telemetry self-diagnostics purposes).
|
||||
You may configure multiple processing pipelines for each destination like shown in below example.
|
||||
|
||||
In this example
|
||||
|
||||
1. First pipeline sends all sampled in spans to Zipkin
|
||||
2. Second pipeline sends spans to ApplicationInsights, but filters them first with custom built `FilteringSpanProcessor`
|
||||
3. Third pipeline adds custom `DebuggingSpanProcessor` that simply logs all calls to debug output
|
||||
|
||||
```csharp
|
||||
using (var tracerFactory = TracerFactory.Create(builder => builder
|
||||
.UseZipkin(o =>
|
||||
{
|
||||
o.Endpoint = new Uri(zipkinUri);
|
||||
})
|
||||
.UseApplicationInsights(
|
||||
o => o.InstrumentationKey = "your-instrumentation-key",
|
||||
p => p.AddProcessor(nextProcessor => new FilteringSpanProcessor(nextProcessor)))
|
||||
.AddProcessorPipeline(pipelineBuilder => pipelineBuilder.AddProcessor(_ => new DebuggingSpanProcessor()))))
|
||||
.SetResource(Resources.CreateServiceResource("test-zipkin"))
|
||||
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### Traces
|
||||
|
||||
```csharp
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,95 +0,0 @@
|
|||
// <copyright file="StubTelemetryChannel.cs" company="OpenTelemetry Authors">
|
||||
// Copyright 2018, 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 theLicense 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 Microsoft.ApplicationInsights.Channel;
|
||||
using System;
|
||||
|
||||
namespace OpenTelemetry.Exporter.ApplicationInsights.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// A stub of <see cref="ITelemetryChannel"/>.
|
||||
/// </summary>
|
||||
public sealed class StubTelemetryChannel : ITelemetryChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StubTelemetryChannel"/> class.
|
||||
/// </summary>
|
||||
public StubTelemetryChannel()
|
||||
{
|
||||
OnSend = telemetry => { };
|
||||
OnFlush = () => { };
|
||||
OnDispose = () => { };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this channel is in developer mode.
|
||||
/// </summary>
|
||||
public bool? DeveloperMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the channel's URI. To this URI the telemetry is expected to be sent.
|
||||
/// </summary>
|
||||
public string EndpointAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to throw an error.
|
||||
/// </summary>
|
||||
public bool ThrowError { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the callback invoked by the <see cref="Send"/> method.
|
||||
/// </summary>
|
||||
public Action<ITelemetry> OnSend { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the callback invoked by the <see cref="Flush"/> method.
|
||||
/// </summary>
|
||||
public Action OnFlush { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the callback invoked by the <see cref="Dispose"/> method.
|
||||
/// </summary>
|
||||
public Action OnDispose { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="ITelemetryChannel.Send"/> method by invoking the <see cref="OnSend"/> callback.
|
||||
/// </summary>
|
||||
public void Send(ITelemetry item)
|
||||
{
|
||||
if (ThrowError)
|
||||
{
|
||||
throw new Exception("test error");
|
||||
}
|
||||
|
||||
OnSend(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="IDisposable.Dispose"/> method.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
OnDispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="ITelemetryChannel.Flush" /> method.
|
||||
/// </summary>
|
||||
public void Flush()
|
||||
{
|
||||
OnFlush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Description>Unit test project for ApplicationInsights Exporter for OpenTelemetry</Description>
|
||||
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
|
||||
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net46</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="xunit.runner.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\OpenTelemetry.Exporter.ApplicationInsights\OpenTelemetry.Exporter.ApplicationInsights.csproj" />
|
||||
<ProjectReference Include="..\..\src\OpenTelemetry\OpenTelemetry.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="Moq" Version="4.11.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="True" />
|
||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
// <copyright file="TracerBuilderConfigurationTests.cs" company="OpenTelemetry Authors">
|
||||
// Copyright 2018, 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 Microsoft.ApplicationInsights.Channel;
|
||||
|
||||
using OpenTelemetry.Trace;
|
||||
using OpenTelemetry.Trace.Configuration;
|
||||
using OpenTelemetry.Trace.Export;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.Exporter.ApplicationInsights.Tests
|
||||
{
|
||||
public class TracerBuilderConfigurationTest
|
||||
{
|
||||
[Fact]
|
||||
public void UseApplicationInsights_ConfiguresExporter()
|
||||
{
|
||||
var sentItems = new ConcurrentQueue<ITelemetry>();
|
||||
|
||||
ITelemetryChannel channel = new StubTelemetryChannel
|
||||
{
|
||||
OnSend = t => sentItems.Enqueue(t),
|
||||
EndpointAddress = "http://foo",
|
||||
};
|
||||
|
||||
var tracer = TracerFactory.Create(b => b
|
||||
.UseApplicationInsights(
|
||||
o => o.TelemetryChannel = channel,
|
||||
p => p.SetExportingProcessor(e => new SimpleSpanProcessor(e))))
|
||||
.GetTracer(null);
|
||||
|
||||
tracer.StartSpan("foo").End();
|
||||
|
||||
Assert.Single(sentItems);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UseApplicationInsights_BadArgs()
|
||||
{
|
||||
TracerBuilder builder = null;
|
||||
Assert.Throws<ArgumentNullException>(() => builder.UseApplicationInsights(_ => { }));
|
||||
Assert.Throws<ArgumentNullException>(() => TracerFactory.Create(b => b.UseApplicationInsights(null)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"parallelizeTestCollections": true
|
||||
}
|
||||
Loading…
Reference in New Issue