From 7dcd6980a115010e1d4e7ed01dd73ae8762266bf Mon Sep 17 00:00:00 2001 From: Oleksiy Dubinin <88040756+rypdal@users.noreply.github.com> Date: Thu, 15 Jun 2023 20:28:11 +0200 Subject: [PATCH 1/2] [OpenTelemetry.Instrumentation.AWSLambda]: update README according to the recent code changes. (#1234) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christian Neumüller --- .../README.md | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/OpenTelemetry.Instrumentation.AWSLambda/README.md b/src/OpenTelemetry.Instrumentation.AWSLambda/README.md index 28adbb4bb6..a41913b46d 100644 --- a/src/OpenTelemetry.Instrumentation.AWSLambda/README.md +++ b/src/OpenTelemetry.Instrumentation.AWSLambda/README.md @@ -15,17 +15,44 @@ Add `AddAWSLambdaConfigurations()` to `TracerProvider`. ```csharp TracerProvider tracerProvider = Sdk.CreateTracerProviderBuilder() // add other instrumentations - .AddAWSLambdaConfigurations() + .AddAWSLambdaConfigurations(options => options.DisableAwsXRayContextExtraction = true) .Build(); ``` +### AWSLambdaInstrumentationOptions + +`AWSLambdaInstrumentationOptions` contains various properties to configure +AWS lambda instrumentation: + +* [`DisableAwsXRayContextExtraction`](/src/OpenTelemetry.Instrumentation.AWSLambda/AWSLambdaInstrumentationOptions.cs) +* [`SetParentFromBatch`](/src/OpenTelemetry.Instrumentation.AWSLambda/AWSLambdaInstrumentationOptions.cs) + ## Instrumentation +`AWSLambdaWrapper` contains tracing methods covering different types of +function handler method signatures. `AWSLambdaWrapper.Trace()` and +`AWSLambdaWrapper.TraceAsync()` are used for wrapping synchronous +and asynchronous function handlers respectively. The `ActivityContext parentContext` +parameter is optional and used to pass a custom parent context. If the parent +is not passed explicitly then it's either extracted from the +input parameter or uses AWS X-Ray headers if AWS X-Ray context extraction is +enabled (see configuration property `DisableAwsXRayContextExtraction`). +The sequence of the parent extraction: +`explicit parent` -> `parent from input parameter` -> `AWS X-Ray headers` -> `default` +The parent extraction is supported for the input types listed in the table below: + +| Type | Parent extraction source | +|------|--------------------------| +| `APIGatewayProxyRequest, APIGatewayHttpApiV2ProxyRequest` | HTTP headers of the request | +| `SQSEvent` | Attributes of the last `SQSMessage` (if `SetParentFromMessageBatch` is `true`) | +| `SNSEvent` | Attributes of the last `SNSRecord` | + ### Lambda Function -1. Create a wrapper function with the same signature as the original Lambda function. -Call `AWSLambdaWrapper.Trace()` API and pass `TracerProvider`, original Lambda function -and its inputs as parameters. +1. Create a wrapper function with the same signature as the original Lambda +function but an added ILambdaContext parameter if it was not already present. +Call `AWSLambdaWrapper.Trace()` or `AWSLambdaWrapper.TraceAsync()` API and pass +`TracerProvider`, original Lambda function and its parameters. 2. Set the wrapper function as the Lambda handler input. @@ -48,14 +75,14 @@ public string OriginalFunctionHandler(JObject input, ILambdaContext context) For using base classes from package [Amazon.Lambda.AspNetCoreServer](https://github.com/aws/aws-lambda-dotnet/tree/master/Libraries/src/Amazon.Lambda.AspNetCoreServer#amazonlambdaaspnetcoreserver), override the `FunctionHandlerAsync` function in `LambdaEntryPoint.cs` file. Call -`AWSLambdaWrapper.Trace()` API and pass `TracerProvider`, original Lambda function +`AWSLambdaWrapper.TraceAsync()` API and pass `TracerProvider`, original Lambda function and its inputs as parameters. Below is an example if using `APIGatewayProxyFunction` as base class. ```csharp public override async Task FunctionHandlerAsync( APIGatewayProxyRequest request, ILambdaContext lambdaContext) -=> await AWSLambdaWrapper.Trace(tracerProvider, base.FunctionHandlerAsync, +=> await AWSLambdaWrapper.TraceAsync(tracerProvider, base.FunctionHandlerAsync, request, lambdaContext); ``` @@ -75,7 +102,7 @@ public class Function .AddHttpClientInstrumentation() .AddAWSInstrumentation() .AddOtlpExporter() - .AddAWSLambdaConfigurations() + .AddAWSLambdaConfigurations(options => options.DisableAwsXRayContextExtraction = true) .Build(); } From 326d071b61a13aca92286733c934f8d5c186ee2b Mon Sep 17 00:00:00 2001 From: xiang17 Date: Fri, 16 Jun 2023 00:43:43 -0700 Subject: [PATCH 2/2] [Instrumentation.Runtime] Add a metric for total paused duration in GC for .NET 7 and greater versions (#1239) --- .../CHANGELOG.md | 4 ++++ .../README.md | 16 ++++++++++++++++ .../RuntimeMetrics.cs | 14 +++++++++++++- .../RuntimeMetricsTests.cs | 3 +++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Instrumentation.Runtime/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.Runtime/CHANGELOG.md index 97ed41a722..81ff30c13d 100644 --- a/src/OpenTelemetry.Instrumentation.Runtime/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.Runtime/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +* Add a metric `process.runtime.dotnet.gc.duration` for total paused duration in + GC for .NET 7 and greater versions + ([#1239](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/1239)) + ## 1.5.0 Released 2023-Jun-06 diff --git a/src/OpenTelemetry.Instrumentation.Runtime/README.md b/src/OpenTelemetry.Instrumentation.Runtime/README.md index 79734bfc79..20ff2da435 100644 --- a/src/OpenTelemetry.Instrumentation.Runtime/README.md +++ b/src/OpenTelemetry.Instrumentation.Runtime/README.md @@ -176,6 +176,22 @@ The API used to retrieve the value is: * [GCGenerationInfo.FragmentationAfterBytes Property](https://docs.microsoft.com/dotnet/api/system.gcgenerationinfo.fragmentationafterbytes) Gets the fragmentation in bytes on exit from the reported collection. +#### process.runtime.dotnet.**gc.duration** + +The total amount of time paused in GC since the process start. + +> **Note** +> This metric is only available when targeting .NET 7 or later. + +| Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values | +|-------|-------------------|------------|------------------|------------------| +| `ns` | ObservableCounter | `Int64` | No Attributes | N/A | + +The API used to retrieve the value is: + +* [GC.GetTotalPauseDuration](https://learn.microsoft.com/dotnet/api/system.gc.gettotalpauseduration) + Gets the total amount of time paused in GC since the beginning of the process. + ### JIT Compiler related metrics These metrics are only available when targeting .NET6 or later. diff --git a/src/OpenTelemetry.Instrumentation.Runtime/RuntimeMetrics.cs b/src/OpenTelemetry.Instrumentation.Runtime/RuntimeMetrics.cs index eb730de55b..bdbd4f2821 100644 --- a/src/OpenTelemetry.Instrumentation.Runtime/RuntimeMetrics.cs +++ b/src/OpenTelemetry.Instrumentation.Runtime/RuntimeMetrics.cs @@ -120,9 +120,9 @@ static RuntimeMetrics() description: "The heap size (including fragmentation), as observed during the latest garbage collection. The value will be unavailable until at least one garbage collection has occurred."); } - // Not valid until .NET 7 where the bug in the API is fixed. See context in https://github.com/open-telemetry/opentelemetry-dotnet-contrib/issues/496 if (Environment.Version.Major >= 7) { + // Not valid until .NET 7 where the bug in the API is fixed. See context in https://github.com/open-telemetry/opentelemetry-dotnet-contrib/issues/496 MeterInstance.CreateObservableUpDownCounter( "process.runtime.dotnet.gc.heap.fragmentation.size", () => @@ -144,6 +144,18 @@ static RuntimeMetrics() }, unit: "bytes", description: "The heap fragmentation, as observed during the latest garbage collection. The value will be unavailable until at least one garbage collection has occurred."); + + // GC.GetTotalPauseDuration() is not available until .NET 7. See context in https://github.com/open-telemetry/opentelemetry-dotnet-contrib/issues/1163 + var mi = typeof(GC).GetMethod("GetTotalPauseDuration", BindingFlags.Public | BindingFlags.Static); + var getTotalPauseDuration = mi?.CreateDelegate>(); + if (getTotalPauseDuration != null) + { + MeterInstance.CreateObservableCounter( + "process.runtime.dotnet.gc.duration", + () => getTotalPauseDuration().Ticks * NanosecondsPerTick, + unit: "ns", + description: "The total amount of time paused in GC since the process start."); + } } MeterInstance.CreateObservableCounter( diff --git a/test/OpenTelemetry.Instrumentation.Runtime.Tests/RuntimeMetricsTests.cs b/test/OpenTelemetry.Instrumentation.Runtime.Tests/RuntimeMetricsTests.cs index 602d35e5bf..b935e0c7d5 100644 --- a/test/OpenTelemetry.Instrumentation.Runtime.Tests/RuntimeMetricsTests.cs +++ b/test/OpenTelemetry.Instrumentation.Runtime.Tests/RuntimeMetricsTests.cs @@ -94,6 +94,9 @@ public void GcMetricsTest() { var gcHeapFragmentationSizeMetric = exportedItems.FirstOrDefault(i => i.Name == "process.runtime.dotnet.gc.heap.fragmentation.size"); Assert.NotNull(gcHeapFragmentationSizeMetric); + + var gcDurationMetric = exportedItems.FirstOrDefault(i => i.Name == "process.runtime.dotnet.gc.duration"); + Assert.NotNull(gcDurationMetric); } #endif }