Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/OpenTelemetry.Exporter.Geneva/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
valid names) and freeze the cache on .NET 8+, serialize metric base-128
strings and HTTP url spans directly into the output buffer instead of via
temporary arrays/strings.
([#4498](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4498))
([#4498](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4498),
[#4684](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4684))

* Assemblies are now digitally signed using cosign.
([#4637](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4637))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ namespace OpenTelemetry.Exporter.Geneva.Tld;
internal abstract class TldLogCommon : IDisposable
{
protected const int MaxSanitizedEventNameLength = 50;
protected const int MaxCachedSanitizedCategoryNames = 10000;
protected const int MaxCachedSanitizedCategoryNames = 10_000;
protected const int MaxCachedCategoryNameLength = 512;

protected static readonly ThreadLocal<List<KeyValuePair<string, object?>>> EnvProperties = new();
protected static readonly ThreadLocal<KeyValuePair<string, object>[]> PartCFields = new(); // This is used to temporarily store the PartC fields from tags
Expand Down Expand Up @@ -311,6 +312,12 @@ private string GetSanitizedCategoryNameRare(string categoryName)
{
var sanitized = SanitizeCategoryName(categoryName);

// Never cache pathologically long category names
if (categoryName.Length > MaxCachedCategoryNameLength)
{
return sanitized;
}

// Lock-free copy-on-write update. The cache is a pure memoization of a
// deterministic, side-effect-free function, so a lost race is harmless:
// the worst case is that the value is recomputed and re-inserted later.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,37 @@ public void GetSanitizedCategoryName_CachesSanitizedResult()
Assert.Same(first, second);
}

[Fact]
public void GetSanitizedCategoryName_AtMaxCachedLength_IsCached()
{
using var probe = CreateProbe();

var categoryName = "a" + new string('b', CategorySanitizerProbe.MaxCachedCategoryNameLengthValue - 1);
var expected = "A" + new string('b', 49);

var first = probe.Sanitize(categoryName);
var second = probe.Sanitize(categoryName);

Assert.Equal(expected, first);
Assert.Same(first, second);
}

[Fact]
public void GetSanitizedCategoryName_ExceedsMaxCachedLength_IsNotCachedButStillSanitized()
{
using var probe = CreateProbe();

var categoryName = "a" + new string('b', CategorySanitizerProbe.MaxCachedCategoryNameLengthValue);
var expected = "A" + new string('b', 49);

var first = probe.Sanitize(categoryName);
var second = probe.Sanitize(categoryName);

Assert.Equal(expected, first);
Assert.Equal(expected, second);
Assert.NotSame(first, second);
}

private static CategorySanitizerProbe CreateProbe()
{
return new CategorySanitizerProbe(new GenevaExporterOptions
Expand All @@ -107,6 +138,8 @@ public CategorySanitizerProbe(GenevaExporterOptions options)
{
}

public static int MaxCachedCategoryNameLengthValue => MaxCachedCategoryNameLength;

public string Sanitize(string categoryName)
=> this.GetSanitizedCategoryName(categoryName);
}
Expand Down