Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
warning-explosive committed Mar 26, 2023
1 parent 4f34ea1 commit e825094
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 55 deletions.
3 changes: 0 additions & 3 deletions Endpoints/GenericEndpoint.Host/GenericEndpoint.Host.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@
</PackageReference>
<PackageReference Include="OpenTelemetry" Version="1.4.0" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.4.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.0.0-rc9.14" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc9.14" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.1.0-rc.2" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
88 changes: 41 additions & 47 deletions Endpoints/GenericEndpoint.Host/HostExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,52 +134,6 @@ internal static void CheckDuplicates(this IHostBuilder hostBuilder, EndpointIden
}
}

internal static ITelemetry SetupTelemetry(
this IHostBuilder hostBuilder,
EndpointIdentity endpointIdentity,
Assembly assembly)
{
var serviceName = endpointIdentity.LogicalName;

var version = assembly.GetCustomAttribute<AssemblyVersionAttribute>()?.Version
?? assembly.GetCustomAttribute<AssemblyFileVersionAttribute>()?.Version
?? assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion
?? "1.0.0.0";

var resourceBuilder = ResourceBuilder
.CreateDefault()
.AddService(
serviceVersion: version,
serviceName: endpointIdentity.LogicalName,
serviceInstanceId: endpointIdentity.InstanceName,
autoGenerateServiceInstanceId: false);

var tracerProvider = OpenTelemetry.Sdk
.CreateTracerProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddSource(serviceName)
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter()
.Build();

var meterProvider = OpenTelemetry.Sdk
.CreateMeterProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddMeter(serviceName)
.AddRuntimeInstrumentation()
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter()
.Build();

return new Telemetry(
tracerProvider!,
tracerProvider.GetTracer(serviceName, version),
meterProvider!,
new Meter(serviceName, version));
}

private static IDependencyContainer BuildDependencyContainer(EndpointOptions options)
{
return DependencyContainer.CreateBoundedAbove(
Expand All @@ -201,7 +155,7 @@ private static IEndpointBuilder ConfigureBuilder(
var integrationTransportInjection = hostBuilder.GetIntegrationTransportInjection();
var settingsDirectoryProvider = hostBuilder.GetSettingsDirectoryProvider();
var frameworkDependenciesProvider = hostBuilder.GetFrameworkDependenciesProvider();
var telemetry = hostBuilder.SetupTelemetry(endpointIdentity, assembly);
var telemetry = SetupTelemetry(endpointIdentity, assembly);

return new EndpointBuilder(endpointIdentity)
.WithEndpointPluginAssemblies(crossCuttingConcernsAssembly)
Expand All @@ -227,5 +181,45 @@ private static IManualRegistration GetIntegrationTransportInjection(this IHostBu

throw new InvalidOperationException(RequireUseTransportCall.Format(RequireTransportInjection));
}

private static ITelemetry SetupTelemetry(
EndpointIdentity endpointIdentity,
Assembly assembly)
{
var serviceName = endpointIdentity.LogicalName;

var version = assembly.GetCustomAttribute<AssemblyVersionAttribute>()?.Version
?? assembly.GetCustomAttribute<AssemblyFileVersionAttribute>()?.Version
?? assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion
?? "1.0.0.0";

var resourceBuilder = ResourceBuilder
.CreateDefault()
.AddService(
serviceVersion: version,
serviceName: endpointIdentity.LogicalName,
serviceInstanceId: endpointIdentity.InstanceName,
autoGenerateServiceInstanceId: false);

var tracerProvider = OpenTelemetry.Sdk
.CreateTracerProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddSource(serviceName)
.AddOtlpExporter()
.Build();

var meterProvider = OpenTelemetry.Sdk
.CreateMeterProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddMeter(serviceName)
.AddOtlpExporter()
.Build();

return new Telemetry(
tracerProvider!,
tracerProvider.GetTracer(serviceName, version),
meterProvider!,
new Meter(serviceName, version));
}
}
}
33 changes: 33 additions & 0 deletions Endpoints/GenericEndpoint.Messaging/MessageHeaders/TraceContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace SpaceEngineers.Core.GenericEndpoint.Messaging.MessageHeaders
{
using System.Collections.Generic;
using System.Linq;
using Basics;

/// <summary>
/// TraceContext
/// </summary>
public class TraceContext : IIntegrationMessageHeader
{
/// <summary> .cctor </summary>
/// <param name="value">Trace context attributes</param>
public TraceContext(Dictionary<string, object> value)
{
Value = value;
}

/// <summary>
/// Trace context attributes
/// </summary>
public Dictionary<string, object> Value { get; }

/// <inheritdoc />
public string StringValue => Value.Select(pair => pair.ToString()).ToString(", ");

/// <inheritdoc />
public override string ToString()
{
return $"[{nameof(TraceContext)}:{StringValue}]";
}
}
}
23 changes: 21 additions & 2 deletions Endpoints/GenericEndpoint/Pipeline/0_TracingMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ namespace SpaceEngineers.Core.GenericEndpoint.Pipeline;

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AutoRegistration.Api.Abstractions;
using AutoRegistration.Api.Attributes;
using AutoRegistration.Api.Enumerations;
using Contract.Abstractions;
using Endpoint;
using Messaging;
using Messaging.MessageHeaders;
using OpenTelemetry;
using OpenTelemetry.Context.Propagation;
using OpenTelemetry.Trace;

/// <summary>
Expand All @@ -29,19 +36,31 @@ public TracingMiddleware(
}

/// <inheritdoc />
[SuppressMessage("Analysis", "CA1308", Justification = "conventional attributes")]
public async Task Handle(
IAdvancedIntegrationContext context,
Func<IAdvancedIntegrationContext, CancellationToken, Task> next,
CancellationToken token)
{
var parentContext = Propagators.DefaultTextMapPropagator.Extract(default, context.Message, ExtractTraceContext);
Baggage.Current = parentContext.Baggage;

var attributes = context
.Message
.Headers
.Select(pair => new KeyValuePair<string, object>($"Message.{pair.Key.Name}", pair.Value.StringValue));
.Select(pair => new KeyValuePair<string, object>($"messaging.message.header.{pair.Key.Name.ToLowerInvariant()}", pair.Value.StringValue));

using (_telemetry.Tracer.StartActiveSpan("MessageHandler", SpanKind.Server, initialAttributes: new SpanAttributes(attributes)))
using (_telemetry.Tracer.StartActiveSpan("MessageHandler", SpanKind.Server, new SpanContext(parentContext.ActivityContext), new SpanAttributes(attributes)))
{
await next(context, token).ConfigureAwait(false);
}
}

private static IEnumerable<string> ExtractTraceContext(IntegrationMessage message, string key)
{
if (message.ReadRequiredHeader<TraceContext>().Value.TryGetValue(key, out var value))
{
yield return (string)value;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
namespace SpaceEngineers.Core.GenericEndpoint.Pipeline
{
using System.Collections.Generic;
using Messaging;
using Messaging.MessageHeaders;
using OpenTelemetry;
using OpenTelemetry.Context.Propagation;
using OpenTelemetry.Trace;
using SpaceEngineers.Core.AutoRegistration.Api.Abstractions;
using SpaceEngineers.Core.AutoRegistration.Api.Attributes;
using SpaceEngineers.Core.AutoRegistration.Api.Enumerations;

[Component(EnLifestyle.Singleton)]
internal class TraceContextPropagationProvider : IIntegrationMessageHeaderProvider,
ICollectionResolvable<IIntegrationMessageHeaderProvider>
{
public void WriteHeaders(IntegrationMessage generalMessage, IntegrationMessage? initiatorMessage)
{
Propagators.DefaultTextMapPropagator.Inject(
new PropagationContext(Tracer.CurrentSpan.Context, Baggage.Current),
generalMessage,
InjectTraceContext);
}

private static void InjectTraceContext(IntegrationMessage message, string key, string value)
{
Dictionary<string, object> traceContextAttributes;

if (message.ReadHeader<TraceContext>() is { } traceContext)
{
traceContextAttributes = traceContext.Value;
}
else
{
traceContextAttributes = new Dictionary<string, object>();
message.WriteHeader(new TraceContext(traceContextAttributes));
}

traceContextAttributes[key] = value;
}
}
}
54 changes: 53 additions & 1 deletion Endpoints/IntegrationTransport.Host/HostExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace SpaceEngineers.Core.IntegrationTransport.Host
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Reflection;
using System.Threading;
Expand All @@ -13,13 +15,17 @@ namespace SpaceEngineers.Core.IntegrationTransport.Host
using CompositionRoot;
using GenericEndpoint.Contract;
using GenericEndpoint.Contract.Abstractions;
using GenericEndpoint.Endpoint;
using GenericEndpoint.Host;
using GenericEndpoint.Host.Builder;
using GenericEndpoint.Host.Registrations;
using GenericHost;
using GenericHost.Api;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using Overrides;
using Registrations;

Expand Down Expand Up @@ -159,7 +165,7 @@ private static ITransportEndpointBuilder ConfigureBuilder(

var settingsDirectoryProvider = hostBuilder.GetSettingsDirectoryProvider();
var frameworkDependenciesProvider = hostBuilder.GetFrameworkDependenciesProvider();
var telemetry = hostBuilder.SetupTelemetry(endpointIdentity, assembly);
var telemetry = SetupTelemetry(endpointIdentity, assembly);

return (ITransportEndpointBuilder)new TransportEndpointBuilder(endpointIdentity)
.WithEndpointPluginAssemblies(crossCuttingConcernsAssembly)
Expand Down Expand Up @@ -204,5 +210,51 @@ private static Type[] GetIntegrationTypes()
.Concat(domainEvents)
.ToArray();
}

[SuppressMessage("Analysis", "CA2000", Justification = "Meter will be disposed in outer scope by dependency container")]
private static ITelemetry SetupTelemetry(
EndpointIdentity endpointIdentity,
Assembly assembly)
{
var serviceName = endpointIdentity.LogicalName;

var version = assembly.GetCustomAttribute<AssemblyVersionAttribute>()?.Version
?? assembly.GetCustomAttribute<AssemblyFileVersionAttribute>()?.Version
?? assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion
?? "1.0.0.0";

var resourceBuilder = ResourceBuilder
.CreateDefault()
.AddService(
serviceVersion: version,
serviceName: endpointIdentity.LogicalName,
serviceInstanceId: endpointIdentity.InstanceName,
autoGenerateServiceInstanceId: false);

var tracerProvider = OpenTelemetry.Sdk
.CreateTracerProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddSource(serviceName)
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter()
.Build();

var meterProvider = OpenTelemetry.Sdk
.CreateMeterProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddMeter(serviceName)
.AddRuntimeInstrumentation()
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter()
.Build();

return new Telemetry(
tracerProvider!,
tracerProvider.GetTracer(serviceName, version),
meterProvider!,
new Meter(serviceName, version));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.0.0-rc9.14" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc9.14" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.1.0-rc.2" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
21 changes: 19 additions & 2 deletions docker-compose-webtest.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,39 @@
version: '3'
services:
postgres:
image: postgres
image: postgres:15.1-alpine
restart: unless-stopped
environment:
- POSTGRES_PASSWORD=Password12!
ports:
- '5432:5432'
rabbit:
image: rabbitmq:3-management
image: rabbitmq:3.11.11-management-alpine
restart: unless-stopped
ports:
- '15672:15672'
- '5672:5672'
jaeger:
image: jaegertracing/all-in-one:1.43.0
environment:
- COLLECTOR_ZIPKIN_HOST_PORT=:9411
- COLLECTOR_OTLP_ENABLED=true
ports:
- 6831:6831/udp # accept jaeger.thrift over Thrift-compact protocol
- 6832:6832/udp # accept jaeger.thrift over Thrift-binary protocol
- 5778:5778 # serve configs (sampling, etc.)
- 16686:16686 # serve frontend
- 4317:4317 # accept OpenTelemetry Protocol (OTLP) over gRPC, if enabled
- 4318:4318 # accept OpenTelemetry Protocol (OTLP) over HTTP, if enabled
- 14250:14250 # accept model.proto
- 14268:14268 # accept jaeger.thrift directly from clients
- 14269:14269 # ???
- 9411:9411 # Zipkin compatible endpoint (optional)
web-app:
depends_on:
- postgres
- rabbit
- jaeger
build:
dockerfile: Dockerfile.webtest
context: .
Expand Down

0 comments on commit e825094

Please sign in to comment.