From e48e8dbd4ce53d58bc9c95955bf96b5f7b5a9ebf Mon Sep 17 00:00:00 2001 From: Adam Furmanek Date: Mon, 8 Dec 2025 15:09:18 +0100 Subject: [PATCH 1/9] Adding CloudEvents docs and samples for ASB and SQS. --- monitoring/metrics/definitions.md | 14 +++ ...pentelemetry_metrics_core_[10,).partial.md | 38 ++++++ ...ntelemetry_metrics_core_[9,10).partial.md} | 0 .../aws/cloud-events/Sqs_9/CloudEvents.sln | 23 ++++ .../Sqs_9/Endpoint/AwsBlobNotification.cs | 10 ++ .../Endpoint/AwsBlobNotificationHandler.cs | 11 ++ .../Sqs_9/Endpoint/Endpoint.csproj | 16 +++ .../cloud-events/Sqs_9/Endpoint/Program.cs | 40 ++++++ samples/aws/cloud-events/Sqs_9/prerelease.txt | 0 samples/aws/cloud-events/sample.md | 73 +++++++++++ .../cloud-events/ASBS_6/CloudEvents.sln | 21 ++++ .../ASBS_6/Endpoint/BlobCreated.cs | 23 ++++ .../ASBS_6/Endpoint/BlobCreatedHandler.cs | 13 ++ .../ASBS_6/Endpoint/Endpoint.csproj | 19 +++ .../cloud-events/ASBS_6/Endpoint/Program.cs | 58 +++++++++ .../ASBS_6/Endpoint/appsettings.json | 12 ++ .../cloud-events/ASBS_6/prerelease.txt | 0 .../cloud-events/sample.md | 53 ++++++++ transports/cloudevents.md | 114 ++++++++++++++++++ 19 files changed, 538 insertions(+) create mode 100644 nservicebus/operations/opentelemetry_metrics_core_[10,).partial.md rename nservicebus/operations/{opentelemetry_metrics_core_[9,).partial.md => opentelemetry_metrics_core_[9,10).partial.md} (100%) create mode 100644 samples/aws/cloud-events/Sqs_9/CloudEvents.sln create mode 100644 samples/aws/cloud-events/Sqs_9/Endpoint/AwsBlobNotification.cs create mode 100644 samples/aws/cloud-events/Sqs_9/Endpoint/AwsBlobNotificationHandler.cs create mode 100644 samples/aws/cloud-events/Sqs_9/Endpoint/Endpoint.csproj create mode 100644 samples/aws/cloud-events/Sqs_9/Endpoint/Program.cs create mode 100644 samples/aws/cloud-events/Sqs_9/prerelease.txt create mode 100644 samples/aws/cloud-events/sample.md create mode 100644 samples/azure-service-bus-netstandard/cloud-events/ASBS_6/CloudEvents.sln create mode 100644 samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/BlobCreated.cs create mode 100644 samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/BlobCreatedHandler.cs create mode 100644 samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/Endpoint.csproj create mode 100644 samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/Program.cs create mode 100644 samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/appsettings.json create mode 100644 samples/azure-service-bus-netstandard/cloud-events/ASBS_6/prerelease.txt create mode 100644 samples/azure-service-bus-netstandard/cloud-events/sample.md create mode 100644 transports/cloudevents.md diff --git a/monitoring/metrics/definitions.md b/monitoring/metrics/definitions.md index 060e6b1de1a..d484039a1e2 100644 --- a/monitoring/metrics/definitions.md +++ b/monitoring/metrics/definitions.md @@ -93,3 +93,17 @@ There are metrics that measure various spects of the [transactional session oper - Dispatch druation - how long it took to dispatch the control message - Attempts - how many times the mechanism attempted to process the control message for a given transaction - Transit time - how long it took between dispatching the control message and starting to process it again + +### Envelope handling metrics + +Various metrics track performance of the envelope handling when interoperating with external systems. The generic metrics include: + +- Envelope unwrapping errors - how many times a single envelope handler failed to unwrap the incoming message + +#### CloudEvents specific metrics + +Metrics related to [CloudEvents](/transports/cloudevents.md) track the following: + +- Unwrapping attempt - number of attempts to unwrap a message +- Invalid messages received - number of messages that don't meet the specification requirements (e.g., they lack mandatory fields) +- Unexpected version received - number of messages that use unexpected specification version \ No newline at end of file diff --git a/nservicebus/operations/opentelemetry_metrics_core_[10,).partial.md b/nservicebus/operations/opentelemetry_metrics_core_[10,).partial.md new file mode 100644 index 00000000000..7dca9f5e772 --- /dev/null +++ b/nservicebus/operations/opentelemetry_metrics_core_[10,).partial.md @@ -0,0 +1,38 @@ +## Meters + +NServiceBus endpoints can be configured to expose metrics related to message processing. To capture meter information, add the appropriate meter source (e.g., `NServiceBus.Core.Pipeline.Incoming`) to the OpenTelemetry configuration: + +> [!NOTE] +> The metric definitions published by NServiceBus are not yet finalized and could change in a minor release. + +snippet: opentelemetry-enablemeters + +### Emitted meters + +Meter source `NServiceBus.Core.Pipeline.Incoming`: + +- [`nservicebus.messaging.successes`](/monitoring/metrics/definitions.md#metrics-captured-number-of-messages-successfully-processed) - Total number of messages processed successfully by the endpoint +- [`nservicebus.messaging.fetches`](/monitoring/metrics/definitions.md#metrics-captured-number-of-messages-pulled-from-queue) - Total number of messages fetched from the queue by the endpoint +- [`nservicebus.messaging.failures`](/monitoring/metrics/definitions.md#metrics-captured-number-of-message-processing-failures) - Total number of messages processed unsuccessfully by the endpoint +- [`nservicebus.messaging.handler_time`](/monitoring/metrics/definitions.md#metrics-captured-handler-time) - The time the user handling code takes to handle a message +- [`nservicebus.messaging.processing_time`](/monitoring/metrics/definitions.md#metrics-captured-processing-time) - The time the endpoint takes to process a message +- [`nservicebus.messaging.critical_time`](/monitoring/metrics/definitions.md#metrics-captured-critical-time) - The time between when a message is sent and when it is fully processed +- [`nservicebus.recoverability.immediate`](/monitoring/metrics/definitions.md#metrics-captured-immediate-retries) - Total number of immediate retries requested +- [`nservicebus.recoverability.delayed`](/monitoring/metrics/definitions.md#metrics-captured-delayed-retries) - Total number of delayed retries requested +- [`nservicebus.recoverability.error`](/monitoring/metrics/definitions.md#metrics-captured-moved-to-error-queue) - Total number of messages sent to the error queue +- [`nservicebus.envelope.unwrapping_error`](/monitoring/metrics/definitions.md#envelope-handling-metrics) - Total number of times when an envelope handler failed to unwrap an incoming message + +Meter source `NServiceBus.TransactionalSession`: + +- [`nservicebus.transactional_session.commit.duration`](/monitoring/metrics/definitions.md#metrics-captured-transactional-session-metrics) - The time the endpoint takes to commit the session in the Transactional Session +- [`nservicebus.transactional_session.dispatch.duration`](/monitoring/metrics/definitions.md#metrics-captured-transactional-session-metrics) - The time the endpoint takes to dispatch the control message in the Transactional Session +- [`nservicebus.transactional_session.control_message.attempts`](/monitoring/metrics/definitions.md#metrics-captured-transactional-session-metrics) - Total number of attempts to process the control message in the Transactional Session +- [`nservicebus.transactional_session.control_message.transit_time`](/monitoring/metrics/definitions.md#metrics-captured-transactional-session-metrics) - The time between dispatching the control message and starting to process it in the Transactional Session + +Meter source `NServiceBus.Envelope.CloudEvents`: + +- [`nservicebus.envelope.cloud_events.received.unwrapping_attempt`](/monitoring/metrics/definitions.md#cloudevents-specific-metrics) - Total number of unwrapping attempts +- [`nservicebus.envelope.cloud_events.received.invalid_message`](/monitoring/metrics/definitions.md#cloudevents-specific-metrics) - Total number of received messages not conforming to the specification +- [`nservicebus.envelope.cloud_events.received.unexpected_version`](/monitoring/metrics/definitions.md#cloudevents-specific-metrics) - Total number of received messages with unexpected version field value + +See the [OpenTelemetry samples](/samples/open-telemetry/) for instructions on how to send metric information to different tools. diff --git a/nservicebus/operations/opentelemetry_metrics_core_[9,).partial.md b/nservicebus/operations/opentelemetry_metrics_core_[9,10).partial.md similarity index 100% rename from nservicebus/operations/opentelemetry_metrics_core_[9,).partial.md rename to nservicebus/operations/opentelemetry_metrics_core_[9,10).partial.md diff --git a/samples/aws/cloud-events/Sqs_9/CloudEvents.sln b/samples/aws/cloud-events/Sqs_9/CloudEvents.sln new file mode 100644 index 00000000000..fae802d7c39 --- /dev/null +++ b/samples/aws/cloud-events/Sqs_9/CloudEvents.sln @@ -0,0 +1,23 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 18 +VisualStudioVersion = 18.3.11222.16 d18.3 +MinimumVisualStudioVersion = 15.0.26730.12 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Endpoint", "Endpoint\Endpoint.csproj", "{7081E12A-888F-4506-A435-970E50BA4C0B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7081E12A-888F-4506-A435-970E50BA4C0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7081E12A-888F-4506-A435-970E50BA4C0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22B1E205-B713-45C3-A041-62CCDDA9646B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22B1E205-B713-45C3-A041-62CCDDA9646B}.Debug|Any CPU.Build.0 = Debug|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6E692BB9-1D3D-4DA0-B777-DB9C754E7342} + EndGlobalSection +EndGlobal diff --git a/samples/aws/cloud-events/Sqs_9/Endpoint/AwsBlobNotification.cs b/samples/aws/cloud-events/Sqs_9/Endpoint/AwsBlobNotification.cs new file mode 100644 index 00000000000..f4c50eff95e --- /dev/null +++ b/samples/aws/cloud-events/Sqs_9/Endpoint/AwsBlobNotification.cs @@ -0,0 +1,10 @@ +#region sqs-cloudevents-message-definition +public class AwsBlobNotification : + IMessage +{ + public string Key { get; set; } + public int Size { get; set; } + public string ETag { get; set; } + public string Sequencer { get; set; } +} +#endregion diff --git a/samples/aws/cloud-events/Sqs_9/Endpoint/AwsBlobNotificationHandler.cs b/samples/aws/cloud-events/Sqs_9/Endpoint/AwsBlobNotificationHandler.cs new file mode 100644 index 00000000000..c302f5fcf63 --- /dev/null +++ b/samples/aws/cloud-events/Sqs_9/Endpoint/AwsBlobNotificationHandler.cs @@ -0,0 +1,11 @@ +using Microsoft.Extensions.Logging; + +public class AwsBlobNotificationHandler(ILogger logger) : + IHandleMessages +{ + public Task Handle(AwsBlobNotification message, IMessageHandlerContext context) + { + logger.LogInformation("Blob {Key} created!", message.Key); + return Task.CompletedTask; + } +} diff --git a/samples/aws/cloud-events/Sqs_9/Endpoint/Endpoint.csproj b/samples/aws/cloud-events/Sqs_9/Endpoint/Endpoint.csproj new file mode 100644 index 00000000000..6d5e1b7ed35 --- /dev/null +++ b/samples/aws/cloud-events/Sqs_9/Endpoint/Endpoint.csproj @@ -0,0 +1,16 @@ + + + + net10.0 + Exe + 14.0 + enable + + + + + + + + + \ No newline at end of file diff --git a/samples/aws/cloud-events/Sqs_9/Endpoint/Program.cs b/samples/aws/cloud-events/Sqs_9/Endpoint/Program.cs new file mode 100644 index 00000000000..65bacc2a983 --- /dev/null +++ b/samples/aws/cloud-events/Sqs_9/Endpoint/Program.cs @@ -0,0 +1,40 @@ +using System.Text.Json; +using Microsoft.Extensions.Hosting; + +Console.Title = "CloudEvents"; + +var builder = Host.CreateApplicationBuilder(args); + +var endpointConfiguration = new EndpointConfiguration("Samples.Sqs.CloudEvents"); +endpointConfiguration.EnableInstallers(); + +#region sqs-cloudevents-serialization +endpointConfiguration.UseSerialization().Options(new JsonSerializerOptions +{ + PropertyNameCaseInsensitive = true, + IncludeFields = true +}); +#endregion + +#region sqs-cloudevents-configuration +var cloudEventsConfiguration = endpointConfiguration.EnableCloudEvents(); +#endregion + +#region sqs-cloudevents-typemapping +cloudEventsConfiguration.TypeMappings["ObjectCreated:Put"] = [typeof(AwsBlobNotification)]; +#endregion + +#region sqs-cloudevents-json-permissive +cloudEvents.EnvelopeUnwrappers.Find().EnvelopeHandlingMode = JsonStructureEnvelopeHandlingMode.Permissive; +#endregion + +var transport = new SqsTransport(); +endpointConfiguration.UseTransport(transport); + + +Console.WriteLine("Press any key, the application is starting"); +Console.ReadKey(); +Console.WriteLine("Starting..."); + +builder.UseNServiceBus(endpointConfiguration); +await builder.Build().RunAsync(); diff --git a/samples/aws/cloud-events/Sqs_9/prerelease.txt b/samples/aws/cloud-events/Sqs_9/prerelease.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/samples/aws/cloud-events/sample.md b/samples/aws/cloud-events/sample.md new file mode 100644 index 00000000000..0c0b1d4d41b --- /dev/null +++ b/samples/aws/cloud-events/sample.md @@ -0,0 +1,73 @@ +--- +title: AmazonSQS CloudEvents Sample +summary: Demonstrates how to consume CloudEvents via the Amazon SQS +reviewed: 2025-12-10 +component: Sqs +related: +- transports/sqs +--- + +## Prerequisites + +### Security and access configuration + +Add the [AWS Access Key ID and AWS Secret Access Key](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) to the following environment variables: + +* Access Key ID in `AWS_ACCESS_KEY_ID` +* Secret Access Key in `AWS_SECRET_ACCESS_KEY` +* Default Region in `AWS_REGION` + +See also [AWS Account Identifiers](https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html), [Managing Access Keys for an AWS Account](https://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html), and [IAM Security Credentials](https://console.aws.amazon.com/iam/home#/security_credential). + +See also [AWS Regions](https://docs.aws.amazon.com/general/latest/gr/rande.html) for a list of available regions. + +### S3 configuration + +The S3 bucket should be configured to generate notifications that are ultimately delivered to the SQS queue matching the endpoint. There are many ways to configure the setup. One example configuration includes: + +- Configuring S3 bucket to [send notifications to SQS](https://docs.aws.amazon.com/AmazonS3/latest/userguide/notification-how-to-event-types-and-destinations.html#supported-notification-event-types) +- Creating [Amazon EventBridge Pipe](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-event-target.html) that picks up the messages from the SQS queue +- Configuring the Pipe to [transform](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-input-transformation.html) the messages to the CloudEvents schema as specified in the [CloudEvents specification](https://github.com/cloudevents/spec/blob/main/cloudevents/adapters/aws-s3.md). +- Configuring the Pipe to call AWS Lambda that would enrich the message with the proper `content-type` property and send the message to the SQS queue matching the endpoint. + +## Code walk-through + +This sample shows an endpoint receiving a CloudEvents message from the Amazon Simple Queue Service (Amazon SQS) + +* The `Endpoint` defines the schema for the CloudEvents message. +* The `Endpoint` enables CloudEvents support and configures the type mapping. +* The `Endpoint` configures the serializer to support fields and properties with different casing. +* The `Endpoint` receives the message and calls the proper handler. + +### CloudEvents message schema + +The message schema is defined as follows: + +snippet: sqs-cloudevents-message-definition + +This schema must match the schema of the [notification generated by S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/notification-how-to-event-types-and-destinations.html#supported-notification-event-types). + +### CloudEvents support configuration + +CloudEvents support must be explicitly enabled: + +snippet: sqs-cloudevents-configuration + +The configuration includes the type mapping to match the messages with the classes: + +snippet: sqs-cloudevents-typemapping + +To handle the JSON structured messages that do not have the `Content-Type` header set properly, enable the Permissive mode: + +snippet: sqs-cloudevents-json-permissive + +To support the differences between uppercase letters and lowercase letters in the schema definition and content, the serializer is configured to use case insensitive mapping: + +snippet: sqs-cloudevents-serialization + + +### Running the sample + +1. Run the sample. +2. Generate the `ObjectCreated:Put` event by creating a new file in the S3 bucket. +3. Observe that the sample prints out the URL of the newly created file. diff --git a/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/CloudEvents.sln b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/CloudEvents.sln new file mode 100644 index 00000000000..86cb4e3fcb6 --- /dev/null +++ b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/CloudEvents.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 18 +VisualStudioVersion = 18.3.11222.16 d18.3 +MinimumVisualStudioVersion = 15.0.26730.12 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Endpoint", "Endpoint\Endpoint.csproj", "{1874F4C3-9250-8342-8F1E-4E2692AD6BE3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1874F4C3-9250-8342-8F1E-4E2692AD6BE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1874F4C3-9250-8342-8F1E-4E2692AD6BE3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1874F4C3-9250-8342-8F1E-4E2692AD6BE3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1874F4C3-9250-8342-8F1E-4E2692AD6BE3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/BlobCreated.cs b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/BlobCreated.cs new file mode 100644 index 00000000000..0832438177b --- /dev/null +++ b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/BlobCreated.cs @@ -0,0 +1,23 @@ +using NServiceBus; + +#region asb-cloudevents-message-definition +public class BlobCreated : + IMessage +{ + public string Api { get; set; } + public string ClientRequestId { get; set; } + public string RequestId { get; set; } + public string ETag { get; set; } + public string ContentType { get; set; } + public int ContentLength { get; set; } + public string BlobType { get; set; } + public string Url { get; set; } + public string Sequencer { get; set; } + public StorageDiagnostics StorageDiagnostics { get; set; } +} + +public class StorageDiagnostics +{ + public string BatchId { get; set; } +} +#endregion diff --git a/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/BlobCreatedHandler.cs b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/BlobCreatedHandler.cs new file mode 100644 index 00000000000..4c21497d2b4 --- /dev/null +++ b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/BlobCreatedHandler.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using NServiceBus; + +public class BlobCreatedHandler(ILogger logger) : + IHandleMessages +{ + public Task Handle(BlobCreated message, IMessageHandlerContext context) + { + logger.LogInformation("Blob {Url} created!", message.Url); + return Task.CompletedTask; + } +} diff --git a/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/Endpoint.csproj b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/Endpoint.csproj new file mode 100644 index 00000000000..0c0717adeb7 --- /dev/null +++ b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/Endpoint.csproj @@ -0,0 +1,19 @@ + + + net10.0 + Exe + 14.0 + + + + + + + + + + + PreserveNewest + + + \ No newline at end of file diff --git a/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/Program.cs b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/Program.cs new file mode 100644 index 00000000000..d34de0da9b3 --- /dev/null +++ b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/Program.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using NServiceBus; + +Console.Title = "Endpoint"; + +var builder = Host.CreateApplicationBuilder(args); + +var endpointConfiguration = new EndpointConfiguration("Samples.ASBS.CloudEvents.Endpoint"); +endpointConfiguration.EnableInstallers(); + +var connectionString = builder.Configuration.GetConnectionString("AzureServiceBusConnectionString"); +if (string.IsNullOrWhiteSpace(connectionString)) +{ + throw new Exception("Could not read the 'AzureServiceBusConnectionString' value. Check the sample prerequisites."); +} + +var transport = new AzureServiceBusTransport(connectionString, TopicTopology.Default); +endpointConfiguration.UseTransport(transport); + +#region asb-cloudevents-serialization +endpointConfiguration.UseSerialization().Options(new JsonSerializerOptions +{ + PropertyNameCaseInsensitive = true, + IncludeFields = true +}); +#endregion + +#region asb-cloudevents-configuration +var cloudEventsConfiguration = endpointConfiguration.EnableCloudEvents(); +#endregion + +#region asb-cloudevents-typemapping +cloudEventsConfiguration.TypeMappings["Microsoft.Storage.BlobCreated"] = [typeof(BlobCreated)]; +#endregion + + +Console.WriteLine("Press any key, the application is starting"); +Console.TreatControlCAsInput = true; +var input = Console.ReadKey(); +if (input.Key == ConsoleKey.C && (input.Modifiers & ConsoleModifiers.Control) != 0) +{ + Environment.Exit(0); +} +Console.WriteLine("Starting..."); + +builder.UseNServiceBus(endpointConfiguration); +var host = builder.Build(); + +await host.StartAsync(); + +Console.WriteLine("Press any key to exit"); +var key = Console.ReadKey(); + +await host.StopAsync(); diff --git a/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/appsettings.json b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/appsettings.json new file mode 100644 index 00000000000..a4183fa434a --- /dev/null +++ b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/Endpoint/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "System": "Information", + "Microsoft": "Information" + } + }, + "ConnectionStrings": { + "AzureServiceBusConnectionString": "" + } +} \ No newline at end of file diff --git a/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/prerelease.txt b/samples/azure-service-bus-netstandard/cloud-events/ASBS_6/prerelease.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/samples/azure-service-bus-netstandard/cloud-events/sample.md b/samples/azure-service-bus-netstandard/cloud-events/sample.md new file mode 100644 index 00000000000..213b45994dd --- /dev/null +++ b/samples/azure-service-bus-netstandard/cloud-events/sample.md @@ -0,0 +1,53 @@ +--- +title: Azure Service Bus CloudEvents Sample +summary: Demonstrates how to consume CloudEvents via the Azure Service Bus +reviewed: 2025-12-08 +component: ASBS +related: +- transports/azure-service-bus +--- + +## Prerequisites + +include: asb-connectionstring-xplat + +The Azure Event Grid should be configured to receive the Azure Blob Storage notifications and deliver them to the Azure Service Bus using the CloudEvents schema. The configuration is described in the [Microsoft documentation](https://learn.microsoft.com/en-us/azure/event-grid/cloud-event-schema#sample-event-using-cloudevents-schema). + +## Code walk-through + +This sample shows an endpoint receiving a CloudEvents message from the Azure Service Bus. Such a message can be created by the Azure Blob Storage and delivered to the Azure Service Bus via the Azure Event Grid. + +* The `Endpoint` defines the schema for the CloudEvents message. +* The `Endpoint` enables CloudEvents support and configures the type mapping. +* The `Endpoint` configures the serializer to support fields and properties with different casing. +* The `Endpoint` receives the message and calls the proper handler. + +### CloudEvents message schema + +The message schema is defined as follows: + +snippet: asb-cloudevents-message-definition + +This schema must match the schema of the [notification generated by the Event Grid](https://learn.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage?tabs=cloud-event-schema#microsoftstorageblobcreated-event). + +### CloudEvents support configuration + +CloudEvents support must be explicitly enabled: + +snippet: asb-cloudevents-configuration + +The configuration includes the type mapping to match the messages with the classes: + +snippet: asb-cloudevents-typemapping + +To support the differences between uppercase letters and lowercase letters in the schema definition and content, the serializer is configured to use case insensitive mapping: + +snippet: asb-cloudevents-serialization + +### Running the sample + +1. Run the sample. +2. Generate the `BlobCreated` event by creating a new file in the Azure Blob Storage container. +3. Observe that the sample prints out the URL of the newly created file. + + diff --git a/transports/cloudevents.md b/transports/cloudevents.md new file mode 100644 index 00000000000..8ae689e2f03 --- /dev/null +++ b/transports/cloudevents.md @@ -0,0 +1,114 @@ +--- +title: CloudEvents support +summary: Explains how to consume CloudEvents in transports +component: Core +reviewed: 2025-12-16 +versions: '[10,]' +--- + +> [!WARNING] +> This is an experimental feature and might change in the future. + +This guideline shows how to receive [CloudEvents](https://cloudevents.io/) in the NServiceBus endpoints. + +## Supported formats + +This section describes [CloudEvents formats](https://github.com/cloudevents/spec/tree/v1.0.2/cloudevents/formats) supported by NServiceBus. + +### JSON + +NServiceBus supports [JSON format](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md#3-envelope) only. It does not support [JSON Batch format](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md#4-json-batch-format). + +The implementation relies on [System.Text.Json](https://learn.microsoft.com/en-us/dotnet/api/system.text.json?view=net-10.0) package to parse the JSON content. + +## Supported bindings + +This section describes [CloudEvents bindings](https://github.com/cloudevents/spec/tree/v1.0.2/cloudevents/bindings) supported by NServiceBus. + +### Strutured Content Mode for HTTP and AMQP + +NServiceBus supports [HTTP Structured Content Mode](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#32-structured-content-mode) and [AMQP Structured Content Mode](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md#32-structured-content-mode). Two implementation modes are provided: Strict and Permissive. + +#### Strict mode + +To recognize the CloudEvents message, the `Content-Type` header must be equal to or contain `application/cloudevents+json`. The implementation will not attempt to deserialize the payload if the `Content-Type` header does not meet the requirements. + +Fields [`id`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id), [`source`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1), [`type`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type), and at least one of `data` and `data_base64` must be present. The [`specversion`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion) is not required to be present or to equal to `1.0`. + + +#### Permissive mode + +To recognize the CloudEvents message, [`type`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) field must be present. The `Content-Type` header is not verified, and the payload is always deserialized. + +### Binary Content Mode for HTTP and AMQP + +NServiceBus supports [HTTP Binary Content Mode](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#31-binary-content-mode) and [AMQP Binary Content Mode](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md#31-binary-content-mode). + +To recognize the CloudEvents message, fields [`id`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id), [`source`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1), and [`type`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) must be present. The [`specversion`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion) is not required to be present or to equal to `1.0`. The field names must be encoded according to the binding specification (e.g., `ce-id` for the `id` field when using HTTP). The implementation will not attempt to deserialize the payload is the headers do not meet the requirements. + +The [HTTP Content-Type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#311-http-content-type) and [AMQP Content-Type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md#321-amqp-content-type) headers are not validated. + +## Configuration + +This section describes the configuration options. + +### Enabling the configuration + +To enable the CloudEvents support: + +snippet: sqs-cloudevents-configuration + +### Type mapping + +`TypeMappings` configure how to match the incoming messages with the class definitions: + +snippet: sqs-cloudevents-typemapping + +### Enabled unwrappers + +The `EnvelopeUnwrappers` property contains the list of enabled modes. By default, both Binary Content Mode and Structured Content Mode in Strict Mode are enabled. + +To enable or disable the modes, modify the `EnvelopeUnwrappers` property and add or remove unwrappers. + +To change the Structured Content Mode to use Permissive Mode, change the mode in the configuration: + +snippet: sqs-cloudevents-json-permissive + +## Metrics and logging + +The package provides metrics and logs insights into every stage of receiving a message. + +When selecting an unwrapper for the message: +- A warning message is logged when the unwrapper fails to unwrap the message. +- A metric is emitted for every unwrapping attempt to show errors. The metric's value indicates whether the unwrapping succeeded or crashed. Mind that if the unwrapper recognizes that it can't unwrap the message (e.g., because the message lacks required fields), then it's considered a successful unwrapping. + +Structured Content Mode in Strict Mode produces the following signals: +- A metric is emitted to indicate if the unwrapper attempts to unwrap the message (i.e., if the message has incorrect `Content-Type` header value). +- A metric is emitted to indicate if the message's body can be deserialized, if the body doesn't contain the required fields, or if the body is correct. +- A warning message is logged to indicate if the message's body cannot be deserialized. +- A warning message is logged for every required field that is missing. +- A metric is emitted to indicate if the version field contains a correct version, if the version field contains an incorrect version, or if the version field is missing. +- A warning message is logged when the version field contains unexpected value or if the version field is missing. + +Structured Content Mode in Permissive Mode produces the following signals: +- A metric is emitted to indicate that the unwrapper attempts to unwrap the message (i.e., for every messages). +- A metric is emitted to indicate when the message's body is correct. +- A metric is emitted to indicate when the version field contains an unexpected value. +- A warning message is logged when the version field contains unexpected value. + +Binary Content Mode produces the following signals: +- A metric is emitted to indicate that the unwrapper attempts to unwrap the message (i.e., for every messages). +- A metric is emitted to indicate when the expected headers are present. +- A metric is emitted to indicate if the version header contains a correct version, if the version header contains an incorrect version, or if the version header is missing. +- A warning message is logged when the version header contains unexpected value or if the version header is missing. + +## Troubleshooting + +To troubleshoot the mechanism, examine the metrics and logs to understand why messages are not unwrapped as CloudEvents. Non-exhaustive list of elements to check includes: + +- Is the mechanism enabled? +- Are correct unwrappers registered? +- Is the mode for Structured Content Mode messages configured correctly? +- Is the JSON deserializer configured to handle lowercase/uppercase letters correctly? +- Do the incoming messages have all required headers and fields? Pay special attention to lowercase/uppercase letters. +- Is the type mapping configured correctly? \ No newline at end of file From a3ec4eccfd9471d521e2415d6604459162037b2d Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 20 Jan 2026 08:30:28 +0100 Subject: [PATCH 2/9] Apply suggestions from code review Co-authored-by: Mauro Servienti --- monitoring/metrics/definitions.md | 4 +-- samples/aws/cloud-events/sample.md | 14 +++++----- .../cloud-events/sample.md | 8 +++--- transports/cloudevents.md | 27 ++++++++++++------- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/monitoring/metrics/definitions.md b/monitoring/metrics/definitions.md index d484039a1e2..7192a192961 100644 --- a/monitoring/metrics/definitions.md +++ b/monitoring/metrics/definitions.md @@ -96,9 +96,9 @@ There are metrics that measure various spects of the [transactional session oper ### Envelope handling metrics -Various metrics track performance of the envelope handling when interoperating with external systems. The generic metrics include: +Various metrics track envelope-handling performance when receiving messages that require envelope unwrapping, such as CloudEvents. The generic metrics include: -- Envelope unwrapping errors - how many times a single envelope handler failed to unwrap the incoming message +- Envelope unwrapping attempts - how many times a single envelope handler attempted to unwrap an incoming message. The metric also reports whether the operation was successful or not, the envelope handler type, and the exception in case of failure #### CloudEvents specific metrics diff --git a/samples/aws/cloud-events/sample.md b/samples/aws/cloud-events/sample.md index 0c0b1d4d41b..3cfc77dc570 100644 --- a/samples/aws/cloud-events/sample.md +++ b/samples/aws/cloud-events/sample.md @@ -1,6 +1,6 @@ --- title: AmazonSQS CloudEvents Sample -summary: Demonstrates how to consume CloudEvents via the Amazon SQS +summary: Demonstrates how to consume CloudEvents received through Amazon SQS reviewed: 2025-12-10 component: Sqs related: @@ -23,12 +23,12 @@ See also [AWS Regions](https://docs.aws.amazon.com/general/latest/gr/rande.html) ### S3 configuration -The S3 bucket should be configured to generate notifications that are ultimately delivered to the SQS queue matching the endpoint. There are many ways to configure the setup. One example configuration includes: +The S3 bucket should be configured to generate notifications that are ultimately delivered to the SQS queue matching the endpoint. The following is a sample configuration that can be used to generate S3 notifications: -- Configuring S3 bucket to [send notifications to SQS](https://docs.aws.amazon.com/AmazonS3/latest/userguide/notification-how-to-event-types-and-destinations.html#supported-notification-event-types) -- Creating [Amazon EventBridge Pipe](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-event-target.html) that picks up the messages from the SQS queue -- Configuring the Pipe to [transform](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-input-transformation.html) the messages to the CloudEvents schema as specified in the [CloudEvents specification](https://github.com/cloudevents/spec/blob/main/cloudevents/adapters/aws-s3.md). -- Configuring the Pipe to call AWS Lambda that would enrich the message with the proper `content-type` property and send the message to the SQS queue matching the endpoint. +- Configure an S3 bucket to [send notifications to SQS](https://docs.aws.amazon.com/AmazonS3/latest/userguide/notification-how-to-event-types-and-destinations.html#supported-notification-event-types) +- Create an [Amazon EventBridge Pipe](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-event-target.html) that picks up the messages from the SQS queue +- Configure the Amazon EventBridge Pipe to [transform](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-input-transformation.html) messages to the CloudEvents schema as specified in the [CloudEvents specification](https://github.com/cloudevents/spec/blob/main/cloudevents/adapters/aws-s3.md) +- Configure the Amazon EventBridge Pipe to call AWS Lambda that would enrich messages with the proper `content-type` property and send them to the SQS queue matching the endpoint ## Code walk-through @@ -53,7 +53,7 @@ CloudEvents support must be explicitly enabled: snippet: sqs-cloudevents-configuration -The configuration includes the type mapping to match the messages with the classes: +The configuration includes the type mapping to match the message's content-type with the .NET types representing the incoming messages: snippet: sqs-cloudevents-typemapping diff --git a/samples/azure-service-bus-netstandard/cloud-events/sample.md b/samples/azure-service-bus-netstandard/cloud-events/sample.md index 213b45994dd..309d0d78b4c 100644 --- a/samples/azure-service-bus-netstandard/cloud-events/sample.md +++ b/samples/azure-service-bus-netstandard/cloud-events/sample.md @@ -1,6 +1,6 @@ --- title: Azure Service Bus CloudEvents Sample -summary: Demonstrates how to consume CloudEvents via the Azure Service Bus +summary: Demonstrates how to consume CloudEvents received through Azure Service Bus reviewed: 2025-12-08 component: ASBS related: @@ -11,11 +11,11 @@ related: include: asb-connectionstring-xplat -The Azure Event Grid should be configured to receive the Azure Blob Storage notifications and deliver them to the Azure Service Bus using the CloudEvents schema. The configuration is described in the [Microsoft documentation](https://learn.microsoft.com/en-us/azure/event-grid/cloud-event-schema#sample-event-using-cloudevents-schema). +Azure Event Grid needs to be configured to receive Azure Blob Storage notifications and deliver them to Azure Service Bus using the CloudEvents schema. The configuration is described in the [Microsoft documentation](https://learn.microsoft.com/en-us/azure/event-grid/cloud-event-schema#sample-event-using-cloudevents-schema). ## Code walk-through -This sample shows an endpoint receiving a CloudEvents message from the Azure Service Bus. Such a message can be created by the Azure Blob Storage and delivered to the Azure Service Bus via the Azure Event Grid. +This sample shows an endpoint receiving a CloudEvents message from Azure Service Bus. Such a message can be created by Azure Blob Storage and delivered to Azure Service Bus via Azure Event Grid. * The `Endpoint` defines the schema for the CloudEvents message. * The `Endpoint` enables CloudEvents support and configures the type mapping. @@ -28,7 +28,7 @@ The message schema is defined as follows: snippet: asb-cloudevents-message-definition -This schema must match the schema of the [notification generated by the Event Grid](https://learn.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage?tabs=cloud-event-schema#microsoftstorageblobcreated-event). +This schema must match the [Event Grid notifications schema](https://learn.microsoft.com/en-us/azure/event-grid/event-schema-blob-storage?tabs=cloud-event-schema#microsoftstorageblobcreated-event). ### CloudEvents support configuration diff --git a/transports/cloudevents.md b/transports/cloudevents.md index 8ae689e2f03..e5ed73b7976 100644 --- a/transports/cloudevents.md +++ b/transports/cloudevents.md @@ -1,13 +1,13 @@ --- title: CloudEvents support -summary: Explains how to consume CloudEvents in transports +summary: Provides details about CloudEvents support in NServiceBus and the platform component: Core reviewed: 2025-12-16 versions: '[10,]' --- > [!WARNING] -> This is an experimental feature and might change in the future. +> This is an experimental feature and, as such, is subject to changes. This guideline shows how to receive [CloudEvents](https://cloudevents.io/) in the NServiceBus endpoints. @@ -17,7 +17,7 @@ This section describes [CloudEvents formats](https://github.com/cloudevents/spec ### JSON -NServiceBus supports [JSON format](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md#3-envelope) only. It does not support [JSON Batch format](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md#4-json-batch-format). +NServiceBus supports the [JSON format](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md#3-envelope). The [JSON Batch format](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md#4-json-batch-format) is not supported. The implementation relies on [System.Text.Json](https://learn.microsoft.com/en-us/dotnet/api/system.text.json?view=net-10.0) package to parse the JSON content. @@ -27,24 +27,31 @@ This section describes [CloudEvents bindings](https://github.com/cloudevents/spe ### Strutured Content Mode for HTTP and AMQP -NServiceBus supports [HTTP Structured Content Mode](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#32-structured-content-mode) and [AMQP Structured Content Mode](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md#32-structured-content-mode). Two implementation modes are provided: Strict and Permissive. +NServiceBus supports [HTTP Structured](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#32-structured-content-mode) and [AMQP Structured](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md#32-structured-content-mode) content modes. For each content mode, two implementations are provided: + +- Strict +- Permissive #### Strict mode -To recognize the CloudEvents message, the `Content-Type` header must be equal to or contain `application/cloudevents+json`. The implementation will not attempt to deserialize the payload if the `Content-Type` header does not meet the requirements. +In Strict mode, the CloudEvents message `Content-Type` header must be equal to or contain `application/cloudevents+json`. The implementation will not attempt to deserialize the payload if the `Content-Type` header does not meet the requirements. Fields [`id`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id), [`source`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1), [`type`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type), and at least one of `data` and `data_base64` must be present. The [`specversion`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion) is not required to be present or to equal to `1.0`. #### Permissive mode -To recognize the CloudEvents message, [`type`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) field must be present. The `Content-Type` header is not verified, and the payload is always deserialized. +In Premissive mode, the CloudEvents message [`type`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) field must be present. The `Content-Type` header is not verified, and a payload deserialization attempt is always executed. ### Binary Content Mode for HTTP and AMQP -NServiceBus supports [HTTP Binary Content Mode](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#31-binary-content-mode) and [AMQP Binary Content Mode](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md#31-binary-content-mode). +NServiceBus supports the [HTTP Binary](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#31-binary-content-mode) and [AMQP Binary](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md#31-binary-content-mode) content modes. + +To recognize the CloudEvents message, the fields [`id`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id), [`source`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1), and [`type`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) must be present. The [`specversion`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion) field is not required to be present or to equal to `1.0`. + +Field names must be encoded according to the binding specification (e.g., `ce-id` for the `id` field when using HTTP). -To recognize the CloudEvents message, fields [`id`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id), [`source`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1), and [`type`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) must be present. The [`specversion`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion) is not required to be present or to equal to `1.0`. The field names must be encoded according to the binding specification (e.g., `ce-id` for the `id` field when using HTTP). The implementation will not attempt to deserialize the payload is the headers do not meet the requirements. +The implementation will not attempt to deserialize the payload if the headers do not meet the requirements. The [HTTP Content-Type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#311-http-content-type) and [AMQP Content-Type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md#321-amqp-content-type) headers are not validated. @@ -52,7 +59,7 @@ The [HTTP Content-Type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudeve This section describes the configuration options. -### Enabling the configuration +### Enabling CloudEvents To enable the CloudEvents support: @@ -60,7 +67,7 @@ snippet: sqs-cloudevents-configuration ### Type mapping -`TypeMappings` configure how to match the incoming messages with the class definitions: +`TypeMappings` configure how to match the incoming message content-type value with the class definition used in the NServiceBus message handler: snippet: sqs-cloudevents-typemapping From 092e12890756f34d261d69e8b8484f8680970429 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 20 Jan 2026 08:31:34 +0100 Subject: [PATCH 3/9] Apply suggestions from code review --- .../operations/opentelemetry_metrics_core_[10,).partial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nservicebus/operations/opentelemetry_metrics_core_[10,).partial.md b/nservicebus/operations/opentelemetry_metrics_core_[10,).partial.md index 7dca9f5e772..c80bcd1d60f 100644 --- a/nservicebus/operations/opentelemetry_metrics_core_[10,).partial.md +++ b/nservicebus/operations/opentelemetry_metrics_core_[10,).partial.md @@ -20,7 +20,7 @@ Meter source `NServiceBus.Core.Pipeline.Incoming`: - [`nservicebus.recoverability.immediate`](/monitoring/metrics/definitions.md#metrics-captured-immediate-retries) - Total number of immediate retries requested - [`nservicebus.recoverability.delayed`](/monitoring/metrics/definitions.md#metrics-captured-delayed-retries) - Total number of delayed retries requested - [`nservicebus.recoverability.error`](/monitoring/metrics/definitions.md#metrics-captured-moved-to-error-queue) - Total number of messages sent to the error queue -- [`nservicebus.envelope.unwrapping_error`](/monitoring/metrics/definitions.md#envelope-handling-metrics) - Total number of times when an envelope handler failed to unwrap an incoming message +- [`nservicebus.envelope.uwrapped`](/monitoring/metrics/definitions.md#envelope-handling-metrics) - Total number of times when an envelope handler failed to unwrap an incoming message. Emitted for every unwrapping attempt Meter source `NServiceBus.TransactionalSession`: From 24f449521a986e9c48219e0c31d71fffe90495d0 Mon Sep 17 00:00:00 2001 From: Adam Furmanek Date: Tue, 20 Jan 2026 08:36:44 +0100 Subject: [PATCH 4/9] Updating versions --- ...).partial.md => opentelemetry_metrics_core_[10.1,).partial.md} | 0 ....partial.md => opentelemetry_metrics_core_[9,10.1).partial.md} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename nservicebus/operations/{opentelemetry_metrics_core_[10,).partial.md => opentelemetry_metrics_core_[10.1,).partial.md} (100%) rename nservicebus/operations/{opentelemetry_metrics_core_[9,10).partial.md => opentelemetry_metrics_core_[9,10.1).partial.md} (100%) diff --git a/nservicebus/operations/opentelemetry_metrics_core_[10,).partial.md b/nservicebus/operations/opentelemetry_metrics_core_[10.1,).partial.md similarity index 100% rename from nservicebus/operations/opentelemetry_metrics_core_[10,).partial.md rename to nservicebus/operations/opentelemetry_metrics_core_[10.1,).partial.md diff --git a/nservicebus/operations/opentelemetry_metrics_core_[9,10).partial.md b/nservicebus/operations/opentelemetry_metrics_core_[9,10.1).partial.md similarity index 100% rename from nservicebus/operations/opentelemetry_metrics_core_[9,10).partial.md rename to nservicebus/operations/opentelemetry_metrics_core_[9,10.1).partial.md From 8e6f012ac45dff9c68c268db4c42059f08bcfeef Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 23 Jan 2026 15:44:43 +0100 Subject: [PATCH 5/9] Apply suggestions from code review Co-authored-by: Hazel Bohon --- transports/cloudevents.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/transports/cloudevents.md b/transports/cloudevents.md index e5ed73b7976..b79e2d69cec 100644 --- a/transports/cloudevents.md +++ b/transports/cloudevents.md @@ -11,6 +11,8 @@ versions: '[10,]' This guideline shows how to receive [CloudEvents](https://cloudevents.io/) in the NServiceBus endpoints. +How are you using CLoudEvents? We want to [hear from you](https://survey.alchemer.com/s3/8658927/CloudEvents-Survey) about how CloudEvents fit into your development life cycle. + ## Supported formats This section describes [CloudEvents formats](https://github.com/cloudevents/spec/tree/v1.0.2/cloudevents/formats) supported by NServiceBus. From d12928c9130413b243579f9da400a01ae57867b1 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 23 Jan 2026 15:45:06 +0100 Subject: [PATCH 6/9] Apply suggestion from @afprtclr --- transports/cloudevents.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transports/cloudevents.md b/transports/cloudevents.md index b79e2d69cec..19f00571ec9 100644 --- a/transports/cloudevents.md +++ b/transports/cloudevents.md @@ -11,7 +11,7 @@ versions: '[10,]' This guideline shows how to receive [CloudEvents](https://cloudevents.io/) in the NServiceBus endpoints. -How are you using CLoudEvents? We want to [hear from you](https://survey.alchemer.com/s3/8658927/CloudEvents-Survey) about how CloudEvents fit into your development life cycle. +How are you using CloudEvents? We want to [hear from you](https://survey.alchemer.com/s3/8658927/CloudEvents-Survey) about how CloudEvents fit into your development life cycle. ## Supported formats From 65122687e0ba1a97eb435c344679a4934f4f2e06 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 23 Jan 2026 15:46:14 +0100 Subject: [PATCH 7/9] Apply suggestion from @mauroservienti Co-authored-by: Mauro Servienti --- transports/cloudevents.md | 1 - 1 file changed, 1 deletion(-) diff --git a/transports/cloudevents.md b/transports/cloudevents.md index 19f00571ec9..f84521bcc4c 100644 --- a/transports/cloudevents.md +++ b/transports/cloudevents.md @@ -40,7 +40,6 @@ In Strict mode, the CloudEvents message `Content-Type` header must be equal to o Fields [`id`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id), [`source`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1), [`type`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type), and at least one of `data` and `data_base64` must be present. The [`specversion`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion) is not required to be present or to equal to `1.0`. - #### Permissive mode In Premissive mode, the CloudEvents message [`type`](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) field must be present. The `Content-Type` header is not verified, and a payload deserialization attempt is always executed. From 97074c656d16c4d9534d761127433f21a962a868 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 23 Jan 2026 15:46:27 +0100 Subject: [PATCH 8/9] Apply suggestion from @mauroservienti Co-authored-by: Mauro Servienti --- transports/cloudevents.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/transports/cloudevents.md b/transports/cloudevents.md index f84521bcc4c..b7ffa3e1c61 100644 --- a/transports/cloudevents.md +++ b/transports/cloudevents.md @@ -21,8 +21,6 @@ This section describes [CloudEvents formats](https://github.com/cloudevents/spec NServiceBus supports the [JSON format](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md#3-envelope). The [JSON Batch format](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md#4-json-batch-format) is not supported. -The implementation relies on [System.Text.Json](https://learn.microsoft.com/en-us/dotnet/api/system.text.json?view=net-10.0) package to parse the JSON content. - ## Supported bindings This section describes [CloudEvents bindings](https://github.com/cloudevents/spec/tree/v1.0.2/cloudevents/bindings) supported by NServiceBus. From 4904bf423709810a64cb6f3cfcfcf282bea6e581 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 23 Jan 2026 15:46:39 +0100 Subject: [PATCH 9/9] Apply suggestion from @mauroservienti Co-authored-by: Mauro Servienti --- samples/azure-service-bus-netstandard/cloud-events/sample.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/samples/azure-service-bus-netstandard/cloud-events/sample.md b/samples/azure-service-bus-netstandard/cloud-events/sample.md index 309d0d78b4c..b174fa4f074 100644 --- a/samples/azure-service-bus-netstandard/cloud-events/sample.md +++ b/samples/azure-service-bus-netstandard/cloud-events/sample.md @@ -49,5 +49,3 @@ snippet: asb-cloudevents-serialization 1. Run the sample. 2. Generate the `BlobCreated` event by creating a new file in the Azure Blob Storage container. 3. Observe that the sample prints out the URL of the newly created file. - -