Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include resource attributes as target_info for Prometheus exporters #5407

Merged
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ae20ec8
Include resource attributes as metrics tags
robertcoltheart Mar 2, 2024
bfb9401
Tidy xmldoc
robertcoltheart Mar 2, 2024
0a0ef68
Fit lint error
robertcoltheart Mar 2, 2024
f6f10ba
Merge branch 'main' into feature/resource-attribute-tags
robertcoltheart Mar 2, 2024
5ddf850
Revert resource attribute labels
robertcoltheart Mar 6, 2024
0a930da
Merge branch 'feature/resource-attribute-tags' of https://github.com/…
robertcoltheart Mar 6, 2024
1fd739b
Tidy PR diff
robertcoltheart Mar 6, 2024
f08dd85
Handle buffer overflow
robertcoltheart Mar 6, 2024
bcb5195
Merge branch 'main' into feature/resource-attribute-tags
robertcoltheart Mar 6, 2024
24f298d
Fix changelog
robertcoltheart Mar 6, 2024
79202c8
Cache target info buffer
robertcoltheart Mar 9, 2024
042ad04
Fix array copy
robertcoltheart Mar 9, 2024
c421b82
Update changelog
robertcoltheart Mar 9, 2024
198576f
Better write performance
robertcoltheart Mar 15, 2024
c383c04
Merge branch 'main' into feature/resource-attribute-tags
robertcoltheart Mar 15, 2024
7ccddaa
Merge branch 'main' into feature/resource-attribute-tags
vishweshbankwar Mar 19, 2024
9f62f61
Update src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/Pr…
robertcoltheart Mar 21, 2024
fec5a35
Update CHANGELOG.md
robertcoltheart Mar 21, 2024
8a298c3
Update CHANGELOG.md
robertcoltheart Mar 21, 2024
529335f
Update CHANGELOG.md
robertcoltheart Mar 21, 2024
1881c43
Update CHANGELOG.md
robertcoltheart Mar 21, 2024
44e9121
Fix wrong comparison
robertcoltheart Mar 21, 2024
a5b09da
Fix linter
robertcoltheart Mar 21, 2024
317ce4c
Merge branch 'main' into feature/resource-attribute-tags
utpilla Mar 21, 2024
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 @@ -2,10 +2,13 @@

## Unreleased

* Added `target_info` to Prometheus exporters when using OpenMetrics format ([#5407](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5407))

* Added option to disable _total suffix addition to counter metrics
([#5305](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5305))

* Export OpenMetrics format from Prometheus exporters ([#5107](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5107))

* For requests with OpenMetrics format, scope info is automatically added
([#5086](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5086)
[#5182](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5182))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

* Added `target_info` to Prometheus exporters when using OpenMetrics format ([#5407](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5407))

* Added option to disable _total suffix addition to counter metrics
([#5305](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5305))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal sealed class PrometheusCollectionManager
private readonly HashSet<string> scopes;
private int metricsCacheCount;
private byte[] buffer = new byte[85000]; // encourage the object to live in LOH (large object heap)
private byte[] targetInfoBuffer;
private int globalLockState;
private ArraySegment<byte> previousDataView;
private DateTime? previousDataViewGeneratedAtUtc;
Expand Down Expand Up @@ -174,13 +175,20 @@ private ExportResult OnCollect(Batch<Metric> metrics)
{
if (this.exporter.OpenMetricsRequested)
{
cursor = this.WriteTargetInfo();

this.scopes.Clear();

foreach (var metric in metrics)
{
if (PrometheusSerializer.CanWriteMetric(metric))
if (!PrometheusSerializer.CanWriteMetric(metric))
{
continue;
}

if (this.scopes.Add(metric.MeterName))
{
if (this.scopes.Add(metric.MeterName))
while (true)
utpilla marked this conversation as resolved.
Show resolved Hide resolved
{
try
{
Expand Down Expand Up @@ -262,6 +270,40 @@ private ExportResult OnCollect(Batch<Metric> metrics)
}
}

private int WriteTargetInfo()
{
if (this.targetInfoBuffer == null)
{
while (true)
{
try
{
var cursor = PrometheusSerializer.WriteTargetInfo(this.buffer, 0, this.exporter.Resource);

this.targetInfoBuffer = new byte[cursor];
Array.Copy(this.buffer, 0, this.targetInfoBuffer, 0, cursor);

break;
}
catch (IndexOutOfRangeException)
{
if (!this.IncreaseBufferSize())
{
throw;
}
}
}
}
else
{
// Buffer will always be large enough for the target_info at this point because we've already
// previously written to the buffer (increasing it as needed) and copied out the target_info buffer.
this.targetInfoBuffer.CopyTo(this.buffer, 0);
robertcoltheart marked this conversation as resolved.
Show resolved Hide resolved
}

return this.targetInfoBuffer.Length;
}

private bool IncreaseBufferSize()
{
var newBufferSize = this.buffer.Length * 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;

namespace OpenTelemetry.Exporter.Prometheus;

Expand All @@ -14,6 +15,7 @@ internal sealed class PrometheusExporter : BaseExporter<Metric>, IPullMetricExpo
{
private Func<int, bool> funcCollect;
private Func<Batch<Metric>, ExportResult> funcExport;
private Resource resource;
private bool disposed;

/// <summary>
Expand Down Expand Up @@ -55,6 +57,8 @@ internal Func<Batch<Metric>, ExportResult> OnExport

internal bool OpenMetricsRequested { get; set; }

internal Resource Resource => this.resource ??= this.ParentProvider.GetResource();

/// <inheritdoc/>
public override ExportResult Export(in Batch<Metric> metrics)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Runtime.CompilerServices;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;

namespace OpenTelemetry.Exporter.Prometheus;

Expand Down Expand Up @@ -396,6 +397,40 @@ public static int WriteTags(byte[] buffer, int cursor, Metric metric, ReadOnlyTa
return cursor;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int WriteTargetInfo(byte[] buffer, int cursor, Resource resource)
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
{
if (!resource.Attributes.Any())
robertcoltheart marked this conversation as resolved.
Show resolved Hide resolved
{
return cursor;
}

cursor = WriteAsciiStringNoEscape(buffer, cursor, "# TYPE target info");
buffer[cursor++] = ASCII_LINEFEED;

cursor = WriteAsciiStringNoEscape(buffer, cursor, "# HELP target Target metadata");
buffer[cursor++] = ASCII_LINEFEED;

cursor = WriteAsciiStringNoEscape(buffer, cursor, "target_info");
buffer[cursor++] = unchecked((byte)'{');

foreach (var attribute in resource.Attributes)
{
cursor = WriteLabel(buffer, cursor, attribute.Key, attribute.Value);

buffer[cursor++] = unchecked((byte)',');
}

cursor--; // Write over the last written comma

buffer[cursor++] = unchecked((byte)'}');
buffer[cursor++] = unchecked((byte)' ');
buffer[cursor++] = unchecked((byte)'1');
buffer[cursor++] = ASCII_LINEFEED;

return cursor;
}

private static string MapPrometheusType(PrometheusType type)
{
return type switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Tests;
using Xunit;

Expand Down Expand Up @@ -150,6 +151,7 @@ public async Task PrometheusExporterMiddlewareIntegration_MeterProvider()
{
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(MeterName)
.ConfigureResource(x => x.Clear().AddService("my_service", serviceInstanceId: "id1"))
.AddPrometheusExporter()
.Build();

Expand Down Expand Up @@ -213,6 +215,7 @@ public async Task PrometheusExporterMiddlewareIntegration_MapEndpoint_WithMeterP
{
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(MeterName)
.ConfigureResource(x => x.Clear().AddService("my_service", serviceInstanceId: "id1"))
.AddPrometheusExporter()
.Build();

Expand Down Expand Up @@ -265,11 +268,12 @@ private static async Task RunPrometheusExporterMiddlewareIntegrationTest(
if (registerMeterProvider)
{
services.AddOpenTelemetry().WithMetrics(builder => builder
.AddMeter(MeterName)
.AddPrometheusExporter(o =>
{
configureOptions?.Invoke(o);
}));
.ConfigureResource(x => x.Clear().AddService("my_service", serviceInstanceId: "id1"))
.AddMeter(MeterName)
.AddPrometheusExporter(o =>
{
configureOptions?.Invoke(o);
}));
}

configureServices?.Invoke(services);
Expand Down Expand Up @@ -322,7 +326,10 @@ private static async Task RunPrometheusExporterMiddlewareIntegrationTest(
string content = await response.Content.ReadAsStringAsync();

string expected = requestOpenMetrics
? "# TYPE otel_scope_info info\n"
? "# TYPE target info\n"
+ "# HELP target Target metadata\n"
+ "target_info{service_name='my_service',service_instance_id='id1'} 1\n"
+ "# TYPE otel_scope_info info\n"
+ "# HELP otel_scope_info Scope metadata\n"
+ $"otel_scope_info{{otel_scope_name='{MeterName}'}} 1\n"
+ "# TYPE counter_double_total counter\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Net.Http;
#endif
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Tests;
using Xunit;

Expand Down Expand Up @@ -175,6 +176,7 @@ private async Task RunPrometheusExporterHttpServerIntegrationTest(bool skipMetri
{
provider = Sdk.CreateMeterProviderBuilder()
.AddMeter(meter.Name)
.ConfigureResource(x => x.Clear().AddService("my_service", serviceInstanceId: "id1"))
.AddPrometheusHttpListener(options =>
{
options.UriPrefixes = new string[] { address };
Expand Down Expand Up @@ -233,7 +235,10 @@ private async Task RunPrometheusExporterHttpServerIntegrationTest(bool skipMetri
var content = await response.Content.ReadAsStringAsync();

var expected = requestOpenMetrics
? "# TYPE otel_scope_info info\n"
? "# TYPE target info\n"
+ "# HELP target Target metadata\n"
+ "target_info{service_name='my_service',service_instance_id='id1'} 1\n"
+ "# TYPE otel_scope_info info\n"
+ "# HELP otel_scope_info Scope metadata\n"
+ $"otel_scope_info{{otel_scope_name='{MeterName}'}} 1\n"
+ "# TYPE counter_double_total counter\n"
Expand Down