I am attempting to get Transaction Search in AWS CloudWatch up and running for our API (ASP.NET WebAPI).
I'm using the .NET AWS SDK and have XRay configured as follows:
public class WebApiApplication : System.Web.HttpApplication
{
public override void Init()
{
base.Init();
AWSXRayASPNET.RegisterXRay(this, "MyAPI");
}
}
I have switched on Transaction Search from CloudWatch settings, so see Ingest OpenTelemetry spans: Enabled. This means under Application Signals I can now go into Transaction Search and view the spans, and can also see my services on the Service Map.
However, when I go into "MyAPI" under Services, I see that there is only one operation under Service Operations. Our API structure has a version number in the path (e.g. https://api.mycompany.com/1.0/Products/1234 or https://api.mycompany.com/1.0/Customers/5678), so the auto-instrumentation has grouped all the different operations under a single operation called "1.0".
What I am really struggling to find any documentation about is how to control/configure that instrumentation. Ideally I would like the operations to be segregated by a part further up the URL e.g. Products or Customers in the example above, or even better full control per URL. I cannot find anything that explains how this works.
Does anyone know?
Edit:
I'm still struggling to understand what is happening with the Operation names in Application Signals.
I have reduced the issue to a very small example:
I have taken a local copy of https://github.com/aws/aws-xray-sdk-dotnet/tree/master and used it to debug a brand new empty .NET Core Web API project instrumented with app.UseXRay("NetCoreAppV2");
I have stepped through and captured the data being sent from the XRay SDK to the Daemon, running locally on my dev machine (1 below).
I then captured this using CloudWatch LiveTail (2 below).
I can see that the data is transformed somewhere on the way, and I do not understand where.
What I am trying to understand is where the operation name "GET /WeatherForecast" comes from.
You can see in (1) below, that the data captured and sent by the XRay SDK does not include this string at all. However (2) contains it in both the "name" and "attributes>aws.local.operation" fields. Something is transforming the data and extracting the operation name - but I cannot work out what.
Almost all of the telemetry in Application Signals is broken down by Operation, so it is key for us that we have some logical structure in the names. In this documentation, you can see the AWS example with Operations multiple levels deep, and structured in a logical way. This is what we want. https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Services-page.html#services-top-metrics
- Sent by XRay SDK:
{
"trace_id": "1-683ef3fb-75a22ea1a5619c2a6b83eb79",
"id": "2380ecbf2e67ae3e",
"start_time": 1748956155.89096,
"end_time": 1748956168.55406,
"name": "NetCoreAppV2",
"aws": {
"xray": {
"sdk_version": "2.15.0",
"sdk": "X-Ray for .NET Core",
"sampling_rule_name": "Default"
}
},
"http": {
"request": {
"url": "https://localhost:7198/WeatherForecast/Testing/124 ",
"method": "GET",
"client_ip": "::1",
"user_agent": "PostmanRuntime/7.44.0"
},
"response": {
"status": 200
}
},
"service": {
"runtime_version": "8.0.16",
"runtime": ".NET Core Framework"
}
}
- Received by CloudWatch (LiveTail), going into the aws/spans log group:
{
"resource": {
"attributes": {
"service.name": "NetCoreAppV2",
"cloud.provider": "aws"
}
},
"traceId": "683ef3fb75a22ea1a5619c2a6b83eb79",
"spanId": "2380ecbf2e67ae3e",
"name": "GET /WeatherForecast",
"kind": "SERVER",
"startTimeUnixNano": 1748956155890961920,
"endTimeUnixNano": 1748956168554057984,
"durationNano": 12663096064,
"attributes": {
"user_agent.original": "PostmanRuntime/7.44.0",
"aws.local.service": "NetCoreAppV2",
"telemetry.extended": "true",
"http.url": "https://localhost:7198/WeatherForecast/Testing/124 ",
"http.client_ip": "::1",
"aws.local.environment": "generic:default",
"client.address": "::1",
"http.status_code": 200,
"aws.local.operation": "GET /WeatherForecast",
"aws.span.kind": "LOCAL_ROOT",
"http.request.method": "GET",
"http.user_agent": "PostmanRuntime/7.44.0",
"aws.xray": {
"sampling_rule_name": "Default",
"sdk_version": "2.15.0",
"sdk": "X-Ray for .NET Core"
},
"PlatformType": "Generic",
"http.method": "GET",
"url.full": "https://localhost:7198/WeatherForecast/Testing/124 ",
"http.response.status_code": 200
},
"status": {
"code": "UNSET"
},
"_aws": {
"xray": {
"name": "NetCoreAppV2",
"type": "segment"
}
}
}