-
Notifications
You must be signed in to change notification settings - Fork 71
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
TelemetryConfiguration.Active is deprecated #121
Comments
Yes, this is puzzling. Logging is set up in Any insights are most welcome. Related: serilog/serilog-aspnetcore#84 |
Cross-posting potential workaround from serilog/serilog-aspnetcore#84 (comment): After checking library sources and experimenting for many hours today, here is a workaround I have arrived at which seems to work. Let me know if I'm shooting myself in the foot. In doing this I have sacrificed logging early startup errors (in
[<EntryPoint>]
let main args =
WebHost
.CreateDefaultBuilder(args)
.CaptureStartupErrors(true)
.UseSerilog(dispose = true)
.UseStartup<Startup>()
.Build()
.Run()
0
type Startup() =
member __.ConfigureServices(services: IServiceCollection) : unit =
services.AddApplicationInsightsTelemetry() |> ignore
let sp = services.BuildServiceProvider()
let telemetryConfig = sp.GetRequiredService<TelemetryConfiguration>()
Log.Logger <-
LoggerConfiguration()
.WriteTo.ApplicationInsights(telemetryConfig, TelemetryConverter.Traces)
.CreateLogger()
services.AddSingleton<ILogger>(Log.Logger) |> ignore |
@cmatskas it works for me 👍 |
I changed it like this and it seems to be working for me: var log = new LoggerConfiguration()
.WriteTo
.ApplicationInsights(TelemetryConfiguration.CreateDefault(), TelemetryConverter.Events)
.CreateLogger(); |
@crgolden AFAIK that will only work if you don't otherwise configure the telemetry configuration through DI (in |
In my AspNetCore 3.0 web app, I got this working with the recommended way of setting up logging in Program.cs with the following code:
In addition to the code above, I also have the normal services.AddApplicationInsightsTelemetry() in Startup/ConfigureServices and the "default" appsetting:
However, I don't have a ApplicationInsights.config at all. I suspect that file won't be read with this code. |
@MathiasRonnblom-Cint I think my comment above applies to your solution, as well. Since you instantiate a new |
I'd be a little wary of using Instead, as I posted over in issue 84, I'd recommend using the constructor of Also, I agree with your feedback above about people creating new instances of |
I got this working in AspNet Core 3.0 and I believe it avoids the pitfalls of the previous solutions. I had to replace return Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
// Add Key Vault or whatever
})
.ConfigureLogging((context, logging) =>
{
logging.ClearProviders();
})
.ConfigureServices((HostBuilderContext context, IServiceCollection services) =>
{
// Explicitly use the configuration previously built above
services.AddApplicationInsightsTelemetry(context.Configuration);
// Add enrichers and processors
services.AddApplicationInsightsKubernetesEnricher();
services.AddApplicationInsightsTelemetryProcessor<HealthCheckTelemetryFilter>();
services.AddSingleton<ILoggerFactory>(provider =>
{
TelemetryConfiguration telemetryConfiguration = provider.GetRequiredService<TelemetryConfiguration>();
var loggerConfiguration = new LoggerConfiguration();
loggerConfiguration.ReadFrom.Configuration(context.Configuration)
.Enrich.WithExceptionDetails()
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.ApplicationInsights(telemetryConfiguration, TelemetryConverter.Traces);
Serilog.Core.Logger logger = loggerConfiguration.CreateLogger();
Log.Logger = logger;
var factory = new SerilogLoggerFactory(logger, true);
return factory;
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<T>();
}); |
By removing If additional arguments were supplied to the initial |
Yeah, I do register those manually for my own app but left them out of the example code above. |
So far the conversation has focused on asp.net core applications but this also needs to be solved for non-http context applications and console applications. for console applications I think something like this should work but have yet to figure out why it is not. Any feed back on how to make this work or improve this is appreciated using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.WorkerService;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.Extensions.DependencyInjection;
using PowerArgs;
using Serilog;
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.WorkerService;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Serilog.Events;
using Serilog.Exceptions;
using Serilog.Extensions.Logging;
using System.Collections.Generic;
using System.Text;
namespace YourApplication
{
class Program
{
static int Main(string[] args)
{
using (var source = new CancellationTokenSource())
{
Console.CancelKeyPress += (sender, e) =>
{
source.Cancel();
};
return MainAsync( source.Token)
.GetAwaiter()
.GetResult();
}
}
private static async Task<int> MainAsync(CancellationToken cancellationToken)
{
ServiceProvider serviceProvider = null;
TelemetryClient telemetryClient = null;
try
{
serviceProvider = Bootstrapper.ConfigureServices()
.BuildServiceProvider();
telemetryClient = serviceProvider.GetRequiredService<TelemetryClient>();
var httpClient = new HttpClient();
var logger = serviceProvider.GetService<ILogger>();
var i = 0;
while (i < 10) // This app runs indefinitely. replace with actual application termination logic.
{
logger.Information("Worker running at: {time}", DateTimeOffset.Now);
// Replace with a name which makes sense for this operation.
using (telemetryClient.StartOperation<RequestTelemetry>("operation"))
{
logger.Warning("A sample warning message. By default, logs with severity Warning or higher is captured by Application Insights");
logger.Information("Calling bing.com");
var res = await httpClient.GetAsync("https://bing.com");
logger.Information("Calling bing completed with status:" + res.StatusCode);
logger.Fatal("Fatal action");
telemetryClient.TrackEvent("Bing call event completed");
}
await Task.Delay(1000);
i++;
}
return 0;
}
catch (Exception e)
{
ILogger logger = null;
try
{
if (serviceProvider != null)
{
logger = serviceProvider.GetService<ILogger>();
}
}
catch { }
if (logger != null)
{
logger.Error(e, "An error has occurred");
}
else
{
Console.Error.WriteLine("An error has occurred" + e.ToString());
}
return -500;
}
finally
{
Log.CloseAndFlush();
// This is to ensure that even if application terminates, telemetry is sent to the back-end.
if (telemetryClient != null)
{
telemetryClient.Flush();
await Task.Delay(5000);
}
if (serviceProvider != null)
{
serviceProvider.Dispose();
}
}
}
}
public static class Bootstrapper
{
private const string InstrumentationKeyFromConfig = "ApplicationInsights:InstrumentationKey";
public static ServiceCollection ConfigureServices()
{
var config = BuildConfiguration();
var services = new ServiceCollection();
services.AddSingleton(provider => config);
// https://docs.microsoft.com/en-us/azure/azure-monitor/app/worker-service
services.AddApplicationInsightsTelemetryWorkerService(config[InstrumentationKeyFromConfig]);
services.ConfigureLogging();
return services;
}
private static IConfiguration BuildConfiguration() => new ConfigurationBuilder()
.AddJsonFile("config/ai.json", false, true)
.Build();
private static void ConfigureLogging(this IServiceCollection services)
{
services.AddSingleton<Serilog.ILogger>(provider =>
{
var configuration = provider.GetRequiredService<IConfiguration>();
var telemetryConfiguration = provider.GetRequiredService<TelemetryConfiguration>();
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithExceptionDetails()
.WriteTo.Console()
.WriteTo.ApplicationInsights(telemetryConfiguration, TelemetryConverter.Traces)
.CreateLogger();
Log.Logger = logger;
return Log.Logger;
});
services.AddSingleton<ILoggerFactory>(provider =>
{
var logger = provider.GetRequiredService<Serilog.ILogger>();
return new SerilogLoggerFactory(logger, true);
});
}
}
} |
I have the the same problem i can't figure out, how set this up properly (for asp net core and console). |
Also wondering what the recommendation is here, doesn't seem like there are any good solutions to this issue yet. |
I'm wondering if there's some potential issues with configuring the Logger inside the "Configure" block or a hosted service.
|
Any updates on this? What's the recommendation to use this in Console apps? |
TelemetryConfiguration.CreateDefault() has been working for me:
|
Just created PR #128 in order to update the README so new users can go straight into |
Is there any real solution to this problem? Creating new telemetry configuration is no-go for me, because then traces are not corellated as well as when they used to with TelemetryConfiguration.Active. |
I also need a way to get the default processors, like adaptive sampling etc, when retrieving the TelemetryConfiguration. For now I need to use TelemetryConfiguration.Active until either a default TelemetryConfiguration is added to the IoC, or Microsoft describe more clearly how I should construct a good confiugration. |
Has a recommended way of doing this come out on top? I'm having a hard time weighing all these suggestions up against each other. |
Likewise. I'm currently doing this: .UseSerilog((hostingContext, loggerConfiguration) => {
// Logging setup needs to be part of Azure Service Fabric setup atm.
// If you work with hostingContext outside the ASF config class library, it will fail due hostingContext not being available. (even though you are literally passing it as a parameter)
loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration)
.Enrich.FromLogContext()
.Enrich.WithProperty("ApplicationName", typeof(T).Assembly.GetName().Name)
.Enrich.WithProperty("Environment", hostingContext.HostingEnvironment)
// TODO: Wait for a solution to have full AppInsights support:
// https://github.com/serilog/serilog-sinks-applicationinsights/issues/121
.WriteTo.Async(x => x.ApplicationInsights(TelemetryConfiguration.CreateDefault(), TelemetryConverter.Traces));
#if DEBUG
// Used to filter out potentially bad data due debugging.
// Very useful when doing Seq dashboards and want to remove logs under debugging session.
loggerConfiguration.Enrich.WithProperty("DebuggerAttached", System.Diagnostics.Debugger.IsAttached);
#endif It works on most apps but when running it on Azure Service Fabric, it doesn't work. UPDATE: Using |
Hi, any update on this issue? I've faced the same problem here. |
Am I missing something or has the API changed again? public static IWebHostBuilder UseSerilog(this IWebHostBuilder builder, Action<WebHostBuilderContext, LoggerConfiguration> configureLogger, bool preserveStaticLogger = false, bool writeToProviders = false) Ah... This all works with ASP.NET Core 3+ |
Any chance 3.4.0-dev-00173 could be published to nuget 'pre-release' please? Where I work allows pre-release packages but only from MS nuget not third parties. |
The service provider overload exists in 3.1.0 and works great. Note that it's on |
Should we close this now, or are there doc tasks yet to pick up? |
@DalSoft @nblumhardt Sorry, I got the packages mixed up. My previous comment was about Serilog.AspNetCore 3.4.0. Not sure though what changes are needed/commited in this repo; with the service provider overload in Serilog.AspNetCore 3.4.0 I don't have the problem mentioned in this issue. |
Anyone using Serilog with AzureFunctions? No-one mentions azure functions in this whole thread, and the Serilog documentation for azurefunctions specifically says to use .Active. So... if we're using Azure functions and can't use any of the suggested work-arounds above, are we back to square one? |
I've tried with the various suggestions that have come up in this thread, but I can't get it to work. Created a separate issue: #142 |
Do I need to literally read this entire thread in order to work out how to setup ApplicationInsights with Serilog in ASP.NET Core 5 or can the README maybe get updated with a small section describing all the 20 million configuration steps that one has to go through in .NET Core in order to just get logging working? |
Would be awesome if someone can bake this down into some README updates; thanks for the nudge @dustinmoris 👍 I don't use AppInsights and don't work on this sink, personally - happy to help where I can, though! Anyone keen to give this a shot? |
If we mark something as deprecated can we put a link to a solution or at least to this thread? |
It seems like this can work
But is there a way to configure the sink to use the IoC container provided TelemetryConfiguration while using the appSettings.json configuration? We currently use the appSettings so that configuring the sinks do not require a code change but we can't do that if we need to take this ☝️ programmatic approach. |
@eluchsinger hi!
"We" would be the App Insights SDK team in this case - the deprecated API isn't one that Serilog controls. |
I was considering writing a blog post about this in the style I have written for Serilog + Seq on ASP.NET Core. I had a blog post ready over a year ago but it was hacky and I didn't felt like it was a good solution. I can revisit this, see if I can make it work well and I'll post it here. |
In case it's helpful, here is what I'm doing (simplified): open System
open Microsoft.ApplicationInsights.Extensibility
open Microsoft.AspNetCore.Hosting
open Microsoft.Extensions.DependencyInjection
open Microsoft.Extensions.Hosting
open Serilog
let initLogger (ctx: HostBuilderContext) (services: IServiceProvider) (loggerConfig: LoggerConfiguration) =
loggerConfig.WriteTo.ApplicationInsights(
services.GetRequiredService<TelemetryConfiguration>(),
TelemetryConverter.Traces)
|> ignore
[<EntryPoint>]
let main args =
Host
.CreateDefaultBuilder(args)
.UseSerilog(initLogger) // This is the relevant line here
.ConfigureWebHostDefaults(..)
.Build()
.Run()
0 |
Hey everyone. I am currently using the solution posted by @jbrezina (And others): #121 (comment). Does anyone know if it is possible to have my app insights logging config in appsettings.json with the right telemtryconfiguration? Right now I have my console config in appsettings.json, but thanks to the issue mentioned above I don't have the app insights in my appsettings. If I could have both that would be great! |
Hi, it's a bit of shame the documentation is kind of unhelpful in this regard. The following works for me as a workaround. Because the respective extension method in LoggerConfigurationApplicationInsightsExtensions.cs is called. "Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.EntityFrameworkCore": "Warning"
}
},
"WriteTo": [
{
"Name": "ApplicationInsights",
"Args": {
"restrictedToMinimumLevel": "Information",
"telemetryClient": {},
"telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
}
}
]
} If an application instrumentation key is necessary or not available through other means, you will also need to set the env variable Or provide it manually through: "telemetryClient": {
"configuration": {
"instrumentationKey": "xxx"
}
} |
We're still keen to update the README if someone familiar with AppInsights can PR some improvements :-) |
This is pretty hacky (sorry), but just wanted to post a possible solution to getting DI configured telemetry into the App Insights sink. Not sure if we need to actually get the TelemetryClient from DI or the TelemetryConfiguration - should be easy enough to change the code to do either. Basically, the code iterates through the configured sinks and uses reflection to find any instance of the App Insights sink. It then injects the client into the sink. When the configuration is built, the logger has the DI configuration instead of whatever defaults. This is especially useful because if you use the Microsoft.ApplicationInsights.WorkerService package, it doesn't set the Active configuration, which causes the the sink to use a basically unconfigured default value. This should allow you to fully configure App Insights/Serilog in appSettings.json separately and per recommendations for both products and make them work together while not relying on the TelemetryConfiguration.Active singleton.
Just put this into a static class, and then call it at the end of your logger configuration. Make sure to call the appropriate App Insights telemetry method in your services code so that App Insights is properly initialized by time the logger is created. This code isn't extensively tested, and won't handle all wrappers/sink aggregates, but I think it gets many of the main wrappers that I saw in the core source. Though Serilog itself isn't built with introspection in mind, it may make sense to modify the configuration extensions to allow introspection, it would be pretty powerful for making things all work together. Alternatively, it would be nice for the Serilog App Insights Sink to be able to grab the TelemetryConfiguration/Client from the service provider, not sure of the order of operations that would be needed to make that happen though. |
For ASP.NET Core, I think the problem is solved by the new version of Serilog.AspNetCore: https://nblumhardt.com/2020/10/bootstrap-logger This allows configuring a bootstrap logger to capture startup errors, and then replace this logger with DI-dependent config later on. |
Unfortunately, the new bootstrapper doesn't solve this particular issue. The only reason it works (for now) is because deep in the bowels of the MSFT App Insights package for ASP.NET, they are actually initializing TelemetryConfig.Active. Other versions of the MSFT App Insights packages (for example WorkerService), don't initialize TelemetryConfig.Active. The current sink design either uses TelemetyConfig.Active or you have to pass in the config through code. The former case won't always work, the latter forces you to define the sink in code. Either way, it causes problems. I'm actually using the bootstrapper in my code, and while it's good for its purpose of capturing logs earlier, it doesn't resolve this issue. |
Getting to the end of this long thread, oh man! Has someone succeeded in using Serilog + AppInsight as sink in WebJob? I wonder since |
I haven't tried, but it looks like ultimately WebJobs sets up the TelemetryConfiguration.Active singleton (see https://github.com/Azure/azure-webjobs-sdk/blob/6799c9f04c0244c9d0ce51fe2386bd7322a20a5e/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Extensions/ApplicationInsightsServiceCollectionExtensions.cs#L189). So, in theory, if you're using the bootstrapper, it should work since the ApplicationInsightsSink will take the configuration from the active configuration if nothing else is provided, and this should be configured by time you're initializing the logger in the UseSerilog extension. In this case, the bootstrapper may be the solution to your issue. Might want to debug after your ReadFrom.Configuration call and look at whether the Sink has the configuration you expect. If they ever stop initializing TelemetryConfig.Active, we run into the same problem though. |
@simbaja Do you mean with the The one that follows next logs to a console locally, but in Azure the complaint is
|
@veikkoeeva, Looking through the source code, and if I'm reading it correctly, it looks like logBuilder.AddApplicationInsightsWebJobs internally calls the services.AddApplicationInsights: https://github.com/Azure/azure-webjobs-sdk/blob/6930c4ea9ec78db12a05a2d0bf38cce42ab04e13/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Extensions/ApplicationInsightsServiceCollectionExtensions.cs#L32. However, if you're using Serilog, you probably don't need the logBuilder.AddApplicationInsightsWebJobs call, as that's setting up the MS loggers from what I see (and possibly adding duplicate services). Your call to services.AddApplicationInsightsTelemetry(AppInsightKey) should set it up for Serilog. If it doesn't perhaps change it to services.AddApplicationInsights(o => o.InstrumentationKey = "key") based on the call here: https://github.com/Azure/azure-webjobs-sdk/blob/6930c4ea9ec78db12a05a2d0bf38cce42ab04e13/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Extensions/ApplicationInsightsServiceCollectionExtensions.cs#L30 (which is what is called internally by WebJobs). Not sure if this helps. It's a bit of a mess at the moment, too many extensions doing different things... |
Hi all, Thanks for all your input on this thread 😃 As @cmeeren points out the original problems with It's difficult, because of the length of the thread, to tell what the state of any related peripheral issue is. I'm closing and locking the thread to avoid losing valuable information in the clutter. Things you can do:
Thanks again! |
Context: I've been working to upgrade some applications to .NET Core 3.0 - this has led me to update a number of packages as well, including App Insights.
Previously the recommendation was to configure AppInsights and Serilog together using the
IHostBuilder
inProgram.cs
, e.g.:But after upgrading to the latest AppInsights, I'm starting to get the warnings (as errors):
and
The first can be overcome by configuring App Insights during
ConfigureServices
, but I'm left a bit stumped as to how to configure Serilog withoutTelemetryConfiguration.Active
- is there a recommended way to do this?Apologies if I've missed something in the documentation - I couldn't spot anything relevant to this.
The text was updated successfully, but these errors were encountered: