Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// <copyright file="IConfigureLoggerProviderBuilder.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>

namespace OpenTelemetry.Logs;

/// <summary>
/// Represents something that configures the <see cref="LoggerProviderBuilder"/> type.
/// </summary>
// Note: This API may be made public if there is a need for it.
internal interface IConfigureLoggerProviderBuilder
{
/// <summary>
/// Invoked to configure a <see cref="LoggerProviderBuilder"/> instance.
/// </summary>
/// <param name="serviceProvider"><see cref="IServiceProvider"/>.</param>
/// <param name="loggerProviderBuilder"><see cref="LoggerProviderBuilder"/>.</param>
void ConfigureBuilder(IServiceProvider serviceProvider, LoggerProviderBuilder loggerProviderBuilder);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// <copyright file="ILoggerProviderBuilder.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.DependencyInjection;

namespace OpenTelemetry.Logs;

/// <summary>
/// Describes a <see cref="LoggerProviderBuilder"/> backed by an <see cref="IServiceCollection"/>.
/// </summary>
// Note: This API may be made public if there is a need for it.
internal interface ILoggerProviderBuilder : IDeferredLoggerProviderBuilder
{
/// <summary>
/// Gets the <see cref="LoggerProvider"/> being constructed by the builder.
/// </summary>
/// <remarks>
/// Note: <see cref="Provider"/> should return <see langword="null"/> until
/// construction has started and the <see cref="IServiceCollection"/> has
/// closed.
/// </remarks>
LoggerProvider? Provider { get; }

/// <summary>
/// Register a callback action to configure the <see
/// cref="IServiceCollection"/> where logging services are configured.
/// </summary>
/// <remarks>
/// Note: Logging services are only available during the application
/// configuration phase. This method should throw a <see
/// cref="NotSupportedException"/> if services are configured after the
/// application <see cref="IServiceProvider"/> has been created.
/// </remarks>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="LoggerProviderBuilder"/> for chaining.</returns>
LoggerProviderBuilder ConfigureServices(Action<IServiceCollection> configure);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// <copyright file="OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.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.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Logs;

/// <summary>
/// Contains extension methods for the <see cref="LoggerProviderBuilder"/> class.
/// </summary>
internal static class OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions
{
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <remarks>
/// Note: The type specified by <typeparamref name="T"/> will be
/// registered as a singleton service into application services.
/// </remarks>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="loggerProviderBuilder"><see cref="LoggerProviderBuilder"/>.</param>
/// <returns>The supplied <see cref="LoggerProviderBuilder"/> for chaining.</returns>
public static LoggerProviderBuilder AddInstrumentation<T>(this LoggerProviderBuilder loggerProviderBuilder)
where T : class
{
loggerProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());

loggerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
builder.AddInstrumentation(() => sp.GetRequiredService<T>());
});

return loggerProviderBuilder;
}

/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="loggerProviderBuilder"><see cref="LoggerProviderBuilder"/>.</param>
/// <param name="instrumentation">Instrumentation instance.</param>
/// <returns>The supplied <see cref="LoggerProviderBuilder"/> for chaining.</returns>
public static LoggerProviderBuilder AddInstrumentation<T>(this LoggerProviderBuilder loggerProviderBuilder, T instrumentation)
where T : class
{
Guard.ThrowIfNull(instrumentation);

loggerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
builder.AddInstrumentation(() => instrumentation);
});

return loggerProviderBuilder;
}

/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="loggerProviderBuilder"><see cref="LoggerProviderBuilder"/>.</param>
/// <param name="instrumentationFactory">Instrumentation factory.</param>
/// <returns>The supplied <see cref="LoggerProviderBuilder"/> for chaining.</returns>
public static LoggerProviderBuilder AddInstrumentation<T>(
this LoggerProviderBuilder loggerProviderBuilder,
Func<IServiceProvider, T> instrumentationFactory)
where T : class
{
Guard.ThrowIfNull(instrumentationFactory);

loggerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
builder.AddInstrumentation(() => instrumentationFactory(sp));
});

return loggerProviderBuilder;
}

/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="loggerProviderBuilder"><see cref="LoggerProviderBuilder"/>.</param>
/// <param name="instrumentationFactory">Instrumentation factory.</param>
/// <returns>The supplied <see cref="LoggerProviderBuilder"/> for chaining.</returns>
public static LoggerProviderBuilder AddInstrumentation<T>(
this LoggerProviderBuilder loggerProviderBuilder,
Func<IServiceProvider, LoggerProvider, T> instrumentationFactory)
where T : class
{
Guard.ThrowIfNull(instrumentationFactory);

loggerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
if (loggerProviderBuilder is ILoggerProviderBuilder iLoggerProviderBuilder
&& iLoggerProviderBuilder.Provider != null)
{
builder.AddInstrumentation(() => instrumentationFactory(sp, iLoggerProviderBuilder.Provider));
}
});

return loggerProviderBuilder;
}

/// <summary>
/// Register a callback action to configure the <see
/// cref="IServiceCollection"/> where logging services are configured.
/// </summary>
/// <remarks>
/// Note: Logging services are only available during the application
/// configuration phase.
/// </remarks>
/// <param name="loggerProviderBuilder"><see cref="LoggerProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="LoggerProviderBuilder"/> for chaining.</returns>
public static LoggerProviderBuilder ConfigureServices(
this LoggerProviderBuilder loggerProviderBuilder,
Action<IServiceCollection> configure)
{
if (loggerProviderBuilder is ILoggerProviderBuilder iLoggerProviderBuilder)
{
iLoggerProviderBuilder.ConfigureServices(configure);
}

return loggerProviderBuilder;
}

/// <summary>
/// Register a callback action to configure the <see
/// cref="LoggerProviderBuilder"/> once the application <see
/// cref="IServiceProvider"/> is available.
/// </summary>
/// <remarks>
/// <para><see cref="ConfigureBuilder"/> is an advanced API and is expected
/// to be used primarily by library authors.</para>
/// Notes:
/// <list type="bullet">
/// <item>Services may NOT be added to the <see cref="IServiceCollection" />
/// (via <see cref="ConfigureServices"/>) inside <see
/// cref="ConfigureBuilder"/> because the <see cref="IServiceProvider"/> has
/// already been created. A <see cref="NotSupportedException"/> will be
/// thrown if services are accessed.</item>
/// <item>Library extension methods (for example <c>AddOtlpExporter</c>
/// inside <c>OpenTelemetry.Exporter.OpenTelemetryProtocol</c>) may depend
/// on services being available today or at any point in the future. It is
/// NOT recommend to call library extension methods from inside <see
/// cref="ConfigureBuilder"/>.</item>
/// </list>
/// For more information see: <see
/// href="https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/docs/trace/customizing-the-sdk/README.md#dependency-injection-support">Dependency
/// injection support</see>.
/// </remarks>
/// <param name="loggerProviderBuilder"><see cref="LoggerProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="LoggerProviderBuilder"/> for chaining.</returns>
internal static LoggerProviderBuilder ConfigureBuilder(
this LoggerProviderBuilder loggerProviderBuilder,
Action<IServiceProvider, LoggerProviderBuilder> configure)
{
if (loggerProviderBuilder is IDeferredLoggerProviderBuilder deferredLoggerProviderBuilder)
{
deferredLoggerProviderBuilder.Configure(configure);
}

return loggerProviderBuilder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// <copyright file="OpenTelemetryDependencyInjectionLoggingServiceCollectionExtensions.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.DependencyInjection;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Logs;

/// <summary>
/// Extension methods for setting up OpenTelemetry logging services in an <see cref="IServiceCollection" />.
/// </summary>
internal static class OpenTelemetryDependencyInjectionLoggingServiceCollectionExtensions
{
/// <summary>
/// Registers an action used to configure the OpenTelemetry <see
/// cref="LoggerProviderBuilder"/> used to create the <see
/// cref="LoggerProvider"/> for the <see cref="IServiceCollection"/> being
/// configured.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>This is safe to be called multiple times and by library authors.
/// Each registered configuration action will be applied
/// sequentially.</item>
/// <item>A <see cref="LoggerProvider"/> will not be created automatically
/// using this method. To begin collecting metrics use the
/// <c>IServiceCollection.AddOpenTelemetry</c> extension in the
/// <c>OpenTelemetry.Extensions.Hosting</c> package.</item>
/// </list>
/// </remarks>
/// <param name="services">The <see cref="IServiceCollection" /> to add
/// services to.</param>
/// <param name="configure">Callback action to configure the <see
/// cref="LoggerProviderBuilder"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls
/// can be chained.</returns>
public static IServiceCollection ConfigureOpenTelemetryLoggerProvider(
this IServiceCollection services,
Action<IServiceProvider, LoggerProviderBuilder> configure)
{
RegisterBuildAction(services, configure);

return services;
}

private static void RegisterBuildAction(IServiceCollection services, Action<IServiceProvider, LoggerProviderBuilder> configure)
{
Guard.ThrowIfNull(services);
Guard.ThrowIfNull(configure);

services.AddSingleton<IConfigureLoggerProviderBuilder>(
new ConfigureLoggerProviderBuilderCallbackWrapper(configure));
}

private sealed class ConfigureLoggerProviderBuilderCallbackWrapper : IConfigureLoggerProviderBuilder
{
private readonly Action<IServiceProvider, LoggerProviderBuilder> configure;

public ConfigureLoggerProviderBuilderCallbackWrapper(Action<IServiceProvider, LoggerProviderBuilder> configure)
{
Guard.ThrowIfNull(configure);

this.configure = configure;
}

public void ConfigureBuilder(IServiceProvider serviceProvider, LoggerProviderBuilder loggerProviderBuilder)
{
this.configure(serviceProvider, loggerProviderBuilder);
}
}
}
1 change: 1 addition & 0 deletions src/OpenTelemetry.Api/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

[assembly: InternalsVisibleTo("OpenTelemetry" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Api.ProviderBuilderExtensions" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Api.ProviderBuilderExtensions.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Api.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Shims.OpenTracing.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)]
Expand Down
Loading