Skip to content

[BUG] LogEventConverter.ConvertToEcs method overwrites the already assigned EcsDocument fields when adding MetaData #546

@hosseinalizadeh-v

Description

@hosseinalizadeh-v

ECS project: Elastic.CommonSchema.Serilog

ECS schema version: latest

ECS .NET assembly version: latest

.NET framework / OS: net9.0 / Windows

Description of the problem, including expected versus actual behavior:
If in our message template we use named parameter which EcsDocument already has the same property name during the conversion of LogEvent to EcsDocment the main property value of EcsDocument will be replaced by the value of the named parameter. To simply reproduce the issue we need to use message template that contains named parameters with the same name of EcsDocument fields. You can also have a look at the unit test below. You can add this test to the Elastic.CommonSchema.Serilog.Tests.MessageTests class.

[Fact]
public void SeesMessageWithMessageProp() => TestLogger((logger, getLogEvents) =>
{
	logger.Information("Info {Message}", "X");

	var logEvents = getLogEvents();
	logEvents.Should().HaveCount(1);

	var ecsEvents = ToEcsEvents(logEvents);

	var (_, info) = ecsEvents.First();
	info.Message.Should().Be("Info X");
	info.Labels.Should().ContainKey("X");

	var x = info.Labels["Message"];
	x.Should().NotBeNull().And.Be("X");
});

In my sample above I used Message named parameter in the message template.

The test above will be failed with the following message.
Expected info.Message to be "Info X" with a length of 6, but "X" has a length of 1, differs near "X" (index 0).

If you have a look at the test output that contains final serialized json you can see the message field value is "X" but the expected is "Info X". Compare it with the MessageTemplate field.

Standard output
{ "@timestamp": "2026-02-12T09:48:29.4267576+01:00", "log.level": "Information", "message": "X", "ecs.version": "9.0.0", "log": { "logger": "Elastic.CommonSchema.Serilog.Tests.MessageTests" }, "labels": { "MessageTemplate": "Info {Message}", "ThreadName": ".NET TP Worker" }, "agent": { "type": "Elastic.CommonSchema.Serilog", "version": "9.0.1-canary.0.9+e5480ff35c391fcc72ec6024d448d8c36b572127" }, "event": { "created": "2026-02-12T09:48:29.4267576+01:00", "severity": 2, "timezone": "Central Europe Standard Time" }, "host": { "os": { "full": "Microsoft Windows 10.0.26200", "platform": "Win32NT", "version": "10.0.26200.0" }, "architecture": "X64", "hostname": "mhahost", "name": "PRG10564" }, "process": { "name": "testhost", "pid": 42228, "thread.id": 11, "thread.name": ".NET TP Worker", "title": "" }, "server": { "user": { "name": "AMUST\\mhosseinalizadeh" } }, "service": { "name": "Elastic.CommonSchema", "type": "dotnet", "version": "9.0.1-canary.0.9+e5480ff35c391fcc72ec6024d448d8c36b572127" }, "user": { "domain": "Test", "name": "mhosseinalizadeh" } }

As far as I checked the issue is in LogEventConverter.ConvertToEcs method. Within this method we try to fetch all the relevant ecs data and fill those ecs properties and at the end there is a call to GetMetadata method that fetches all the remaining properties that are not ECS relevant properties (including the named parameters used in the message template). Then we call ecsEvent.AssignField method to set metadata.

.
.
.

var metaData = GetMetadata(logEvent, configuration.LogEventPropertiesToFilter);
foreach (var kv in metaData)
	ecsEvent.AssignField(kv.Key, kv.Value);
.
.
.

The point is that AssignField may set the value for all the fields of EcsDocument not only Metadata or Labels.
So in my example because I have Message named parameter, the path to be set in EcsDocument is "message" and because the EcsDocument has the Message field then the value will be replaced by the value of Message named parameter which is wrong.

Before calling AssignField method the value of the EcsDocument.Message property is correct because it is filled by ecsEvent.Message = logEvent.RenderMessage(configuration.MessageFormatProvider); and there is no problem. The issue happens after filling metadata because it replaces the Message field value.

Please note that the same issue may happen for other EcsDocument string properties like SpanId, TraceId and TransactionId.

Possible solution:
I think the solution would be using another method like AssignField that fills only Metadata or Labels not other fields in this case. Because they are already set correctly. So that we can ensure we will not replace the values that already set for EcsDocument properties by ConvertToEcs method. Unfortunately we do not have such a method currently :(

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions