Skip to content

Commit fa46aa0

Browse files
authored
Fix OTel histogram metrics (#2207)
* Fix OTel histogram metrics * Also add skipped files counter * Fix descriptions * Fix
1 parent 10e5a38 commit fa46aa0

File tree

2 files changed

+45
-24
lines changed

2 files changed

+45
-24
lines changed

src/Elastic.Documentation.ServiceDefaults/Extensions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,16 @@ private static TBuilder AddOpenTelemetryExporters<TBuilder>(this TBuilder builde
8080
var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
8181

8282
if (useOtlpExporter)
83+
{
84+
// Configure delta temporality for Elasticsearch compatibility
85+
// See: https://www.elastic.co/docs/reference/opentelemetry/compatibility/limitations#histograms-in-delta-temporality-only
86+
_ = builder.Services.Configure<MetricReaderOptions>(options =>
87+
{
88+
options.TemporalityPreference = MetricReaderTemporalityPreference.Delta;
89+
});
90+
8391
_ = builder.Services.AddOpenTelemetry().UseOtlpExporter();
92+
}
8493

8594
// Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
8695
//if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))

src/services/Elastic.Documentation.Assembler/Deploying/Synchronization/AwsS3SyncApplyStrategy.cs

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,45 @@ IDiagnosticsCollector collector
2727
// Meter for OpenTelemetry metrics
2828
private static readonly Meter SyncMeter = new(TelemetryConstants.AssemblerSyncInstrumentationName);
2929

30-
// Deployment-level metrics (low cardinality)
31-
private static readonly Histogram<long> FilesPerDeploymentHistogram = SyncMeter.CreateHistogram<long>(
30+
// Deployment-level metrics (histograms for distribution analysis, counters for totals)
31+
// Note: Histograms require delta temporality to work with Elasticsearch
32+
// See Extensions.cs where MetricTemporalityPreference.Delta is configured
33+
private static readonly Histogram<double> FilesPerDeploymentHistogram = SyncMeter.CreateHistogram<double>(
3234
"docs.deployment.files.count",
3335
"files",
34-
"Number of files synced per deployment operation");
36+
"Number of files per deployment operation (added + updated + deleted + skipped)");
3537

36-
private static readonly Counter<long> FilesAddedCounter = SyncMeter.CreateCounter<long>(
38+
private static readonly Counter<double> FilesTotalCounter = SyncMeter.CreateCounter<double>(
39+
"docs.deployment.files.total",
40+
"files",
41+
"Total number of files in deployment (added + updated + deleted + skipped)");
42+
43+
private static readonly Counter<double> FilesAddedCounter = SyncMeter.CreateCounter<double>(
3744
"docs.sync.files.added.total",
3845
"files",
3946
"Total number of files added to S3");
4047

41-
private static readonly Counter<long> FilesUpdatedCounter = SyncMeter.CreateCounter<long>(
48+
private static readonly Counter<double> FilesUpdatedCounter = SyncMeter.CreateCounter<double>(
4249
"docs.sync.files.updated.total",
4350
"files",
4451
"Total number of files updated in S3");
4552

46-
private static readonly Counter<long> FilesDeletedCounter = SyncMeter.CreateCounter<long>(
53+
private static readonly Counter<double> FilesDeletedCounter = SyncMeter.CreateCounter<double>(
4754
"docs.sync.files.deleted.total",
4855
"files",
4956
"Total number of files deleted from S3");
5057

51-
private static readonly Histogram<long> FileSizeHistogram = SyncMeter.CreateHistogram<long>(
58+
private static readonly Counter<double> FilesSkippedCounter = SyncMeter.CreateCounter<double>(
59+
"docs.sync.files.skipped.total",
60+
"files",
61+
"Total number of files skipped (unchanged)");
62+
63+
private static readonly Histogram<double> FileSizeHistogram = SyncMeter.CreateHistogram<double>(
5264
"docs.sync.file.size",
5365
"By",
5466
"Distribution of file sizes synced to S3");
5567

56-
private static readonly Counter<long> FilesByExtensionCounter = SyncMeter.CreateCounter<long>(
68+
private static readonly Counter<double> FilesByExtensionCounter = SyncMeter.CreateCounter<double>(
5769
"docs.sync.files.by_extension",
5870
"files",
5971
"File operations grouped by extension");
@@ -95,7 +107,7 @@ public async Task Apply(SyncPlan plan, Cancel ctx = default)
95107
var updateCount = plan.UpdateRequests.Count;
96108
var deleteCount = plan.DeleteRequests.Count;
97109
var skipCount = plan.SkipRequests.Count;
98-
var totalFiles = addCount + updateCount + deleteCount;
110+
var totalFiles = addCount + updateCount + deleteCount + skipCount;
99111

100112
// Add aggregate metrics to span
101113
_ = applyActivity?.SetTag("docs.sync.files.added", addCount);
@@ -105,24 +117,33 @@ public async Task Apply(SyncPlan plan, Cancel ctx = default)
105117
_ = applyActivity?.SetTag("docs.sync.files.total", totalFiles);
106118

107119
// Record deployment-level metrics (always emit, even if 0)
120+
// Histogram for distribution analysis (p50, p95, p99)
108121
FilesPerDeploymentHistogram.Record(totalFiles);
109122

110-
// Always record per-operation counts (even if 0) so metrics show consistent data
123+
// Record per-operation histograms (for distribution analysis by operation type)
111124
FilesPerDeploymentHistogram.Record(addCount, [new("operation", "add")]);
112125
FilesPerDeploymentHistogram.Record(updateCount, [new("operation", "update")]);
113126
FilesPerDeploymentHistogram.Record(deleteCount, [new("operation", "delete")]);
114127
FilesPerDeploymentHistogram.Record(skipCount, [new("operation", "skip")]);
115128

129+
// Counter for simple totals and rates
130+
FilesTotalCounter.Add(totalFiles);
131+
132+
// Record counter versions for easy dashboard queries (always emit, even if 0)
133+
FilesAddedCounter.Add(addCount);
134+
FilesUpdatedCounter.Add(updateCount);
135+
FilesDeletedCounter.Add(deleteCount);
136+
FilesSkippedCounter.Add(skipCount);
137+
116138
_logger.LogInformation(
117139
"Deployment sync: {TotalFiles} files ({AddCount} added, {UpdateCount} updated, {DeleteCount} deleted, {SkipCount} skipped) in {Environment}",
118140
totalFiles, addCount, updateCount, deleteCount, skipCount, context.Environment.Name);
119141

120142
await Upload(plan, ctx);
121143
await Delete(plan, ctx);
122144

123-
// Record sync duration
124-
SyncDurationHistogram.Record(sw.Elapsed.TotalSeconds,
125-
[new("operation", "sync")]);
145+
// Record sync duration (both histogram for distribution and counter for total)
146+
SyncDurationHistogram.Record(sw.Elapsed.TotalSeconds);
126147
}
127148

128149
private async Task Upload(SyncPlan plan, Cancel ctx)
@@ -147,14 +168,8 @@ private async Task Upload(SyncPlan plan, Cancel ctx)
147168
var fileSize = context.WriteFileSystem.FileInfo.New(upload.LocalPath).Length;
148169
var extension = Path.GetExtension(upload.DestinationPath).ToLowerInvariant();
149170

150-
// Record counters
151-
if (operation == "add")
152-
FilesAddedCounter.Add(1);
153-
else
154-
FilesUpdatedCounter.Add(1);
155-
156-
// Record file size distribution
157-
FileSizeHistogram.Record(fileSize, [new("operation", operation)]);
171+
// Record file size distribution (histogram for p50, p95, p99 analysis)
172+
FileSizeHistogram.Record(fileSize);
158173

159174
// Record by extension (low cardinality)
160175
if (!string.IsNullOrEmpty(extension))
@@ -222,9 +237,6 @@ private async Task Delete(SyncPlan plan, Cancel ctx)
222237
{
223238
var extension = Path.GetExtension(delete.DestinationPath).ToLowerInvariant();
224239

225-
// Record counter
226-
FilesDeletedCounter.Add(1);
227-
228240
// Record by extension (low cardinality)
229241
if (!string.IsNullOrEmpty(extension))
230242
{

0 commit comments

Comments
 (0)