Skip to content

Commit 80a746f

Browse files
committed
Support enrichment of LogRecords.
1 parent dd4e212 commit 80a746f

File tree

4 files changed

+129
-0
lines changed

4 files changed

+129
-0
lines changed

src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
OpenTelemetry.Logs.LogRecord.AddAttribute(System.Collections.Generic.KeyValuePair<string!, object?> attribute) -> void
2+
OpenTelemetry.Logs.LogRecord.AddAttributes(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string!, object?>>! attributes) -> void
13
OpenTelemetry.OpenTelemetryBuilderSdkExtensions
24
OpenTelemetry.Trace.ActivityExportProcessorOptions
35
OpenTelemetry.Trace.ActivityExportProcessorOptions.ActivityExportProcessorOptions() -> void

src/OpenTelemetry/Logs/LogRecord.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public sealed class LogRecord
2121
internal IReadOnlyList<KeyValuePair<string, object?>>? AttributeData;
2222
internal List<KeyValuePair<string, object?>>? AttributeStorage;
2323
internal List<object?>? ScopeStorage;
24+
internal LogRecordEnrichedAttributes? EnrichedAttributeStorage;
2425
internal LogRecordSource Source = LogRecordSource.CreatedManually;
2526
internal int PoolReferenceCount = int.MaxValue;
2627

@@ -445,6 +446,30 @@ public void ForEachScope<TState>(Action<LogRecordScope, TState> callback, TState
445446
}
446447
}
447448

449+
/// <summary>
450+
/// Add an attribute to the <see cref="LogRecord"/>.
451+
/// </summary>
452+
/// <param name="attribute">Attribute to add.</param>
453+
public void AddAttribute(KeyValuePair<string, object?> attribute)
454+
{
455+
var enrichedAttributes = this.EnsureEnrichedAttributes();
456+
457+
enrichedAttributes.Add(attribute);
458+
}
459+
460+
/// <summary>
461+
/// Add attributes to the <see cref="LogRecord"/>.
462+
/// </summary>
463+
/// <param name="attributes">Attributes to add.</param>
464+
public void AddAttributes(IEnumerable<KeyValuePair<string, object?>> attributes)
465+
{
466+
Guard.ThrowIfNull(attributes);
467+
468+
var enrichedAttributes = this.EnsureEnrichedAttributes();
469+
470+
enrichedAttributes.Add(attributes);
471+
}
472+
448473
/// <summary>
449474
/// Gets a reference to the <see cref="LogRecordData"/> for the log message.
450475
/// </summary>
@@ -544,6 +569,20 @@ private void BufferLogScopes()
544569
this.ILoggerData.BufferedScopes = scopeStorage;
545570
}
546571

572+
private LogRecordEnrichedAttributes EnsureEnrichedAttributes()
573+
{
574+
if (this.Attributes is not LogRecordEnrichedAttributes enrichedAttributes)
575+
{
576+
enrichedAttributes = this.EnrichedAttributeStorage ??= new();
577+
578+
enrichedAttributes.Reset(this.Attributes);
579+
580+
this.Attributes = enrichedAttributes;
581+
}
582+
583+
return enrichedAttributes;
584+
}
585+
547586
internal struct LogRecordILoggerData
548587
{
549588
public string? TraceState;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using System.Collections;
5+
using System.Diagnostics;
6+
7+
using OpenTelemetry.Internal;
8+
9+
namespace OpenTelemetry.Logs;
10+
11+
internal sealed class LogRecordEnrichedAttributes : IReadOnlyList<KeyValuePair<string, object?>>
12+
{
13+
private readonly List<KeyValuePair<string, object?>> enrichedAttributes = new();
14+
private IReadOnlyList<KeyValuePair<string, object?>> initialAttributes;
15+
16+
public LogRecordEnrichedAttributes()
17+
{
18+
this.initialAttributes = Array.Empty<KeyValuePair<string, object?>>();
19+
}
20+
21+
public int Count => this.initialAttributes.Count + this.enrichedAttributes.Count;
22+
23+
public KeyValuePair<string, object?> this[int index]
24+
{
25+
get
26+
{
27+
Guard.ThrowIfNegative(index);
28+
29+
var initialAttributes = this.initialAttributes;
30+
31+
var count = initialAttributes.Count;
32+
if (index < count)
33+
{
34+
return initialAttributes[index];
35+
}
36+
37+
return this.enrichedAttributes[index - count];
38+
}
39+
}
40+
41+
public void Reset(IReadOnlyList<KeyValuePair<string, object?>>? initialAttributes)
42+
{
43+
this.initialAttributes = initialAttributes ?? Array.Empty<KeyValuePair<string, object?>>();
44+
this.enrichedAttributes.Clear();
45+
}
46+
47+
public void Add(KeyValuePair<string, object?> attribute)
48+
{
49+
this.enrichedAttributes.Add(attribute);
50+
}
51+
52+
public void Add(IEnumerable<KeyValuePair<string, object?>> attributes)
53+
{
54+
Debug.Assert(attributes != null, "attributes was null");
55+
56+
this.enrichedAttributes.AddRange(attributes);
57+
}
58+
59+
public IEnumerator<KeyValuePair<string, object?>> GetEnumerator()
60+
{
61+
for (var i = 0; i < this.Count; i++)
62+
{
63+
yield return this[i];
64+
}
65+
}
66+
67+
IEnumerator IEnumerable.GetEnumerator()
68+
=> this.GetEnumerator();
69+
}

src/Shared/Guard.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ namespace System.Diagnostics.CodeAnalysis
3939
internal sealed class NotNullAttribute : Attribute
4040
{
4141
}
42+
43+
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
44+
internal sealed class DoesNotReturnAttribute : Attribute
45+
{
46+
}
4247
}
4348
#endif
4449

@@ -115,6 +120,16 @@ public static void ThrowIfZero(int value, string message = "Must not be zero", [
115120
}
116121
}
117122

123+
[DebuggerHidden]
124+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
125+
public static void ThrowIfNegative(int value, [CallerArgumentExpression("value")] string? paramName = null)
126+
{
127+
if (value < 0)
128+
{
129+
ThrowNegative(paramName);
130+
}
131+
}
132+
118133
/// <summary>
119134
/// Throw an exception if the value is not considered a valid timeout.
120135
/// </summary>
@@ -199,5 +214,9 @@ private static void Range<T>(T value, string? paramName, T min, T max, string? m
199214
throw new ArgumentOutOfRangeException(paramName, value, exMessage);
200215
}
201216
}
217+
218+
[DoesNotReturn]
219+
private static void ThrowNegative(string? paramName) =>
220+
throw new ArgumentOutOfRangeException(paramName, "Must be a non-negative value");
202221
}
203222
}

0 commit comments

Comments
 (0)