1

Just starting using Serilog + ElasticSearch and was wondering if there is an elegant way to log a params object array in one log entry. So far the only way I have been able to manage it is looping through each params which creates a separate log entry for each one. Any way to combine them into one log entry?

Thanks!

Sample:

public static void MethodEntry<T>(string methodName, params object[] parameters)
{
    if (parameters.Length > 0)
        foreach (var param in parameters) // Will create parameters.Length number of log entries
            Log.ForContext(typeof(T)).Debug("Entering {MethodName} with {@Param}", methodName, param);
    else
        Log.ForContext(typeof(T)).Debug("Entering {MethodName}", methodName);
}

EDIT:

Sinks used:

  • Serilog
  • Serilog.Sinks.Elasticsearch (which includes The File, PeriodicBatching, & RollingFile Sinks)
  • Couple Enrichers like Environment and ThreadId
Hershizer33
  • 1,206
  • 2
  • 23
  • 46
  • Have you tried to just past parameters to Log? Something like the following: `Log.ForContext(typeof(T)).Debug("Entering {MethodName} with {@Parameters}", methodName, parameters);` ? – Samvel Petrosov Sep 11 '17 at 20:38
  • @SamvelPetrosov I did try that, but it resulted in the memory usage spiking until crash with no log entries written. – Hershizer33 Sep 11 '17 at 20:40
  • How many parameters do you pass? – Samvel Petrosov Sep 11 '17 at 20:41
  • @SamvelPetrosov In the crash's case it was 2 (it was an event so `object sender` and `EventArgs e`) – Hershizer33 Sep 11 '17 at 20:42
  • Which sinks do you use? Please add the initial config of the Serilog – Samvel Petrosov Sep 11 '17 at 20:50
  • @SamvelPetrosov Updated post. Mostly just Serilog + ElasticSearch sink, which comes with File, PeriodicBatching, & RollingFile sinks. – Hershizer33 Sep 11 '17 at 20:55
  • I have tried writing Log with `Log.ForContext(typeof(T)).Debug("Entering {MethodName} with {@Parameters}", methodName, parameters);` with RollingFile sink and it works ok for me. I think the problem is in your sink. – Samvel Petrosov Sep 11 '17 at 20:56
  • What object were passed in with `params`? – Hershizer33 Sep 11 '17 at 21:01
  • http://take.ms/uq4Dw – Samvel Petrosov Sep 11 '17 at 21:02
  • @SamvelPetrosov Interesting, it seems to be because my `sender` object is in a very big enterprise app, and thus this `sender` object is massive with a ton of nested stuff. It crashes trying to parse it all. It was able to get your example to work too, but the `sender` object was so much smaller. – Hershizer33 Sep 11 '17 at 21:07
  • Using `@Parameters` will recursively serialize the parameter values, hence the memory usage spike :-). The same code would work without the `@`, I think. – Nicholas Blumhardt Sep 11 '17 at 22:25

2 Answers2

2

If you know the specific type of your Sender object you can use the following feature of Serilog to avoid logging of the not required information:

Log.Logger = new LoggerConfiguration()
    .Destructure.ByTransforming<YOUR_SENDER_TYPE>(
        r => new { firstValue = r.firstValue, secondValue = r.secondValue })
    .WriteTo .... 

More about logging structured data you can find in the official documentation Serilog Structured Data

Samvel Petrosov
  • 7,580
  • 2
  • 22
  • 46
  • Interesting! My only concern is isn't `sender` in events in .NET always just a generic `object`? Then the override would apply to all `object`s instead of just the `sender` one... – Hershizer33 Sep 11 '17 at 21:13
  • 1
    Yeah that's why I have started my answer from "If you know the specific type". For example when you do a button click as sender there is boxed "Button" object so the checking `is Button` will return true. – Samvel Petrosov Sep 11 '17 at 21:14
  • 1
    Gotcha, still `Destructure` is great to know so thanks! If there's not specific answer for Event `sender` then I will accept this one in a day or too. – Hershizer33 Sep 11 '17 at 21:16
1
public static void MethodEntry<T>(string methodName, params object[] parameters)
{
    Log.ForContext<T>()
        .ForContext("Parameters", parameters)
        .Debug("Entering {MethodName}", methodName);
}

This should do what you're after.

Nicholas Blumhardt
  • 30,271
  • 4
  • 90
  • 101
  • I tried this way with the following objects: `Dim testStr = "test"` & `Dim testObj = New With {Key .Name = "Test", .Price = 1.29}`. The log entry is not written at all, no crash or exception just seems to skip the call. Call: `_logger.MethodEntry(NameOf(TestMethod), testStr, testObj)` Method: `log.ForContext("Parameters", parameters).Debug("Entering {MethodName}", methodName);` where `parameters` is `params object[] parameters`. Any thoughts? – Hershizer33 Sep 13 '17 at 20:18
  • I'm still having issues with this, any thoughts? – Hershizer33 Sep 18 '17 at 17:53
  • Do you have `Debug`-level logging turned on? One thing to check. – Nicholas Blumhardt Sep 19 '17 at 02:25
  • Yes, I did check that to make sure I wasn't going crazy haha – Hershizer33 Sep 19 '17 at 02:30