GithubHelp home page GithubHelp logo

datalust / nlog-targets-seq Goto Github PK

View Code? Open in Web Editor NEW
20.0 6.0 12.0 378 KB

An NLog target that writes events to Seq. Built for NLog 4.5+.

Home Page: https://getseq.net

License: Apache License 2.0

PowerShell 3.05% C# 96.95%
nlog-target nlog seq

nlog-targets-seq's People

Contributors

dependabot[bot] avatar gkinsman avatar kodraus avatar nameofthedragon avatar nblumhardt avatar snakefoot avatar

Stargazers

 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

nlog-targets-seq's Issues

`@m` is message template in stead of message?

image

{
  "@t": "2018-04-06T10:52:17.2967668Z",
  "@mt": "Removed sequence entry for Job: {Job.Id} as it completed with the state: {Job.State}.",
  "@m": "Removed sequence entry for Job: {Job.Id} as it completed with the state: {Job.State}.",
  "@i": "5f2536b7",
  "@l": "Debug",
  "MachineName": "XXX",
  "SiteName": "XXX",
  "Logged": "2018/04/06 12:52:17.296",
  "Level": "Debug",
  "Solution": "XXX",
  "Message": "Removed sequence entry for Job: \"223234\" as it completed with the state: \"Deleted\".",
  "Logger": "CleanupSequenceJobFilterAttribute",
  "Properties": "Job.Id=223234|Job.State=Deleted",
  "Https": "false",
  "RemoteAddress": ": - ",
  "Callsite": "CleanupSequenceJobFilterAttribute.OnStateApplied",
  "Job.Id": "223234",
  "Job.State": "Deleted"
}

Shouldn't @m be the value in the Message and not the MessageTemplate aka @mt ? Dont know if this is a log target issue or a configuration issue either in seq or with nlog?

Cant get Seq target to work with $configsetting

Hello,
This example https://github.com/304NotModified/NLog-Demo-cases/tree/master/AspNetCore2WithConfigSetting
works fine unitl I try to add a Seq target with a ${configsetting}

To reproduce:

  1. Add Target.Register<SeqTarget>("Seq"); as first line in Program.cs
  2. Change second target in nlog.config to:
<target xsi:type="Seq" name="ownFile-web" serverUrl="${configsetting:name=serverUrl}">
  <property name="Source" value="Seq Target Test"/>
</target>
  1. Add "serverUrl": "http://webtest4:5341/" to appsettings.json
  2. Add <PackageReference Include="NLog.Targets.Seq" Version="1.2.0-dev-00075" /> to csproj

internal log:

Error Seq Target[ownFile-web]: Error initializing target Exception: System.UriFormatException: Invalid URI: The format of the URI could not be determined.

Am I doing something wrong?

Everything else than Error or Fatal messages will be ignored

We are sending events to our seq server by using an API key.
When using minimum level (API key configuration page on SEQ) Info no Info level events are accepted on the seq server. Error and fatal level events will get through. Same for Debug or Verbose. Only accepting all events (setting minimum level to blank) will result in getting Info level / debug level events as well.

I assume that at some point the target is setting the event level not according to what seq expects, maybe?

It only works with NLog 4.5.0-alpha2

Hi,
I am testing on vs2015 on a simple project and it works but if i update NLog
NLog 4.5.0-alpha2 -> NLog 4.5.0-alpha3
or NLog 4.5.0-alpha2 -> NLog 5.0.0-beta5
nothing is logged in seq. Code:

       
 logger.Info("Hello, {Server}, from {Library}", server, library);

 // Text logging: the two properties are captured using positional arguments:
 logger.Info("Goodbye, {0}, from {1}", server, library);

Enable auto detection of proxy configuration

            IWebProxy proxy = WebRequest.GetSystemWebProxy();
            proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
            request.Proxy = proxy;
            request.PreAuthenticate = true;

Cache the default proxy to avoid auto lookup for every WebRequest.

Maybe a tristate (Explicit Proxy, Auto Proxy, Without Proxy - null):

https://stackoverflow.com/questions/2519655/httpwebrequest-is-extremely-slow

Can also be configured globally for the entire application:

<system.net>
    <defaultProxy enabled="true" useDefaultCredentials="true">
         <proxy usesystemdefault="True" />
    </defaultProxy>
</system.net>

https://msdn.microsoft.com/en-us/library/dkwyc043.aspx

Removing prorepries from Seq

There are paragraph about how to add custom properties, but I can't remove default ones. E.g. I want to remove ActionName from AspNetCore request (it's added automatically), and I can't. I tried it with
<propertyFilter> <remove regexToMatch="ActionName" /> </propertyFilter>
or excludeProperties="ActionName" in target, or overriding as <property name="ActionName" value="something" />, but it's got overriden and initial ActionName stays in log
More detailed config:
<target name="seq" xsi:type="BufferingWrapper" bufferSize="1000" flushTimeout="2000" > <target xsi:type="Seq" serverUrl="http://localhost:5341" apiKey="" excludeProperties="ActionName" > <propertyFilter> <remove regexToMatch="ActionName" /> </propertyFilter> <property name="MachineName" value="${machinename}" /> <property name="ActionName" value="something" /> </target> </target>

Collections aren't being logged in NLog 4.5 RTM

I just tried the examples here without explicitly fiddling with layout.

https://github.com/nlog/nlog/wiki/How-to-use-structured-logging

They all log as expected to file but for Seq the collection examples just output type names, e.g., Test System.String[] instead of Test "a", "b."

logger.Info("Test {value1}", new List<string> { "a", "b" }); // list of strings. Result: Test "a", "b"
logger.Info("Test {value1}", new[] { "a", "b" }); // array. Result: Test "a", "b"
logger.Info("Test {value1}", new Dictionary<string, int> { { "key1", 1 }, { "key2", 2 } }); // dict. Result:  Test "key1"=1, "key2"=2

I notice that Seq.Client.NLog is Oct 9th, so is that an issue?

Structured data being ToString'd rather than recorder as raw JSON

I'm trying to use ILogger.BeginScope to record structured object data, and have it recorded in Seq in JSON format so it can be queried, but it's consistently showing up as just strings, which is doesn't allow me to query it. I posted some of the issue here stackoverflow, and also tried one of the viable suggestions, but it doesn't work either.

I'm not sure if this is an issue in NLog or NLog.Targets.Seq.

I made an example web api controller in my .net 6 c# app for testing this, and the output in Seq is below after running it.

In the following test, only the first row (ObjectsOp2) generates the desired JSON format in Seq that is actually searchable as structured data.

I tried one of the viable stackoverflow suggestions of using a scope level layout ${scopenested:format=@}, but that produces JSON in string format rather than raw JSON in Seq, so it's not searchable or a workable solution. It gets output in each log as the Scope property.

Is there a bug in NLog.Targets.Seq specifically for the layout ${scopenested:format=@}? Seems like that should work.

NlogController

    [ApiController]
    [Route("[controller]")]
    public class NlogController : Controller
    {
        private readonly ILogger<NlogController> _logger;

        public NlogController(ILogger<NlogController> logger)
        {
            _logger = logger;
        }

        public class Test1Class
        {
            public class Test1InnerClass
            {
                public string Name { get; set; } = "";
                public string Description { get; set; } = "";
            }
            public int Id { get; set; }
            public List<Test1InnerClass> Tags { get; set; } = new List<Test1InnerClass>();
        }

        [HttpPost(nameof(Test1))]
        public Task Test1()
        {
            var objects = new Test1Class
            {
                Id = 1,
                Tags =
                {
                    new Test1Class.Test1InnerClass
                    {
                        Name = "global",
                        Description = "global tag"
                    },
                    new Test1Class.Test1InnerClass
                    {
                        Name = "exactMatch",
                        Description = "exactMatch tag"
                    }
                }
            };

            using (_logger.BeginScope(new Dictionary<string, object>
            {
                ["OrderId"] = 3456,
                ["ObjectsScope1"] = objects,
                ["@ObjectsScope2"] = objects,
                ["{@ObjectsScope3}"] = objects
            }))
            {
                _logger.LogInformation("String message with no additional parameters tied to it.");
                _logger.LogInformation("String message with a parameter tied to it using format: {{ObjectsOp1}}. {ObjectsOp1}", objects);
                _logger.LogInformation("String message with a parameter tied to it using format: {{@ObjectsOp2}}. {@ObjectsOp2}", objects);
            }

            return Task.CompletedTask;
        }
    }

appsettings.json

  "NLog": {
    "autoReload": true,
    "throwConfigExceptions": true,
    "internalLogLevel": "Info",
    "internalLogFile": "${basedir}/internal-nlog.txt",
    "extensions": [
      { "assembly": "NLog.Extensions.Logging" },
      { "assembly": "NLog.Web.AspNetCore" },
      { "assembly": "Microsoft.Data.SqlClient" },
      { "assembly": "NLog.Targets.Seq" }
    ],
    "default-wrapper": {
      "type": "AsyncWrapper",
      "overflowAction": "Block"
    },
    "targets": {
      "async": true,
      "logconsole": {
        "type": "Console"
      },
      "seq": {
        "type": "BufferingWrapper",
        "bufferSize": 200,
        "flushTimeout": 2000,
        "slidingTimeout": false,
        "target": {
          "type": "Seq",
          "serverUrl": "http://localhost:4005",
          "apiKey": "",
          "properties": [
            {
              "name": "Level",
              "value": "${level}"
            },
            {
              "name": "Scope",
              "value": "${scopenested:format=@}"
            },
            {
              "name": "CacheValueTest",
              "value": "${scopeproperty:CacheValue:format=@}"
            },
            {
              "name": "MachineName",
              "value": "${machinename}"
            },
            {
              "name": "Logger",
              "value": "${logger}"
            },
            {
              "name": "Callsite",
              "value": "${callsite}"
            },
            {
              "name": "Exception",
              "value": "${exception:tostring}"
            },
            {
              "name": "TraceId",
              "value": "${aspnet-TraceIdentifier}"
            },
            {
              "name": "Url",
              "value": "${aspnet-request-url}${aspnet-request-querystring}"
            },
            {
              "name": "Referer",
              "value": "${aspnet-request-referrer}"
            },
            {
              "name": "RequestMethod",
              "value": "${aspnet-request-method}"
            },
            {
              "name": "UserAgent",
              "value": "${aspnet-request-useragent}"
            },
            {
              "name": "ClientIpAddress",
              "value": "${aspnet-request-ip:CheckForwardedForHeader=true}"
            }
          ]
        }
      },
    "rules": [
      {
        "logger": "*",
        "minLevel": "Debug",
        "writeTo": "logconsole"
      },
      {
        "logger": "Ripple.*",
        "minLevel": "Debug",
        "writeTo": "seq"
      },
      {
        "logger": "Microsoft.*",
        "minLevel": "Off",
        "final": true
      }
    ]

row 1

{
  "@t": "2022-05-31T21:11:07.7751772Z",
  "@mt": "String message with a parameter tied to it using format: {{@ObjectsOp2}}. {@ObjectsOp2}",
  "@m": "String message with a parameter tied to it using format: {@ObjectsOp2}. {\n  \"Id\": 1,\n  \"Tags\": [\n    {\n      \"Name\": \"global\",\n      \"Description\": \"global tag\"\n    },\n    {\n      \"Name\": \"exactMatch\",\n      \"Description\": \"exactMatch tag\"\n    }\n  ]\n}",
  "@i": "11088dc7",
  "Level": "Info",
  "Scope": "[ { \"ConnectionId\": \"0HMI3987KKG0L\" }, { \"RequestId\": \"0HMI3987KKG0L:00000009\", \"RequestPath\": \"/Nlog/Test1\" }, { \"ActionId\": \"bd4fb72b-ea24-43d6-8960-5211ec8dbaae\", \"ActionName\": \"Ripple.Rest.Controllers.NlogController.Test1 (Ripple.Rest)\" }, { \"UserName\": \"Unknown User\", \"UserId\": 0 }, { \"OrderId\": 3456, \"ObjectsScope1\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]}, \"@ObjectsScope2\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]}, \"{@ObjectsScope3}\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]} } ]",
  "CacheValueTest": "null",
  "MachineName": "DESKTOP-QVMC0TS",
  "Logger": "Ripple.Rest.Controllers.NlogController",
  "Callsite": "Ripple.Rest.Controllers.NlogController.Test1",
  "TraceId": "00-8c95b52c3ee70d8cadd18547a13d9816-56e4d8037b71839f-00",
  "Url": "https://localhost/Nlog/Test1",
  "Referer": "https://localhost:7165/swagger/index.html",
  "RequestMethod": "POST",
  "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36",
  "ClientIpAddress": "::1",
  "ConnectionId": "0HMI3987KKG0L",
  "RequestId": "0HMI3987KKG0L:00000009",
  "RequestPath": "/Nlog/Test1",
  "ActionId": "bd4fb72b-ea24-43d6-8960-5211ec8dbaae",
  "ActionName": "Ripple.Rest.Controllers.NlogController.Test1 (Ripple.Rest)",
  "UserName": "Unknown User",
  "UserId": 0,
  "OrderId": 3456,
  "ObjectsScope1": "Ripple.Rest.Controllers.NlogController+Test1Class",
  "@@ObjectsScope2": "Ripple.Rest.Controllers.NlogController+Test1Class",
  "{@ObjectsScope3}": "Ripple.Rest.Controllers.NlogController+Test1Class",
  "ObjectsOp2": {
    "Id": 1,
    "Tags": [
      {
        "Name": "global",
        "Description": "global tag"
      },
      {
        "Name": "exactMatch",
        "Description": "exactMatch tag"
      }
    ]
  }
}

row 2

{
  "@t": "2022-05-31T21:11:07.7717526Z",
  "@mt": "String message with a parameter tied to it using format: {{ObjectsOp1}}. {ObjectsOp1}",
  "@m": "String message with a parameter tied to it using format: {ObjectsOp1}. Ripple.Rest.Controllers.NlogController+Test1Class",
  "@i": "a4227fe6",
  "Level": "Info",
  "Scope": "[ { \"ConnectionId\": \"0HMI3987KKG0L\" }, { \"RequestId\": \"0HMI3987KKG0L:00000009\", \"RequestPath\": \"/Nlog/Test1\" }, { \"ActionId\": \"bd4fb72b-ea24-43d6-8960-5211ec8dbaae\", \"ActionName\": \"Ripple.Rest.Controllers.NlogController.Test1 (Ripple.Rest)\" }, { \"UserName\": \"Unknown User\", \"UserId\": 0 }, { \"OrderId\": 3456, \"ObjectsScope1\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]}, \"@ObjectsScope2\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]}, \"{@ObjectsScope3}\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]} } ]",
  "CacheValueTest": "null",
  "MachineName": "DESKTOP-QVMC0TS",
  "Logger": "Ripple.Rest.Controllers.NlogController",
  "Callsite": "Ripple.Rest.Controllers.NlogController.Test1",
  "TraceId": "00-8c95b52c3ee70d8cadd18547a13d9816-56e4d8037b71839f-00",
  "Url": "https://localhost/Nlog/Test1",
  "Referer": "https://localhost:7165/swagger/index.html",
  "RequestMethod": "POST",
  "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36",
  "ClientIpAddress": "::1",
  "ConnectionId": "0HMI3987KKG0L",
  "RequestId": "0HMI3987KKG0L:00000009",
  "RequestPath": "/Nlog/Test1",
  "ActionId": "bd4fb72b-ea24-43d6-8960-5211ec8dbaae",
  "ActionName": "Ripple.Rest.Controllers.NlogController.Test1 (Ripple.Rest)",
  "UserName": "Unknown User",
  "UserId": 0,
  "OrderId": 3456,
  "ObjectsScope1": "Ripple.Rest.Controllers.NlogController+Test1Class",
  "@@ObjectsScope2": "Ripple.Rest.Controllers.NlogController+Test1Class",
  "{@ObjectsScope3}": "Ripple.Rest.Controllers.NlogController+Test1Class",
  "ObjectsOp1": "Ripple.Rest.Controllers.NlogController+Test1Class"
}

row 3

{
  "@t": "2022-05-31T21:11:07.7717526Z",
  "@mt": "String message with a parameter tied to it using format: {{ObjectsOp1}}. {ObjectsOp1}",
  "@m": "String message with a parameter tied to it using format: {ObjectsOp1}. Ripple.Rest.Controllers.NlogController+Test1Class",
  "@i": "a4227fe6",
  "Level": "Info",
  "Scope": "[ { \"ConnectionId\": \"0HMI3987KKG0L\" }, { \"RequestId\": \"0HMI3987KKG0L:00000009\", \"RequestPath\": \"/Nlog/Test1\" }, { \"ActionId\": \"bd4fb72b-ea24-43d6-8960-5211ec8dbaae\", \"ActionName\": \"Ripple.Rest.Controllers.NlogController.Test1 (Ripple.Rest)\" }, { \"UserName\": \"Unknown User\", \"UserId\": 0 }, { \"OrderId\": 3456, \"ObjectsScope1\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]}, \"@ObjectsScope2\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]}, \"{@ObjectsScope3}\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]} } ]",
  "CacheValueTest": "null",
  "MachineName": "DESKTOP-QVMC0TS",
  "Logger": "Ripple.Rest.Controllers.NlogController",
  "Callsite": "Ripple.Rest.Controllers.NlogController.Test1",
  "TraceId": "00-8c95b52c3ee70d8cadd18547a13d9816-56e4d8037b71839f-00",
  "Url": "https://localhost/Nlog/Test1",
  "Referer": "https://localhost:7165/swagger/index.html",
  "RequestMethod": "POST",
  "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36",
  "ClientIpAddress": "::1",
  "ConnectionId": "0HMI3987KKG0L",
  "RequestId": "0HMI3987KKG0L:00000009",
  "RequestPath": "/Nlog/Test1",
  "ActionId": "bd4fb72b-ea24-43d6-8960-5211ec8dbaae",
  "ActionName": "Ripple.Rest.Controllers.NlogController.Test1 (Ripple.Rest)",
  "UserName": "Unknown User",
  "UserId": 0,
  "OrderId": 3456,
  "ObjectsScope1": "Ripple.Rest.Controllers.NlogController+Test1Class",
  "@@ObjectsScope2": "Ripple.Rest.Controllers.NlogController+Test1Class",
  "{@ObjectsScope3}": "Ripple.Rest.Controllers.NlogController+Test1Class",
  "ObjectsOp1": "Ripple.Rest.Controllers.NlogController+Test1Class"
}

Compatibility with NLog 5.0.0

After upgrading NLog to 5.0.0 and NLog.Extensions.Logging to 5.0.0 the Seq target does not work anymore. I get an exception on:

NLogConfigurationException: Failed to create Target of type: Seq
NLog.Config.LoggingConfigurationParser.FactoryCreateInstance(string classType, INamedItemFactory<T, Type> factory)

I am using the default appsettings.json configuration as shown in the documentation for this package.

I did see in the breaking changes for NLog 5.0.0 that they changes some properties (such as bufferSize and flushTimeout from int to Layout in this commit part of changes to the BufferWrapper feature also used by this packages, see PR/Commit: https://github.com/NLog/NLog/pull/4858/files

The NLog 4.7.14 and NLog.Extensions.Logging 1.7.4 I was using in combination with NLog.Targets.Seq 2.1.0 does work. This prevents upgrading to NLog 5.0.0

Custom LayoutRenderers (lambda) and properties

Right now, when using properties as described in the readme.md you can use layout renderers as long as they're available by adding them as an extension (I believe). I'm however using the LayoutRenderer.Register lambda, which fails the initialization of the Seq target if I use that layout renderer because it hasn't been registered yet when NLog initializes itself and the target.

Could a solution be allowing adding properties to the SeqTarget Properties member? Right now that's not possible because of the private setter. Any other ideas?

Arrays inside dicts?

I have an Seq target like so:

<targets>
    <target name="seq" xsi:type="BufferingWrapper" bufferSize="1000" flushTimeout="2000">
        <target xsi:type="Seq" serverUrl="https://ourServer" apiKey="asd" />
    </target>
</targets>

<rules>
    <logger name="*" minlevel="Trace" writeTo="seq" />
</rules>

<extensions>
    <add assembly="NLog.Targets.Seq" />
</extensions>

And I can push some additional scope properties:

logger.PushScopeProperty("ArrayTest", New Integer() {1, 2, 3})
logger.PushScopeProperty("DictTest", New Dictionary(Of String, Object) From {{"KeyWithArray", New Integer() {1, 2, 3}}, {"KeyWithString", "Hello"}})

Now, in the case of ArrayTest and ArrayInDictTest, Seq recognizes these as JSON. However, in the latter case, the array inside the dictionary is treated as empty:

ArrayTest
[1, 2, 3]

DictTest
{
KeyWithArray: [],
KeyWithString: 'Hello'
}

Both keys are there, but only the string gets a value.

This is with target versions 2.1.0 and 3.0.0 on .NET 4.7.2, and Seq version 2023.4.10146.

(I'm not a 100% that this is on the target's end. However, I believe it works with the equivalent Serilog NuGet package.)

could not work with nlog5.0x

could not work with nlog5.0x
it is good with nlog4.7.15

version:
NLog.Targets.Seq V2.10
net4.72 / net6.0
Seq 2021.4

Substitute serverUrl value in NLog.config from appsettings

Hello, is it possible to substitute serverUrl value in NLog.config from appsettings like this?

<nlog>
  <targets>
    <target name="seq" type="Seq" serverUrl="${appsetting:name=SeqEndpointUrl}" apiKey="some api key">
  </targets>
</nlog>

I've also tried to make nlog variable, it does not work as well ;/

However, <property value/> substitutoin works somehow:

<target name="seq" type="Seq" serverUrl="http://ihavetohardcodethis.com" apiKey="some api key">
  <property name="Source" value="${appsetting:name=Works}" />
</target>

RenderingsLayout produces invalid CLEF under various circumstances

For events to be valid "compact JSON", the @r renderings property array must have exactly one element per formatted message template token.

In RenderingsTarget, the rendering isn't included in the array if the capture type is other than Normal, if there are no properties on the event, or if the property is missing: https://github.com/datalust/nlog-targets-seq/blob/dev/src/NLog.Targets.Seq/RenderingsLayout.cs#L55

This means an event like:

Logger.Info("Hello {@Broken:000}", 5);

produces "@r":[] when instead it should either include a placeholder value, or be omitted entirely.

Efficiently detect when positional placeholders appear in the message template

Here, we want to check if a positional template is being used so that the Parameters collection can be included:

https://github.com/datalust/nlog-targets-seq/blob/dev/src/NLog.Targets.Seq/LogEventInfoFormatter.cs#L134

@304NotModified any suggestions here? It seems like it's basically the same API requirement as #2 - get access to the parsed message template.

I imagine this might be as simple as just re-parsing the template in the target when required.

Enhancement: add support for includeAllProperties option

When serializing to a file it is possible to serialize all properties with layout render like this:

<layout xsi:type="JsonLayout" includeAllProperties="true" maxRecursionLimit="20" excludeProperties="...." >

It is not possible to add includeAllProperties, maxRecursionLimit and excludeProperties to seq target.

Background for this request:
I am trying to log properties using nlog-targests-seq so they are searchable.
I know I can use @ to serialize objects in messages - but is seems not possible for user properties?

Pseudo c# code that works (I can e.g. search for x.status=0 i seq):
class MyClass { public int status { get; set; } };
var x = new MyClass();
log.Debug().Message("Write {@x}", x).Write();

Pseudo c# code not working (only x class name is serialized so I can not search for x.status=0):
class MyClass { public int status { get; set; }
var x= new MyClass();
log.Debug().Message("Write Hi").Property("x", x).Write();

Today I have to format every property into the message string - this does not seem like an optimal method for structured logging.

Enh: perfs, reliability and durability

I am very happy to see the structured efforts of NLog 4.5 finally coming to fruition and a "real" Seq target! ๐ŸŽ‰ โค๏ธ

Because this target sends logs over the network, it is important that:

  • Logs are batched to minimize network round-trips;
  • Unavailable network or other failures don't prevent the app from working thanks to buffering;
  • In case of errors, a "safe" retry policy is in place (e.g. circuit breaker, expo. back-off);
  • There is an option for durability: buffered message are sync. flushed to disk until their are sent.

For the last bullet, it is important that messages be human-readable (not necessarily "nice", their json payload would be acceptable).
Lack of this feature would mean having a second file target beside the seq target. It would absolutely work but it would be a waste of resources since a lot of work would be duplicated for no reason.

Add an attribute in property tag to indicate passed value is json

I am using NLog and currently using a custom layout renderer to convert all properties to json to file based on following SO answer.
setup works properly for File target where json gets serialized

and I have following setup for NLog.Targets.Seq

<target name="seq" xsi:type="Seq" serverUrl="http://localhost:5341">
<property name ='properties' value='${json-event-properties}'/>
</target>

this gets sent as string instead of a json object to seq.
I verified it by downloading Raw Json from Seq.

I think adding an attribute to let Nlog.Targets.Seq know that passed string is json and making necessary changes in the nuget will help resolve the issue.
e.g.

<target name="seq" xsi:type="Seq" serverUrl="http://localhost:5341">
<property name ='properties' value='${json-event-properties}' isJson=true/>
</target>

Destructuring `@` operator support

The following should log structured data:

logger.Info("Hello, {@User}", new User { Name = "Alice" });

While the example without @ should log using ToString():

logger.Info("Hello, {User}", new User { Name = "Alice" });

At present, both will use ToString, although in both cases the value of the A property will be the User object.

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.