Skip to content

Commit

Permalink
ILogger integration - part 1 (#1308)
Browse files Browse the repository at this point in the history
* ilogger integration

* update changelog

* s/name/categoryName/g

* TODO comment
  • Loading branch information
reyang authored Sep 25, 2020
1 parent 56a34f3 commit 6529c43
Show file tree
Hide file tree
Showing 12 changed files with 305 additions and 0 deletions.
7 changes: 7 additions & 0 deletions OpenTelemetry.sln
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentati
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.GrpcService", "examples\GrpcService\Examples.GrpcService.csproj", "{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "getting-started", "docs\logs\getting-started\getting-started.csproj", "{B3F03725-23A0-4582-9526-F6A7E38F35CC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -378,6 +380,10 @@ Global
{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED}.Release|Any CPU.Build.0 = Release|Any CPU
{B3F03725-23A0-4582-9526-F6A7E38F35CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B3F03725-23A0-4582-9526-F6A7E38F35CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3F03725-23A0-4582-9526-F6A7E38F35CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3F03725-23A0-4582-9526-F6A7E38F35CC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -406,6 +412,7 @@ Global
{FCDCF532-A163-40DA-80B7-7530AA1182C4} = {5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818}
{B26BE278-C9DA-4067-A0EE-6A4227B3DC87} = {3862190B-E2C5-418E-AFDC-DB281FB5C705}
{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E}
{B3F03725-23A0-4582-9526-F6A7E38F35CC} = {3862190B-E2C5-418E-AFDC-DB281FB5C705}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521}
Expand Down
2 changes: 2 additions & 0 deletions build/Common.props
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
<MicrosoftCodeAnalysisFxCopAnalyzersPkgVer>[3.3.0]</MicrosoftCodeAnalysisFxCopAnalyzersPkgVer>
<MicrosoftCodeCoveragePkgVer>[16.7.1]</MicrosoftCodeCoveragePkgVer>
<MicrosoftExtensionsHostingAbstractionsPkgVer>[2.1.0,5.0)</MicrosoftExtensionsHostingAbstractionsPkgVer>
<MicrosoftExtensionsLoggingPkgVer>[2.1.0,6.0)</MicrosoftExtensionsLoggingPkgVer>
<MicrosoftExtensionsLoggingConfigurationPkgVer>[2.1.0,6.0)</MicrosoftExtensionsLoggingConfigurationPkgVer>
<MicrosoftNETFrameworkReferenceAssembliesPkgVer>[1.0.0,2.0)</MicrosoftNETFrameworkReferenceAssembliesPkgVer>
<MicrosoftSourceLinkGitHubPkgVer>[1.0.0,2.0)</MicrosoftSourceLinkGitHubPkgVer>
<NewtonsoftJsonPkgVer>[12.0.2,13.0)</NewtonsoftJsonPkgVer>
Expand Down
1 change: 1 addition & 0 deletions docs/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Please sort alphabetically.
Refer to https://docs.microsoft.com/en-us/nuget/concepts/package-versioning for semver syntax.
-->
<MicrosoftExtensionsLoggingPkgVer>[5.0.0-rc.1.20451.14,6.0)</MicrosoftExtensionsLoggingPkgVer>
<OpenTelemetryExporterConsolePkgVer>[0.4.0-beta.2,1.0)</OpenTelemetryExporterConsolePkgVer>
<OpenTelemetryPkgVer>[0.4.0-beta.2,1.0)</OpenTelemetryPkgVer>
</PropertyGroup>
Expand Down
32 changes: 32 additions & 0 deletions docs/logs/getting-started/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// <copyright file="Program.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 Microsoft.Extensions.Logging;

public class Program
{
public static void Main()
{
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry();
});
var logger = loggerFactory.CreateLogger<Program>();

logger.LogInformation("Hello, World!");
logger.LogInformation("Hello from {name} {price}.", "artichoke", 3.99);
}
}
3 changes: 3 additions & 0 deletions docs/logs/getting-started/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Getting Started with OpenTelemetry .NET in 5 Minutes

TBD
6 changes: 6 additions & 0 deletions docs/logs/getting-started/getting-started.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPkgVer)" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions src/OpenTelemetry.Api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Added `ILogger`/`Microsoft.Extensions.Logging` integration
([#1308](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1308))

## 0.6.0-beta.1

Released 2020-Sep-15
Expand Down
93 changes: 93 additions & 0 deletions src/OpenTelemetry/Logs/OpenTelemetryLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// <copyright file="OpenTelemetryLogger.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>

#if NETSTANDARD2_0
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Extensions.Logging;

namespace OpenTelemetry.Logs
{
internal class OpenTelemetryLogger : ILogger
{
private readonly string categoryName;

internal OpenTelemetryLogger(string categoryName, OpenTelemetryLoggerOptions options)
{
this.categoryName = categoryName ?? throw new ArgumentNullException(nameof(categoryName));

if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
}

internal IExternalScopeProvider ScopeProvider { get; set; }

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if (!this.IsEnabled(logLevel))
{
return;
}

var timestamp = DateTime.UtcNow;

if (state is IReadOnlyCollection<KeyValuePair<string, object>> dict)
{
var isUnstructuredLog = dict.Count == 1;

// TODO: remove the console output after finished the plumbing work to log processors/exporters
if (isUnstructuredLog)
{
foreach (var entry in dict)
{
Console.WriteLine($"{this.categoryName}({logLevel}, Id={eventId}): {entry.Value}");
}
}
else
{
Console.WriteLine($"{this.categoryName}({logLevel}, Id={eventId}):");
foreach (var entry in dict)
{
if (string.Equals(entry.Key, "{OriginalFormat}", StringComparison.Ordinal))
{
Console.WriteLine($" $format: {entry.Value}");
continue;
}

Console.WriteLine($" {entry.Key}: {entry.Value}");
}
}

if (exception != null)
{
Console.WriteLine($" $exception: {exception}");
}
}
}

public bool IsEnabled(LogLevel logLevel)
{
return logLevel != LogLevel.None;
}

public IDisposable BeginScope<TState>(TState state) => this.ScopeProvider?.Push(state) ?? null;
}
}
#endif
26 changes: 26 additions & 0 deletions src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// <copyright file="OpenTelemetryLoggerOptions.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>

#if NETSTANDARD2_0
using Microsoft.Extensions.Logging;

namespace OpenTelemetry.Logs
{
public class OpenTelemetryLoggerOptions
{
}
}
#endif
79 changes: 79 additions & 0 deletions src/OpenTelemetry/Logs/OpenTelemetryLoggerProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// <copyright file="OpenTelemetryLoggerProvider.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>

#if NETSTANDARD2_0
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace OpenTelemetry.Logs
{
[ProviderAlias("OpenTelemetry")]
public class OpenTelemetryLoggerProvider : ILoggerProvider, ISupportExternalScope
{
private readonly IOptionsMonitor<OpenTelemetryLoggerOptions> options;
private readonly IDictionary<string, ILogger> loggers;
private IExternalScopeProvider scopeProvider;

public OpenTelemetryLoggerProvider(IOptionsMonitor<OpenTelemetryLoggerOptions> options)
{
this.options = options;
this.loggers = new Dictionary<string, ILogger>(StringComparer.Ordinal);
}

internal IExternalScopeProvider ScopeProvider
{
get
{
if (this.scopeProvider == null)
{
this.scopeProvider = new LoggerExternalScopeProvider();
}

return this.scopeProvider;
}
}

void ISupportExternalScope.SetScopeProvider(IExternalScopeProvider scopeProvider)
{
// TODO: set existing loggers
this.scopeProvider = scopeProvider;
}

public ILogger CreateLogger(string categoryName)
{
lock (this.loggers)
{
ILogger logger;

if (this.loggers.TryGetValue(categoryName, out logger))
{
return logger;
}

logger = new OpenTelemetryLogger(categoryName, this.options.CurrentValue);
this.loggers.Add(categoryName, logger);
return logger;
}
}

public void Dispose()
{
}
}
}
#endif
48 changes: 48 additions & 0 deletions src/OpenTelemetry/Logs/OpenTelemetryLoggingExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// <copyright file="OpenTelemetryLoggingExtensions.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>

#if NETSTANDARD2_0
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Configuration;
using OpenTelemetry.Logs;

namespace Microsoft.Extensions.Logging
{
public static class OpenTelemetryLoggingExtensions
{
public static ILoggingBuilder AddOpenTelemetry(this ILoggingBuilder builder, Action<OpenTelemetryLoggerOptions> configure = null)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}

builder.AddConfiguration();
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, OpenTelemetryLoggerProvider>());

if (configure != null)
{
builder.Services.Configure(configure);
}

return builder;
}
}
}
#endif
5 changes: 5 additions & 0 deletions src/OpenTelemetry/OpenTelemetry.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="$(SystemReflectionEmitLightweightPkgVer)" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPkgVer)" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="$(MicrosoftExtensionsLoggingConfigurationPkgVer)" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Api\OpenTelemetry.Api.csproj" />
</ItemGroup>
Expand Down

0 comments on commit 6529c43

Please sign in to comment.