Skip to content

Commit

Permalink
RDINC-847 Open Tracing draft version
Browse files Browse the repository at this point in the history
  • Loading branch information
fraliv13 committed Mar 25, 2019
1 parent d80b636 commit aaddbc0
Show file tree
Hide file tree
Showing 16 changed files with 406 additions and 2 deletions.
3 changes: 2 additions & 1 deletion Directory.Build.props
@@ -1,7 +1,8 @@
<Project>
<Import Project="dependencies.props" />
<PropertyGroup>
<Version>$(GitVersion_NuGetVersion)</Version>
<!--<Version>$(GitVersion_NuGetVersion)</Version>-->
<Version>3.5.1-alpha.2</Version>
<Authors>Totalsoft</Authors>
<Company>Totalsoft</Company>
<PackageTags>totalsoft charisma</PackageTags>
Expand Down
19 changes: 18 additions & 1 deletion NBB.sln
Expand Up @@ -277,10 +277,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NBB.Worker", "template\Work
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{FF63A085-1882-4B60-8EF0-F416990EDCEB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NBB.Tools.AutoMapperExtensions.Tests", "test\UnitTests\Tools\NBB.Tools.AutoMapperExtensions.Tests\NBB.Tools.AutoMapperExtensions.Tests.csproj", "{A0D92D4E-A1FD-48A6-A59D-21082695ECAC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NBB.Tools.AutoMapperExtensions.Tests", "test\UnitTests\Tools\NBB.Tools.AutoMapperExtensions.Tests\NBB.Tools.AutoMapperExtensions.Tests.csproj", "{A0D92D4E-A1FD-48A6-A59D-21082695ECAC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NBB.Tools.AutoMapperExtensions", "src\Tools\NBB.Tools.AutomapperExtensions\NBB.Tools.AutoMapperExtensions.csproj", "{9B8B7158-4194-442F-83D7-346FDFF51DB1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NBB.Messaging.OpenTracing", "src\Messaging\NBB.Messaging.OpenTracing\NBB.Messaging.OpenTracing.csproj", "{B5C4D462-E7AF-4146-9618-75FF242E148C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Serilog", "Serilog", "{48E5BC6A-5846-4AD7-BFFB-C1D04C5C1BC2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NBB.Tools.Serilog.OpenTracingSink", "src\Tools\Serilog\NBB.Tools.Serilog.OpenTracingSink\NBB.Tools.Serilog.OpenTracingSink.csproj", "{9DDF53B1-7728-4CF3-BEBE-2057A6956F59}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -645,6 +651,14 @@ Global
{9B8B7158-4194-442F-83D7-346FDFF51DB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B8B7158-4194-442F-83D7-346FDFF51DB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B8B7158-4194-442F-83D7-346FDFF51DB1}.Release|Any CPU.Build.0 = Release|Any CPU
{B5C4D462-E7AF-4146-9618-75FF242E148C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B5C4D462-E7AF-4146-9618-75FF242E148C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B5C4D462-E7AF-4146-9618-75FF242E148C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B5C4D462-E7AF-4146-9618-75FF242E148C}.Release|Any CPU.Build.0 = Release|Any CPU
{9DDF53B1-7728-4CF3-BEBE-2057A6956F59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9DDF53B1-7728-4CF3-BEBE-2057A6956F59}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9DDF53B1-7728-4CF3-BEBE-2057A6956F59}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9DDF53B1-7728-4CF3-BEBE-2057A6956F59}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -773,6 +787,9 @@ Global
{FF63A085-1882-4B60-8EF0-F416990EDCEB} = {90E022FB-CA1B-49DD-9BEA-CE7F8E74E8BB}
{A0D92D4E-A1FD-48A6-A59D-21082695ECAC} = {FF63A085-1882-4B60-8EF0-F416990EDCEB}
{9B8B7158-4194-442F-83D7-346FDFF51DB1} = {70EA3420-74E3-4C9D-9858-57EC01AD31B3}
{B5C4D462-E7AF-4146-9618-75FF242E148C} = {584C62C0-2AE6-4DD6-9BCF-8FF28B7122CE}
{48E5BC6A-5846-4AD7-BFFB-C1D04C5C1BC2} = {70EA3420-74E3-4C9D-9858-57EC01AD31B3}
{9DDF53B1-7728-4CF3-BEBE-2057A6956F59} = {48E5BC6A-5846-4AD7-BFFB-C1D04C5C1BC2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {23A42379-616A-43EF-99BC-803DF151F54E}
Expand Down
3 changes: 3 additions & 0 deletions dependencies.props
Expand Up @@ -17,5 +17,8 @@
<SerilogSinksMSSqlServerPackageVersion>5.1.2</SerilogSinksMSSqlServerPackageVersion>
<SerilogAspNetCorePackageVersion>2.1.1</SerilogAspNetCorePackageVersion>
<AutoMapperPackageVersion>8.0.0</AutoMapperPackageVersion>
<OpenTracingPackageVersion>0.12.0</OpenTracingPackageVersion>
<OpenTracingContribPackageVersion>0.5.0</OpenTracingContribPackageVersion>
<JaegerPackageVersion>0.2.2</JaegerPackageVersion>
</PropertyGroup>
</Project>
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="OpenTracing" Version="$(OpenTracingPackageVersion)" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Core\NBB.Core.Pipeline\NBB.Core.Pipeline.csproj" />
<ProjectReference Include="..\..\Correlation\NBB.Correlation\NBB.Correlation.csproj" />
<ProjectReference Include="..\NBB.Messaging.Abstractions\NBB.Messaging.Abstractions.csproj" />
</ItemGroup>

</Project>
@@ -0,0 +1,66 @@
using NBB.Core.Abstractions;
using NBB.Correlation;
using NBB.Messaging.Abstractions;
using NBB.Messaging.DataContracts;
using OpenTracing;
using OpenTracing.Propagation;
using OpenTracing.Tag;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace NBB.Messaging.OpenTracing.Publisher
{
public class OpenTracingPublisherDecorator : IMessageBusPublisher
{
private readonly IMessageBusPublisher _inner;
private readonly ITracer _tracer;

public OpenTracingPublisherDecorator(IMessageBusPublisher inner, ITracer tracer)
{
_inner = inner;
_tracer = tracer;
}

public Task PublishAsync<T>(T message, CancellationToken cancellationToken, Action<MessagingEnvelope> customizer = null, string topicName = null)
{
void NewCustomizer(MessagingEnvelope outgoingEnvelope)
{
if (_tracer.ActiveSpan != null)
{
_tracer.Inject(_tracer.ActiveSpan.Context, BuiltinFormats.TextMap,
new TextMapInjectAdapter(outgoingEnvelope.Headers));
}

customizer?.Invoke(outgoingEnvelope);
}

string operationName = $"Publisher {message.GetType().GetPrettyName()}";
using (var scope = _tracer.BuildSpan(operationName)
.WithTag(Tags.Component, "NBB.Messaging.Publisher")
.WithTag(Tags.SpanKind, Tags.SpanKindServer)
.WithTag("correlationId", CorrelationManager.GetCorrelationId()?.ToString())
.StartActive(finishSpanOnDispose: true))
{
try
{
return _inner.PublishAsync(message, cancellationToken, NewCustomizer);
}
catch (Exception exception)
{
scope.Span.Log(new Dictionary<string, object>(3)
{
{ LogFields.Event, Tags.Error.Key },
{ LogFields.ErrorKind, exception.GetType().Name },
{ LogFields.ErrorObject, exception }
});

scope.Span.SetTag(Tags.Error, true);

throw;
}
}
}
}
}
@@ -0,0 +1,21 @@
using NBB.Core.Pipeline;
using NBB.Messaging.DataContracts;

namespace NBB.Messaging.OpenTracing.Subscriber
{
public static class MessagingPipelineExtensions
{
/// <summary>
/// Adds to the pipeline a middleware that creates an OpenTracing span.
/// </summary>
/// <param name="pipelineBuilder">The pipeline builder.</param>
/// <returns>The pipeline builder for further configuring the pipeline. It is used used in the fluent configuration API.</returns>
public static IPipelineBuilder<MessagingEnvelope> UseOpenTracing(
this IPipelineBuilder<MessagingEnvelope> pipelineBuilder)
=> UseMiddleware<OpenTracingMiddleware>(pipelineBuilder);


private static IPipelineBuilder<MessagingEnvelope> UseMiddleware<TMiddleware>(this IPipelineBuilder<MessagingEnvelope> pipelineBuilder) where TMiddleware : IPipelineMiddleware<MessagingEnvelope>
=> pipelineBuilder.UseMiddleware<TMiddleware, MessagingEnvelope>();
}
}
@@ -0,0 +1,58 @@
using NBB.Core.Pipeline;
using NBB.Messaging.DataContracts;
using OpenTracing;
using OpenTracing.Propagation;
using OpenTracing.Tag;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using NBB.Core.Abstractions;
using NBB.Correlation;
using NBB.Messaging.Abstractions;

namespace NBB.Messaging.OpenTracing.Subscriber
{
public class OpenTracingMiddleware : IPipelineMiddleware<MessagingEnvelope>
{
private readonly ITracer _tracer;

public OpenTracingMiddleware(ITracer tracer)
{
_tracer = tracer;
}

public async Task Invoke(MessagingEnvelope data, CancellationToken cancellationToken, Func<Task> next)
{
var extractedSpanContext = _tracer.Extract(BuiltinFormats.TextMap, new TextMapExtractAdapter(data.Headers));
string operationName = $"Subscriber {data.Payload.GetType().GetPrettyName()}";

using(var scope = _tracer.BuildSpan(operationName)
.AsChildOf(extractedSpanContext)
.WithTag(Tags.Component, "NBB.Messaging.Subscriber")
.WithTag(Tags.SpanKind, Tags.SpanKindServer)
.WithTag("correlationId", CorrelationManager.GetCorrelationId()?.ToString())
.StartActive(finishSpanOnDispose: true)) {

try
{
await next();
}
catch (Exception exception)
{
scope.Span.Log(new Dictionary<string, object>(3)
{
{ LogFields.Event, Tags.Error.Key },
{ LogFields.ErrorKind, exception.GetType().Name },
{ LogFields.ErrorObject, exception }
});

scope.Span.SetTag(Tags.Error, true);

throw;
}
}
return;
}
}
}
@@ -0,0 +1,30 @@
using System.Collections.Generic;
using System.Linq;
using Serilog.Events;

namespace NBB.Tools.Serilog.OpenTracingSink.Internal
{
internal static class OpenTracingContribFilter
{
private static List<string> ExcludedLogSources = new List<string>()
{
"Microsoft.EntityFrameworkCore",
"Microsoft.AspNetCore.Hosting"
};


public static bool ShouldExclude(LogEvent logEvent)
{
const string sourceContextPropertyName = global::Serilog.Core.Constants.SourceContextPropertyName;

if (!logEvent.Properties.TryGetValue(sourceContextPropertyName, out var source) ||
!(source is ScalarValue scalarSource) ||
!(scalarSource.Value is string stringValue))
{
return false;
}

return ExcludedLogSources.Any(x => stringValue.StartsWith(x));
}
}
}
@@ -0,0 +1,68 @@
using OpenTracing;
using OpenTracing.Util;
using Serilog.Core;
using Serilog.Events;
using System;
using System.Collections.Generic;

namespace NBB.Tools.Serilog.OpenTracingSink.Internal
{
internal class OpenTracingSink : ILogEventSink
{
private readonly ITracer _tracer;
private readonly Func<LogEvent, bool> _filter;

public OpenTracingSink(Func<LogEvent, bool> filter = null)
{
_tracer = GlobalTracer.Instance;
_filter = filter ?? (logEvent => false);
}

public void Emit(LogEvent logEvent)
{
ISpan span = _tracer.ActiveSpan;

if (span == null)
{
// Creating a new span for a log message seems brutal so we ignore messages if we can't attach it to an active span.
return;
}

if (_tracer.IsNoopTracer())
{
return;
}

if (_filter(logEvent))
{
return;
}

var fields = new Dictionary<string, object>();

try
{
fields[LogFields.Event] = "log";
fields[LogFields.Message] = logEvent.RenderMessage();
fields["level"] = logEvent.Level;

if (logEvent.Exception != null)
{
fields[LogFields.ErrorKind] = logEvent.Exception.GetType().FullName;
fields[LogFields.ErrorObject] = logEvent.Exception;
}

foreach (var property in logEvent.Properties)
{
fields[property.Key] = property.Value.ToString();
}
}
catch (Exception logException)
{
fields["opentracing.contrib.netcore.error"] = logException.ToString();
}

span.Log(fields);
}
}
}
@@ -0,0 +1,20 @@
using OpenTracing;
using OpenTracing.Noop;
using OpenTracing.Util;

namespace NBB.Tools.Serilog.OpenTracingSink.Internal
{
internal static class TracerExtensions
{
public static bool IsNoopTracer(this ITracer tracer)
{
if (tracer is NoopTracer)
return true;

if (tracer is GlobalTracer && !GlobalTracer.IsRegistered())
return true;

return false;
}
}
}
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="OpenTracing" Version="$(OpenTracingPackageVersion)" />
<PackageReference Include="Serilog" Version="$(SerilogPackageVersion)" />
</ItemGroup>
</Project>
@@ -0,0 +1,28 @@
using NBB.Tools.Serilog.OpenTracingSink.Internal;
using Serilog;
using Serilog.Configuration;
using Serilog.Core;
using Serilog.Events;
using System;

namespace NBB.Tools.Serilog.OpenTracingSink
{
public static class OpenTracingConfigurationExtensions
{
public static LoggerConfiguration OpenTracing(
this LoggerSinkConfiguration sinkConfiguration,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
LoggingLevelSwitch levelSwitch = null,
bool exludeOpenTracingContribEvents = true
)
{
if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));

var sink = exludeOpenTracingContribEvents ?
new Internal.OpenTracingSink(OpenTracingContribFilter.ShouldExclude) :
new Internal.OpenTracingSink();

return sinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch);
}
}
}

0 comments on commit aaddbc0

Please sign in to comment.