Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ OpenTelemetry.Exporter.Geneva.GenevaExporterHelperExtensions
OpenTelemetry.Exporter.Geneva.GenevaExporterOptions
OpenTelemetry.Exporter.Geneva.GenevaExporterOptions.ConnectionString.get -> string?
OpenTelemetry.Exporter.Geneva.GenevaExporterOptions.ConnectionString.set -> void
OpenTelemetry.Exporter.Geneva.GenevaExporterOptions.ResourceFieldNames.get -> System.Collections.Generic.IEnumerable<string!>?
OpenTelemetry.Exporter.Geneva.GenevaExporterOptions.ResourceFieldNames.init -> void
OpenTelemetry.Exporter.Geneva.GenevaExporterOptions.CustomFields.get -> System.Collections.Generic.IEnumerable<string!>?
OpenTelemetry.Exporter.Geneva.GenevaExporterOptions.CustomFields.set -> void
OpenTelemetry.Exporter.Geneva.GenevaExporterOptions.EventNameExportMode.get -> OpenTelemetry.Exporter.Geneva.EventNameExportMode
Expand Down
4 changes: 3 additions & 1 deletion src/OpenTelemetry.Exporter.Geneva/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Add ResourceFieldNames to filter resource attributes to send to Geneva
([#3552](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/3552))

## 1.14.0

Released 2025-Nov-13
Expand All @@ -22,7 +25,6 @@ Released 2025-Oct-29
* Support for specifying resource attributes, including
`service.name`, `service.instanceId`, and custom attributes.
([#3214](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/3214))

* Allow custom string size limit in custom fields.
([#3360](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/3360))

Expand Down
38 changes: 22 additions & 16 deletions src/OpenTelemetry.Exporter.Geneva/GenevaExporterOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ namespace OpenTelemetry.Exporter.Geneva;
/// </summary>
public class GenevaExporterOptions
{
private IReadOnlyDictionary<string, object> fields = new Dictionary<string, object>(1)
{
[Schema.V40.PartA.Ver] = "4.0",
};
private IReadOnlyDictionary<string, object> prepopulatedFields = new Dictionary<string, object>();

private IReadOnlyDictionary<string, string>? tableNameMappings;

Expand All @@ -33,6 +30,16 @@ public class GenevaExporterOptions
/// </summary>
public IEnumerable<string>? CustomFields { get; set; }

/// <summary>
/// Gets ResourceFieldNames.
///
/// ResourceFieldNames specifies which resource attribute fields should be sent to Geneva.
///
/// Any resource attributes not in ResourceFieldNames are ignored.
/// If ResourceFieldNames is not provided, no resource attributes will be sent to Geneva.
/// </summary>
public IEnumerable<string>? ResourceFieldNames { get; init; }

/// <summary>
/// Gets or sets the exception stack trace export mode.
/// </summary>
Expand Down Expand Up @@ -103,21 +110,14 @@ public IReadOnlyDictionary<string, string>? TableNameMappings
/// </summary>
public IReadOnlyDictionary<string, object> PrepopulatedFields
{
get => this.fields;
get => this.prepopulatedFields;
set
{
Guard.ThrowIfNull(value);

var schemaVersion = "4.0";

if (value.ContainsKey(Schema.V40.PartA.Ver))
if (value.ContainsKey(Schema.V40.PartA.Ver) && value[Schema.V40.PartA.Ver] as string is not "4.0")
{
schemaVersion = value[Schema.V40.PartA.Ver] as string;
}

if (schemaVersion is not "2.1" and not "4.0")
{
throw new ArgumentException("Unsupported schema version, only 2.1 and 4.0 are supported.");
throw new ArgumentException("Unsupported schema version, only 4.0 is supported.");
}

if (value.ContainsKey(Schema.V40.PartA.Name))
Expand All @@ -130,7 +130,7 @@ public IReadOnlyDictionary<string, object> PrepopulatedFields
throw new ArgumentException("Event timestamp cannot be pre-populated.");
}

var copy = new Dictionary<string, object>(value.Count + 1) { [Schema.V40.PartA.Ver] = schemaVersion };
var copy = new Dictionary<string, object>(value.Count + 1);
foreach (var entry in value)
{
var val = entry.Value;
Expand All @@ -155,10 +155,16 @@ public IReadOnlyDictionary<string, object> PrepopulatedFields
throw new ArgumentException($"Type `{entry.Value.GetType()}` (key = `{entry.Key}`) is not allowed. Only bool, byte, sbyte, short, ushort, int, uint, long, ulong, float, double, and string are supported.");
}

if (entry.Key == Schema.V40.PartA.Ver)
{
// This key is now set by the exporters, and is only accepted for legacy reasons.
continue;
}

copy[entry.Key] = val; // shallow copy
}

this.fields = copy;
this.prepopulatedFields = copy;
}
}
}
7 changes: 1 addition & 6 deletions src/OpenTelemetry.Exporter.Geneva/GenevaTraceExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,9 @@ public GenevaTraceExporter(GenevaExporterOptions options)
throw new NotSupportedException($"Protocol '{connectionStringBuilder.Protocol}' is not supported");
}

Resources.Resource ResourceProvider()
{
return connectionStringBuilder.HonorResourceAttributes ? this.ParentProvider.GetResource() : Resources.Resource.Empty;
}

if (useMsgPackExporter)
{
var msgPackTraceExporter = new MsgPackTraceExporter(options, ResourceProvider);
var msgPackTraceExporter = new MsgPackTraceExporter(options, this.ParentProvider.GetResource);
this.IsUsingUnixDomainSocket = msgPackTraceExporter.IsUsingUnixDomainSocket;
this.exportActivity = msgPackTraceExporter.Export;
this.exporter = msgPackTraceExporter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,6 @@ public string EtwSession
public bool PrivatePreviewEnableAFDCorrelationIdEnrichment => this.parts.TryGetValue(nameof(this.PrivatePreviewEnableAFDCorrelationIdEnrichment), out var value)
&& bool.TrueString.Equals(value, StringComparison.OrdinalIgnoreCase);

public bool HonorResourceAttributes => this.parts.TryGetValue(nameof(this.HonorResourceAttributes), out var value)
&& bool.TrueString.Equals(value, StringComparison.OrdinalIgnoreCase);

public int PrivatePreviewLogMessagePackStringSizeLimit
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ internal ArraySegment<byte> SerializeLogRecord(LogRecord logRecord)
cntFields += 1;
}

cursor = AddPartAField(buffer, cursor, Schema.V40.PartA.Ver, "4.0");
cntFields += 1;

cursor = MessagePackSerializer.SerializeAsciiString(buffer, cursor, "env_time");
cursor = MessagePackSerializer.SerializeUtcDateTime(buffer, cursor, timestamp); // LogRecord.Timestamp should already be converted to UTC format in the SDK
cntFields += 1;
Expand Down
Loading