diff --git a/src/Elastic.CommonSchema.NLog/EcsLayout.cs b/src/Elastic.CommonSchema.NLog/EcsLayout.cs
index c7583220..6fe3ced0 100644
--- a/src/Elastic.CommonSchema.NLog/EcsLayout.cs
+++ b/src/Elastic.CommonSchema.NLog/EcsLayout.cs
@@ -304,7 +304,9 @@ public NLogEcsDocument RenderEcsDocument(LogEventInfo logEvent)
ecsEvent.Event = GetEvent(logEvent);
ecsEvent.Process = GetProcess(logEvent);
ecsEvent.Tags = GetTags(logEvent);
+#pragma warning disable CS0618 // Obsolete Labels
ecsEvent.Labels = GetLabels(logEvent);
+#pragma warning restore CS0618
ecsEvent.Http = GetHttp(logEvent);
ecsEvent.Url = GetUrl(logEvent);
diff --git a/src/Elastic.CommonSchema/EcsDocument.Generated.cs b/src/Elastic.CommonSchema/EcsDocument.Generated.cs
index fbdefb92..08951555 100644
--- a/src/Elastic.CommonSchema/EcsDocument.Generated.cs
+++ b/src/Elastic.CommonSchema/EcsDocument.Generated.cs
@@ -36,9 +36,10 @@ public partial class EcsDocument : BaseFieldSet , IAs, ICodeSignature, IElf, IEn
/// Container for additional metadata against this event.
///
/// When working with unknown fields use .
- /// This will try to assign valid ECS fields to their respective property
+ /// This will try to assign valid ECS fields to their respective property
/// Failing that it will assign strings to and everything else to
///
+ [Obsolete("Use Attributes instead. Metadata values will be merged into Attributes during serialization.")]
[JsonPropertyName("metadata"), DataMember(Name = "metadata")]
[JsonConverter(typeof(MetadataDictionaryConverter))]
public MetadataDictionary? Metadata { get; set; }
diff --git a/src/Elastic.CommonSchema/EcsDocument.OTel.cs b/src/Elastic.CommonSchema/EcsDocument.OTel.cs
new file mode 100644
index 00000000..b7df5ced
--- /dev/null
+++ b/src/Elastic.CommonSchema/EcsDocument.OTel.cs
@@ -0,0 +1,41 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
+
+namespace Elastic.CommonSchema;
+
+public partial class EcsDocument
+{
+ ///
+ /// Passthrough key-value store for OTel semantic convention attributes.
+ /// In Elasticsearch, attributes is a passthrough field type where the prefix can be omitted during queries.
+ /// In JSON source, data is nested under an attributes object.
+ ///
+ [JsonPropertyName("attributes"), DataMember(Name = "attributes")]
+ public MetadataDictionary? Attributes { get; set; }
+
+ ///
+ /// Assigns an OTel attribute value. Always stores in .
+ /// If the OTel name maps to an ECS field (via ),
+ /// also sets the corresponding ECS property via .
+ ///
+ /// The OTel semantic convention attribute name
+ /// The value to assign
+ public void AssignOTelField(string otelName, object value)
+ {
+ // Always store in Attributes
+ Attributes ??= new MetadataDictionary();
+ Attributes[otelName] = value;
+
+ // If there's a mapping to an ECS field, also set it
+ if (OTelMappings.OTelToEcs.TryGetValue(otelName, out var ecsPath))
+ AssignField(ecsPath, value);
+ else
+ // For match relations, the OTel name IS the ECS name — try direct assignment
+ AssignField(otelName, value);
+ }
+}
diff --git a/src/Elastic.CommonSchema/EcsDocument.cs b/src/Elastic.CommonSchema/EcsDocument.cs
index a5c92774..55e515ce 100644
--- a/src/Elastic.CommonSchema/EcsDocument.cs
+++ b/src/Elastic.CommonSchema/EcsDocument.cs
@@ -97,6 +97,9 @@ public static TEcsDocument CreateNewWithDefaults(
if (options?.IncludeActivityData is null or true)
SetActivityData(doc);
+ // Process remaining OTel resource attributes through the mapping table
+ ApplyOTelResourceAttributes(doc, initialCache.OTelResourceAttributes);
+
return doc;
}
@@ -121,6 +124,48 @@ private static IDictionary ParseOTelResourceAttributes(string? r
return keyValues;
}
+ // Attributes already handled by specific code in GetService/GetHost
+ private static readonly HashSet HandledResourceAttributes = new()
+ {
+ "service.name", "service.version", "service.instance.id",
+ "deployment.environment",
+ "host.name", "host.type", "host.arch"
+ };
+
+ private static void ApplyOTelResourceAttributes(EcsDocument doc, IDictionary? resourceAttributes)
+ {
+ if (resourceAttributes == null || resourceAttributes.Count == 0) return;
+
+ foreach (var kvp in resourceAttributes)
+ {
+ var attrName = kvp.Key;
+ var attrValue = kvp.Value;
+
+ // Skip attributes already handled by specific code
+ if (HandledResourceAttributes.Contains(attrName)) continue;
+
+ // Check if this OTel attribute name maps to an ECS field
+ if (OTelMappings.OTelToEcs.TryGetValue(attrName, out var ecsPath))
+ {
+ // Equivalent mapping: set ECS property and store in Attributes
+ doc.AssignField(ecsPath, attrValue);
+ doc.Attributes ??= new MetadataDictionary();
+ doc.Attributes[attrName] = attrValue;
+ }
+ else if (OTelMappings.AllBidirectionalEcsFields.Contains(attrName))
+ {
+ // Match relation: OTel name IS the ECS name
+ doc.AssignField(attrName, attrValue);
+ }
+ else
+ {
+ // Unknown attribute: store in Attributes only
+ doc.Attributes ??= new MetadataDictionary();
+ doc.Attributes[attrName] = attrValue;
+ }
+ }
+ }
+
///
/// Create an instance of that defaults to the assembly from
diff --git a/src/Elastic.CommonSchema/FieldSets.Generated.cs b/src/Elastic.CommonSchema/FieldSets.Generated.cs
index e7e46e1f..71d4e35e 100644
--- a/src/Elastic.CommonSchema/FieldSets.Generated.cs
+++ b/src/Elastic.CommonSchema/FieldSets.Generated.cs
@@ -173,6 +173,7 @@ public abstract class BaseFieldSet {
/// Example: `docker` and `k8s` labels.
/// {"application": "foo-bar", "env": "production"}
///
+ [Obsolete("Use EcsDocument.Attributes instead. Labels values will be merged into Attributes during serialization.")]
[JsonPropertyName("labels"), DataMember(Name = "labels")]
public Labels? Labels { get; set; }
}
@@ -605,6 +606,7 @@ public abstract class ContainerFieldSet {
/// Image labels.
///
///
+ [Obsolete("Use EcsDocument.Attributes instead. Labels values will be merged into Attributes during serialization.")]
[JsonPropertyName("labels"), DataMember(Name = "labels")]
public ContainerLabels? Labels { get; set; }
}
diff --git a/src/Elastic.CommonSchema/IndexComponents.Generated.cs b/src/Elastic.CommonSchema/IndexComponents.Generated.cs
index def12d37..5255fbfc 100644
--- a/src/Elastic.CommonSchema/IndexComponents.Generated.cs
+++ b/src/Elastic.CommonSchema/IndexComponents.Generated.cs
@@ -345,6 +345,10 @@ public static class IndexComponents
""@timestamp"": {
""type"": ""date""
},
+ ""attributes"": {
+ ""type"": ""passthrough"",
+ ""priority"": 10
+ },
""labels"": {
""type"": ""object""
},
@@ -359,8 +363,7 @@ public static class IndexComponents
}
}
}
-}
-"
+}"
},
{
"ecs_9.3.0_client",
diff --git a/src/Elastic.CommonSchema/IndexTemplates.Generated.cs b/src/Elastic.CommonSchema/IndexTemplates.Generated.cs
index 669fa81f..5dfda513 100644
--- a/src/Elastic.CommonSchema/IndexTemplates.Generated.cs
+++ b/src/Elastic.CommonSchema/IndexTemplates.Generated.cs
@@ -110,7 +110,7 @@ public static string GetIndexTemplateForElasticsearchComposable(string indexPatt
""codec"": ""best_compression"",
""mapping"": {
""total_fields"": {
- ""limit"": 3000
+ ""limit"": 3212
}
}
}
@@ -9562,7 +9562,7 @@ public static string GetIndexTemplateForElasticsearchLegacy(string indexPattern
""index"": {
""mapping"": {
""total_fields"": {
- ""limit"": 10000
+ ""limit"": 3212
}
},
""refresh_interval"": ""5s""
diff --git a/src/Elastic.CommonSchema/OTelMappings.Generated.cs b/src/Elastic.CommonSchema/OTelMappings.Generated.cs
new file mode 100644
index 00000000..e3ba0e1d
--- /dev/null
+++ b/src/Elastic.CommonSchema/OTelMappings.Generated.cs
@@ -0,0 +1,281 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+/*
+IMPORTANT NOTE
+==============
+This file has been generated.
+If you wish to submit a PR please modify the original csharp file and submit the PR with that change. Thanks!
+*/
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Elastic.CommonSchema
+{
+ ///
+ /// Bidirectional mapping tables between ECS field paths and OTel semantic convention attribute names.
+ /// Only includes match and equivalent relations.
+ ///
+ public static class OTelMappings
+ {
+ ///
+ /// ECS field path to OTel attribute name(s) for fields where the names differ (equivalent relation).
+ /// For match relations the names are identical and not listed here.
+ ///
+ public static readonly IReadOnlyDictionary EcsToOTel =
+ new ReadOnlyDictionary(new Dictionary
+ {
+ { "cloud.service.name", new[] { "cloud.platform" } },
+ { "container.image.hash.all", new[] { "container.image.repo_digests" } },
+ { "container.image.tag", new[] { "container.image.tags" } },
+ { "container.runtime", new[] { "container.runtime.name" } },
+ { "error.message", new[] { "exception.message" } },
+ { "error.stack_trace", new[] { "exception.stacktrace" } },
+ { "faas.execution", new[] { "faas.invocation_id" } },
+ { "faas.trigger.type", new[] { "faas.trigger" } },
+ { "file.ctime", new[] { "file.changed" } },
+ { "file.gid", new[] { "file.group.id" } },
+ { "file.group", new[] { "file.group.name" } },
+ { "file.mtime", new[] { "file.modified" } },
+ { "file.owner", new[] { "file.owner.name" } },
+ { "file.target_path", new[] { "file.symbolic_link.target_path" } },
+ { "file.uid", new[] { "file.owner.id" } },
+ { "gen_ai.system", new[] { "gen_ai.provider.name" } },
+ { "geo.city_name", new[] { "geo.locality.name" } },
+ { "geo.continent_code", new[] { "geo.continent.code" } },
+ { "geo.country_iso_code", new[] { "geo.country.iso_code" } },
+ { "geo.region_iso_code", new[] { "geo.region.iso_code" } },
+ { "host.architecture", new[] { "host.arch" } },
+ { "http.request.body.bytes", new[] { "http.request.body.size" } },
+ { "http.request.bytes", new[] { "http.request.size" } },
+ { "http.request.method", new[] { "http.request.method_original" } },
+ { "http.response.body.bytes", new[] { "http.response.body.size" } },
+ { "http.response.bytes", new[] { "http.response.size" } },
+ { "network.protocol", new[] { "network.protocol.name" } },
+ { "os.full", new[] { "os.description" } },
+ { "process.args", new[] { "process.command_args" } },
+ { "process.executable", new[] { "process.executable.path" } },
+ { "service.environment", new[] { "deployment.environment.name" } },
+ { "service.node.name", new[] { "service.instance.id" } },
+ });
+
+ ///
+ /// OTel attribute name to ECS field path for fields where the names differ (equivalent relation).
+ /// For match relations the names are identical and not listed here.
+ ///
+ public static readonly IReadOnlyDictionary OTelToEcs =
+ new ReadOnlyDictionary(new Dictionary
+ {
+ { "cloud.platform", "cloud.service.name" },
+ { "container.image.repo_digests", "container.image.hash.all" },
+ { "container.image.tags", "container.image.tag" },
+ { "container.runtime.name", "container.runtime" },
+ { "deployment.environment.name", "service.environment" },
+ { "exception.message", "error.message" },
+ { "exception.stacktrace", "error.stack_trace" },
+ { "faas.invocation_id", "faas.execution" },
+ { "faas.trigger", "faas.trigger.type" },
+ { "file.changed", "file.ctime" },
+ { "file.group.id", "file.gid" },
+ { "file.group.name", "file.group" },
+ { "file.modified", "file.mtime" },
+ { "file.owner.id", "file.uid" },
+ { "file.owner.name", "file.owner" },
+ { "file.symbolic_link.target_path", "file.target_path" },
+ { "gen_ai.provider.name", "gen_ai.system" },
+ { "geo.continent.code", "geo.continent_code" },
+ { "geo.country.iso_code", "geo.country_iso_code" },
+ { "geo.locality.name", "geo.city_name" },
+ { "geo.region.iso_code", "geo.region_iso_code" },
+ { "host.arch", "host.architecture" },
+ { "http.request.body.size", "http.request.body.bytes" },
+ { "http.request.method_original", "http.request.method" },
+ { "http.request.size", "http.request.bytes" },
+ { "http.response.body.size", "http.response.body.bytes" },
+ { "http.response.size", "http.response.bytes" },
+ { "network.protocol.name", "network.protocol" },
+ { "os.description", "os.full" },
+ { "process.command_args", "process.args" },
+ { "process.executable.path", "process.executable" },
+ { "service.instance.id", "service.node.name" },
+ });
+
+ ///
+ /// All bidirectional ECS field paths (both match and equivalent).
+ /// These are ECS fields that have a corresponding OTel semantic convention.
+ ///
+ public static readonly IReadOnlyCollection AllBidirectionalEcsFields = new HashSet
+ {
+ "client.address",
+ "client.port",
+ "cloud.account.id",
+ "cloud.availability_zone",
+ "cloud.provider",
+ "cloud.region",
+ "cloud.service.name",
+ "container.id",
+ "container.image.hash.all",
+ "container.image.name",
+ "container.image.tag",
+ "container.name",
+ "container.runtime",
+ "destination.address",
+ "destination.port",
+ "device.id",
+ "device.manufacturer",
+ "device.model.identifier",
+ "device.model.name",
+ "dns.question.name",
+ "error.message",
+ "error.stack_trace",
+ "error.type",
+ "faas.coldstart",
+ "faas.execution",
+ "faas.name",
+ "faas.trigger.type",
+ "faas.version",
+ "file.accessed",
+ "file.attributes",
+ "file.created",
+ "file.ctime",
+ "file.directory",
+ "file.extension",
+ "file.fork_name",
+ "file.gid",
+ "file.group",
+ "file.inode",
+ "file.mode",
+ "file.mtime",
+ "file.name",
+ "file.owner",
+ "file.path",
+ "file.size",
+ "file.target_path",
+ "file.uid",
+ "gen_ai.agent.description",
+ "gen_ai.agent.id",
+ "gen_ai.agent.name",
+ "gen_ai.operation.name",
+ "gen_ai.output.type",
+ "gen_ai.request.choice.count",
+ "gen_ai.request.encoding_formats",
+ "gen_ai.request.frequency_penalty",
+ "gen_ai.request.max_tokens",
+ "gen_ai.request.model",
+ "gen_ai.request.presence_penalty",
+ "gen_ai.request.seed",
+ "gen_ai.request.stop_sequences",
+ "gen_ai.request.temperature",
+ "gen_ai.request.top_k",
+ "gen_ai.request.top_p",
+ "gen_ai.response.finish_reasons",
+ "gen_ai.response.id",
+ "gen_ai.response.model",
+ "gen_ai.system",
+ "gen_ai.token.type",
+ "gen_ai.tool.call.id",
+ "gen_ai.tool.name",
+ "gen_ai.tool.type",
+ "gen_ai.usage.input_tokens",
+ "gen_ai.usage.output_tokens",
+ "geo.city_name",
+ "geo.continent_code",
+ "geo.country_iso_code",
+ "geo.postal_code",
+ "geo.region_iso_code",
+ "host.architecture",
+ "host.id",
+ "host.ip",
+ "host.mac",
+ "host.name",
+ "host.type",
+ "http.request.body.bytes",
+ "http.request.bytes",
+ "http.request.method",
+ "http.response.body.bytes",
+ "http.response.bytes",
+ "http.response.status_code",
+ "log.file.path",
+ "network.protocol",
+ "network.transport",
+ "network.type",
+ "os.full",
+ "os.name",
+ "os.version",
+ "process.args",
+ "process.args_count",
+ "process.command_line",
+ "process.executable",
+ "process.group_leader.pid",
+ "process.interactive",
+ "process.pid",
+ "process.real_user.id",
+ "process.real_user.name",
+ "process.saved_user.id",
+ "process.saved_user.name",
+ "process.session_leader.pid",
+ "process.title",
+ "process.user.id",
+ "process.user.name",
+ "process.vpid",
+ "process.working_directory",
+ "server.address",
+ "server.port",
+ "service.environment",
+ "service.name",
+ "service.node.name",
+ "service.version",
+ "source.address",
+ "source.port",
+ "tls.cipher",
+ "tls.client.certificate",
+ "tls.client.certificate_chain",
+ "tls.client.hash.md5",
+ "tls.client.hash.sha1",
+ "tls.client.hash.sha256",
+ "tls.client.issuer",
+ "tls.client.ja3",
+ "tls.client.not_after",
+ "tls.client.not_before",
+ "tls.client.subject",
+ "tls.client.supported_ciphers",
+ "tls.curve",
+ "tls.established",
+ "tls.next_protocol",
+ "tls.resumed",
+ "tls.server.certificate",
+ "tls.server.certificate_chain",
+ "tls.server.hash.md5",
+ "tls.server.hash.sha1",
+ "tls.server.hash.sha256",
+ "tls.server.issuer",
+ "tls.server.ja3s",
+ "tls.server.not_after",
+ "tls.server.not_before",
+ "tls.server.subject",
+ "url.domain",
+ "url.extension",
+ "url.fragment",
+ "url.full",
+ "url.original",
+ "url.path",
+ "url.port",
+ "url.query",
+ "url.registered_domain",
+ "url.scheme",
+ "url.subdomain",
+ "url.top_level_domain",
+ "user_agent.name",
+ "user_agent.original",
+ "user_agent.version",
+ "user.email",
+ "user.full_name",
+ "user.hash",
+ "user.id",
+ "user.name",
+ "user.roles",
+ };
+ }
+}
diff --git a/src/Elastic.CommonSchema/PropDispatch.Generated.cs b/src/Elastic.CommonSchema/PropDispatch.Generated.cs
index 1bca65fe..3746756b 100644
--- a/src/Elastic.CommonSchema/PropDispatch.Generated.cs
+++ b/src/Elastic.CommonSchema/PropDispatch.Generated.cs
@@ -5,7 +5,7 @@
/*
IMPORTANT NOTE
==============
-This file has been generated.
+This file has been generated.
If you wish to submit a PR please modify the original csharp file and submit the PR with that change. Thanks!
*/
@@ -24,7 +24,7 @@ If you wish to submit a PR please modify the original csharp file and submit the
namespace Elastic.CommonSchema
{
///
- public partial class EcsDocument : BaseFieldSet
+ public partial class EcsDocument : BaseFieldSet
{
///
/// Set ECS fields by name on .
@@ -43,9 +43,9 @@ public partial class EcsDocument : BaseFieldSet
public void AssignField(string path, object value)
{
var assigned = LogTemplateProperties.All.Contains(path) && TrySet(this, path, value);
- if (!assigned && LogTemplateEntities.All.Contains(path))
+ if (!assigned && LogTemplateEntities.All.Contains(path))
assigned = TrySetEntity(this, path, value);
- if (!assigned)
+ if (!assigned)
SetMetaOrLabel(this, path, value);
}
}
@@ -688,9 +688,9 @@ bool TypeCheck(Dictionary templatedObject, string typeName) =>
}
}
- internal static bool TrySet(EcsDocument document, string path, object value)
+ internal static bool TrySet(EcsDocument document, string path, object value)
{
- switch (path)
+ switch (path)
{
case "@timestamp":
case "Timestamp":
@@ -3257,6 +3257,9 @@ internal static bool TrySet(EcsDocument document, string path, object value)
case "X509VersionNumber":
return TrySetX509(document, path, value);
default:
+ // OTel equivalent name fallback: look up OTel name -> ECS path, then retry
+ if (OTelMappings.OTelToEcs.TryGetValue(path, out var ecsPath))
+ return TrySet(document, ecsPath, value);
return false;
}
}
@@ -3304,7 +3307,7 @@ public static bool TrySetAgent(EcsDocument document, string path, object value)
{
var assign = TryAssignAgent(path);
if (assign == null) return false;
-
+
var entity = document.Agent ?? new Agent();
var assigned = assign(entity, value);
if (assigned) document.Agent = entity;
@@ -3327,7 +3330,7 @@ public static bool TrySetAs(IAs document, string path, object value)
{
var assign = TryAssignAs(path);
if (assign == null) return false;
-
+
var entity = document.As ?? new As();
var assigned = assign(entity, value);
if (assigned) document.As = entity;
@@ -3440,7 +3443,7 @@ public static bool TrySetClient(EcsDocument document, string path, object value)
{
var assign = TryAssignClient(path);
if (assign == null) return false;
-
+
var entity = document.Client ?? new Client();
var assigned = assign(entity, value);
if (assigned) document.Client = entity;
@@ -3473,6 +3476,7 @@ public static Func TryAssignCloud(string path)
"CloudRegion" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Region = p),
"cloud.service.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ServiceName = p),
"CloudServiceName" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ServiceName = p),
+ "cloud.platform" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ServiceName = p),
"cloud.entity.display_name" => static (e, v) => TryAssignEntity("entity.display_name")(e.Entity ??= new Entity(),v),
"CloudEntityDisplayName" => static (e, v) => TryAssignEntity("entity.display_name")(e.Entity ??= new Entity(),v),
"cloud.entity.id" => static (e, v) => TryAssignEntity("entity.id")(e.Entity ??= new Entity(),v),
@@ -3495,7 +3499,7 @@ public static bool TrySetCloud(EcsDocument document, string path, object value)
{
var assign = TryAssignCloud(path);
if (assign == null) return false;
-
+
var entity = document.Cloud ?? new Cloud();
var assigned = assign(entity, value);
if (assigned) document.Cloud = entity;
@@ -3536,7 +3540,7 @@ public static bool TrySetCodeSignature(ICodeSignature document, string path, obj
{
var assign = TryAssignCodeSignature(path);
if (assign == null) return false;
-
+
var entity = document.CodeSignature ?? new CodeSignature();
var assigned = assign(entity, value);
if (assigned) document.CodeSignature = entity;
@@ -3567,6 +3571,7 @@ public static Func TryAssignContainer(string path)
"ContainerNetworkIngressBytes" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.NetworkIngressBytes = p),
"container.runtime" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Runtime = p),
"ContainerRuntime" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Runtime = p),
+ "container.runtime.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Runtime = p),
"container.security_context.privileged" => static (e, v) => TrySetBool(e, v, static (ee, p) => ee.SecurityContextPrivileged = p),
"ContainerSecurityContextPrivileged" => static (e, v) => TrySetBool(e, v, static (ee, p) => ee.SecurityContextPrivileged = p),
_ => null
@@ -3577,7 +3582,7 @@ public static bool TrySetContainer(EcsDocument document, string path, object val
{
var assign = TryAssignContainer(path);
if (assign == null) return false;
-
+
var entity = document.Container ?? new Container();
var assigned = assign(entity, value);
if (assigned) document.Container = entity;
@@ -3602,7 +3607,7 @@ public static bool TrySetDataStream(EcsDocument document, string path, object va
{
var assign = TryAssignDataStream(path);
if (assign == null) return false;
-
+
var entity = document.DataStream ?? new DataStream();
var assigned = assign(entity, value);
if (assigned) document.DataStream = entity;
@@ -3715,7 +3720,7 @@ public static bool TrySetDestination(EcsDocument document, string path, object v
{
var assign = TryAssignDestination(path);
if (assign == null) return false;
-
+
var entity = document.Destination ?? new Destination();
var assigned = assign(entity, value);
if (assigned) document.Destination = entity;
@@ -3754,7 +3759,7 @@ public static bool TrySetDevice(EcsDocument document, string path, object value)
{
var assign = TryAssignDevice(path);
if (assign == null) return false;
-
+
var entity = document.Device ?? new Device();
var assigned = assign(entity, value);
if (assigned) document.Device = entity;
@@ -3851,7 +3856,7 @@ public static bool TrySetDll(EcsDocument document, string path, object value)
{
var assign = TryAssignDll(path);
if (assign == null) return false;
-
+
var entity = document.Dll ?? new Dll();
var assigned = assign(entity, value);
if (assigned) document.Dll = entity;
@@ -3890,7 +3895,7 @@ public static bool TrySetDns(EcsDocument document, string path, object value)
{
var assign = TryAssignDns(path);
if (assign == null) return false;
-
+
var entity = document.Dns ?? new Dns();
var assigned = assign(entity, value);
if (assigned) document.Dns = entity;
@@ -3911,7 +3916,7 @@ public static bool TrySetEcs(EcsDocument document, string path, object value)
{
var assign = TryAssignEcs(path);
if (assign == null) return false;
-
+
var entity = document.Ecs ?? new Ecs();
var assigned = assign(entity, value);
if (assigned) document.Ecs = entity;
@@ -3972,7 +3977,7 @@ public static bool TrySetElf(IElf document, string path, object value)
{
var assign = TryAssignElf(path);
if (assign == null) return false;
-
+
var entity = document.Elf ?? new Elf();
var assigned = assign(entity, value);
if (assigned) document.Elf = entity;
@@ -4009,7 +4014,7 @@ public static bool TrySetEmail(EcsDocument document, string path, object value)
{
var assign = TryAssignEmail(path);
if (assign == null) return false;
-
+
var entity = document.Email ?? new Email();
var assigned = assign(entity, value);
if (assigned) document.Email = entity;
@@ -4042,7 +4047,7 @@ public static bool TrySetEntity(IEntity document, string path, object value)
{
var assign = TryAssignEntity(path);
if (assign == null) return false;
-
+
var entity = document.Entity ?? new Entity();
var assigned = assign(entity, value);
if (assigned) document.Entity = entity;
@@ -4059,8 +4064,10 @@ public static Func TryAssignError(string path)
"ErrorId" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Id = p),
"error.message" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Message = p),
"ErrorMessage" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Message = p),
+ "exception.message" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Message = p),
"error.stack_trace" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.StackTrace = p),
"ErrorStackTrace" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.StackTrace = p),
+ "exception.stacktrace" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.StackTrace = p),
"error.type" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Type = p),
"ErrorType" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Type = p),
_ => null
@@ -4071,7 +4078,7 @@ public static bool TrySetError(EcsDocument document, string path, object value)
{
var assign = TryAssignError(path);
if (assign == null) return false;
-
+
var entity = document.Error ?? new Error();
var assigned = assign(entity, value);
if (assigned) document.Error = entity;
@@ -4138,7 +4145,7 @@ public static bool TrySetEvent(EcsDocument document, string path, object value)
{
var assign = TryAssignEvent(path);
if (assign == null) return false;
-
+
var entity = document.Event ?? new Event();
var assigned = assign(entity, value);
if (assigned) document.Event = entity;
@@ -4153,6 +4160,7 @@ public static Func TryAssignFaas(string path)
"FaasColdstart" => static (e, v) => TrySetBool(e, v, static (ee, p) => ee.Coldstart = p),
"faas.execution" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Execution = p),
"FaasExecution" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Execution = p),
+ "faas.invocation_id" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Execution = p),
"faas.id" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Id = p),
"FaasId" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Id = p),
"faas.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Name = p),
@@ -4161,6 +4169,7 @@ public static Func TryAssignFaas(string path)
"FaasTriggerRequestId" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.TriggerRequestId = p),
"faas.trigger.type" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.TriggerType = p),
"FaasTriggerType" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.TriggerType = p),
+ "faas.trigger" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.TriggerType = p),
"faas.version" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Version = p),
"FaasVersion" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Version = p),
_ => null
@@ -4171,7 +4180,7 @@ public static bool TrySetFaas(EcsDocument document, string path, object value)
{
var assign = TryAssignFaas(path);
if (assign == null) return false;
-
+
var entity = document.Faas ?? new Faas();
var assigned = assign(entity, value);
if (assigned) document.Faas = entity;
@@ -4188,6 +4197,7 @@ public static Func TryAssignFile(string path)
"FileCreated" => static (e, v) => TrySetDateTimeOffset(e, v, static (ee, p) => ee.Created = p),
"file.ctime" => static (e, v) => TrySetDateTimeOffset(e, v, static (ee, p) => ee.Ctime = p),
"FileCtime" => static (e, v) => TrySetDateTimeOffset(e, v, static (ee, p) => ee.Ctime = p),
+ "file.changed" => static (e, v) => TrySetDateTimeOffset(e, v, static (ee, p) => ee.Ctime = p),
"file.device" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Device = p),
"FileDevice" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Device = p),
"file.directory" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Directory = p),
@@ -4200,8 +4210,10 @@ public static Func TryAssignFile(string path)
"FileForkName" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ForkName = p),
"file.gid" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Gid = p),
"FileGid" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Gid = p),
+ "file.group.id" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Gid = p),
"file.group" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Group = p),
"FileGroup" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Group = p),
+ "file.group.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Group = p),
"file.inode" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Inode = p),
"FileInode" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Inode = p),
"file.mime_type" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.MimeType = p),
@@ -4210,6 +4222,7 @@ public static Func TryAssignFile(string path)
"FileMode" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Mode = p),
"file.mtime" => static (e, v) => TrySetDateTimeOffset(e, v, static (ee, p) => ee.Mtime = p),
"FileMtime" => static (e, v) => TrySetDateTimeOffset(e, v, static (ee, p) => ee.Mtime = p),
+ "file.modified" => static (e, v) => TrySetDateTimeOffset(e, v, static (ee, p) => ee.Mtime = p),
"file.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Name = p),
"FileName" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Name = p),
"file.origin_referrer_url" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.OriginReferrerUrl = p),
@@ -4218,16 +4231,19 @@ public static Func TryAssignFile(string path)
"FileOriginUrl" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.OriginUrl = p),
"file.owner" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Owner = p),
"FileOwner" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Owner = p),
+ "file.owner.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Owner = p),
"file.path" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Path = p),
"FilePath" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Path = p),
"file.size" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.Size = p),
"FileSize" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.Size = p),
"file.target_path" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.TargetPath = p),
"FileTargetPath" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.TargetPath = p),
+ "file.symbolic_link.target_path" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.TargetPath = p),
"file.type" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Type = p),
"FileType" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Type = p),
"file.uid" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Uid = p),
"FileUid" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Uid = p),
+ "file.owner.id" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Uid = p),
"file.hash.cdhash" => static (e, v) => TryAssignHash("hash.cdhash")(e.Hash ??= new Hash(),v),
"FileHashCdhash" => static (e, v) => TryAssignHash("hash.cdhash")(e.Hash ??= new Hash(),v),
"file.hash.md5" => static (e, v) => TryAssignHash("hash.md5")(e.Hash ??= new Hash(),v),
@@ -4388,7 +4404,7 @@ public static bool TrySetFile(EcsDocument document, string path, object value)
{
var assign = TryAssignFile(path);
if (assign == null) return false;
-
+
var entity = document.File ?? new File();
var assigned = assign(entity, value);
if (assigned) document.File = entity;
@@ -4433,6 +4449,7 @@ public static Func TryAssignGenAi(string path)
"GenAiResponseModel" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ResponseModel = p),
"gen_ai.system" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.System = p),
"GenAiSystem" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.System = p),
+ "gen_ai.provider.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.System = p),
"gen_ai.token.type" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.TokenType = p),
"GenAiTokenType" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.TokenType = p),
"gen_ai.tool.call.id" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ToolCallId = p),
@@ -4453,7 +4470,7 @@ public static bool TrySetGenAi(EcsDocument document, string path, object value)
{
var assign = TryAssignGenAi(path);
if (assign == null) return false;
-
+
var entity = document.GenAi ?? new GenAi();
var assigned = assign(entity, value);
if (assigned) document.GenAi = entity;
@@ -4466,12 +4483,15 @@ public static Func TryAssignGeo(string path)
{
"geo.city_name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.CityName = p),
"GeoCityName" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.CityName = p),
+ "geo.locality.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.CityName = p),
"geo.continent_code" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ContinentCode = p),
"GeoContinentCode" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ContinentCode = p),
+ "geo.continent.code" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ContinentCode = p),
"geo.continent_name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ContinentName = p),
"GeoContinentName" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ContinentName = p),
"geo.country_iso_code" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.CountryIsoCode = p),
"GeoCountryIsoCode" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.CountryIsoCode = p),
+ "geo.country.iso_code" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.CountryIsoCode = p),
"geo.country_name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.CountryName = p),
"GeoCountryName" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.CountryName = p),
"geo.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Name = p),
@@ -4480,6 +4500,7 @@ public static Func TryAssignGeo(string path)
"GeoPostalCode" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.PostalCode = p),
"geo.region_iso_code" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RegionIsoCode = p),
"GeoRegionIsoCode" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RegionIsoCode = p),
+ "geo.region.iso_code" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RegionIsoCode = p),
"geo.region_name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RegionName = p),
"GeoRegionName" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RegionName = p),
"geo.timezone" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Timezone = p),
@@ -4492,7 +4513,7 @@ public static bool TrySetGeo(IGeo document, string path, object value)
{
var assign = TryAssignGeo(path);
if (assign == null) return false;
-
+
var entity = document.Geo ?? new Geo();
var assigned = assign(entity, value);
if (assigned) document.Geo = entity;
@@ -4517,7 +4538,7 @@ public static bool TrySetGroup(IGroup document, string path, object value)
{
var assign = TryAssignGroup(path);
if (assign == null) return false;
-
+
var entity = document.Group ?? new Group();
var assigned = assign(entity, value);
if (assigned) document.Group = entity;
@@ -4552,7 +4573,7 @@ public static bool TrySetHash(IHash document, string path, object value)
{
var assign = TryAssignHash(path);
if (assign == null) return false;
-
+
var entity = document.Hash ?? new Hash();
var assigned = assign(entity, value);
if (assigned) document.Hash = entity;
@@ -4565,6 +4586,7 @@ public static Func TryAssignHost(string path)
{
"host.architecture" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Architecture = p),
"HostArchitecture" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Architecture = p),
+ "host.arch" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Architecture = p),
"host.boot.id" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.BootId = p),
"HostBootId" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.BootId = p),
"host.cpu.usage" => static (e, v) => TrySetFloat(e, v, static (ee, p) => ee.CpuUsage = p),
@@ -4665,7 +4687,7 @@ public static bool TrySetHost(EcsDocument document, string path, object value)
{
var assign = TryAssignHost(path);
if (assign == null) return false;
-
+
var entity = document.Host ?? new Host();
var assigned = assign(entity, value);
if (assigned) document.Host = entity;
@@ -4678,24 +4700,29 @@ public static Func TryAssignHttp(string path)
{
"http.request.body.bytes" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.RequestBodyBytes = p),
"HttpRequestBodyBytes" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.RequestBodyBytes = p),
+ "http.request.body.size" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.RequestBodyBytes = p),
"http.request.body.content" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestBodyContent = p),
"HttpRequestBodyContent" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestBodyContent = p),
"http.request.bytes" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.RequestBytes = p),
"HttpRequestBytes" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.RequestBytes = p),
+ "http.request.size" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.RequestBytes = p),
"http.request.id" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestId = p),
"HttpRequestId" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestId = p),
"http.request.method" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestMethod = p),
"HttpRequestMethod" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestMethod = p),
+ "http.request.method_original" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestMethod = p),
"http.request.mime_type" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestMimeType = p),
"HttpRequestMimeType" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestMimeType = p),
"http.request.referrer" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestReferrer = p),
"HttpRequestReferrer" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.RequestReferrer = p),
"http.response.body.bytes" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.ResponseBodyBytes = p),
"HttpResponseBodyBytes" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.ResponseBodyBytes = p),
+ "http.response.body.size" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.ResponseBodyBytes = p),
"http.response.body.content" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ResponseBodyContent = p),
"HttpResponseBodyContent" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ResponseBodyContent = p),
"http.response.bytes" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.ResponseBytes = p),
"HttpResponseBytes" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.ResponseBytes = p),
+ "http.response.size" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.ResponseBytes = p),
"http.response.mime_type" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ResponseMimeType = p),
"HttpResponseMimeType" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.ResponseMimeType = p),
"http.response.status_code" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.ResponseStatusCode = p),
@@ -4710,7 +4737,7 @@ public static bool TrySetHttp(EcsDocument document, string path, object value)
{
var assign = TryAssignHttp(path);
if (assign == null) return false;
-
+
var entity = document.Http ?? new Http();
var assigned = assign(entity, value);
if (assigned) document.Http = entity;
@@ -4735,7 +4762,7 @@ public static bool TrySetInterface(EcsDocument document, string path, object val
{
var assign = TryAssignInterface(path);
if (assign == null) return false;
-
+
var entity = document.Interface ?? new Interface();
var assigned = assign(entity, value);
if (assigned) document.Interface = entity;
@@ -4766,7 +4793,7 @@ public static bool TrySetLog(EcsDocument document, string path, object value)
{
var assign = TryAssignLog(path);
if (assign == null) return false;
-
+
var entity = document.Log ?? new Log();
var assigned = assign(entity, value);
if (assigned) document.Log = entity;
@@ -4803,7 +4830,7 @@ public static bool TrySetMacho(IMacho document, string path, object value)
{
var assign = TryAssignMacho(path);
if (assign == null) return false;
-
+
var entity = document.Macho ?? new Macho();
var assigned = assign(entity, value);
if (assigned) document.Macho = entity;
@@ -4832,6 +4859,7 @@ public static Func TryAssignNetwork(string path)
"NetworkPackets" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.Packets = p),
"network.protocol" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Protocol = p),
"NetworkProtocol" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Protocol = p),
+ "network.protocol.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Protocol = p),
"network.transport" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Transport = p),
"NetworkTransport" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Transport = p),
"network.type" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Type = p),
@@ -4848,7 +4876,7 @@ public static bool TrySetNetwork(EcsDocument document, string path, object value
{
var assign = TryAssignNetwork(path);
if (assign == null) return false;
-
+
var entity = document.Network ?? new Network();
var assigned = assign(entity, value);
if (assigned) document.Network = entity;
@@ -4917,7 +4945,7 @@ public static bool TrySetObserver(EcsDocument document, string path, object valu
{
var assign = TryAssignObserver(path);
if (assign == null) return false;
-
+
var entity = document.Observer ?? new Observer();
var assigned = assign(entity, value);
if (assigned) document.Observer = entity;
@@ -4974,7 +5002,7 @@ public static bool TrySetOrchestrator(EcsDocument document, string path, object
{
var assign = TryAssignOrchestrator(path);
if (assign == null) return false;
-
+
var entity = document.Orchestrator ?? new Orchestrator();
var assigned = assign(entity, value);
if (assigned) document.Orchestrator = entity;
@@ -4997,7 +5025,7 @@ public static bool TrySetOrganization(EcsDocument document, string path, object
{
var assign = TryAssignOrganization(path);
if (assign == null) return false;
-
+
var entity = document.Organization ?? new Organization();
var assigned = assign(entity, value);
if (assigned) document.Organization = entity;
@@ -5012,6 +5040,7 @@ public static Func TryAssignOs(string path)
"OsFamily" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Family = p),
"os.full" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Full = p),
"OsFull" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Full = p),
+ "os.description" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Full = p),
"os.kernel" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Kernel = p),
"OsKernel" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Kernel = p),
"os.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Name = p),
@@ -5030,7 +5059,7 @@ public static bool TrySetOs(IOs document, string path, object value)
{
var assign = TryAssignOs(path);
if (assign == null) return false;
-
+
var entity = document.Os ?? new Os();
var assigned = assign(entity, value);
if (assigned) document.Os = entity;
@@ -5075,7 +5104,7 @@ public static bool TrySetPackage(EcsDocument document, string path, object value
{
var assign = TryAssignPackage(path);
if (assign == null) return false;
-
+
var entity = document.Package ?? new Package();
var assigned = assign(entity, value);
if (assigned) document.Package = entity;
@@ -5126,7 +5155,7 @@ public static bool TrySetPe(IPe document, string path, object value)
{
var assign = TryAssignPe(path);
if (assign == null) return false;
-
+
var entity = document.Pe ?? new Pe();
var assigned = assign(entity, value);
if (assigned) document.Pe = entity;
@@ -5147,6 +5176,7 @@ public static Func TryAssignProcess(string path)
"ProcessEntityId" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.EntityId = p),
"process.executable" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Executable = p),
"ProcessExecutable" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Executable = p),
+ "process.executable.path" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Executable = p),
"process.exit_code" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.ExitCode = p),
"ProcessExitCode" => static (e, v) => TrySetLong(e, v, static (ee, p) => ee.ExitCode = p),
"process.interactive" => static (e, v) => TrySetBool(e, v, static (ee, p) => ee.Interactive = p),
@@ -5595,7 +5625,7 @@ public static bool TrySetProcess(EcsDocument document, string path, object value
{
var assign = TryAssignProcess(path);
if (assign == null) return false;
-
+
var entity = document.Process ?? new Process();
var assigned = assign(entity, value);
if (assigned) document.Process = entity;
@@ -5626,7 +5656,7 @@ public static bool TrySetRegistry(EcsDocument document, string path, object valu
{
var assign = TryAssignRegistry(path);
if (assign == null) return false;
-
+
var entity = document.Registry ?? new Registry();
var assigned = assign(entity, value);
if (assigned) document.Registry = entity;
@@ -5645,7 +5675,7 @@ public static bool TrySetRelated(EcsDocument document, string path, object value
{
var assign = TryAssignRelated(path);
if (assign == null) return false;
-
+
var entity = document.Related ?? new Related();
var assigned = assign(entity, value);
if (assigned) document.Related = entity;
@@ -5676,7 +5706,7 @@ public static bool TrySetRisk(IRisk document, string path, object value)
{
var assign = TryAssignRisk(path);
if (assign == null) return false;
-
+
var entity = document.Risk ?? new Risk();
var assigned = assign(entity, value);
if (assigned) document.Risk = entity;
@@ -5713,7 +5743,7 @@ public static bool TrySetRule(EcsDocument document, string path, object value)
{
var assign = TryAssignRule(path);
if (assign == null) return false;
-
+
var entity = document.Rule ?? new Rule();
var assigned = assign(entity, value);
if (assigned) document.Rule = entity;
@@ -5826,7 +5856,7 @@ public static bool TrySetServer(EcsDocument document, string path, object value)
{
var assign = TryAssignServer(path);
if (assign == null) return false;
-
+
var entity = document.Server ?? new Server();
var assigned = assign(entity, value);
if (assigned) document.Server = entity;
@@ -5841,6 +5871,7 @@ public static Func TryAssignService(string path)
"ServiceAddress" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Address = p),
"service.environment" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Environment = p),
"ServiceEnvironment" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Environment = p),
+ "deployment.environment.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Environment = p),
"service.ephemeral_id" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.EphemeralId = p),
"ServiceEphemeralId" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.EphemeralId = p),
"service.id" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Id = p),
@@ -5849,6 +5880,7 @@ public static Func TryAssignService(string path)
"ServiceName" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.Name = p),
"service.node.name" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.NodeName = p),
"ServiceNodeName" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.NodeName = p),
+ "service.instance.id" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.NodeName = p),
"service.node.role" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.NodeRole = p),
"ServiceNodeRole" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.NodeRole = p),
"service.state" => static (e, v) => TrySetString(e, v, static (ee, p) => ee.State = p),
@@ -5879,7 +5911,7 @@ public static bool TrySetService(EcsDocument document, string path, object value
{
var assign = TryAssignService(path);
if (assign == null) return false;
-
+
var entity = document.Service ?? new Service();
var assigned = assign(entity, value);
if (assigned) document.Service = entity;
@@ -5992,7 +6024,7 @@ public static bool TrySetSource(EcsDocument document, string path, object value)
{
var assign = TryAssignSource(path);
if (assign == null) return false;
-
+
var entity = document.Source ?? new Source();
var assigned = assign(entity, value);
if (assigned) document.Source = entity;
@@ -6353,7 +6385,7 @@ public static bool TrySetThreat(EcsDocument document, string path, object value)
{
var assign = TryAssignThreat(path);
if (assign == null) return false;
-
+
var entity = document.Threat ?? new Threat();
var assigned = assign(entity, value);
if (assigned) document.Threat = entity;
@@ -6446,7 +6478,7 @@ public static bool TrySetTls(EcsDocument document, string path, object value)
{
var assign = TryAssignTls(path);
if (assign == null) return false;
-
+
var entity = document.Tls ?? new Tls();
var assigned = assign(entity, value);
if (assigned) document.Tls = entity;
@@ -6493,7 +6525,7 @@ public static bool TrySetUrl(EcsDocument document, string path, object value)
{
var assign = TryAssignUrl(path);
if (assign == null) return false;
-
+
var entity = document.Url ?? new Url();
var assigned = assign(entity, value);
if (assigned) document.Url = entity;
@@ -6556,7 +6588,7 @@ public static bool TrySetUser(IUser document, string path, object value)
{
var assign = TryAssignUser(path);
if (assign == null) return false;
-
+
var entity = document.User ?? new User();
var assigned = assign(entity, value);
if (assigned) document.User = entity;
@@ -6597,7 +6629,7 @@ public static bool TrySetUserAgent(EcsDocument document, string path, object val
{
var assign = TryAssignUserAgent(path);
if (assign == null) return false;
-
+
var entity = document.UserAgent ?? new UserAgent();
var assigned = assign(entity, value);
if (assigned) document.UserAgent = entity;
@@ -6620,7 +6652,7 @@ public static bool TrySetVlan(IVlan document, string path, object value)
{
var assign = TryAssignVlan(path);
if (assign == null) return false;
-
+
var entity = document.Vlan ?? new Vlan();
var assigned = assign(entity, value);
if (assigned) document.Vlan = entity;
@@ -6671,7 +6703,7 @@ public static bool TrySetVolume(EcsDocument document, string path, object value)
{
var assign = TryAssignVolume(path);
if (assign == null) return false;
-
+
var entity = document.Volume ?? new Volume();
var assigned = assign(entity, value);
if (assigned) document.Volume = entity;
@@ -6714,7 +6746,7 @@ public static bool TrySetVulnerability(EcsDocument document, string path, object
{
var assign = TryAssignVulnerability(path);
if (assign == null) return false;
-
+
var entity = document.Vulnerability ?? new Vulnerability();
var assigned = assign(entity, value);
if (assigned) document.Vulnerability = entity;
@@ -6755,7 +6787,7 @@ public static bool TrySetX509(IX509 document, string path, object value)
{
var assign = TryAssignX509(path);
if (assign == null) return false;
-
+
var entity = document.X509 ?? new X509();
var assigned = assign(entity, value);
if (assigned) document.X509 = entity;
diff --git a/src/Elastic.CommonSchema/PropDispatch.cs b/src/Elastic.CommonSchema/PropDispatch.cs
index 68806606..6aa98d72 100644
--- a/src/Elastic.CommonSchema/PropDispatch.cs
+++ b/src/Elastic.CommonSchema/PropDispatch.cs
@@ -30,21 +30,8 @@ internal static partial class PropDispatch
{
public static void SetMetaOrLabel(EcsDocument document, string path, object value)
{
- switch (value)
- {
- case string s:
- document.Labels ??= new Labels();
- document.Labels[path] = s;
- break;
- case bool b:
- document.Labels ??= new Labels();
- document.Labels[path] = b.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
- break;
- default:
- document.Metadata ??= new MetadataDictionary();
- document.Metadata[path] = value;
- break;
- }
+ document.Attributes ??= new MetadataDictionary();
+ document.Attributes[path] = value;
}
private static bool TrySetLong(T target, object value, Action set)
diff --git a/src/Elastic.CommonSchema/SemConv.Generated.cs b/src/Elastic.CommonSchema/SemConv.Generated.cs
new file mode 100644
index 00000000..8663c5ec
--- /dev/null
+++ b/src/Elastic.CommonSchema/SemConv.Generated.cs
@@ -0,0 +1,861 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+/*
+IMPORTANT NOTE
+==============
+This file has been generated.
+If you wish to submit a PR please modify the original csharp file and submit the PR with that change. Thanks!
+*/
+
+namespace Elastic.CommonSchema
+{
+ ///
+ /// OpenTelemetry semantic convention attribute name constants.
+ /// Use these with and .
+ ///
+ public static class SemConv
+ {
+ ///
+ /// OTel client.address (match: same as ECS)
+ ///
+ public const string ClientAddress = "client.address";
+
+ ///
+ /// OTel client.port (match: same as ECS)
+ ///
+ public const string ClientPort = "client.port";
+
+ ///
+ /// OTel cloud.account.id (match: same as ECS)
+ ///
+ public const string CloudAccountId = "cloud.account.id";
+
+ ///
+ /// OTel cloud.availability_zone (match: same as ECS)
+ ///
+ public const string CloudAvailabilityZone = "cloud.availability_zone";
+
+ ///
+ /// OTel cloud.platform (equivalent: ECS cloud.service.name)
+ ///
+ public const string CloudPlatform = "cloud.platform";
+
+ ///
+ /// OTel cloud.provider (match: same as ECS)
+ ///
+ public const string CloudProvider = "cloud.provider";
+
+ ///
+ /// OTel cloud.region (match: same as ECS)
+ ///
+ public const string CloudRegion = "cloud.region";
+
+ ///
+ /// OTel container.id (match: same as ECS)
+ ///
+ public const string ContainerId = "container.id";
+
+ ///
+ /// OTel container.image.name (match: same as ECS)
+ ///
+ public const string ContainerImageName = "container.image.name";
+
+ ///
+ /// OTel container.image.repo_digests (equivalent: ECS container.image.hash.all)
+ ///
+ public const string ContainerImageRepoDigests = "container.image.repo_digests";
+
+ ///
+ /// OTel container.image.tags (equivalent: ECS container.image.tag)
+ ///
+ public const string ContainerImageTags = "container.image.tags";
+
+ ///
+ /// OTel container.name (match: same as ECS)
+ ///
+ public const string ContainerName = "container.name";
+
+ ///
+ /// OTel container.runtime.name (equivalent: ECS container.runtime)
+ ///
+ public const string ContainerRuntimeName = "container.runtime.name";
+
+ ///
+ /// OTel deployment.environment.name (equivalent: ECS service.environment)
+ ///
+ public const string DeploymentEnvironmentName = "deployment.environment.name";
+
+ ///
+ /// OTel destination.address (match: same as ECS)
+ ///
+ public const string DestinationAddress = "destination.address";
+
+ ///
+ /// OTel destination.port (match: same as ECS)
+ ///
+ public const string DestinationPort = "destination.port";
+
+ ///
+ /// OTel device.id (match: same as ECS)
+ ///
+ public const string DeviceId = "device.id";
+
+ ///
+ /// OTel device.manufacturer (match: same as ECS)
+ ///
+ public const string DeviceManufacturer = "device.manufacturer";
+
+ ///
+ /// OTel device.model.identifier (match: same as ECS)
+ ///
+ public const string DeviceModelIdentifier = "device.model.identifier";
+
+ ///
+ /// OTel device.model.name (match: same as ECS)
+ ///
+ public const string DeviceModelName = "device.model.name";
+
+ ///
+ /// OTel dns.question.name (match: same as ECS)
+ ///
+ public const string DnsQuestionName = "dns.question.name";
+
+ ///
+ /// OTel error.type (match: same as ECS)
+ ///
+ public const string ErrorType = "error.type";
+
+ ///
+ /// OTel exception.message (equivalent: ECS error.message)
+ ///
+ public const string ExceptionMessage = "exception.message";
+
+ ///
+ /// OTel exception.stacktrace (equivalent: ECS error.stack_trace)
+ ///
+ public const string ExceptionStacktrace = "exception.stacktrace";
+
+ ///
+ /// OTel faas.coldstart (match: same as ECS)
+ ///
+ public const string FaasColdstart = "faas.coldstart";
+
+ ///
+ /// OTel faas.invocation_id (equivalent: ECS faas.execution)
+ ///
+ public const string FaasInvocationId = "faas.invocation_id";
+
+ ///
+ /// OTel faas.name (match: same as ECS)
+ ///
+ public const string FaasName = "faas.name";
+
+ ///
+ /// OTel faas.trigger (equivalent: ECS faas.trigger.type)
+ ///
+ public const string FaasTrigger = "faas.trigger";
+
+ ///
+ /// OTel faas.version (match: same as ECS)
+ ///
+ public const string FaasVersion = "faas.version";
+
+ ///
+ /// OTel file.accessed (match: same as ECS)
+ ///
+ public const string FileAccessed = "file.accessed";
+
+ ///
+ /// OTel file.attributes (match: same as ECS)
+ ///
+ public const string FileAttributes = "file.attributes";
+
+ ///
+ /// OTel file.changed (equivalent: ECS file.ctime)
+ ///
+ public const string FileChanged = "file.changed";
+
+ ///
+ /// OTel file.created (match: same as ECS)
+ ///
+ public const string FileCreated = "file.created";
+
+ ///
+ /// OTel file.directory (match: same as ECS)
+ ///
+ public const string FileDirectory = "file.directory";
+
+ ///
+ /// OTel file.extension (match: same as ECS)
+ ///
+ public const string FileExtension = "file.extension";
+
+ ///
+ /// OTel file.fork_name (match: same as ECS)
+ ///
+ public const string FileForkName = "file.fork_name";
+
+ ///
+ /// OTel file.group.id (equivalent: ECS file.gid)
+ ///
+ public const string FileGroupId = "file.group.id";
+
+ ///
+ /// OTel file.group.name (equivalent: ECS file.group)
+ ///
+ public const string FileGroupName = "file.group.name";
+
+ ///
+ /// OTel file.inode (match: same as ECS)
+ ///
+ public const string FileInode = "file.inode";
+
+ ///
+ /// OTel file.mode (match: same as ECS)
+ ///
+ public const string FileMode = "file.mode";
+
+ ///
+ /// OTel file.modified (equivalent: ECS file.mtime)
+ ///
+ public const string FileModified = "file.modified";
+
+ ///
+ /// OTel file.name (match: same as ECS)
+ ///
+ public const string FileName = "file.name";
+
+ ///
+ /// OTel file.owner.id (equivalent: ECS file.uid)
+ ///
+ public const string FileOwnerId = "file.owner.id";
+
+ ///
+ /// OTel file.owner.name (equivalent: ECS file.owner)
+ ///
+ public const string FileOwnerName = "file.owner.name";
+
+ ///
+ /// OTel file.path (match: same as ECS)
+ ///
+ public const string FilePath = "file.path";
+
+ ///
+ /// OTel file.size (match: same as ECS)
+ ///
+ public const string FileSize = "file.size";
+
+ ///
+ /// OTel file.symbolic_link.target_path (equivalent: ECS file.target_path)
+ ///
+ public const string FileSymbolicLinkTargetPath = "file.symbolic_link.target_path";
+
+ ///
+ /// OTel gen_ai.agent.description (match: same as ECS)
+ ///
+ public const string GenAiAgentDescription = "gen_ai.agent.description";
+
+ ///
+ /// OTel gen_ai.agent.id (match: same as ECS)
+ ///
+ public const string GenAiAgentId = "gen_ai.agent.id";
+
+ ///
+ /// OTel gen_ai.agent.name (match: same as ECS)
+ ///
+ public const string GenAiAgentName = "gen_ai.agent.name";
+
+ ///
+ /// OTel gen_ai.operation.name (match: same as ECS)
+ ///
+ public const string GenAiOperationName = "gen_ai.operation.name";
+
+ ///
+ /// OTel gen_ai.output.type (match: same as ECS)
+ ///
+ public const string GenAiOutputType = "gen_ai.output.type";
+
+ ///
+ /// OTel gen_ai.provider.name (equivalent: ECS gen_ai.system)
+ ///
+ public const string GenAiProviderName = "gen_ai.provider.name";
+
+ ///
+ /// OTel gen_ai.request.choice.count (match: same as ECS)
+ ///
+ public const string GenAiRequestChoiceCount = "gen_ai.request.choice.count";
+
+ ///
+ /// OTel gen_ai.request.encoding_formats (match: same as ECS)
+ ///
+ public const string GenAiRequestEncodingFormats = "gen_ai.request.encoding_formats";
+
+ ///
+ /// OTel gen_ai.request.frequency_penalty (match: same as ECS)
+ ///
+ public const string GenAiRequestFrequencyPenalty = "gen_ai.request.frequency_penalty";
+
+ ///
+ /// OTel gen_ai.request.max_tokens (match: same as ECS)
+ ///
+ public const string GenAiRequestMaxTokens = "gen_ai.request.max_tokens";
+
+ ///
+ /// OTel gen_ai.request.model (match: same as ECS)
+ ///
+ public const string GenAiRequestModel = "gen_ai.request.model";
+
+ ///
+ /// OTel gen_ai.request.presence_penalty (match: same as ECS)
+ ///
+ public const string GenAiRequestPresencePenalty = "gen_ai.request.presence_penalty";
+
+ ///
+ /// OTel gen_ai.request.seed (match: same as ECS)
+ ///
+ public const string GenAiRequestSeed = "gen_ai.request.seed";
+
+ ///
+ /// OTel gen_ai.request.stop_sequences (match: same as ECS)
+ ///
+ public const string GenAiRequestStopSequences = "gen_ai.request.stop_sequences";
+
+ ///
+ /// OTel gen_ai.request.temperature (match: same as ECS)
+ ///
+ public const string GenAiRequestTemperature = "gen_ai.request.temperature";
+
+ ///
+ /// OTel gen_ai.request.top_k (match: same as ECS)
+ ///
+ public const string GenAiRequestTopK = "gen_ai.request.top_k";
+
+ ///
+ /// OTel gen_ai.request.top_p (match: same as ECS)
+ ///
+ public const string GenAiRequestTopP = "gen_ai.request.top_p";
+
+ ///
+ /// OTel gen_ai.response.finish_reasons (match: same as ECS)
+ ///
+ public const string GenAiResponseFinishReasons = "gen_ai.response.finish_reasons";
+
+ ///
+ /// OTel gen_ai.response.id (match: same as ECS)
+ ///
+ public const string GenAiResponseId = "gen_ai.response.id";
+
+ ///
+ /// OTel gen_ai.response.model (match: same as ECS)
+ ///
+ public const string GenAiResponseModel = "gen_ai.response.model";
+
+ ///
+ /// OTel gen_ai.token.type (match: same as ECS)
+ ///
+ public const string GenAiTokenType = "gen_ai.token.type";
+
+ ///
+ /// OTel gen_ai.tool.call.id (match: same as ECS)
+ ///
+ public const string GenAiToolCallId = "gen_ai.tool.call.id";
+
+ ///
+ /// OTel gen_ai.tool.name (match: same as ECS)
+ ///
+ public const string GenAiToolName = "gen_ai.tool.name";
+
+ ///
+ /// OTel gen_ai.tool.type (match: same as ECS)
+ ///
+ public const string GenAiToolType = "gen_ai.tool.type";
+
+ ///
+ /// OTel gen_ai.usage.input_tokens (match: same as ECS)
+ ///
+ public const string GenAiUsageInputTokens = "gen_ai.usage.input_tokens";
+
+ ///
+ /// OTel gen_ai.usage.output_tokens (match: same as ECS)
+ ///
+ public const string GenAiUsageOutputTokens = "gen_ai.usage.output_tokens";
+
+ ///
+ /// OTel geo.continent.code (equivalent: ECS geo.continent_code)
+ ///
+ public const string GeoContinentCode = "geo.continent.code";
+
+ ///
+ /// OTel geo.country.iso_code (equivalent: ECS geo.country_iso_code)
+ ///
+ public const string GeoCountryIsoCode = "geo.country.iso_code";
+
+ ///
+ /// OTel geo.locality.name (equivalent: ECS geo.city_name)
+ ///
+ public const string GeoLocalityName = "geo.locality.name";
+
+ ///
+ /// OTel geo.postal_code (match: same as ECS)
+ ///
+ public const string GeoPostalCode = "geo.postal_code";
+
+ ///
+ /// OTel geo.region.iso_code (equivalent: ECS geo.region_iso_code)
+ ///
+ public const string GeoRegionIsoCode = "geo.region.iso_code";
+
+ ///
+ /// OTel host.arch (equivalent: ECS host.architecture)
+ ///
+ public const string HostArch = "host.arch";
+
+ ///
+ /// OTel host.id (match: same as ECS)
+ ///
+ public const string HostId = "host.id";
+
+ ///
+ /// OTel host.ip (match: same as ECS)
+ ///
+ public const string HostIp = "host.ip";
+
+ ///
+ /// OTel host.mac (match: same as ECS)
+ ///
+ public const string HostMac = "host.mac";
+
+ ///
+ /// OTel host.name (match: same as ECS)
+ ///
+ public const string HostName = "host.name";
+
+ ///
+ /// OTel host.type (match: same as ECS)
+ ///
+ public const string HostType = "host.type";
+
+ ///
+ /// OTel http.request.body.size (equivalent: ECS http.request.body.bytes)
+ ///
+ public const string HttpRequestBodySize = "http.request.body.size";
+
+ ///
+ /// OTel http.request.method_original (equivalent: ECS http.request.method)
+ ///
+ public const string HttpRequestMethodOriginal = "http.request.method_original";
+
+ ///
+ /// OTel http.request.size (equivalent: ECS http.request.bytes)
+ ///
+ public const string HttpRequestSize = "http.request.size";
+
+ ///
+ /// OTel http.response.body.size (equivalent: ECS http.response.body.bytes)
+ ///
+ public const string HttpResponseBodySize = "http.response.body.size";
+
+ ///
+ /// OTel http.response.size (equivalent: ECS http.response.bytes)
+ ///
+ public const string HttpResponseSize = "http.response.size";
+
+ ///
+ /// OTel http.response.status_code (match: same as ECS)
+ ///
+ public const string HttpResponseStatusCode = "http.response.status_code";
+
+ ///
+ /// OTel log.file.path (match: same as ECS)
+ ///
+ public const string LogFilePath = "log.file.path";
+
+ ///
+ /// OTel network.protocol.name (equivalent: ECS network.protocol)
+ ///
+ public const string NetworkProtocolName = "network.protocol.name";
+
+ ///
+ /// OTel network.transport (match: same as ECS)
+ ///
+ public const string NetworkTransport = "network.transport";
+
+ ///
+ /// OTel network.type (match: same as ECS)
+ ///
+ public const string NetworkType = "network.type";
+
+ ///
+ /// OTel os.description (equivalent: ECS os.full)
+ ///
+ public const string OsDescription = "os.description";
+
+ ///
+ /// OTel os.name (match: same as ECS)
+ ///
+ public const string OsName = "os.name";
+
+ ///
+ /// OTel os.version (match: same as ECS)
+ ///
+ public const string OsVersion = "os.version";
+
+ ///
+ /// OTel process.args_count (match: same as ECS)
+ ///
+ public const string ProcessArgsCount = "process.args_count";
+
+ ///
+ /// OTel process.command_args (equivalent: ECS process.args)
+ ///
+ public const string ProcessCommandArgs = "process.command_args";
+
+ ///
+ /// OTel process.command_line (match: same as ECS)
+ ///
+ public const string ProcessCommandLine = "process.command_line";
+
+ ///
+ /// OTel process.executable.path (equivalent: ECS process.executable)
+ ///
+ public const string ProcessExecutablePath = "process.executable.path";
+
+ ///
+ /// OTel process.group_leader.pid (match: same as ECS)
+ ///
+ public const string ProcessGroupLeaderPid = "process.group_leader.pid";
+
+ ///
+ /// OTel process.interactive (match: same as ECS)
+ ///
+ public const string ProcessInteractive = "process.interactive";
+
+ ///
+ /// OTel process.pid (match: same as ECS)
+ ///
+ public const string ProcessPid = "process.pid";
+
+ ///
+ /// OTel process.real_user.id (match: same as ECS)
+ ///
+ public const string ProcessRealUserId = "process.real_user.id";
+
+ ///
+ /// OTel process.real_user.name (match: same as ECS)
+ ///
+ public const string ProcessRealUserName = "process.real_user.name";
+
+ ///
+ /// OTel process.saved_user.id (match: same as ECS)
+ ///
+ public const string ProcessSavedUserId = "process.saved_user.id";
+
+ ///
+ /// OTel process.saved_user.name (match: same as ECS)
+ ///
+ public const string ProcessSavedUserName = "process.saved_user.name";
+
+ ///
+ /// OTel process.session_leader.pid (match: same as ECS)
+ ///
+ public const string ProcessSessionLeaderPid = "process.session_leader.pid";
+
+ ///
+ /// OTel process.title (match: same as ECS)
+ ///
+ public const string ProcessTitle = "process.title";
+
+ ///
+ /// OTel process.user.id (match: same as ECS)
+ ///
+ public const string ProcessUserId = "process.user.id";
+
+ ///
+ /// OTel process.user.name (match: same as ECS)
+ ///
+ public const string ProcessUserName = "process.user.name";
+
+ ///
+ /// OTel process.vpid (match: same as ECS)
+ ///
+ public const string ProcessVpid = "process.vpid";
+
+ ///
+ /// OTel process.working_directory (match: same as ECS)
+ ///
+ public const string ProcessWorkingDirectory = "process.working_directory";
+
+ ///
+ /// OTel server.address (match: same as ECS)
+ ///
+ public const string ServerAddress = "server.address";
+
+ ///
+ /// OTel server.port (match: same as ECS)
+ ///
+ public const string ServerPort = "server.port";
+
+ ///
+ /// OTel service.instance.id (equivalent: ECS service.node.name)
+ ///
+ public const string ServiceInstanceId = "service.instance.id";
+
+ ///
+ /// OTel service.name (match: same as ECS)
+ ///
+ public const string ServiceName = "service.name";
+
+ ///
+ /// OTel service.version (match: same as ECS)
+ ///
+ public const string ServiceVersion = "service.version";
+
+ ///
+ /// OTel source.address (match: same as ECS)
+ ///
+ public const string SourceAddress = "source.address";
+
+ ///
+ /// OTel source.port (match: same as ECS)
+ ///
+ public const string SourcePort = "source.port";
+
+ ///
+ /// OTel tls.cipher (match: same as ECS)
+ ///
+ public const string TlsCipher = "tls.cipher";
+
+ ///
+ /// OTel tls.client.certificate (match: same as ECS)
+ ///
+ public const string TlsClientCertificate = "tls.client.certificate";
+
+ ///
+ /// OTel tls.client.certificate_chain (match: same as ECS)
+ ///
+ public const string TlsClientCertificateChain = "tls.client.certificate_chain";
+
+ ///
+ /// OTel tls.client.hash.md5 (match: same as ECS)
+ ///
+ public const string TlsClientHashMd5 = "tls.client.hash.md5";
+
+ ///
+ /// OTel tls.client.hash.sha1 (match: same as ECS)
+ ///
+ public const string TlsClientHashSha1 = "tls.client.hash.sha1";
+
+ ///
+ /// OTel tls.client.hash.sha256 (match: same as ECS)
+ ///
+ public const string TlsClientHashSha256 = "tls.client.hash.sha256";
+
+ ///
+ /// OTel tls.client.issuer (match: same as ECS)
+ ///
+ public const string TlsClientIssuer = "tls.client.issuer";
+
+ ///
+ /// OTel tls.client.ja3 (match: same as ECS)
+ ///
+ public const string TlsClientJa3 = "tls.client.ja3";
+
+ ///
+ /// OTel tls.client.not_after (match: same as ECS)
+ ///
+ public const string TlsClientNotAfter = "tls.client.not_after";
+
+ ///
+ /// OTel tls.client.not_before (match: same as ECS)
+ ///
+ public const string TlsClientNotBefore = "tls.client.not_before";
+
+ ///
+ /// OTel tls.client.subject (match: same as ECS)
+ ///
+ public const string TlsClientSubject = "tls.client.subject";
+
+ ///
+ /// OTel tls.client.supported_ciphers (match: same as ECS)
+ ///
+ public const string TlsClientSupportedCiphers = "tls.client.supported_ciphers";
+
+ ///
+ /// OTel tls.curve (match: same as ECS)
+ ///
+ public const string TlsCurve = "tls.curve";
+
+ ///
+ /// OTel tls.established (match: same as ECS)
+ ///
+ public const string TlsEstablished = "tls.established";
+
+ ///
+ /// OTel tls.next_protocol (match: same as ECS)
+ ///
+ public const string TlsNextProtocol = "tls.next_protocol";
+
+ ///
+ /// OTel tls.resumed (match: same as ECS)
+ ///
+ public const string TlsResumed = "tls.resumed";
+
+ ///
+ /// OTel tls.server.certificate (match: same as ECS)
+ ///
+ public const string TlsServerCertificate = "tls.server.certificate";
+
+ ///
+ /// OTel tls.server.certificate_chain (match: same as ECS)
+ ///
+ public const string TlsServerCertificateChain = "tls.server.certificate_chain";
+
+ ///
+ /// OTel tls.server.hash.md5 (match: same as ECS)
+ ///
+ public const string TlsServerHashMd5 = "tls.server.hash.md5";
+
+ ///
+ /// OTel tls.server.hash.sha1 (match: same as ECS)
+ ///
+ public const string TlsServerHashSha1 = "tls.server.hash.sha1";
+
+ ///
+ /// OTel tls.server.hash.sha256 (match: same as ECS)
+ ///
+ public const string TlsServerHashSha256 = "tls.server.hash.sha256";
+
+ ///
+ /// OTel tls.server.issuer (match: same as ECS)
+ ///
+ public const string TlsServerIssuer = "tls.server.issuer";
+
+ ///
+ /// OTel tls.server.ja3s (match: same as ECS)
+ ///
+ public const string TlsServerJa3s = "tls.server.ja3s";
+
+ ///
+ /// OTel tls.server.not_after (match: same as ECS)
+ ///
+ public const string TlsServerNotAfter = "tls.server.not_after";
+
+ ///
+ /// OTel tls.server.not_before (match: same as ECS)
+ ///
+ public const string TlsServerNotBefore = "tls.server.not_before";
+
+ ///
+ /// OTel tls.server.subject (match: same as ECS)
+ ///
+ public const string TlsServerSubject = "tls.server.subject";
+
+ ///
+ /// OTel url.domain (match: same as ECS)
+ ///
+ public const string UrlDomain = "url.domain";
+
+ ///
+ /// OTel url.extension (match: same as ECS)
+ ///
+ public const string UrlExtension = "url.extension";
+
+ ///
+ /// OTel url.fragment (match: same as ECS)
+ ///
+ public const string UrlFragment = "url.fragment";
+
+ ///
+ /// OTel url.full (match: same as ECS)
+ ///
+ public const string UrlFull = "url.full";
+
+ ///
+ /// OTel url.original (match: same as ECS)
+ ///
+ public const string UrlOriginal = "url.original";
+
+ ///
+ /// OTel url.path (match: same as ECS)
+ ///
+ public const string UrlPath = "url.path";
+
+ ///
+ /// OTel url.port (match: same as ECS)
+ ///
+ public const string UrlPort = "url.port";
+
+ ///
+ /// OTel url.query (match: same as ECS)
+ ///
+ public const string UrlQuery = "url.query";
+
+ ///
+ /// OTel url.registered_domain (match: same as ECS)
+ ///
+ public const string UrlRegisteredDomain = "url.registered_domain";
+
+ ///
+ /// OTel url.scheme (match: same as ECS)
+ ///
+ public const string UrlScheme = "url.scheme";
+
+ ///
+ /// OTel url.subdomain (match: same as ECS)
+ ///
+ public const string UrlSubdomain = "url.subdomain";
+
+ ///
+ /// OTel url.top_level_domain (match: same as ECS)
+ ///
+ public const string UrlTopLevelDomain = "url.top_level_domain";
+
+ ///
+ /// OTel user_agent.name (match: same as ECS)
+ ///
+ public const string UserAgentName = "user_agent.name";
+
+ ///
+ /// OTel user_agent.original (match: same as ECS)
+ ///
+ public const string UserAgentOriginal = "user_agent.original";
+
+ ///
+ /// OTel user_agent.version (match: same as ECS)
+ ///
+ public const string UserAgentVersion = "user_agent.version";
+
+ ///
+ /// OTel user.email (match: same as ECS)
+ ///
+ public const string UserEmail = "user.email";
+
+ ///
+ /// OTel user.full_name (match: same as ECS)
+ ///
+ public const string UserFullName = "user.full_name";
+
+ ///
+ /// OTel user.hash (match: same as ECS)
+ ///
+ public const string UserHash = "user.hash";
+
+ ///
+ /// OTel user.id (match: same as ECS)
+ ///
+ public const string UserId = "user.id";
+
+ ///
+ /// OTel user.name (match: same as ECS)
+ ///
+ public const string UserName = "user.name";
+
+ ///
+ /// OTel user.roles (match: same as ECS)
+ ///
+ public const string UserRoles = "user.roles";
+
+ }
+}
diff --git a/src/Elastic.CommonSchema/Serialization/EcsDocumentJsonConverter.Generated.cs b/src/Elastic.CommonSchema/Serialization/EcsDocumentJsonConverter.Generated.cs
index 50c33808..2fc50643 100644
--- a/src/Elastic.CommonSchema/Serialization/EcsDocumentJsonConverter.Generated.cs
+++ b/src/Elastic.CommonSchema/Serialization/EcsDocumentJsonConverter.Generated.cs
@@ -34,14 +34,14 @@ JsonSerializerOptions options
{
"log.level" => ReadString(ref reader, ref loglevel),
"ecs.version" => ReadString(ref reader, ref ecsVersion),
- "metadata" => ReadProp(ref reader, "metadata", ecsEvent, (b, v) => b.Metadata = v, options),
+ "metadata" => ReadMetadataIntoAttributes(ref reader, ecsEvent, options),
"@timestamp" => ReadDateTime(ref reader, ref @timestamp, options),
"message" => ReadProp(ref reader, "message", ecsEvent, (b, v) => b.Message = v, options),
"tags" => ReadProp(ref reader, "tags", ecsEvent, (b, v) => b.Tags = v, options),
"span.id" => ReadProp(ref reader, "span.id", ecsEvent, (b, v) => b.SpanId = v, options),
"trace.id" => ReadProp(ref reader, "trace.id", ecsEvent, (b, v) => b.TraceId = v, options),
"transaction.id" => ReadProp(ref reader, "transaction.id", ecsEvent, (b, v) => b.TransactionId = v, options),
- "labels" => ReadProp(ref reader, "labels", ecsEvent, (b, v) => b.Labels = v, options),
+ "labels" => ReadLabelsIntoAttributes(ref reader, ecsEvent, options),
"agent" => ReadProp(ref reader, "agent", EcsJsonContext.Default.Agent, ecsEvent, (b, v) => b.Agent = v),
"as" => ReadProp(ref reader, "as", EcsJsonContext.Default.As, ecsEvent, (b, v) => b.As = v),
"client" => ReadProp(ref reader, "client", EcsJsonContext.Default.Client, ecsEvent, (b, v) => b.Client = v),
@@ -94,6 +94,7 @@ JsonSerializerOptions options
"volume" => ReadProp(ref reader, "volume", EcsJsonContext.Default.Volume, ecsEvent, (b, v) => b.Volume = v),
"vulnerability" => ReadProp(ref reader, "vulnerability", EcsJsonContext.Default.Vulnerability, ecsEvent, (b, v) => b.Vulnerability = v),
"x509" => ReadProp(ref reader, "x509", EcsJsonContext.Default.X509, ecsEvent, (b, v) => b.X509 = v),
+ "attributes" => ReadOTelAttributes(ref reader, ecsEvent, options),
_ =>
typeof(EcsDocument) == ecsEvent.GetType()
? false
@@ -125,7 +126,6 @@ public override void Write(Utf8JsonWriter writer, TBase value, JsonSerializerOpt
WriteProp(writer, "span.id", value.SpanId, options);
WriteProp(writer, "trace.id", value.TraceId, options);
WriteProp(writer, "transaction.id", value.TransactionId, options);
- WriteProp(writer, "labels", value.Labels, options);
// Complex types
WriteProp(writer, "agent", value.Agent, EcsJsonContext.Default.Agent, options);
@@ -178,7 +178,7 @@ public override void Write(Utf8JsonWriter writer, TBase value, JsonSerializerOpt
WriteProp(writer, "volume", value.Volume, EcsJsonContext.Default.Volume, options);
WriteProp(writer, "vulnerability", value.Vulnerability, EcsJsonContext.Default.Vulnerability, options);
WriteProp(writer, "x509", value.X509, EcsJsonContext.Default.X509, options);
- WriteProp(writer, "metadata", value.Metadata, options);
+ WriteConsolidatedAttributes(writer, value, options);
if (typeof(EcsDocument) != value.GetType())
value.WriteAdditionalProperties((k, v) => WriteProp(writer, k, v, options));
diff --git a/src/Elastic.CommonSchema/Serialization/EcsDocumentJsonConverter.cs b/src/Elastic.CommonSchema/Serialization/EcsDocumentJsonConverter.cs
index 8d60bac3..9eeaa1ef 100644
--- a/src/Elastic.CommonSchema/Serialization/EcsDocumentJsonConverter.cs
+++ b/src/Elastic.CommonSchema/Serialization/EcsDocumentJsonConverter.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information
using System;
+using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -97,6 +98,175 @@ private static void WriteTimestamp(Utf8JsonWriter writer, BaseFieldSet value, Js
var converter = GetDateTimeOffsetConverter(options);
converter.Write(writer, value.Timestamp.Value, options);
}
+
+ #pragma warning disable CS0618 // Obsolete
+ private static void WriteConsolidatedAttributes(Utf8JsonWriter writer, TBase value, JsonSerializerOptions options)
+ {
+ // Merge Labels, Metadata, Attributes — Attributes wins over Metadata wins over Labels
+ var hasLabels = value.Labels is { Count: > 0 };
+ var hasMetadata = value.Metadata is { Count: > 0 };
+ var hasAttributes = value.Attributes is { Count: > 0 };
+
+ if (!hasLabels && !hasMetadata && !hasAttributes) return;
+
+ var merged = new MetadataDictionary();
+ if (hasLabels)
+ foreach (var kvp in value.Labels!) merged[kvp.Key] = kvp.Value;
+ if (hasMetadata)
+ foreach (var kvp in value.Metadata!) merged[kvp.Key] = kvp.Value;
+ if (hasAttributes)
+ foreach (var kvp in value.Attributes!) merged[kvp.Key] = kvp.Value;
+
+ WriteProp(writer, "attributes", merged, options);
+ }
+ #pragma warning restore CS0618
+
+ private static bool ReadLabelsIntoAttributes(ref Utf8JsonReader reader, TBase ecsEvent, JsonSerializerOptions options)
+ {
+ if (reader.TokenType == JsonTokenType.Null)
+ return true;
+
+ if (reader.TokenType != JsonTokenType.StartObject)
+ return false;
+
+ ecsEvent.Attributes ??= new MetadataDictionary();
+
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonTokenType.EndObject)
+ break;
+
+ if (reader.TokenType != JsonTokenType.PropertyName)
+ throw new JsonException("Expected property name in labels object");
+
+ var key = reader.GetString()!;
+ reader.Read();
+
+ // Labels are always strings
+ var value = reader.TokenType == JsonTokenType.Null ? null : reader.GetString();
+ if (value != null)
+ ecsEvent.Attributes[key] = value;
+ }
+ return true;
+ }
+
+ [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "We always provide a static JsonTypeInfoResolver")]
+ [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", Justification = "We always provide a static JsonTypeInfoResolver")]
+ private static bool ReadMetadataIntoAttributes(ref Utf8JsonReader reader, TBase ecsEvent, JsonSerializerOptions options)
+ {
+ if (reader.TokenType == JsonTokenType.Null)
+ return true;
+
+ if (reader.TokenType != JsonTokenType.StartObject)
+ return false;
+
+ ecsEvent.Attributes ??= new MetadataDictionary();
+
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonTokenType.EndObject)
+ break;
+
+ if (reader.TokenType != JsonTokenType.PropertyName)
+ throw new JsonException("Expected property name in metadata object");
+
+ var key = reader.GetString()!;
+ reader.Read();
+
+ object? value = reader.TokenType switch
+ {
+ JsonTokenType.String => reader.GetString(),
+ JsonTokenType.Number => reader.TryGetInt64(out var l) ? l : reader.GetDouble(),
+ JsonTokenType.True => true,
+ JsonTokenType.False => false,
+ JsonTokenType.Null => null,
+ JsonTokenType.StartObject => JsonSerializer.Deserialize(ref reader, options),
+ JsonTokenType.StartArray => ReadJsonArray(ref reader, options),
+ _ => JsonSerializer.Deserialize