Reputation: 433
I need a way to write to Windows' event viewer in my app that's using dnx. But, the EventLog
class isn't available in the System.Diagnostics
namespace so I'm stuck. Is there any other way to write to the EventViewer?
Upvotes: 26
Views: 52125
Reputation: 301
EventLog.WriteEntry
is a static method in Diagnostics:
System.Diagnostics.EventLog.WriteEntry(source, message, MessageType, EventId);
I've been calling it for years & it works fine. 1 line of code vs all the other answers & it directly answers the question asked
Defaults to the application event log. Using custom logs takes more work, including reg key permissions.
Upvotes: 2
Reputation: 3816
Writing to the Event Log in .Net Core requires first a Nuget package installation
Install-Package Microsoft.Extensions.Logging.EventLog -Version 3.1.2
Note that the correct version to install depends on the version of .Net Core you are running.The package above was tested OK with .Net Core.
Then we need to add EventLog. In the Program class we can do this like so:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.EventLog;
namespace SomeAcme.SomeApi
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddEventLog(new EventLogSettings()
{
**SourceName = "SomeApi",
LogName = "SomeApi",**
Filter = (x, y) => y >= LogLevel.Warning
});
logging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
And our appsettings.json file includes setup:
{
"ConnectionStrings": {
"DefaultConnection": "Server=.\\SQLEXPRESS;Database=SomeApi;Trusted_Connection=True;MultipleActiveResultSets=true"
},
**"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},**
"AllowedHosts": "*"
}
We can inject the ILogger instance
using SomeAcme.SomeApi.SomeModels;
using SomeAcme.SomeApi.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace SomeAcme.SomeApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class SomeController : ControllerBase
{
private readonly ISomeService _healthUnitService;
private readonly ILogger<SomeController> _logger;
public SomeController(ISomeService someService, ILogger<SomeController> logger)
{
_someService= someService;
_logger = logger;
}
// GET: api/Some
[HttpGet]
public IEnumerable<SomeModel> GetAll()
{
return _someService.GetAll();
}
}
}
More advanced use, add a global exception handler inside Configure method of Startup class in .Net Core:
//Set up a global error handler for handling Unhandled exceptions in the API by logging it and giving a HTTP 500 Error with diagnostic information in Development and Staging
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = 500; // or another Status accordingly to Exception Type
context.Response.ContentType = "application/json";
var status = context.Features.Get<IStatusCodeReExecuteFeature>();
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
var ex = error.Error;
string exTitle = "Http 500 Internal Server Error in SomeAcme.SomeApi occured. The unhandled error is: ";
string exceptionString = !env.IsProduction() ? (new ExceptionModel
{
Message = exTitle + ex.Message,
InnerException = ex?.InnerException?.Message,
StackTrace = ex?.StackTrace,
OccuredAt = DateTime.Now,
QueryStringOfException = status?.OriginalQueryString,
RouteOfException = status?.OriginalPath
}).ToString() : new ExceptionModel()
{
Message = exTitle + ex.Message,
OccuredAt = DateTime.Now
}.ToString();
try
{
_logger.LogError(exceptionString);
}
catch (Exception err)
{
Console.WriteLine(err);
}
await context.Response.WriteAsync(exceptionString, Encoding.UTF8);
}
});
});
And finally a helper model to pack our exception information into.
using System;
using Newtonsoft.Json;
namespace SomeAcme.SomeApi.Models
{
/// <summary>
/// Exception model for generic useful information to be returned to client caller
/// </summary>
public class ExceptionModel
{
public string Message { get; set; }
public string InnerException { get; set; }
public DateTime OccuredAt { get; set; }
public string StackTrace { get; set; }
public string RouteOfException { get; set; }
public string QueryStringOfException { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
}
The tricky bit here is to get hold of a logger inside the Startup class. You can inject ILoggerFactory for this and just do :
_logger = loggerFactory.CreateLogger<Startup>();
Where _logger is used in the global error handler above.
Now back again to the question of how to write to the event log, look at the source code for SomeController above. We inject ILogger here. Just use that instance and it offers different methods for writing to your configured logs. Since we added in the Program class event log, this happens automatically.
Before you test out the code above, run the following Powershell script as administrator to get your event log source:
New-EventLog -LogName SomeApi -SourceName SomeApi
What I like with this approach is that if we do everything correct, the exceptions pops up inside the SomeApi source nicely and not inside the application event log (clutter IMHO).
Upvotes: 13
Reputation: 246
Add from NuGet
Microsoft.Extensions.Logging.EventLog
Version 2.1.1
CM> Install-Package Microsoft.Extensions.Logging.EventLog -Version 2.1.1
Include the namespace Microsoft.Extensions.Logging.EventLog
in the Program.cs
file
This resolved my problem.
Upvotes: 24
Reputation: 801
it is available in 2.0 but you have to install the compatibility pack. https://github.com/dotnet/corefx/issues/25440
Here for more information: https://blogs.msdn.microsoft.com/dotnet/2017/11/16/announcing-the-windows-compatibility-pack-for-net-core/
Upvotes: 1
Reputation: 29
Good news! EventLog is already ported to corefx and will be available in .NET Core 2.1.
Right now you can download a preview package System.Diagnostics.EventLog from their MyGet feed.
Upvotes: 1