Coder Social home page Coder Social logo

serilog-enrichers-environment's Introduction

Serilog.Enrichers.Environment

Enriches Serilog events with information from the execution environment.

Build status NuGet Version

To use the enricher, first install the NuGet package:

dotnet add package Serilog.Enrichers.Environment

Then, apply the enricher to you LoggerConfiguration:

Log.Logger = new LoggerConfiguration()
    .Enrich.WithMachineName()
    // ...other configuration...
    .CreateLogger();

The WithMachineName() enricher will add a MachineName property to produced events.

Included enrichers

The package includes:

  • WithMachineName() - adds MachineName based on either %COMPUTERNAME% (Windows) or $HOSTNAME (macOS, Linux)
  • WithEnvironmentUserName() - adds EnvironmentUserName based on USERNAME and USERDOMAIN (if available)
  • WithEnvironmentName() - adds EnvironmentName based on ASPNETCORE_ENVIRONMENT or DOTNET_ENVIRONMENT (when both are available then 'ASPNETCORE_ENVIRONMENT' takes precedence, when none are available then the fallback value will be 'Production')
  • WithEnvironmentVariable(string envVarName, string propertyName = null) - adds an <envVarName> property to the log event with the value for the specified environment variable. Optional <propertyName> will override <envVarName> as propertyName.

Copyright © 2016 Serilog Contributors - Provided under the Apache License, Version 2.0.

serilog-enrichers-environment's People

Contributors

0xced avatar colin-gourlay avatar dls314 avatar dsteinweg avatar gfoidl avatar jakobra avatar khellang avatar kvpt avatar marcel-b avatar maximrouiller avatar merbla avatar nblumhardt avatar nevets82 avatar numpsy avatar osudude avatar simoncropp avatar skomis-mm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

serilog-enrichers-environment's Issues

Version 2.1.3 does not provide correct MachineName

With the newest version 2.1.3 we are getting the wrong MachineName attached to our logs. At least it is not the machine name. (I have obfuscated the MachineName)

This is an entry written with 2.1.2

{"Timestamp":"2019-05-20T18:12:18.7714079+00:00","Level":"Warning","MessageTemplate":"No XML encryptor configured. Key {KeyId:B} may be persisted to storage in unencrypted form.","Properties":{"KeyId":"2b3669f8-7c20-40da-b5cd-84214c9603f5","EventId":{"Id":35},"SourceContext":"Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager","MachineName":"company.product.environment.service","ThreadId":1},"Renderings":{"KeyId":[{"Format":"B","Rendering":"{2b3669f8-7c20-40da-b5cd-84214c9603f5}"}]}}

This is one written with 2.1.3

{"Timestamp":"2019-05-20T17:36:18.3793019+00:00","Level":"Warning","MessageTemplate":"No XML encryptor configured. Key {KeyId:B} may be persisted to storage in unencrypted form.","Properties":{"KeyId":"17c4225e-a144-4059-b8e5-fc002265e678","EventId":{"Id":35},"SourceContext":"Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager","MachineName":"company","ThreadId":1},"Renderings":{"KeyId":[{"Format":"B","Rendering":"{17c4225e-a144-4059-b8e5-fc002265e678}"}]}}

We are using alpine-images (2.1.10) with non-root user if it is relevant. Opening a shell on the running container and executing ECHO %HOSTNAME prints out "company.product.environment.service". No matter if I use 2.1.2 or 2.1.3.

Some more info about the non-root user. The username is company and it is part of group company

Adding Serilog Enrichers using App Config

For Serilog logs enrichment using an App config how can i add standard enrichers like ProcessId, ThreadId, MachineName? The syntax to add property enricher is below but am trying to use the above standard enrichers. There's an option to implement application json which i want to avoid as it needs Serilog 2.6. Any ideas how this can be done?

As an aside question using LoggerConfiguration().ReadFrom.KeyValuePairs(...) how i can pass standard enrichers i.e. ThreadId, Environment, Process enrichers.

Using hostsettings.json results in incorrect environment name

When using a hostsettings.json file to set the environment, only the built-in source context logs come through with the correct environment. Any custom code that calls an ILogger log method enriches the logs with the default value of "Production".

Add enricher for Thread identity name

Many of our apps use claims based authentication where the Thread Principal is set via middleware and drilling down to the name reveals the current user. This is helpful when troubleshooting logs. Note, this probably will required serilog to be able to inject an IHttpContextAccessor instance to the enricher constructor to be able to get at the current user. This could be done via middleware but thats painful.

Assembly no longer signed?

Hi @nblumhardt, thanks for all your work on Serilog and related projects.

I was updating Serilog.Enrichers.Environment in my project from v2.3.0 to v3.0.0, only to find my project couldn't build because the v3.0.0 package/assembly is no longer signed / strong-named. My project requires that its signed, and v2.3.0 used to be signed as well, but v3.0.0 is not.

I think here's the commit which removed the signing config from the project file:
c7f8654#diff-bdddceb047569349e2376607484813b0b7a6b1482ec331a3418b3e9425ad187bL10

I noticed that the .snk file still lives in the /assets/ folder, so perhaps this was an unintentional removal of the signing config?

Whats the situation with WithEnvironmentVariable?

There already appears to be an issue about this (see #15) but there's an open question (last comment) to do with WithEnvironmentVariable.

Main README mentions WithEnvironmentVariable but doesn't appear to be included in the latest release. v2.2.0.

Merge dev branch?

Hi, there's a bug in the "stable" release for logging the MachineName property in Ubuntu/Linux machines that was fixed in the dev branch, 6 months ago.

There's any reason that it was not merged to master? I ask this because to use the fix, I was required to reference the 2.1.3-dev-00752 version of the nuget package.

Thanks!

GetEnvironmentUserName is returning the incorrect result for ASP .NET applications because ENV_USER_NAME is not being defined as expected

(This is against 2.1.1 net452 from NuGet)

When ENV_USER_NAME is defined (for the full .NET framework), Environment.UserName is supposed to be used. This would result in accurate reporting of application pool identities for ASP.NET applications.

That is not the case however: ENV_USER_NAME doesn't seem to have been defined at build time, and I have confirmed this with DotPeek:

 private static string GetEnvironmentUserName()
    {
      string environmentVariable1 = Environment.GetEnvironmentVariable("USERDOMAIN");
      string environmentVariable2 = Environment.GetEnvironmentVariable("USERNAME");
      if (string.IsNullOrWhiteSpace(environmentVariable1))
        return environmentVariable2;
      return string.Format("{0}\\{1}", (object) environmentVariable1, (object) environmentVariable2);
    }

This results in inaccurate username information for ASP.NET applications: when the application pools run as a different user, this will consistently report SYSTEM or Network Service (i.e. MACHINENAME$)

I am guessing that perhaps this section of project.json is not being honoured or working as expected?

  "net4.5": {
      "define": ["ENV_USER_NAME"]
    },

CachedPropertyEnricher

Feels like CachedPropertyEnricher should be moved to Serilog.Core.Enrichers near PropertyEnricher

Machine Name appears `null` on Docker (works fine in Windows)

Using serilog-enrichers-environment v2.1.3 with FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim on docker

MachineName appears to be null, where the code below returns both inquiries with the correct value.

Console.WriteLine($"HOSTNAME: {Environment.GetEnvironmentVariable("HOSTNAME")}\nMACHINENAME: {Environment.MachineName}");

image

appsettings.json

	"Serilog": {
		"MinimumLevel": {
			"Default": "Debug"
		},
		"Using": [
			"Serilog.Sinks.Seq"
		],
		"WriteTo": [
			{
				"Name": "Seq",
				"Args": {
					"serverUrl": "http://localhost:5341"
				}
			}
		],
		"Enrich": [
			"FromLogContext",
			"WithMachineName",
			"WithThreadId",
			"WithProcessId"
		],
		"Properties": {
			"Configuration": "DEVELOPMENT",
			"ApplicationName": "Test"
		}

Program.cs

	public class Program
	{
		public static async Task Main(string[] args)
		{
			Console.WriteLine($"HOSTNAME: {Environment.GetEnvironmentVariable("HOSTNAME")}\nMACHINENAME: {Environment.MachineName}");

			await Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args)
					.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
							.ReadFrom.Configuration(hostingContext.Configuration)
					)
					.ConfigureServices((hostContext, services) =>
					{
						services.AddMyService(hostContext.Configuration);
					})
					.RunConsoleAsync();
		}
	}

.Net console app not logging with Enricher

I have a console app that logs to file but the Enrichers aren't being included.

    static void Main()
    {
        Log.Logger = new LoggerConfiguration()
            .Enrich.WithMachineName()
            .Enrich.FromLogContext()
            .Enrich.WithThreadId()
            .Enrich.WithEnvironmentUserName()
            .WriteTo.RollingFile("logs\\log-{Date}.txt")
            .WriteTo.Console()
            .CreateLogger();

        try
        {
            throw new DivideByZeroException();
        }
        catch(Exception ex)
        {
            Log.Error(ex, $"Self generated exception {ex.Message}");
        }

        Log.Information("Information example");
        Log.Debug("Debug example ");
    }

example log:

    2019-01-07 12:37:34.737 -08:00 [Error] Self generated exception Attempted to divide by zero.
            System.DivideByZeroException: Attempted to divide by zero.
            at TransformationService.Program.Main() in 
            \Program.cs:line 65
    2019-01-07 12:37:34.808 -08:00 [Information] Information

In my webapi when using serilog I didn't have to modify the template to get the information.

-Markus

Handling null machine names

So when this enricher is run on a linux machine, it outputs "null" in place of the machine name. I think if the machine name isn't able to be obtained, something less obtrusive should be returned such as an empty string.

Lower NetStandard Version

Hi,

Is it possible to lower .NetStandard version to target .NetStandard 1.3, like in the two others enrichers ?

The only dependency is System.Runtime.Extensions which is available from .NetStandard 1.1, so it should be possible.

Thanks.

Add support for enricher constructor dependency injection

In .NET core, Microsoft got rid of good old HttpContext.Current. You now have to get at it by injecting IHttpContextAccessor into your class constructor that needs to read various http header values. It would be nice if we could inject IHttpContextAccessor into our constructor for enriching values based upon the current http request context (yes, this is possible via middleware but P.I.T.A.). Enricher properties of interest would be various request headers and the user name for the current request.

How can I get machine name into variable ?

I don't want to use Properties column for MSSQL and want to have a single column with machine name and have it's value in the table.

I tried below to retrieve machine name and other properties:

var machineName = new LoggerConfiguration().Enrich.WithMachineName().ToString();
var environmentUserName = new LoggerConfiguration().Enrich.WithEnvironmentUserName().ToString();
var environmentName = new LoggerConfiguration().Enrich.WithEnvironmentName().ToString();
var threadID = new LoggerConfiguration().Enrich.WithThreadId().ToString();
var threadName = new LoggerConfiguration().Enrich.WithThreadName().ToString();
var processID = new LoggerConfiguration().Enrich.WithProcessId().ToString();
var processName = new LoggerConfiguration().Enrich.WithProcessName().ToString();

However, in database they are not coming right and even in variable:

image

Is there any possibility that I get them in variable and insert in to custom columns of my own ?

Feature request: Environmental Variables

Can you add an enricher that adds Envars to the logs.

Something like:
.Enrich.WithEnvironmentVariable("EnvName")

and for windows(cant find this in dn core)
.Enrich.WithEnvironmentVariable("EnvName",EnvironmentVariableTarget.Machine)

Function Enricher

First off, apologies if this is in the wrong location as it didn't exactly fit any of the repos

I had a need where I wanted to enrich a log event with the current value of a property at the time it was logged. Specifically, we have desktop applications that are able to change Environment dynamically, so I wanted a way to reflect that in log messages -- and route log events to the correct sinks. I know ForContext<> already does this to some degree, but I didn't want to have to worry about popping and re-pushing when the property value changes.

So, took the existing property enricher and changed it to enrich with the result of the function. I am sharing below to see if anyone else might be interested or will know if it runs counter to a specific design choice. Also, if anyone has a better way of doing it, I'd be interested in that as well.

The code:

public class FunctionEnricher : ILogEventEnricher
    {
        readonly string _name;
        readonly Func<object> _value;
        readonly bool _destructureObjects;

        /// <summary>
        /// Create a new Function enricher.
        /// </summary>
        /// <param name="name">The name of the property.</param>
        /// <param name="value">Function to evaluate.</param>
        /// <returns>A handle to later remove the property from the context.</returns>
        /// <param name="destructureObjects">If true, and the value is a non-primitive, non-array type,
        /// then the value will be converted to a structure; otherwise, unknown types will
        /// be converted to scalars, which are generally stored as strings.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public FunctionEnricher(string name, Func<object> value, bool destructureObjects = false)
        {
            if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Property name must not be null or empty.", nameof(name));
            _name = name;
            _value = value;
            _destructureObjects = destructureObjects;
        }

        /// <summary>
        /// Enrich the log event.
        /// </summary>
        /// <param name="logEvent">The log event to enrich.</param>
        /// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
        public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
        {
            if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
            if (propertyFactory == null) throw new ArgumentNullException(nameof(propertyFactory));
            var property = propertyFactory.CreateProperty(_name, _value.Invoke(), _destructureObjects);
            logEvent.AddPropertyIfAbsent(property);
        }
    }

And an example of it's usage:

static void Main(string[] args)
        {
            string env = "test";

            var log = GetLoggerConfiguration(()=>env)
                        .WriteTo.Logger(lc=> lc.Filter.ByExcluding(Matching.WithProperty("Environment","prod"))
                                               .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Environment} {Message:lj}{NewLine}"))
                        .WriteTo.Logger(lc => lc.Filter.ByIncludingOnly(Matching.WithProperty("Environment", "prod"))
                                               .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] prodonly {Message:lj}{NewLine}"))
                        .WriteTo.Console()
                        .CreateLogger();

            log.Error("This is a test log message");

            env = "prod";

            log.Error("This is another log message");

            Console.ReadLine();

        }

  public static LoggerConfiguration GetLoggerConfiguration(Func<object> Environment)
        {

            var _loggerConfig = new LoggerConfiguration()
                            .Enrich.FromLogContext()
                            .Enrich.WithProperty("ApplicationInstanceId", ApplicationInstanceId)
                            .Enrich.With(new FunctionValueEnricher("Environment",()=>Environment));
                            
            return _loggerConfig;
        }

And the output:
[15:22:23 ERR] test This is a test log message
[15:22:23 ERR] This is a test log message
[15:22:24 ERR] prodonly This is another log message
[15:22:24 ERR] This is another log message

Azure Functions Environment

Please capture Azure Functions Environment as well:

if (string.IsNullOrWhiteSpace(environmentName))
{
    environmentName = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT");
}

here

private static LogEventProperty CreateProperty(ILogEventPropertyFactory propertyFactory)

as per

https://docs.microsoft.com/en-us/azure/azure-functions/functions-app-settings#azure_functions_environment

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.