-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[AzureMonitorLiveMetrics] poc refactor metrics (#40669)
* refactor doublebuffer * refactor to remove OTel Metrics API. * revert change to DocumentBuffer & DoubleBuffer * refactor to use Document to track metrics * cleanup * struct
- Loading branch information
1 parent
d810209
commit 5235895
Showing
9 changed files
with
302 additions
and
312 deletions.
There are no files selected for viewing
14 changes: 14 additions & 0 deletions
14
...itor/Azure.Monitor.OpenTelemetry.LiveMetrics/src/Customizations/Models/DocumentIngress.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System.Diagnostics; | ||
|
||
namespace Azure.Monitor.OpenTelemetry.LiveMetrics.Models | ||
{ | ||
/// <summary> Additional properties used to calculate metrics. </summary> | ||
internal partial class DocumentIngress | ||
{ | ||
public bool Extension_IsSuccess { get; set; } | ||
public double Extension_Duration { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
139 changes: 139 additions & 0 deletions
139
sdk/monitor/Azure.Monitor.OpenTelemetry.LiveMetrics/src/Internals/LiveMetricsBuffer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System.Collections.Generic; | ||
|
||
namespace Azure.Monitor.OpenTelemetry.LiveMetrics.Internals | ||
{ | ||
/// <summary> | ||
/// This class encapsulates metrics sent to Live Metrics. | ||
/// </summary> | ||
internal struct LiveMetricsBuffer | ||
{ | ||
// REQUEST | ||
internal long RequestsCount; | ||
internal double RequestsDuration; | ||
internal long RequestsSuccededCount; | ||
internal long RequestsFailedCount; | ||
|
||
// DEPENDENCY | ||
internal long DependenciesCount; | ||
internal double DependenciesDuration; | ||
internal long DependenciesSuccededCount; | ||
internal long DependenciesFailedCount; | ||
|
||
// EXCEPTIONS | ||
internal long ExceptionsCount; | ||
|
||
public void RecordRequestSucceeded(double duration) | ||
{ | ||
RequestsCount++; | ||
RequestsDuration += duration; | ||
RequestsSuccededCount++; | ||
} | ||
|
||
public void RecordRequestFailed(double duration) | ||
{ | ||
RequestsCount++; | ||
RequestsDuration += duration; | ||
RequestsFailedCount++; | ||
} | ||
|
||
public void RecordDependencySucceeded(double duration) | ||
{ | ||
DependenciesCount++; | ||
DependenciesDuration += duration; | ||
DependenciesSuccededCount++; | ||
} | ||
|
||
public void RecordDependencyFailed(double duration) | ||
{ | ||
DependenciesCount++; | ||
DependenciesDuration += duration; | ||
DependenciesFailedCount++; | ||
} | ||
|
||
public void RecordException() | ||
{ | ||
ExceptionsCount++; | ||
} | ||
|
||
public IEnumerable<Models.MetricPoint> GetMetricPoints() | ||
{ | ||
// REQUESTS | ||
if (RequestsCount > 0) | ||
{ | ||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.RequestsPerSecondMetricIdValue, | ||
Value = RequestsCount, | ||
Weight = 1 | ||
}; | ||
|
||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.RequestDurationMetricIdValue, | ||
Value = (float)(RequestsDuration / RequestsCount), | ||
Weight = 1 | ||
}; | ||
|
||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.RequestsSucceededPerSecondMetricIdValue, | ||
Value = RequestsSuccededCount, | ||
Weight = 1 | ||
}; | ||
|
||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.RequestsFailedPerSecondMetricIdValue, | ||
Value = RequestsFailedCount, | ||
Weight = 1 | ||
}; | ||
} | ||
|
||
// DEPENDENCIES | ||
if (DependenciesCount > 0) | ||
{ | ||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.DependenciesPerSecondMetricIdValue, | ||
Value = DependenciesCount, | ||
Weight = 1 | ||
}; | ||
|
||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.DependencyDurationMetricIdValue, | ||
Value = (float)(DependenciesDuration / DependenciesCount), | ||
Weight = 1 | ||
}; | ||
|
||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.DependencySucceededPerSecondMetricIdValue, | ||
Value = DependenciesSuccededCount, | ||
Weight = 1 | ||
}; | ||
|
||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.DependencyFailedPerSecondMetricIdValue, | ||
Value = DependenciesFailedCount, | ||
Weight = 1 | ||
}; | ||
} | ||
|
||
// EXCEPTIONS | ||
if (ExceptionsCount > 0) | ||
{ | ||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.ExceptionsPerSecondMetricIdValue, | ||
Value = ExceptionsCount, | ||
Weight = 1 | ||
}; | ||
} | ||
} | ||
} | ||
} |
120 changes: 120 additions & 0 deletions
120
sdk/monitor/Azure.Monitor.OpenTelemetry.LiveMetrics/src/Internals/Manager.Metrics.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using Azure.Monitor.OpenTelemetry.Exporter.Internals; | ||
using Azure.Monitor.OpenTelemetry.LiveMetrics.Models; | ||
|
||
namespace Azure.Monitor.OpenTelemetry.LiveMetrics.Internals | ||
{ | ||
/// <summary> | ||
/// This partial class encapsulates all the metrics that are tracked and reported to the Live Metrics service. | ||
/// </summary> | ||
internal partial class Manager | ||
{ | ||
internal readonly DoubleBuffer _documentBuffer = new(); | ||
|
||
private PerformanceCounter _performanceCounter_ProcessorTime = new PerformanceCounter(categoryName: "Processor", counterName: "% Processor Time", instanceName: "_Total"); | ||
private PerformanceCounter _performanceCounter_CommittedBytes = new PerformanceCounter(categoryName: "Memory", counterName: "Committed Bytes"); | ||
|
||
public MonitoringDataPoint GetDataPoint() | ||
{ | ||
var dataPoint = new MonitoringDataPoint | ||
{ | ||
Version = SdkVersionUtils.s_sdkVersion.Truncate(SchemaConstants.Tags_AiInternalSdkVersion_MaxLength), | ||
InvariantVersion = 5, | ||
Instance = liveMetricsResource?.RoleInstance ?? "UNKNOWN_INSTANCE", | ||
RoleName = liveMetricsResource?.RoleName, | ||
MachineName = Environment.MachineName, // TODO: MOVE TO PLATFORM | ||
// TODO: Is the Stream ID expected to be unique per post? Testing suggests this is not necessary. | ||
StreamId = _streamId, | ||
Timestamp = DateTime.UtcNow, | ||
//TODO: Provide feedback to service team to get this removed, it not a part of AI SDK. | ||
TransmissionTime = DateTime.UtcNow, | ||
IsWebApp = IsWebAppRunningInAzure(), | ||
PerformanceCollectionSupported = true, | ||
// AI SDK relies on PerformanceCounter to collect CPU and Memory metrics. | ||
// Follow up with service team to get this removed for OTEL based live metrics. | ||
// TopCpuProcesses = null, | ||
// TODO: Configuration errors are thrown when filter is applied. | ||
// CollectionConfigurationErrors = null, | ||
}; | ||
|
||
LiveMetricsBuffer liveMetricsBuffer = new(); | ||
DocumentBuffer filledBuffer = _documentBuffer.FlipDocumentBuffers(); | ||
foreach (var item in filledBuffer.ReadAllAndClear()) | ||
{ | ||
dataPoint.Documents.Add(item); | ||
|
||
if (item.DocumentType == DocumentIngressDocumentType.Request) | ||
{ | ||
// Export needs to divide by count to get the average. | ||
// this.AIRequestDurationAveInMs = requestCount > 0 ? (double)requestDurationInTicks / TimeSpan.TicksPerMillisecond / requestCount : 0; | ||
if (item.Extension_IsSuccess) | ||
{ | ||
liveMetricsBuffer.RecordRequestSucceeded(item.Extension_Duration); | ||
} | ||
else | ||
{ | ||
liveMetricsBuffer.RecordRequestFailed(item.Extension_Duration); | ||
} | ||
} | ||
else if (item.DocumentType == DocumentIngressDocumentType.RemoteDependency) | ||
{ | ||
// Export needs to divide by count to get the average. | ||
// this.AIDependencyCallDurationAveInMs = dependencyCount > 0 ? (double)dependencyDurationInTicks / TimeSpan.TicksPerMillisecond / dependencyCount : 0; | ||
// Export DependencyDurationLiveMetric, Meter: LiveMetricMeterName | ||
// (2023 - 11 - 03T23: 20:56.0282406Z, 2023 - 11 - 03T23: 21:00.9830153Z] Histogram Value: Sum: 798.9463000000001 Count: 7 Min: 4.9172 Max: 651.8997 | ||
if (item.Extension_IsSuccess) | ||
{ | ||
liveMetricsBuffer.RecordDependencySucceeded(item.Extension_Duration); | ||
} | ||
else | ||
{ | ||
liveMetricsBuffer.RecordDependencyFailed(item.Extension_Duration); | ||
} | ||
} | ||
else if (item.DocumentType == DocumentIngressDocumentType.Exception) | ||
{ | ||
liveMetricsBuffer.RecordException(); | ||
} | ||
else | ||
{ | ||
Debug.WriteLine($"Unknown DocumentType: {item.DocumentType}"); | ||
} | ||
} | ||
|
||
foreach (var metricPoint in liveMetricsBuffer.GetMetricPoints()) | ||
{ | ||
dataPoint.Metrics.Add(metricPoint); | ||
} | ||
|
||
foreach (var metricPoint in CollectPerfCounters()) | ||
{ | ||
dataPoint.Metrics.Add(metricPoint); | ||
} | ||
|
||
return dataPoint; | ||
} | ||
|
||
public IEnumerable<Models.MetricPoint> CollectPerfCounters() | ||
{ | ||
// PERFORMANCE COUNTERS | ||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.MemoryCommittedBytesMetricIdValue, | ||
Value = _performanceCounter_CommittedBytes.NextValue(), | ||
Weight = 1 | ||
}; | ||
|
||
yield return new Models.MetricPoint | ||
{ | ||
Name = LiveMetricConstants.MetricId.ProcessorTimeMetricIdValue, | ||
Value = _performanceCounter_ProcessorTime.NextValue(), | ||
Weight = 1 | ||
}; | ||
} | ||
} | ||
} |
Oops, something went wrong.