Explains how to setup Application Insights for .NET 5 Console Application and Dependency Injection.
Demonstrated with a .NET 5 Console application. Example project can also be found on GitHub.
If you already have a Console Application you can directly skip to setting up Application Insights.
Install:
SetBasePath
+ AddJsonFile
)e.g.
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.0" />
<PackageReference Include="NLog" Version="4.6.5" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.5.1" />
</ItemGroup>
Create nlog.config (lowercase all) file in the root of your application project (File Properties: Copy Always)
We use this example:
<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogFile="c:\temp\skylogs\nlog-internal.log"
internalLogLevel="Info" >
<!-- the targets to write to -->
<targets>
<!-- write logs to file -->
<target xsi:type="File" name="logfile" fileName="c:\temp\skylogs\skylogs.log"
layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
<target xsi:type="Console" name="logconsole"
layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<logger name="*" minlevel="Trace" writeTo="logfile,logconsole" />
</rules>
</nlog>
It is recommended to read the NLog Tutorial. For more detailed information about config file can be found here.
If you like to include other targets or layout renderers, check the Platform support.
Ensure to configure your project-file to copy NLog.config to the output directory:
<ItemGroup>
<None Update="nlog.config" CopyToOutputDirectory="Always" />
</ItemGroup>
Person
classpublic class Person
{
public string Name { get; set; }
private readonly ILogger<Person> _logger;
public Person(ILogger<Person> logger)
{
_logger = logger;
}
public void Talk(string text)
{
_logger.LogInformation("Person {name} spoke {text}", Name, text);
}
}
private static IServiceProvider BuildDi(IConfiguration config)
{
return new ServiceCollection()
//Add DI Classes here
.AddTransient<Person>()
.AddLogging(loggingBuilder =>
{
// configure Logging with NLog
loggingBuilder.ClearProviders();
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
loggingBuilder.AddNLog(config);
})
.BuildServiceProvider();
}
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
Main
First create the DI container, then get your Person
and start running!
static void Main(string[] args)
{
var logger = LogManager.GetCurrentClassLogger();
try
{
var config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
var servicesProvider = BuildDi(config);
using (servicesProvider as IDisposable)
{
var person = servicesProvider.GetRequiredService<Person>();
person.Name = "Sky";
person.Talk("Hello");
Console.WriteLine("Press ANY key to exit");
Console.ReadKey();
}
}
catch (Exception ex)
{
// NLog: catch any exception and log it.
logger.Error(ex, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
LogManager.Shutdown();
}
}
private static IServiceProvider BuildDi(IConfiguration config)
{
return new ServiceCollection()
//Add DI Classes here
.AddTransient<Person>() // Runner is the custom class
.AddLogging(loggingBuilder =>
{
// configure Logging with NLog
loggingBuilder.ClearProviders();
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
loggingBuilder.AddNLog(config);
})
.BuildServiceProvider();
}
2021-05-22 12:33:20.8486|Info|Person Sky spoke Hello |name=Sky, text=Hello
Next step, see Configure NLog with nlog.config
Install:
e.g.
<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.17.0" />
</ItemGroup>
This package says
WorkerService
but can be used in plain Console Application as well.
Main
to add Application InsightsServiceCollection
.AddApplicationInsightsTelemetryWorkerService("YOUR_INSTRUMENTATION_KEY")
private static IServiceProvider BuildDi(IConfiguration config)
{
return new ServiceCollection()
//Add DI Classes here
.AddTransient<Person>()
.AddLogging(loggingBuilder =>
{
// configure Logging with NLog
loggingBuilder.ClearProviders();
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
loggingBuilder.AddNLog(config);
})
.AddApplicationInsightsTelemetryWorkerService("YOUR_INSTRUMENTATION_KEY")
.BuildServiceProvider();
}
TelemetryClient
to track events or whateverTelemetryClient
instance:var telemetryClient = servicesProvider.GetRequiredService<TelemetryClient>();
telemetryClient.TrackEvent($"Person {person.Name} spoke");
telemetryClient.Flush();
Thread.Sleep(500);
Flush()
method actually sends the request to Application Insights but it’s not synchronous, so callingThread.Sleep(500)
to make sure it completes.
Main
looks something like this:static void Main(string[] args)
{
var logger = LogManager.GetCurrentClassLogger();
try
{
var config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
var servicesProvider = BuildDi(config);
using (servicesProvider as IDisposable)
{
var person = servicesProvider.GetRequiredService<Person>();
var telemetryClient = servicesProvider.GetRequiredService<TelemetryClient>();
person.Name = "Sky";
person.Talk("Hello");
telemetryClient.TrackEvent($"Person {person.Name} spoke");
telemetryClient.Flush();
Thread.Sleep(500);
Console.WriteLine("Press ANY key to exit");
Console.ReadKey();
}
}
catch (Exception ex)
{
// NLog: catch any exception and log it.
logger.Error(ex, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
LogManager.Shutdown();
}
}