Skip to content

Commit

Permalink
Enable Activity tracking on generic host (dotnet#37892)
Browse files Browse the repository at this point in the history
* Enable Activity tracking on generic host

* Add test

* Remove trailing whitespace

* Bad merge

* React to W3C format change

* Remove conditional fact
  • Loading branch information
shirhatti authored Jun 22, 2020
1 parent ab119ad commit 083f85b
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/libraries/Microsoft.Extensions.Hosting/src/Host.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ public static IHostBuilder CreateDefaultBuilder(string[] args)
// Add the EventLogLoggerProvider on windows machines
logging.AddEventLog();
}

logging.Configure(options =>
{
options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
| ActivityTrackingOptions.TraceId
| ActivityTrackingOptions.ParentId;
});

})
.UseDefaultServiceProvider((context, options) =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -60,6 +61,45 @@ public void CreateDefaultBuilder_RegistersEventSourceLogger()
args.Payload.OfType<string>().Any(p => p.Contains("Request starting")));
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/34580", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)]
public void CreateDefaultBuilder_EnablesActivityTracking()
{
var parentActivity = new Activity("ParentActivity");
parentActivity.Start();
var activity = new Activity("ChildActivity");
activity.Start();
var id = activity.Id;
var logger = new ScopeDelegateLogger((scopeObjectList) =>
{
Assert.Equal(1, scopeObjectList.Count);
var activityDictionary = (scopeObjectList.FirstOrDefault() as IEnumerable<KeyValuePair<string, object>>)
.ToDictionary(x => x.Key, x => x.Value);
switch (activity.IdFormat)
{
case ActivityIdFormat.Hierarchical:
Assert.Equal(activity.Id, activityDictionary["SpanId"]);
Assert.Equal(activity.RootId, activityDictionary["TraceId"]);
Assert.Equal(activity.ParentId, activityDictionary["ParentId"]);
break;
case ActivityIdFormat.W3C:
Assert.Equal(activity.SpanId.ToHexString(), activityDictionary["SpanId"]);
Assert.Equal(activity.TraceId.ToHexString(), activityDictionary["TraceId"]);
Assert.Equal(activity.ParentSpanId.ToHexString(), activityDictionary["ParentId"]);
break;
}
});
var loggerProvider = new ScopeDelegateLoggerProvider(logger);
var host = Host.CreateDefaultBuilder()
.ConfigureLogging(logging =>
{
logging.AddProvider(loggerProvider);
})
.Build();

logger.LogInformation("Dummy log");
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/34580", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)]
public void CreateDefaultBuilder_EnablesScopeValidation()
Expand Down Expand Up @@ -178,6 +218,65 @@ public ServiceB(ServiceC c)

internal class ServiceC { }

private class ScopeDelegateLoggerProvider : ILoggerProvider, ISupportExternalScope
{
private ScopeDelegateLogger _logger;
private IExternalScopeProvider _scopeProvider;
public ScopeDelegateLoggerProvider(ScopeDelegateLogger logger)
{
_logger = logger;
}
public ILogger CreateLogger(string categoryName)
{
_logger.ScopeProvider = _scopeProvider;
return _logger;
}

public void Dispose()
{
}

public void SetScopeProvider(IExternalScopeProvider scopeProvider)
{
_scopeProvider = scopeProvider;
}
}

private class ScopeDelegateLogger : ILogger
{
private Action<List<object>> _logDelegate;
internal IExternalScopeProvider ScopeProvider { get; set; }
public ScopeDelegateLogger(Action<List<object>> logDelegate)
{
_logDelegate = logDelegate;
}
public IDisposable BeginScope<TState>(TState state)
{
Scopes.Add(state);
return new Scope();
}

public List<object> Scopes { get; set; } = new List<object>();

public bool IsEnabled(LogLevel logLevel) => true;

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
ScopeProvider.ForEachScope((scopeObject, state) =>
{
Scopes.Add(scopeObject);
}, 0);
_logDelegate(Scopes);
}

private class Scope : IDisposable
{
public void Dispose()
{
}
}
}

private class TestEventListener : EventListener
{
private volatile bool _disposed;
Expand Down

0 comments on commit 083f85b

Please sign in to comment.