I have the following configuration in my .NET Framework 4.7.2 console app:
var containerBuilder = new ContainerBuilder();
containerBuilder.Register(CreateTelemetryClient).As<TelemetryClient>().OnRelease(HandleTelemetryClientDisposal);
private static void HandleTelemetryClientDisposal(TelemetryClient client)
{
client.Flush();
}
private static TelemetryClient CreateTelemetryClient(IComponentContext context)
{
var instrumentationKey = ConfigurationManager.AppSettings["ApplicationInsights:InstrumentationKey"];
var configuration = TelemetryConfiguration.CreateDefault();
configuration.InstrumentationKey = instrumentationKey;
var telemetryClient = new TelemetryClient(configuration);
telemetryClient.Context.InstrumentationKey = instrumentationKey;
var telemetryInitializer = context.Resolve<ITelemetryInitializer>();
configuration.TelemetryInitializers.Add(telemetryInitializer);
return telemetryClient;
}
This correctly configures the telemetry client for Application Insights logging. However, the OnRelease(HandleTelemetryClientDisposal)
is never called and therefore neither is client.Flush()
which I believe is why my logs aren't appearing in App Insights.
Why isn't this being called - have I configured this incorrectly?
Edit to show more code:
class Program
{
public static void Main(string[] args)
{
var jobHostConfig = new JobHostConfiguration();
IocConfig.Configure(jobHostConfig );
}
}
public static void Configure(JobHostConfiguration jobHostConfiguratio)
{
var containerBuilder = new ContainerBuilder();
RegisterDependencies(containerBuilder);
jobHostConfiguration.JobActivator = new AutofacActivator(containerBuilder.Build());
}
private static void RegisterDependencies(ContainerBuilder containerBuilder)
{
containerBuilder.Register(CreateTelemetryClient).As<TelemetryClient>().OnRelease(HandleTelemetryClientDisposal);
}
It's hard to tell exactly what's going on since I don't know what JobHostConfiguration
, JobActivator
, or AutofacActivator
are, however, I do know Autofac. Some quick Googling makes me think this has something to do with Hangfire, so if this doesn't answer your question... it might be good to mention Hangfire in the question and/or tag it hangfire
because it's going to have to do with Hangfire application lifecycle things.
OnRelease happens when the lifetime scope is disposed. We have some docs on it, but that's the gist - it's like adding IDisposable
to a class that isn't disposable. There's a lot of doc explaining how disposal relates to containers and scopes.
From a practical standpoint, what it means is if nothing calls Dispose
on the container or lifetime scope, you won't get OnRelease
called.
var builder = new ContainerBuilder();
builder.Register(CreateTelemetryClient)
.As<TelemetryClient>()
.OnRelease(HandleTelemetryClientDisposal);
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
var client = scope.Resolve<TelemetryClient>();
// When this closing brace is hit, the lifetime scope
// will be disposed, and the OnRelease will be called.
}
You'll notice I showed the example using a lifetime scope. If you had resolved from the container directly, you'd have to dispose of the container... and then you can't use the container anymore.
This is where my lack of knowledge of Hangfire comes in. I don't know when the TelemetryClient
is being resolved, I don't know what's using it, I don't know if it's coming from the container or from a lifetime scope, and I don't know when the container/scope is being disposed. That's something you're going to have to figure out, but it looks like the Hangfire.Autofac README covers some of the examples.
The symptom you describe, though, where OnRelease
is never called so Flush
is never called... indicates that things aren't being disposed of properly, so that's where you'd need to start looking. This is, of course, assuming that something is resolving it in the first place - if nothing resolves it, then there's nothing to dispose, and of course the OnRelease
won't be called. Again, there's nothing in your code showing anything consuming the TelemetryClient
, so as a standalone example... no, you'd never see OnRelease
called because there's nothing in your code shown here that takes a dependency on a TelemetryClient
. The client won't be resolved simply by virtue of registering it. Something has to consume it.