Skip to content
Merged
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4883775
[Exporter.Prometheus] Avoid struct copies
martincostello Jun 21, 2026
3cd1eba
[Exporter.Prometheus] Add dots and values escaping
martincostello Jun 21, 2026
977cac7
[Exporter.Prometheus] Fix sorting
martincostello Jun 21, 2026
8549b36
[Exporter.Prometheus] Address feedback
martincostello Jun 21, 2026
f42506e
[Exporter.Prometheus] Update test coverage
martincostello Jun 21, 2026
190a68b
[Exporter.Prometheus] Extend tests
martincostello Jun 21, 2026
c0844b9
[Exporter.Prometheus] Add allow-utf-8 escaping
martincostello Jun 21, 2026
7ff2f62
[Exporter.Prometheus] Update CHANGELOGs
martincostello Jun 21, 2026
d36104e
[Exporter.Prometheus] Extend test coverage
martincostello Jun 21, 2026
51aff69
[Exporter.Prometheus] Add new benchmark
martincostello Jun 21, 2026
0b7bd2b
[Exporter.Prometheus] Reduce allocations
martincostello Jun 21, 2026
7baa8e0
[Exporter.Prometheus] Wrap lines
martincostello Jun 21, 2026
3913d6d
[Exporter.Prometheus] Further reduce allocations
martincostello Jun 21, 2026
d434d3b
Merge branch 'main' into gh-7246
martincostello Jun 21, 2026
f93ac58
Merge branch 'main' into gh-7246-allow-utf-8
martincostello Jun 21, 2026
f79b46b
Merge branch 'main' into gh-7246
martincostello Jun 22, 2026
3a6995a
Merge branch 'main' into gh-7246-allow-utf-8
martincostello Jun 22, 2026
dbe44d4
Merge remote-tracking branch 'origin/main' into gh-7246
martincostello Jun 24, 2026
d80f412
Merge branch 'gh-7246' into gh-7246-allow-utf-8
martincostello Jun 24, 2026
8c8a028
[Exporter.Prometheus] Fix CHANGELOGs
martincostello Jun 24, 2026
e4bf711
[Exporter.Prometheus] Address feedback
martincostello Jun 24, 2026
a5bf82c
[Exporter.Prometheus] Reduce allocations
martincostello Jun 25, 2026
f86a8c0
Merge branch 'main' into gh-7246
martincostello Jun 29, 2026
c7bbf26
[Exporter.Prometheus] Fix merge
martincostello Jun 29, 2026
3fb26e8
[Exporter.Prometheus] Address feedback
martincostello Jun 29, 2026
de68faf
[Exporter.Prometheus] Fix typo
martincostello Jun 29, 2026
249e431
Merge branch 'gh-7246' into gh-7246-allow-utf-8
martincostello Jun 29, 2026
02ecad4
Merge branch 'gh-7246-allow-utf-8' into cache-label-collections
martincostello Jun 29, 2026
7c2480e
[Exporter.Prometheus] Fix SA1202
martincostello Jun 29, 2026
b82f586
Merge branch 'gh-7246-allow-utf-8' into cache-label-collections
martincostello Jun 29, 2026
d55091b
Merge branch 'main' into cache-label-collections
martincostello Jul 3, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ internal abstract class TextFormatSerializer
private static readonly long UnixEpochTicks = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).Ticks;
#endif

// Scope labels (otel_scope_*) depend only on the Metric's invariant
// scope (meter name/version/schema-url/tags) and are not affected by
// the negotiated escaping scheme, so the built label collections can
// be computed once per Metric and reused across every serialization
// call instead of being rebuilt for each call to WriteMetric.
#if NET
private static readonly ConditionalWeakTable<Metric, List<KeyValuePair<string, string>>> ScopeLabelsCache = [];
private static readonly ConditionalWeakTable<Metric, List<LabelData>> ScopeLabelDataCache = [];
#else
private static readonly ConditionalWeakTable<Metric, List<KeyValuePair<string, string>>> ScopeLabelsCache = new();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for myself: [] is not working on .NET Fx for this case.

private static readonly ConditionalWeakTable<Metric, List<LabelData>> ScopeLabelDataCache = new();
#endif

private static readonly string[] ReservedExemplarLabelNames = ["trace_id", "span_id"];
private static readonly double[] ExactPowersOfTen =
[
Expand Down Expand Up @@ -813,7 +826,7 @@ internal int WriteTags(

if (!options.SuppressScopeInfo)
{
foreach (var scopeLabel in CreateScopeLabelData(metric))
foreach (var scopeLabel in GetScopeLabelData(metric))
{
// Scope labels (otel_scope_*) are already in their target Prometheus form, so they
// are written verbatim and not re-escaped by the negotiated scheme, exactly as the
Expand All @@ -837,7 +850,7 @@ void WriteScopeLabels()
// tags they can never collide with an already-written label. They only need to be
// written (which also records their output keys so point tags can detect a collision
// with a scope label).
foreach (var scopeLabel in CreateScopeLabels(metric))
foreach (var scopeLabel in GetScopeLabels(metric))
{
_ = TryWriteLabel(scopeLabel.Key, scopeLabel.Value, isScopeLabel: true);
}
Expand Down Expand Up @@ -1290,12 +1303,15 @@ private static string NormalizeLabelKey(string value)
return builder.ToString();
}

private static List<KeyValuePair<string, string>> GetScopeLabels(Metric metric)
=> ScopeLabelsCache.GetValue(metric, CreateScopeLabels);

private static List<KeyValuePair<string, string>> CreateScopeLabels(Metric metric)
{
var orderedKeys = new List<string>();
var labelsByOutputKey = new Dictionary<string, List<LabelData>>(StringComparer.Ordinal);

foreach (var label in CreateScopeLabelData(metric))
foreach (var label in GetScopeLabelData(metric))
{
if (!labelsByOutputKey.TryGetValue(label.OutputKey, out var bucket))
{
Expand All @@ -1317,6 +1333,9 @@ private static List<KeyValuePair<string, string>> CreateScopeLabels(Metric metri
return scopeLabels;
}

private static List<LabelData> GetScopeLabelData(Metric metric)
=> ScopeLabelDataCache.GetValue(metric, CreateScopeLabelData);

private static List<LabelData> CreateScopeLabelData(Metric metric)
{
var scopeLabels = new List<LabelData>(3)
Expand Down