diff --git a/.changesets/docs_eh_instrumentation_examples.md b/.changesets/docs_eh_instrumentation_examples.md new file mode 100644 index 0000000000..040fe32d24 --- /dev/null +++ b/.changesets/docs_eh_instrumentation_examples.md @@ -0,0 +1,5 @@ +### Add instrumentation configuration examples ([PR #6487](https://github.com/apollographql/router/pull/6487)) + +The docs for router telemetry have new example configurations for common use cases for [selectors](https://www.apollographql.com/docs/graphos/reference/router/telemetry/instrumentation/selectors) and [condition](https://www.apollographql.com/docs/graphos/reference/router/telemetry/instrumentation/conditions). + +By [@shorgi](https://github.com/shorgi) in https://github.com/apollographql/router/pull/6487 \ No newline at end of file diff --git a/docs/source/reference/router/telemetry/instrumentation/conditions.mdx b/docs/source/reference/router/telemetry/instrumentation/conditions.mdx index e98316df27..79ed89b061 100644 --- a/docs/source/reference/router/telemetry/instrumentation/conditions.mdx +++ b/docs/source/reference/router/telemetry/instrumentation/conditions.mdx @@ -154,3 +154,77 @@ The available basic conditions: | `any` | A list of conditions of which at least one must be true | You can create complex conditions by using these basic conditions as building blocks. + +## Example condition configurations + +Some example configuration of common use cases for conditions. + +### Event for a specific subgraph + +You can trigger an event for a specific subgraph by configuring a condition with the subgraph's name. + +The example below uses the [`subgraph_name`](/router/configuration/telemetry/instrumentation/selectors#subgraph) selector to log subgraph responses for the subgraph named "products": + +```yaml title=router.yaml +telemetry: + instrumentation: + events: + subgraph: + response: + level: info + condition: + eq: + - subgraph_name: true + - "products" +``` + +### On GraphQL error + +You can use the [`on_graphql_error`](/router/configuration/telemetry/instrumentation/selectors#supergraph) selector to create a condition based on whether or not a GraphQL error is present. + +The example configuration below uses `on_graphql_error` to log only supergraph responses that contain GraphQL errors: + +```yaml title="router.yaml" +telemetry: + instrumentation: + events: + router: + request: + level: info + condition: # Only log the router request if you sent `x-log-request` with the value `enabled` + eq: + - request_header: x-log-request + - "enabled" + response: off + error: error + supergraph: + response: + level: info + condition: # Only log supergraph response containing GraphQL errors + eq: + - on_graphql_error: true + - true + error: error +``` + +### On large payloads + +For observability of large payloads, you can set attributes using conditions that indicate whether the length of a request or response exceeds a threshold. + +The example below sets a custom attribute to `true` if the length of a request is greater than 100: + +```yaml +telemetry: + instrumentation: + spans: + mode: spec_compliant + router: + attributes: + trace_id: true + payload_is_to_big: # Set this attribute to true if the value of content-length header is > than 100 + static: true + condition: + gt: + - request_header: "content-length" + - 100 +``` diff --git a/docs/source/reference/router/telemetry/instrumentation/selectors.mdx b/docs/source/reference/router/telemetry/instrumentation/selectors.mdx index 828ee39b65..02a8867e54 100644 --- a/docs/source/reference/router/telemetry/instrumentation/selectors.mdx +++ b/docs/source/reference/router/telemetry/instrumentation/selectors.mdx @@ -13,6 +13,7 @@ An example of a selector, `request_header`, of the router service on a custom sp telemetry: instrumentation: spans: + mode: spec_compliant router: attributes: "my_attribute": @@ -31,17 +32,17 @@ The router service is the initial entrypoint for all requests. It is HTTP centri | Selector | Defaultable | Values | Description | |-----------------------|-------------|-----------------------------|----------------------------------------------------------------------| -| `trace_id` | Yes | `open_telemetry`\|`datadog` | The trace ID | -| `operation_name` | Yes | `string`\|`hash` | The operation name from the query | -| `studio_operation_id` | Yes | `true`\|`false` | The Apollo Studio operation id | +| `trace_id` | Yes | `open_telemetry` \| `datadog` | The trace ID | +| `operation_name` | Yes | `string` \| `hash` | The operation name from the query | +| `studio_operation_id` | Yes | `true` \| `false` | The Apollo Studio operation id | | `request_header` | Yes | | The name of the request header | | `request_context` | Yes | | The name of a request context key | | `response_header` | Yes | | The name of a response header | -| `response_status` | Yes | `code`\|`reason` | The response status | +| `response_status` | Yes | `code` \| `reason` | The response status | | `response_context` | Yes | | The name of a response context key | | `baggage` | Yes | | The name of a baggage item | | `env` | Yes | | The name of an environment variable | -| `on_graphql_error` | No | `true`\|`false` | Boolean set to true if the response payload contains a GraphQL error | +| `on_graphql_error` | No | `true` \| `false` | Boolean set to true if the response payload contains a GraphQL error | | `static` | No | | A static string value | | `error` | No | `reason` | a string value containing error reason when it's a critical error | @@ -51,18 +52,18 @@ The supergraph service is executed after query parsing but before query executio | Selector | Defaultable | Values | Description | |--------------------|-------------|-------------------------------------------------------|-----------------------------------------------------------------------------------| -| `operation_name` | Yes | `string`\|`hash` | The operation name from the query | +| `operation_name` | Yes | `string` \| `hash` | The operation name from the query | | `operation_kind` | No | `string` | The operation kind from the query | -| `query` | Yes | `string`\|`aliases`\|`depth`\|`height`\|`root_fields` | The GraphQL query | +| `query` | Yes | `string` \| `aliases` \| `depth` \| `height` \| `root_fields` | The GraphQL query | | `query_variable` | Yes | | The name of a GraphQL query variable | | `request_header` | Yes | | The name of a request header | | `response_header` | Yes | | The name of a response header | -| `is_primary_response` | No | `true`\|`false` | Boolean returning true if it's the primary response and not events like subscription events or deferred responses | +| `is_primary_response` | No | `true` \| `false` | Boolean returning true if it's the primary response and not events like subscription events or deferred responses | | `response_data` | Yes | | JSON Path into the supergraph response body data (it might impact performance) | | `response_errors` | Yes | | JSON Path into the supergraph response body errors (it might impact performance) | | `request_context` | Yes | | The name of a request context key | | `response_context` | Yes | | The name of a response context key | -| `on_graphql_error` | No | `true`\|`false` | Boolean set to true if the response payload contains a GraphQL error | +| `on_graphql_error` | No | `true` \| `false` | Boolean set to true if the response payload contains a GraphQL error | | `baggage` | Yes | | The name of a baggage item | | `env` | Yes | | The name of an environment variable | | `static` | No | | A static string value | @@ -74,30 +75,30 @@ The subgraph service executes multiple times during query execution, with each e | Selector | Defaultable | Values | Description | |-----------------------------|-------------|------------------|--------------------------------------------------------------------------------| -| `subgraph_operation_name` | Yes | `string`\|`hash` | The operation name from the subgraph query | +| `subgraph_operation_name` | Yes | `string` \| `hash` | The operation name from the subgraph query | | `subgraph_operation_kind` | No | `string` | The operation kind from the subgraph query | | `subgraph_query` | Yes | `string` | The GraphQL query to the subgraph | -| `subgraph_name` | No | `true`\|`false` | The subgraph name | +| `subgraph_name` | No | `true` \| `false` | The subgraph name | | `subgraph_query_variable` | Yes | | The name of a subgraph query variable | | `subgraph_response_data` | Yes | | JSON Path into the subgraph response body data (it might impact performance) | | `subgraph_response_errors` | Yes | | JSON Path into the subgraph response body errors (it might impact performance) | | `subgraph_request_header` | Yes | | The name of a subgraph request header | | `subgraph_response_header` | Yes | | The name of a subgraph response header | -| `subgraph_response_status` | Yes | `code`\|`reason` | The status of a subgraph response | -| `subgraph_on_graphql_error` | No | `true`\|`false` | Boolean set to true if the subgraph response payload contains a GraphQL error | -| `supergraph_operation_name` | Yes | `string`\|`hash` | The operation name from the supergraph query | +| `subgraph_response_status` | Yes | `code` \| `reason` | The status of a subgraph response | +| `subgraph_on_graphql_error` | No | `true` \| `false` | Boolean set to true if the subgraph response payload contains a GraphQL error | +| `supergraph_operation_name` | Yes | `string` \| `hash` | The operation name from the supergraph query | | `supergraph_operation_kind` | Yes | `string` | The operation kind from the supergraph query | | `supergraph_query` | Yes | `string` | The graphql query to the supergraph | | `supergraph_query_variable` | Yes | | The name of a supergraph query variable | | `supergraph_request_header` | Yes | | The name of a supergraph request header | -| `subgraph_resend_count` | Yes | `true`\|`false` | Number of retries for an http request to a subgraph | +| `subgraph_resend_count` | Yes | `true` \| `false` | Number of retries for an http request to a subgraph | | `request_context` | Yes | | The name of a request context key | | `response_context` | Yes | | The name of a response context key | | `baggage` | Yes | | The name of a baggage item | | `env` | Yes | | The name of an environment variable | | `static` | No | | A static string value | | `error` | No | `reason` | A string value containing error reason when it's a critical error | -| `cache` | No | `hit`\|`miss` | Returns the number of cache hit or miss for this subgraph request | +| `cache` | No | `hit` \| `miss` | Returns the number of cache hit or miss for this subgraph request | ### GraphQL @@ -109,5 +110,111 @@ GraphQL metrics are extracted from the response data the router returns to clien | `field_name` | No | `string` | The name of a field from the response data | | `field_type` | No | `string` | The type of a field from the response data | | `type_name` | No | | The GraphQL type from the response data | -| `operation_name` | Yes | `string`\|`hash` | The operation name of the query | +| `operation_name` | Yes | `string` \| `hash` | The operation name of the query | | `static` | No | | A static string value | + + +## Example selector configurations + +Some example configurations of common use cases for selectors: + +### Configuring trace ID + +Logging the trace ID of a request that has GraphQL errors: + +```yaml title="router.yaml" +telemetry: + instrumentation: + events: + router: + my.event: + message: 'An event occurred' + level: error + on: response + condition: + eq: + - on_graphql_error: true + - true + attributes: + # The trace ID from the request + id_from_header: + trace_id: open_telemetry +``` + +### Setting JSON paths + +Configuring selectors with JSON paths, such as supergraph `response_data` and `response_errors`: + +```yaml title="router.yaml" +telemetry: + exporters: + metrics: + prometheus: + enabled: true + instrumentation: + instruments: + supergraph: + my.request.on_graphql_error: + value: event_unit + type: counter + unit: error + description: my description + condition: + exists: + response_errors: "$.[0].extensions.code" + attributes: + response_errors: + response_errors: "$.[0].extensions.code" +``` + +### Getting GraphQL operation info + +Configuring the `query` selector to get information about GraphQL operations, with an example for a custom view of operation limits: + +```yaml +telemetry: + exporters: + metrics: + common: + views: + # Define a custom view because operation limits are different than the default latency-oriented view of OpenTelemetry + - name: oplimits.* + aggregation: + histogram: + buckets: + - 0 + - 5 + - 10 + - 25 + - 50 + - 100 + - 500 + - 1000 + instrumentation: + instruments: + supergraph: + oplimits.aliases: + value: + query: aliases + type: histogram + unit: number + description: "Aliases for an operation" + oplimits.depth: + value: + query: depth + type: histogram + unit: number + description: "Depth for an operation" + oplimits.height: + value: + query: height + type: histogram + unit: number + description: "Height for an operation" + oplimits.root_fields: + value: + query: root_fields + type: histogram + unit: number + description: "Root fields for an operation" +```