-
Couldn't load subscription status.
- Fork 2
feat: Add support for non-core ASP.Net. #199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
ed9b3cc
Add support for non-core ASP.Net.
kinyoklion 5a23b99
Remove old code from plugin.
kinyoklion a62830a
Add classic ASP example.
kinyoklion 437ef79
Remove classic ASP app.
kinyoklion df564cc
Revert solution changes.
kinyoklion 4751a9a
Documentation.
kinyoklion 823e6a9
Merge branch 'main' into rlamb/asp-net-classic
kinyoklion 1e7037a
Apply custom logging config.
kinyoklion b6ec50f
Maintain instance of logger factory.
kinyoklion 9ef15c5
Fix example code.
kinyoklion cf499ea
Per key samplers.
kinyoklion d0f8177
Merge branch 'main' into rlamb/asp-net-classic
kinyoklion 6d3c092
Minor docs updates.
kinyoklion a55fb75
Merge branch 'main' into rlamb/asp-net-classic
kinyoklion File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
105 changes: 105 additions & 0 deletions
105
...y/observability-dotnet/src/LaunchDarkly.Observability/Asp/Core/ObservabilityExtensions.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using LaunchDarkly.Observability.Otel; | ||
| using LaunchDarkly.Logging; | ||
| using LaunchDarkly.Observability.Logging; | ||
| using LaunchDarkly.Observability.Sampling; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.Hosting; | ||
| using Microsoft.Extensions.Logging; | ||
| using OpenTelemetry; | ||
| using OpenTelemetry.Resources; | ||
| using OpenTelemetry.Trace; | ||
| using OpenTelemetry.Exporter; | ||
| using OpenTelemetry.Logs; | ||
| using OpenTelemetry.Metrics; | ||
|
|
||
| // ReSharper disable once CheckNamespace | ||
| namespace LaunchDarkly.Observability | ||
| { | ||
| /// <summary> | ||
| /// Static class containing extension methods for configuring observability | ||
| /// </summary> | ||
| public static class ObservabilityExtensions | ||
| { | ||
| private class LdObservabilityHostedService : IHostedService | ||
| { | ||
| private readonly ObservabilityConfig _config; | ||
| private readonly ILoggerProvider _loggerProvider; | ||
|
|
||
| public LdObservabilityHostedService(ObservabilityConfig config, IServiceProvider provider) | ||
| { | ||
| _loggerProvider = provider.GetService<ILoggerProvider>(); | ||
| _config = config; | ||
| } | ||
|
|
||
| public Task StartAsync(CancellationToken cancellationToken) | ||
| { | ||
| Observe.Initialize(_config, _loggerProvider); | ||
| return Task.CompletedTask; | ||
| } | ||
|
|
||
| public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; | ||
| } | ||
|
|
||
| internal static void AddLaunchDarklyObservabilityWithConfig(this IServiceCollection services, | ||
| ObservabilityConfig config, Logger logger = null) | ||
| { | ||
| DebugLogger.SetLogger(logger); | ||
|
|
||
| var sampler = CommonOtelOptions.GetSampler(config); | ||
|
|
||
| var resourceBuilder = CommonOtelOptions.GetResourceBuilder(config); | ||
|
|
||
| services.AddOpenTelemetry().WithTracing(tracing => | ||
| { | ||
| tracing | ||
| .WithCommonLaunchDarklyConfig(config, resourceBuilder, sampler) | ||
| .AddAspNetCoreInstrumentation(options => { options.RecordException = true; }); | ||
| }).WithLogging(logging => | ||
| { | ||
| logging.SetResourceBuilder(resourceBuilder) | ||
| .AddProcessor(new SamplingLogProcessor(sampler)) | ||
| .AddOtlpExporter(options => | ||
| { | ||
| options.WithCommonLaunchDarklyLoggingExport(config); | ||
| }); | ||
| config.ExtendedLoggerConfiguration?.Invoke(logging); | ||
| }).WithMetrics(metrics => | ||
| { | ||
| metrics | ||
| .WithCommonLaunchDarklyConfig(config, resourceBuilder) | ||
| .AddAspNetCoreInstrumentation(); | ||
| }); | ||
|
|
||
| // Attach a hosted service which will allow us to get a logger provider instance from the built | ||
| // service collection. | ||
| services.AddHostedService((serviceProvider) => | ||
| new LdObservabilityHostedService(config, serviceProvider)); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Add the LaunchDarkly Observability services. This function would typically be called by the LaunchDarkly | ||
| /// Observability plugin. This should only be called by the end user if the Observability plugin needs to be | ||
| /// initialized earlier than the LaunchDarkly client. | ||
| /// </summary> | ||
| /// <param name="services">The service collection</param> | ||
| /// <param name="sdkKey">The LaunchDarkly SDK</param> | ||
| /// <param name="configure">A method to configure the services</param> | ||
| /// <returns>The service collection</returns> | ||
| public static IServiceCollection AddLaunchDarklyObservability( | ||
| this IServiceCollection services, | ||
| string sdkKey, | ||
| Action<ObservabilityConfig.ObservabilityConfigBuilder> configure) | ||
| { | ||
| var builder = ObservabilityConfig.Builder(); | ||
| configure(builder); | ||
|
|
||
| var config = builder.Build(sdkKey); | ||
| AddLaunchDarklyObservabilityWithConfig(services, config); | ||
| return services; | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
...kly/observability-dotnet/src/LaunchDarkly.Observability/Asp/Legacy/ObservabilityPlugin.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using LaunchDarkly.Sdk.Integrations.Plugins; | ||
| using LaunchDarkly.Sdk.Server.Hooks; | ||
| using LaunchDarkly.Sdk.Server.Interfaces; | ||
| using LaunchDarkly.Sdk.Server.Plugins; | ||
| using LaunchDarkly.Sdk.Server.Telemetry; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using OpenTelemetry.Logs; | ||
|
|
||
| // ReSharper disable once CheckNamespace | ||
| namespace LaunchDarkly.Observability | ||
| { | ||
| public class ObservabilityPlugin : Plugin | ||
| { | ||
| private readonly ObservabilityPluginBuilder _config; | ||
| private readonly IServiceCollection _services; | ||
|
|
||
| /// <summary> | ||
| /// Create a new builder for <see cref="ObservabilityPlugin"/>. | ||
| /// <para> | ||
| /// When using this builder, LaunchDarkly client must be constructed before your application is built. | ||
| /// For example: | ||
| /// | ||
| /// <code> | ||
| /// TODO: Add example. | ||
|
||
| /// </code> | ||
| /// </para> | ||
| /// </summary> | ||
| /// <returns>A new <see cref="ObservabilityPluginBuilder"/> instance for configuring the observability plugin.</returns> | ||
| public static ObservabilityPluginBuilder Builder() => | ||
| new ObservabilityPluginBuilder(); | ||
|
|
||
| internal ObservabilityPlugin(ObservabilityPluginBuilder config) : base( | ||
| "LaunchDarkly.Observability") | ||
| { | ||
| _config = config; | ||
| } | ||
|
|
||
| internal ObservabilityPlugin() : base("LaunchDarkly.Observability") | ||
| { | ||
| _services = null; | ||
| _config = null; | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public override void Register(ILdClient client, EnvironmentMetadata metadata) | ||
| { | ||
| if (_services == null || _config == null) return; | ||
| var config = _config.BuildConfig(metadata.Credential); | ||
| OpenTelemetry.Register(config); | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public override IList<Hook> GetHooks(EnvironmentMetadata metadata) | ||
| { | ||
| return new List<Hook> | ||
| { | ||
| TracingHook.Builder().IncludeValue().Build() | ||
| }; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Used to build an instance of the Observability Plugin. | ||
| /// </summary> | ||
| public sealed class ObservabilityPluginBuilder : BaseBuilder<ObservabilityPluginBuilder> | ||
| { | ||
| /// <summary> | ||
| /// Build an <see cref="ObservabilityPlugin"/> instance with the configured settings. | ||
| /// </summary> | ||
| /// <returns>The constructed <see cref="ObservabilityPlugin"/>.</returns> | ||
| public ObservabilityPlugin Build() | ||
| { | ||
| return new ObservabilityPlugin(this); | ||
| } | ||
| } | ||
| } | ||
| } | ||
81 changes: 81 additions & 0 deletions
81
...kly/observability-dotnet/src/LaunchDarkly.Observability/Asp/Legacy/OpenTelemetryConfig.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| using LaunchDarkly.Logging; | ||
| using LaunchDarkly.Observability.Otel; | ||
| using Microsoft.Extensions.Logging; | ||
| using OpenTelemetry; | ||
| using OpenTelemetry.Logs; | ||
| using OpenTelemetry.Metrics; | ||
| using OpenTelemetry.Trace; | ||
|
|
||
| // ReSharper disable once CheckNamespace | ||
| namespace LaunchDarkly.Observability | ||
| { | ||
| public static class OpenTelemetry | ||
| { | ||
| private static TracerProvider _tracerProvider; | ||
| private static MeterProvider _meterProvider; | ||
| private static readonly object ProviderLock = new object(); | ||
|
|
||
| /// <summary> | ||
| /// Extension method which adds LaunchDarkly logging to a logging factory. | ||
| /// | ||
| /// <code> | ||
| /// using (var factory = LoggerFactory.Create(builder => { builder.AddLaunchDarklyLogging(config); })) { | ||
| /// // Use factory to get logger which uses LaunchDarkly loging. | ||
| /// } | ||
| /// </code> | ||
| /// </summary> | ||
| /// <param name="loggingBuilder">the logging builder for the factory</param> | ||
| /// <param name="config">the LaunchDarkly observability configuration</param> | ||
| public static void AddLaunchDarklyLogging(this ILoggingBuilder loggingBuilder, ObservabilityConfig config) | ||
| { | ||
| loggingBuilder.AddOpenTelemetry(options => | ||
| { | ||
| options.SetResourceBuilder(CommonOtelOptions.GetResourceBuilder(config)) | ||
| .AddProcessor(new SamplingLogProcessor(CommonOtelOptions.GetSampler(config))) | ||
| .AddOtlpExporter(exportOptions => { exportOptions.WithCommonLaunchDarklyLoggingExport(config); }); | ||
| }); | ||
| } | ||
|
|
||
| public static void Register(ObservabilityConfig config, Logger debugLogger = null) | ||
| { | ||
| lock (ProviderLock) | ||
| { | ||
| // If the providers are set, then the implementation has already been configured. | ||
| if (_tracerProvider != null) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| var resourceBuilder = CommonOtelOptions.GetResourceBuilder(config); | ||
| var sampler = CommonOtelOptions.GetSampler(config); | ||
|
|
||
| _tracerProvider = global::OpenTelemetry.Sdk.CreateTracerProviderBuilder() | ||
| .WithCommonLaunchDarklyConfig(config, resourceBuilder, sampler) | ||
| .AddAspNetInstrumentation() | ||
| .Build(); | ||
|
|
||
| _meterProvider = global::OpenTelemetry.Sdk.CreateMeterProviderBuilder() | ||
| .WithCommonLaunchDarklyConfig(config, resourceBuilder) | ||
| .AddAspNetInstrumentation() | ||
| .Build(); | ||
| } | ||
|
|
||
| using (var factory = LoggerFactory.Create(builder => { builder.AddLaunchDarklyLogging(config); })) | ||
| { | ||
| var logger = factory.CreateLogger<ObservabilityPlugin>(); | ||
| Observe.Initialize(config, logger); | ||
| } | ||
cursor[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| public static void Shutdown() | ||
| { | ||
| lock (ProviderLock) | ||
| { | ||
| _tracerProvider?.Dispose(); | ||
| _meterProvider?.Dispose(); | ||
| _tracerProvider = null; | ||
| _meterProvider = null; | ||
| } | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.