diff --git a/.changesets/feat_bnjjj_feat_4319.md b/.changesets/feat_bnjjj_feat_4319.md new file mode 100644 index 0000000000..e765d0095c --- /dev/null +++ b/.changesets/feat_bnjjj_feat_4319.md @@ -0,0 +1,43 @@ +### Add support of instruments in configuration for telemetry ([Issue #4319](https://github.com/apollographql/router/issues/4319)) + +Add support for custom and standard instruments through the configuration file. You'll be able to add your own custom metrics just using the configuration file. They may: +- be conditional +- get values from selectors, for instance headers, context or body +- have different types like `histogram` or `counter`. + +Example: + +```yaml title="router.yaml" +telemetry: + instrumentation: + instruments: + router: + http.server.active_requests: true + acme.request.duration: + value: duration + type: counter + unit: kb + description: "my description" + attributes: + http.response.status_code: true + "my_attribute": + response_header: "x-my-header" + + supergraph: + acme.graphql.requests: + value: unit + type: counter + unit: count + description: "supergraph requests" + + subgraph: + acme.graphql.subgraph.errors: + value: unit + type: counter + unit: count + description: "my description" +``` + +[Documentation](https://www.apollographql.com/docs/router/configuration/telemetry/instrumentation/instruments) + +By [@bnjjj](https://github.com/bnjjj) in https://github.com/apollographql/router/pull/4771 \ No newline at end of file diff --git a/apollo-router/src/configuration/metrics.rs b/apollo-router/src/configuration/metrics.rs index 8d42c9b1ef..093675a010 100644 --- a/apollo-router/src/configuration/metrics.rs +++ b/apollo-router/src/configuration/metrics.rs @@ -307,6 +307,14 @@ impl InstrumentData { "$..events", opt.instruments, "$..instruments", + opt.instruments.router, + "$..instruments.router", + opt.instruments.supergraph, + "$..instruments.supergraph", + opt.instruments.subgraph, + "$..instruments.subgraph", + opt.instruments.default_attribute_requirement_level, + "$..instruments.default_attribute_requirement_level", opt.spans, "$..spans", opt.spans.mode, diff --git a/apollo-router/src/configuration/snapshots/apollo_router__configuration__metrics__test__metrics@telemetry.router.yaml.snap b/apollo-router/src/configuration/snapshots/apollo_router__configuration__metrics__test__metrics@telemetry.router.yaml.snap index 0e904afcdc..842ddd0340 100644 --- a/apollo-router/src/configuration/snapshots/apollo_router__configuration__metrics__test__metrics@telemetry.router.yaml.snap +++ b/apollo-router/src/configuration/snapshots/apollo_router__configuration__metrics__test__metrics@telemetry.router.yaml.snap @@ -8,7 +8,11 @@ expression: "&metrics.non_zero()" - value: 1 attributes: opt.events: false - opt.instruments: false + opt.instruments: true + opt.instruments.default_attribute_requirement_level: false + opt.instruments.router: true + opt.instruments.subgraph: true + opt.instruments.supergraph: true opt.logging.experimental_when_header: true opt.metrics.otlp: true opt.metrics.prometheus: true diff --git a/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap b/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap index f45def97f7..98ebb36d81 100644 --- a/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap +++ b/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap @@ -6673,12 +6673,12 @@ expression: "&schema" "description": "Instrumentation configuration", "type": "object", "properties": { - "spans": { - "description": "Span configuration", + "instruments": { + "description": "Instrument configuration", "type": "object", "properties": { - "default_attribute_requirement_level": { - "description": "The attributes to include by default in spans based on their level as specified in the otel semantic conventions and Apollo documentation.", + "default_requirement_level": { + "description": "The attributes and instruments to include by default in instruments based on their level as specified in the otel semantic conventions and Apollo documentation.", "oneOf": [ { "description": "No default attributes set on spans, you have to set it one by one in the configuration to enable some attributes", @@ -6703,2364 +6703,18250 @@ expression: "&schema" } ] }, - "mode": { - "description": "Use new OpenTelemetry spec compliant span attributes or preserve existing. This will be defaulted in future to `spec_compliant`, eventually removed in future.", - "oneOf": [ - { - "description": "Keep the request span as root span and deprecated attributes. This option will eventually removed.", - "type": "string", - "enum": [ - "deprecated" - ] - }, - { - "description": "Use new OpenTelemetry spec compliant span attributes or preserve existing. This will be the default in future.", - "type": "string", - "enum": [ - "spec_compliant" - ] - } - ] - }, "router": { - "description": "Configuration of router spans. Log events inherit attributes from the containing span, so attributes configured here will be included on log events for a request. Router spans contain http request and response information and therefore contain http specific attributes.", + "description": "Router service instruments. For more information see documentation on Router lifecycle.", "type": "object", "properties": { - "attributes": { - "description": "Custom attributes that are attached to the router span.", - "type": "object", - "properties": { - "baggage": { - "description": "All key values from trace baggage.", - "default": null, - "type": "boolean", - "nullable": true - }, - "dd.trace_id": { - "description": "The datadog trace ID. This can be output in logs and used to correlate traces in Datadog.", - "default": null, - "type": "boolean", - "nullable": true - }, - "error.type": { - "description": "Describes a class of error the operation ended with. Examples: * timeout * name_resolution_error * 500 Requirement level: Conditionally Required: If request has ended with an error.", - "default": null, - "type": "boolean", - "nullable": true - }, - "http.request.body.size": { - "description": "The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true - }, - "http.request.method": { - "description": "HTTP request method. Examples: * GET * POST * HEAD Requirement level: Required", - "default": null, - "type": "boolean", - "nullable": true - }, - "http.response.body.size": { - "description": "The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true - }, - "http.response.status_code": { - "description": "HTTP response status code. Examples: * 200 Requirement level: Conditionally Required: If and only if one was received/sent.", - "default": null, - "type": "boolean", - "nullable": true - }, - "http.route": { - "description": "The matched route (path template in the format used by the respective server framework). Examples: * /graphql Requirement level: Conditionally Required: If and only if it’s available", - "default": null, - "type": "boolean", - "nullable": true - }, - "network.local.address": { - "description": "Local socket address. Useful in case of a multi-IP host. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Opt-In", - "default": null, - "type": "boolean", - "nullable": true - }, - "network.local.port": { - "description": "Local socket port. Useful in case of a multi-port host. Examples: * 65123 Requirement level: Opt-In", - "default": null, - "type": "boolean", - "nullable": true - }, - "network.peer.address": { - "description": "Peer address of the network connection - IP address or Unix domain socket name. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true - }, - "network.peer.port": { - "description": "Peer port number of the network connection. Examples: * 65123 Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true - }, - "network.protocol.name": { - "description": "OSI application layer or non-OSI equivalent. Examples: * http * spdy Requirement level: Recommended: if not default (http).", - "default": null, - "type": "boolean", - "nullable": true - }, - "network.protocol.version": { - "description": "Version of the protocol specified in network.protocol.name. Examples: * 1.0 * 1.1 * 2 * 3 Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true - }, - "network.transport": { - "description": "OSI transport layer. Examples: * tcp * udp Requirement level: Conditionally Required", - "default": null, - "type": "boolean", - "nullable": true - }, - "network.type": { - "description": "OSI network layer or non-OSI equivalent. Examples: * ipv4 * ipv6 Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true - }, - "server.address": { - "description": "Name of the local HTTP server that received the request. Examples: * example.com * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true - }, - "server.port": { - "description": "Port of the local HTTP server that received the request. Examples: * 80 * 8080 * 443 Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true - }, - "trace_id": { - "description": "The OpenTelemetry trace ID. This can be output in logs.", - "default": null, - "type": "boolean", - "nullable": true + "http.server.active_requests": { + "description": "Counter of active requests", + "anyOf": [ + { + "type": "null" }, - "url.path": { - "description": "The URI path component Examples: * /search Requirement level: Required", - "default": null, - "type": "boolean", - "nullable": true + { + "type": "boolean" }, - "url.query": { - "description": "The URI query component Examples: * q=OpenTelemetry Requirement level: Conditionally Required: If and only if one was received/sent.", - "default": null, - "type": "boolean", - "nullable": true + { + "type": "object", + "required": [ + "attributes" + ], + "properties": { + "attributes": { + "type": "object", + "properties": { + "http.request.method": { + "default": false, + "type": "boolean" + }, + "server.address": { + "default": false, + "type": "boolean" + }, + "server.port": { + "default": false, + "type": "boolean" + }, + "url.scheme": { + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "http.server.request.body.size": { + "description": "Histogram of server request body size", + "anyOf": [ + { + "type": "null" }, - "url.scheme": { - "description": "The URI scheme component identifying the used protocol. Examples: * http * https Requirement level: Required", - "default": null, - "type": "boolean", - "nullable": true + { + "type": "boolean" }, - "user_agent.original": { - "description": "Value of the HTTP User-Agent header sent by the client. Examples: * CERN-LineMode/2.15 * libwww/2.17b3 Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true - } - }, - "additionalProperties": { - "anyOf": [ - { - "description": "A header from the request", - "type": "object", - "required": [ - "request_header" - ], - "properties": { - "default": { - "description": "Optional default value.", - "anyOf": [ - { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" - }, - { - "description": "f64 values", - "type": "number", - "format": "double" - }, - { - "description": "String values", - "type": "string" - }, - { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } + { + "type": "object", + "required": [ + "attributes" + ], + "properties": { + "attributes": { + "description": "Common attributes for http server and client. See https://opentelemetry.io/docs/specs/semconv/http/http-spans/#common-attributes", + "type": "object", + "properties": { + "baggage": { + "description": "All key values from trace baggage.", + "default": null, + "type": "boolean", + "nullable": true + }, + "dd.trace_id": { + "description": "The datadog trace ID. This can be output in logs and used to correlate traces in Datadog.", + "default": null, + "type": "boolean", + "nullable": true + }, + "error.type": { + "description": "Describes a class of error the operation ended with. Examples: * timeout * name_resolution_error * 500 Requirement level: Conditionally Required: If request has ended with an error.", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.request.body.size": { + "description": "The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.request.method": { + "description": "HTTP request method. Examples: * GET * POST * HEAD Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.response.body.size": { + "description": "The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.response.status_code": { + "description": "HTTP response status code. Examples: * 200 Requirement level: Conditionally Required: If and only if one was received/sent.", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.route": { + "description": "The matched route (path template in the format used by the respective server framework). Examples: * /graphql Requirement level: Conditionally Required: If and only if it’s available", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.local.address": { + "description": "Local socket address. Useful in case of a multi-IP host. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Opt-In", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.local.port": { + "description": "Local socket port. Useful in case of a multi-port host. Examples: * 65123 Requirement level: Opt-In", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.peer.address": { + "description": "Peer address of the network connection - IP address or Unix domain socket name. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.peer.port": { + "description": "Peer port number of the network connection. Examples: * 65123 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.protocol.name": { + "description": "OSI application layer or non-OSI equivalent. Examples: * http * spdy Requirement level: Recommended: if not default (http).", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.protocol.version": { + "description": "Version of the protocol specified in network.protocol.name. Examples: * 1.0 * 1.1 * 2 * 3 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.transport": { + "description": "OSI transport layer. Examples: * tcp * udp Requirement level: Conditionally Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.type": { + "description": "OSI network layer or non-OSI equivalent. Examples: * ipv4 * ipv6 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "server.address": { + "description": "Name of the local HTTP server that received the request. Examples: * example.com * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "server.port": { + "description": "Port of the local HTTP server that received the request. Examples: * 80 * 8080 * 443 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "trace_id": { + "description": "The OpenTelemetry trace ID. This can be output in logs.", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.path": { + "description": "The URI path component Examples: * /search Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.query": { + "description": "The URI query component Examples: * q=OpenTelemetry Requirement level: Conditionally Required: If and only if one was received/sent.", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.scheme": { + "description": "The URI scheme component identifying the used protocol. Examples: * http * https Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "user_agent.original": { + "description": "Value of the HTTP User-Agent header sent by the client. Examples: * CERN-LineMode/2.15 * libwww/2.17b3 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "description": "A header from the request", + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" } - ] + }, + "additionalProperties": false + }, + { + "description": "The request method.", + "type": "object", + "required": [ + "request_method" + ], + "properties": { + "request_method": { + "description": "The request method enabled or not", + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "description": "A header from the response", + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "The trace ID of the request.", + "type": "object", + "required": [ + "trace_id" + ], + "properties": { + "trace_id": { + "description": "The format of the trace ID.", + "oneOf": [ + { + "description": "Open Telemetry trace ID, a hex string.", + "type": "string", + "enum": [ + "open_telemetry" + ] + }, + { + "description": "Datadog trace ID, a u64.", + "type": "string", + "enum": [ + "datadog" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "A value from context.", + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A value from baggage.", + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "description": "A value from an environment variable.", + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + } + }, + "additionalProperties": false + } + ] + }, + "http.server.request.duration": { + "description": "Histogram of server request duration", + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "required": [ + "attributes" + ], + "properties": { + "attributes": { + "description": "Common attributes for http server and client. See https://opentelemetry.io/docs/specs/semconv/http/http-spans/#common-attributes", + "type": "object", + "properties": { + "baggage": { + "description": "All key values from trace baggage.", + "default": null, + "type": "boolean", + "nullable": true + }, + "dd.trace_id": { + "description": "The datadog trace ID. This can be output in logs and used to correlate traces in Datadog.", + "default": null, + "type": "boolean", + "nullable": true + }, + "error.type": { + "description": "Describes a class of error the operation ended with. Examples: * timeout * name_resolution_error * 500 Requirement level: Conditionally Required: If request has ended with an error.", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.request.body.size": { + "description": "The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.request.method": { + "description": "HTTP request method. Examples: * GET * POST * HEAD Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.response.body.size": { + "description": "The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.response.status_code": { + "description": "HTTP response status code. Examples: * 200 Requirement level: Conditionally Required: If and only if one was received/sent.", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.route": { + "description": "The matched route (path template in the format used by the respective server framework). Examples: * /graphql Requirement level: Conditionally Required: If and only if it’s available", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.local.address": { + "description": "Local socket address. Useful in case of a multi-IP host. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Opt-In", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.local.port": { + "description": "Local socket port. Useful in case of a multi-port host. Examples: * 65123 Requirement level: Opt-In", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.peer.address": { + "description": "Peer address of the network connection - IP address or Unix domain socket name. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.peer.port": { + "description": "Peer port number of the network connection. Examples: * 65123 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.protocol.name": { + "description": "OSI application layer or non-OSI equivalent. Examples: * http * spdy Requirement level: Recommended: if not default (http).", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.protocol.version": { + "description": "Version of the protocol specified in network.protocol.name. Examples: * 1.0 * 1.1 * 2 * 3 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.transport": { + "description": "OSI transport layer. Examples: * tcp * udp Requirement level: Conditionally Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.type": { + "description": "OSI network layer or non-OSI equivalent. Examples: * ipv4 * ipv6 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "server.address": { + "description": "Name of the local HTTP server that received the request. Examples: * example.com * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "server.port": { + "description": "Port of the local HTTP server that received the request. Examples: * 80 * 8080 * 443 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "trace_id": { + "description": "The OpenTelemetry trace ID. This can be output in logs.", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.path": { + "description": "The URI path component Examples: * /search Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.query": { + "description": "The URI query component Examples: * q=OpenTelemetry Requirement level: Conditionally Required: If and only if one was received/sent.", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.scheme": { + "description": "The URI scheme component identifying the used protocol. Examples: * http * https Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "user_agent.original": { + "description": "Value of the HTTP User-Agent header sent by the client. Examples: * CERN-LineMode/2.15 * libwww/2.17b3 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "description": "A header from the request", + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "The request method.", + "type": "object", + "required": [ + "request_method" + ], + "properties": { + "request_method": { + "description": "The request method enabled or not", + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "description": "A header from the response", + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "The trace ID of the request.", + "type": "object", + "required": [ + "trace_id" + ], + "properties": { + "trace_id": { + "description": "The format of the trace ID.", + "oneOf": [ + { + "description": "Open Telemetry trace ID, a hex string.", + "type": "string", + "enum": [ + "open_telemetry" + ] + }, + { + "description": "Datadog trace ID, a u64.", + "type": "string", + "enum": [ + "datadog" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "A value from context.", + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A value from baggage.", + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "description": "A value from an environment variable.", + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + } + }, + "additionalProperties": false + } + ] + }, + "http.server.response.body.size": { + "description": "Histogram of server response body size", + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "required": [ + "attributes" + ], + "properties": { + "attributes": { + "description": "Common attributes for http server and client. See https://opentelemetry.io/docs/specs/semconv/http/http-spans/#common-attributes", + "type": "object", + "properties": { + "baggage": { + "description": "All key values from trace baggage.", + "default": null, + "type": "boolean", + "nullable": true + }, + "dd.trace_id": { + "description": "The datadog trace ID. This can be output in logs and used to correlate traces in Datadog.", + "default": null, + "type": "boolean", + "nullable": true + }, + "error.type": { + "description": "Describes a class of error the operation ended with. Examples: * timeout * name_resolution_error * 500 Requirement level: Conditionally Required: If request has ended with an error.", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.request.body.size": { + "description": "The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.request.method": { + "description": "HTTP request method. Examples: * GET * POST * HEAD Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.response.body.size": { + "description": "The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.response.status_code": { + "description": "HTTP response status code. Examples: * 200 Requirement level: Conditionally Required: If and only if one was received/sent.", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.route": { + "description": "The matched route (path template in the format used by the respective server framework). Examples: * /graphql Requirement level: Conditionally Required: If and only if it’s available", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.local.address": { + "description": "Local socket address. Useful in case of a multi-IP host. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Opt-In", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.local.port": { + "description": "Local socket port. Useful in case of a multi-port host. Examples: * 65123 Requirement level: Opt-In", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.peer.address": { + "description": "Peer address of the network connection - IP address or Unix domain socket name. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.peer.port": { + "description": "Peer port number of the network connection. Examples: * 65123 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.protocol.name": { + "description": "OSI application layer or non-OSI equivalent. Examples: * http * spdy Requirement level: Recommended: if not default (http).", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.protocol.version": { + "description": "Version of the protocol specified in network.protocol.name. Examples: * 1.0 * 1.1 * 2 * 3 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.transport": { + "description": "OSI transport layer. Examples: * tcp * udp Requirement level: Conditionally Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.type": { + "description": "OSI network layer or non-OSI equivalent. Examples: * ipv4 * ipv6 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "server.address": { + "description": "Name of the local HTTP server that received the request. Examples: * example.com * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "server.port": { + "description": "Port of the local HTTP server that received the request. Examples: * 80 * 8080 * 443 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "trace_id": { + "description": "The OpenTelemetry trace ID. This can be output in logs.", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.path": { + "description": "The URI path component Examples: * /search Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.query": { + "description": "The URI query component Examples: * q=OpenTelemetry Requirement level: Conditionally Required: If and only if one was received/sent.", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.scheme": { + "description": "The URI scheme component identifying the used protocol. Examples: * http * https Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "user_agent.original": { + "description": "Value of the HTTP User-Agent header sent by the client. Examples: * CERN-LineMode/2.15 * libwww/2.17b3 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "description": "A header from the request", + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "The request method.", + "type": "object", + "required": [ + "request_method" + ], + "properties": { + "request_method": { + "description": "The request method enabled or not", + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "description": "A header from the response", + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "The trace ID of the request.", + "type": "object", + "required": [ + "trace_id" + ], + "properties": { + "trace_id": { + "description": "The format of the trace ID.", + "oneOf": [ + { + "description": "Open Telemetry trace ID, a hex string.", + "type": "string", + "enum": [ + "open_telemetry" + ] + }, + { + "description": "Datadog trace ID, a u64.", + "type": "string", + "enum": [ + "datadog" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "A value from context.", + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A value from baggage.", + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "description": "A value from an environment variable.", + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + } + }, + "additionalProperties": false + } + ] + } + }, + "additionalProperties": { + "type": "object", + "required": [ + "description", + "type", + "unit", + "value" + ], + "properties": { + "attributes": { + "description": "Attributes to include on the instrument.", + "type": "object", + "properties": { + "baggage": { + "description": "All key values from trace baggage.", + "default": null, + "type": "boolean", + "nullable": true + }, + "dd.trace_id": { + "description": "The datadog trace ID. This can be output in logs and used to correlate traces in Datadog.", + "default": null, + "type": "boolean", + "nullable": true + }, + "error.type": { + "description": "Describes a class of error the operation ended with. Examples: * timeout * name_resolution_error * 500 Requirement level: Conditionally Required: If request has ended with an error.", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.request.body.size": { + "description": "The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.request.method": { + "description": "HTTP request method. Examples: * GET * POST * HEAD Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.response.body.size": { + "description": "The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.response.status_code": { + "description": "HTTP response status code. Examples: * 200 Requirement level: Conditionally Required: If and only if one was received/sent.", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.route": { + "description": "The matched route (path template in the format used by the respective server framework). Examples: * /graphql Requirement level: Conditionally Required: If and only if it’s available", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.local.address": { + "description": "Local socket address. Useful in case of a multi-IP host. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Opt-In", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.local.port": { + "description": "Local socket port. Useful in case of a multi-port host. Examples: * 65123 Requirement level: Opt-In", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.peer.address": { + "description": "Peer address of the network connection - IP address or Unix domain socket name. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.peer.port": { + "description": "Peer port number of the network connection. Examples: * 65123 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.protocol.name": { + "description": "OSI application layer or non-OSI equivalent. Examples: * http * spdy Requirement level: Recommended: if not default (http).", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.protocol.version": { + "description": "Version of the protocol specified in network.protocol.name. Examples: * 1.0 * 1.1 * 2 * 3 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.transport": { + "description": "OSI transport layer. Examples: * tcp * udp Requirement level: Conditionally Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.type": { + "description": "OSI network layer or non-OSI equivalent. Examples: * ipv4 * ipv6 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "server.address": { + "description": "Name of the local HTTP server that received the request. Examples: * example.com * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "server.port": { + "description": "Port of the local HTTP server that received the request. Examples: * 80 * 8080 * 443 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "trace_id": { + "description": "The OpenTelemetry trace ID. This can be output in logs.", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.path": { + "description": "The URI path component Examples: * /search Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.query": { + "description": "The URI query component Examples: * q=OpenTelemetry Requirement level: Conditionally Required: If and only if one was received/sent.", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.scheme": { + "description": "The URI scheme component identifying the used protocol. Examples: * http * https Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "user_agent.original": { + "description": "Value of the HTTP User-Agent header sent by the client. Examples: * CERN-LineMode/2.15 * libwww/2.17b3 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "description": "A header from the request", + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "The request method.", + "type": "object", + "required": [ + "request_method" + ], + "properties": { + "request_method": { + "description": "The request method enabled or not", + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "description": "A header from the response", + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "The trace ID of the request.", + "type": "object", + "required": [ + "trace_id" + ], + "properties": { + "trace_id": { + "description": "The format of the trace ID.", + "oneOf": [ + { + "description": "Open Telemetry trace ID, a hex string.", + "type": "string", + "enum": [ + "open_telemetry" + ] + }, + { + "description": "Datadog trace ID, a u64.", + "type": "string", + "enum": [ + "datadog" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "A value from context.", + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A value from baggage.", + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "description": "A value from an environment variable.", + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + }, + "condition": { + "description": "The instrument conditions.", + "oneOf": [ + { + "description": "A condition to check a selection against a value.", + "type": "object", + "required": [ + "eq" + ], + "properties": { + "eq": { + "type": "array", + "items": { + "anyOf": [ + { + "description": "A constant value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ] + }, + { + "description": "Selector to extract a value from the pipeline.", + "anyOf": [ + { + "description": "A header from the request", + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "The request method.", + "type": "object", + "required": [ + "request_method" + ], + "properties": { + "request_method": { + "description": "The request method enabled or not", + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "description": "A header from the response", + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "The trace ID of the request.", + "type": "object", + "required": [ + "trace_id" + ], + "properties": { + "trace_id": { + "description": "The format of the trace ID.", + "oneOf": [ + { + "description": "Open Telemetry trace ID, a hex string.", + "type": "string", + "enum": [ + "open_telemetry" + ] + }, + { + "description": "Datadog trace ID, a u64.", + "type": "string", + "enum": [ + "datadog" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "A value from context.", + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A value from baggage.", + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "description": "A value from an environment variable.", + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + ] + }, + "maxItems": 2, + "minItems": 2 + } + }, + "additionalProperties": false + }, + { + "description": "A condition to check a selection against a selector.", + "type": "object", + "required": [ + "exists" + ], + "properties": { + "exists": { + "anyOf": [ + { + "description": "A header from the request", + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "The request method.", + "type": "object", + "required": [ + "request_method" + ], + "properties": { + "request_method": { + "description": "The request method enabled or not", + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "description": "A header from the response", + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "The trace ID of the request.", + "type": "object", + "required": [ + "trace_id" + ], + "properties": { + "trace_id": { + "description": "The format of the trace ID.", + "oneOf": [ + { + "description": "Open Telemetry trace ID, a hex string.", + "type": "string", + "enum": [ + "open_telemetry" + ] + }, + { + "description": "Datadog trace ID, a u64.", + "type": "string", + "enum": [ + "datadog" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "A value from context.", + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A value from baggage.", + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "description": "A value from an environment variable.", + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "All sub-conditions must be true.", + "type": "object", + "required": [ + "all" + ], + "properties": { + "all": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_RouterSelector" + } + } + }, + "additionalProperties": false + }, + { + "description": "At least one sub-conditions must be true.", + "type": "object", + "required": [ + "any" + ], + "properties": { + "any": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_RouterSelector" + } + } + }, + "additionalProperties": false + }, + { + "description": "The sub-condition must not be true", + "type": "object", + "required": [ + "not" + ], + "properties": { + "not": { + "$ref": "#/definitions/Condition_for_RouterSelector" + } + }, + "additionalProperties": false + }, + { + "description": "Static true condition", + "type": "string", + "enum": [ + "true" + ] + }, + { + "description": "Static false condition", + "type": "string", + "enum": [ + "false" + ] + } + ] + }, + "description": { + "description": "The description of the instrument.", + "type": "string" + }, + "type": { + "description": "The type of instrument.", + "oneOf": [ + { + "description": "A monotonic counter https://opentelemetry.io/docs/specs/otel/metrics/data-model/#sums", + "type": "string", + "enum": [ + "counter" + ] + }, + { + "description": "A histogram https://opentelemetry.io/docs/specs/otel/metrics/data-model/#histogram", + "type": "string", + "enum": [ + "histogram" + ] + } + ] + }, + "unit": { + "description": "The units of the instrument, e.g. \"ms\", \"bytes\", \"requests\".", + "type": "string" + }, + "value": { + "description": "The value of the instrument.", + "anyOf": [ + { + "type": "string", + "enum": [ + "duration", + "unit" + ] + }, + { + "anyOf": [ + { + "description": "A header from the request", + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "The request method.", + "type": "object", + "required": [ + "request_method" + ], + "properties": { + "request_method": { + "description": "The request method enabled or not", + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "description": "A header from the response", + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "The trace ID of the request.", + "type": "object", + "required": [ + "trace_id" + ], + "properties": { + "trace_id": { + "description": "The format of the trace ID.", + "oneOf": [ + { + "description": "Open Telemetry trace ID, a hex string.", + "type": "string", + "enum": [ + "open_telemetry" + ] + }, + { + "description": "Datadog trace ID, a u64.", + "type": "string", + "enum": [ + "datadog" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "A value from context.", + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A value from baggage.", + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "description": "A value from an environment variable.", + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + ] + } + } + } + }, + "subgraph": { + "description": "Subgraph service instruments. For more information see documentation on Router lifecycle.", + "type": "object", + "properties": { + "http.client.request.body.size": { + "description": "Histogram of client request body size", + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "required": [ + "attributes" + ], + "properties": { + "attributes": { + "type": "object", + "properties": { + "subgraph.graphql.document": { + "description": "The GraphQL document being executed. Examples: * query findBookById { bookById(id: ?) { name } } Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.graphql.operation.name": { + "description": "The name of the operation being executed. Examples: * findBookById Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.graphql.operation.type": { + "description": "The type of the operation being executed. Examples: * query * subscription * mutation Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.name": { + "description": "The name of the subgraph Examples: * products Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "type": "object", + "required": [ + "subgraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_operation_name": { + "description": "The operation name from the subgraph query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_operation_kind" + ], + "properties": { + "subgraph_operation_kind": { + "description": "The kind of the subgraph operation (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_query": { + "description": "The graphql query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_query_variable": { + "description": "The name of a subgraph query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", + "type": "object", + "required": [ + "subgraph_response_body" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_body": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_data" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_data": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_errors" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_errors": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_request_header": { + "description": "The name of a subgraph request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_response_header": { + "description": "The name of a subgraph response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_status" + ], + "properties": { + "subgraph_response_status": { + "description": "The subgraph http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_operation_name": { + "description": "The supergraph query operation name.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_kind" + ], + "properties": { + "supergraph_operation_kind": { + "description": "The supergraph query operation kind (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_query": { + "description": "The supergraph query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "supergraph_query_variable": { + "description": "The supergraph query variable name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_request_header": { + "description": "The supergraph request header name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + } + }, + "additionalProperties": false + } + ] + }, + "http.client.request.duration": { + "description": "Histogram of client request duration", + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "required": [ + "attributes" + ], + "properties": { + "attributes": { + "type": "object", + "properties": { + "subgraph.graphql.document": { + "description": "The GraphQL document being executed. Examples: * query findBookById { bookById(id: ?) { name } } Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.graphql.operation.name": { + "description": "The name of the operation being executed. Examples: * findBookById Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.graphql.operation.type": { + "description": "The type of the operation being executed. Examples: * query * subscription * mutation Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.name": { + "description": "The name of the subgraph Examples: * products Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "type": "object", + "required": [ + "subgraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_operation_name": { + "description": "The operation name from the subgraph query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_operation_kind" + ], + "properties": { + "subgraph_operation_kind": { + "description": "The kind of the subgraph operation (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_query": { + "description": "The graphql query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_query_variable": { + "description": "The name of a subgraph query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", + "type": "object", + "required": [ + "subgraph_response_body" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_body": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_data" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_data": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_errors" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_errors": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_request_header": { + "description": "The name of a subgraph request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_response_header": { + "description": "The name of a subgraph response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_status" + ], + "properties": { + "subgraph_response_status": { + "description": "The subgraph http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_operation_name": { + "description": "The supergraph query operation name.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_kind" + ], + "properties": { + "supergraph_operation_kind": { + "description": "The supergraph query operation kind (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_query": { + "description": "The supergraph query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "supergraph_query_variable": { + "description": "The supergraph query variable name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_request_header": { + "description": "The supergraph request header name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + } + }, + "additionalProperties": false + } + ] + }, + "http.client.response.body.size": { + "description": "Histogram of client response body size", + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "required": [ + "attributes" + ], + "properties": { + "attributes": { + "type": "object", + "properties": { + "subgraph.graphql.document": { + "description": "The GraphQL document being executed. Examples: * query findBookById { bookById(id: ?) { name } } Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.graphql.operation.name": { + "description": "The name of the operation being executed. Examples: * findBookById Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.graphql.operation.type": { + "description": "The type of the operation being executed. Examples: * query * subscription * mutation Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.name": { + "description": "The name of the subgraph Examples: * products Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "type": "object", + "required": [ + "subgraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_operation_name": { + "description": "The operation name from the subgraph query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_operation_kind" + ], + "properties": { + "subgraph_operation_kind": { + "description": "The kind of the subgraph operation (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_query": { + "description": "The graphql query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_query_variable": { + "description": "The name of a subgraph query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", + "type": "object", + "required": [ + "subgraph_response_body" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_body": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_data" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_data": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_errors" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_errors": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_request_header": { + "description": "The name of a subgraph request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_response_header": { + "description": "The name of a subgraph response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_status" + ], + "properties": { + "subgraph_response_status": { + "description": "The subgraph http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_operation_name": { + "description": "The supergraph query operation name.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_kind" + ], + "properties": { + "supergraph_operation_kind": { + "description": "The supergraph query operation kind (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_query": { + "description": "The supergraph query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "supergraph_query_variable": { + "description": "The supergraph query variable name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_request_header": { + "description": "The supergraph request header name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + } + }, + "additionalProperties": false + } + ] + } + }, + "additionalProperties": { + "type": "object", + "required": [ + "description", + "type", + "unit", + "value" + ], + "properties": { + "attributes": { + "description": "Attributes to include on the instrument.", + "type": "object", + "properties": { + "subgraph.graphql.document": { + "description": "The GraphQL document being executed. Examples: * query findBookById { bookById(id: ?) { name } } Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.graphql.operation.name": { + "description": "The name of the operation being executed. Examples: * findBookById Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.graphql.operation.type": { + "description": "The type of the operation being executed. Examples: * query * subscription * mutation Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.name": { + "description": "The name of the subgraph Examples: * products Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "type": "object", + "required": [ + "subgraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_operation_name": { + "description": "The operation name from the subgraph query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_operation_kind" + ], + "properties": { + "subgraph_operation_kind": { + "description": "The kind of the subgraph operation (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_query": { + "description": "The graphql query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_query_variable": { + "description": "The name of a subgraph query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", + "type": "object", + "required": [ + "subgraph_response_body" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_body": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_data" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_data": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_errors" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_errors": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_request_header": { + "description": "The name of a subgraph request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_response_header": { + "description": "The name of a subgraph response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_status" + ], + "properties": { + "subgraph_response_status": { + "description": "The subgraph http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_operation_name": { + "description": "The supergraph query operation name.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_kind" + ], + "properties": { + "supergraph_operation_kind": { + "description": "The supergraph query operation kind (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_query": { + "description": "The supergraph query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "supergraph_query_variable": { + "description": "The supergraph query variable name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_request_header": { + "description": "The supergraph request header name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + }, + "condition": { + "description": "The instrument conditions.", + "oneOf": [ + { + "description": "A condition to check a selection against a value.", + "type": "object", + "required": [ + "eq" + ], + "properties": { + "eq": { + "type": "array", + "items": { + "anyOf": [ + { + "description": "A constant value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ] + }, + { + "description": "Selector to extract a value from the pipeline.", + "anyOf": [ + { + "type": "object", + "required": [ + "subgraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_operation_name": { + "description": "The operation name from the subgraph query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_operation_kind" + ], + "properties": { + "subgraph_operation_kind": { + "description": "The kind of the subgraph operation (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_query": { + "description": "The graphql query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_query_variable": { + "description": "The name of a subgraph query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", + "type": "object", + "required": [ + "subgraph_response_body" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_body": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_data" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_data": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_errors" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_errors": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_request_header": { + "description": "The name of a subgraph request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_response_header": { + "description": "The name of a subgraph response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_status" + ], + "properties": { + "subgraph_response_status": { + "description": "The subgraph http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_operation_name": { + "description": "The supergraph query operation name.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_kind" + ], + "properties": { + "supergraph_operation_kind": { + "description": "The supergraph query operation kind (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_query": { + "description": "The supergraph query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "supergraph_query_variable": { + "description": "The supergraph query variable name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_request_header": { + "description": "The supergraph request header name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + ] + }, + "maxItems": 2, + "minItems": 2 + } + }, + "additionalProperties": false + }, + { + "description": "A condition to check a selection against a selector.", + "type": "object", + "required": [ + "exists" + ], + "properties": { + "exists": { + "anyOf": [ + { + "type": "object", + "required": [ + "subgraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_operation_name": { + "description": "The operation name from the subgraph query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_operation_kind" + ], + "properties": { + "subgraph_operation_kind": { + "description": "The kind of the subgraph operation (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_query": { + "description": "The graphql query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_query_variable": { + "description": "The name of a subgraph query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", + "type": "object", + "required": [ + "subgraph_response_body" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_body": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_data" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_data": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_errors" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_errors": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_request_header": { + "description": "The name of a subgraph request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_response_header": { + "description": "The name of a subgraph response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_status" + ], + "properties": { + "subgraph_response_status": { + "description": "The subgraph http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_operation_name": { + "description": "The supergraph query operation name.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_kind" + ], + "properties": { + "supergraph_operation_kind": { + "description": "The supergraph query operation kind (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_query": { + "description": "The supergraph query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "supergraph_query_variable": { + "description": "The supergraph query variable name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_request_header": { + "description": "The supergraph request header name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "All sub-conditions must be true.", + "type": "object", + "required": [ + "all" + ], + "properties": { + "all": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_SubgraphSelector" + } + } + }, + "additionalProperties": false + }, + { + "description": "At least one sub-conditions must be true.", + "type": "object", + "required": [ + "any" + ], + "properties": { + "any": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_SubgraphSelector" + } + } + }, + "additionalProperties": false + }, + { + "description": "The sub-condition must not be true", + "type": "object", + "required": [ + "not" + ], + "properties": { + "not": { + "$ref": "#/definitions/Condition_for_SubgraphSelector" + } + }, + "additionalProperties": false + }, + { + "description": "Static true condition", + "type": "string", + "enum": [ + "true" + ] + }, + { + "description": "Static false condition", + "type": "string", + "enum": [ + "false" + ] + } + ] + }, + "description": { + "description": "The description of the instrument.", + "type": "string" + }, + "type": { + "description": "The type of instrument.", + "oneOf": [ + { + "description": "A monotonic counter https://opentelemetry.io/docs/specs/otel/metrics/data-model/#sums", + "type": "string", + "enum": [ + "counter" + ] + }, + { + "description": "A histogram https://opentelemetry.io/docs/specs/otel/metrics/data-model/#histogram", + "type": "string", + "enum": [ + "histogram" + ] + } + ] + }, + "unit": { + "description": "The units of the instrument, e.g. \"ms\", \"bytes\", \"requests\".", + "type": "string" + }, + "value": { + "description": "The value of the instrument.", + "anyOf": [ + { + "type": "string", + "enum": [ + "duration", + "unit" + ] + }, + { + "anyOf": [ + { + "type": "object", + "required": [ + "subgraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_operation_name": { + "description": "The operation name from the subgraph query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_operation_kind" + ], + "properties": { + "subgraph_operation_kind": { + "description": "The kind of the subgraph operation (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_query": { + "description": "The graphql query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_query_variable": { + "description": "The name of a subgraph query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", + "type": "object", + "required": [ + "subgraph_response_body" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_body": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_data" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_data": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_errors" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_errors": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_request_header": { + "description": "The name of a subgraph request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_response_header": { + "description": "The name of a subgraph response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_status" + ], + "properties": { + "subgraph_response_status": { + "description": "The subgraph http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_operation_name": { + "description": "The supergraph query operation name.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_kind" + ], + "properties": { + "supergraph_operation_kind": { + "description": "The supergraph query operation kind (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_query": { + "description": "The supergraph query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "supergraph_query_variable": { + "description": "The supergraph query variable name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_request_header": { + "description": "The supergraph request header name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + ] + } + } + } + }, + "supergraph": { + "description": "Supergraph service instruments. For more information see documentation on Router lifecycle.", + "type": "object", + "additionalProperties": { + "type": "object", + "required": [ + "description", + "type", + "unit", + "value" + ], + "properties": { + "attributes": { + "description": "Attributes to include on the instrument.", + "type": "object", + "properties": { + "graphql.document": { + "description": "The GraphQL document being executed. Examples: * query findBookById { bookById(id: ?) { name } } Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "graphql.operation.name": { + "description": "The name of the operation being executed. Examples: * findBookById Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "graphql.operation.type": { + "description": "The type of the operation being executed. Examples: * query * subscription * mutation Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "type": "object", + "required": [ + "operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "operation_name": { + "description": "The operation name from the query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "operation_kind" + ], + "properties": { + "operation_kind": { + "description": "The operation kind from the query (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "query": { + "description": "The graphql query.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "query_variable": { + "description": "The name of a graphql query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "response_header": { + "description": "The name of the response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + }, + "condition": { + "description": "The instrument conditions.", + "oneOf": [ + { + "description": "A condition to check a selection against a value.", + "type": "object", + "required": [ + "eq" + ], + "properties": { + "eq": { + "type": "array", + "items": { + "anyOf": [ + { + "description": "A constant value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ] + }, + { + "description": "Selector to extract a value from the pipeline.", + "anyOf": [ + { + "type": "object", + "required": [ + "operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "operation_name": { + "description": "The operation name from the query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "operation_kind" + ], + "properties": { + "operation_kind": { + "description": "The operation kind from the query (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "query": { + "description": "The graphql query.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "query_variable": { + "description": "The name of a graphql query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "response_header": { + "description": "The name of the response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + ] + }, + "maxItems": 2, + "minItems": 2 + } + }, + "additionalProperties": false + }, + { + "description": "A condition to check a selection against a selector.", + "type": "object", + "required": [ + "exists" + ], + "properties": { + "exists": { + "anyOf": [ + { + "type": "object", + "required": [ + "operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "operation_name": { + "description": "The operation name from the query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "operation_kind" + ], + "properties": { + "operation_kind": { + "description": "The operation kind from the query (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "query": { + "description": "The graphql query.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "query_variable": { + "description": "The name of a graphql query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "response_header": { + "description": "The name of the response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "All sub-conditions must be true.", + "type": "object", + "required": [ + "all" + ], + "properties": { + "all": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_SupergraphSelector" + } + } + }, + "additionalProperties": false + }, + { + "description": "At least one sub-conditions must be true.", + "type": "object", + "required": [ + "any" + ], + "properties": { + "any": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_SupergraphSelector" + } + } + }, + "additionalProperties": false + }, + { + "description": "The sub-condition must not be true", + "type": "object", + "required": [ + "not" + ], + "properties": { + "not": { + "$ref": "#/definitions/Condition_for_SupergraphSelector" + } + }, + "additionalProperties": false + }, + { + "description": "Static true condition", + "type": "string", + "enum": [ + "true" + ] + }, + { + "description": "Static false condition", + "type": "string", + "enum": [ + "false" + ] + } + ] + }, + "description": { + "description": "The description of the instrument.", + "type": "string" + }, + "type": { + "description": "The type of instrument.", + "oneOf": [ + { + "description": "A monotonic counter https://opentelemetry.io/docs/specs/otel/metrics/data-model/#sums", + "type": "string", + "enum": [ + "counter" + ] + }, + { + "description": "A histogram https://opentelemetry.io/docs/specs/otel/metrics/data-model/#histogram", + "type": "string", + "enum": [ + "histogram" + ] + } + ] + }, + "unit": { + "description": "The units of the instrument, e.g. \"ms\", \"bytes\", \"requests\".", + "type": "string" + }, + "value": { + "description": "The value of the instrument.", + "anyOf": [ + { + "type": "string", + "enum": [ + "duration", + "unit" + ] + }, + { + "anyOf": [ + { + "type": "object", + "required": [ + "operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "operation_name": { + "description": "The operation name from the query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "operation_kind" + ], + "properties": { + "operation_kind": { + "description": "The operation kind from the query (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "query": { + "description": "The graphql query.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "query_variable": { + "description": "The name of a graphql query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "response_header": { + "description": "The name of the response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + ] + } + } + } + } + }, + "additionalProperties": false + }, + "spans": { + "description": "Span configuration", + "type": "object", + "properties": { + "default_attribute_requirement_level": { + "description": "The attributes to include by default in spans based on their level as specified in the otel semantic conventions and Apollo documentation.", + "oneOf": [ + { + "description": "No default attributes set on spans, you have to set it one by one in the configuration to enable some attributes", + "type": "string", + "enum": [ + "none" + ] + }, + { + "description": "Attributes that are marked as required in otel semantic conventions and apollo documentation will be included (default)", + "type": "string", + "enum": [ + "required" + ] + }, + { + "description": "Attributes that are marked as required or recommended in otel semantic conventions and apollo documentation will be included", + "type": "string", + "enum": [ + "recommended" + ] + } + ] + }, + "mode": { + "description": "Use new OpenTelemetry spec compliant span attributes or preserve existing. This will be defaulted in future to `spec_compliant`, eventually removed in future.", + "oneOf": [ + { + "description": "Keep the request span as root span and deprecated attributes. This option will eventually removed.", + "type": "string", + "enum": [ + "deprecated" + ] + }, + { + "description": "Use new OpenTelemetry spec compliant span attributes or preserve existing. This will be the default in future.", + "type": "string", + "enum": [ + "spec_compliant" + ] + } + ] + }, + "router": { + "description": "Configuration of router spans. Log events inherit attributes from the containing span, so attributes configured here will be included on log events for a request. Router spans contain http request and response information and therefore contain http specific attributes.", + "type": "object", + "properties": { + "attributes": { + "description": "Custom attributes that are attached to the router span.", + "type": "object", + "properties": { + "baggage": { + "description": "All key values from trace baggage.", + "default": null, + "type": "boolean", + "nullable": true + }, + "dd.trace_id": { + "description": "The datadog trace ID. This can be output in logs and used to correlate traces in Datadog.", + "default": null, + "type": "boolean", + "nullable": true + }, + "error.type": { + "description": "Describes a class of error the operation ended with. Examples: * timeout * name_resolution_error * 500 Requirement level: Conditionally Required: If request has ended with an error.", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.request.body.size": { + "description": "The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.request.method": { + "description": "HTTP request method. Examples: * GET * POST * HEAD Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.response.body.size": { + "description": "The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. Examples: * 3495 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.response.status_code": { + "description": "HTTP response status code. Examples: * 200 Requirement level: Conditionally Required: If and only if one was received/sent.", + "default": null, + "type": "boolean", + "nullable": true + }, + "http.route": { + "description": "The matched route (path template in the format used by the respective server framework). Examples: * /graphql Requirement level: Conditionally Required: If and only if it’s available", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.local.address": { + "description": "Local socket address. Useful in case of a multi-IP host. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Opt-In", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.local.port": { + "description": "Local socket port. Useful in case of a multi-port host. Examples: * 65123 Requirement level: Opt-In", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.peer.address": { + "description": "Peer address of the network connection - IP address or Unix domain socket name. Examples: * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.peer.port": { + "description": "Peer port number of the network connection. Examples: * 65123 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.protocol.name": { + "description": "OSI application layer or non-OSI equivalent. Examples: * http * spdy Requirement level: Recommended: if not default (http).", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.protocol.version": { + "description": "Version of the protocol specified in network.protocol.name. Examples: * 1.0 * 1.1 * 2 * 3 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.transport": { + "description": "OSI transport layer. Examples: * tcp * udp Requirement level: Conditionally Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "network.type": { + "description": "OSI network layer or non-OSI equivalent. Examples: * ipv4 * ipv6 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "server.address": { + "description": "Name of the local HTTP server that received the request. Examples: * example.com * 10.1.2.80 * /tmp/my.sock Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "server.port": { + "description": "Port of the local HTTP server that received the request. Examples: * 80 * 8080 * 443 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "trace_id": { + "description": "The OpenTelemetry trace ID. This can be output in logs.", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.path": { + "description": "The URI path component Examples: * /search Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.query": { + "description": "The URI query component Examples: * q=OpenTelemetry Requirement level: Conditionally Required: If and only if one was received/sent.", + "default": null, + "type": "boolean", + "nullable": true + }, + "url.scheme": { + "description": "The URI scheme component identifying the used protocol. Examples: * http * https Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + }, + "user_agent.original": { + "description": "Value of the HTTP User-Agent header sent by the client. Examples: * CERN-LineMode/2.15 * libwww/2.17b3 Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "description": "A header from the request", + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "The request method.", + "type": "object", + "required": [ + "request_method" + ], + "properties": { + "request_method": { + "description": "The request method enabled or not", + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "description": "A header from the response", + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "The trace ID of the request.", + "type": "object", + "required": [ + "trace_id" + ], + "properties": { + "trace_id": { + "description": "The format of the trace ID.", + "oneOf": [ + { + "description": "Open Telemetry trace ID, a hex string.", + "type": "string", + "enum": [ + "open_telemetry" + ] + }, + { + "description": "Datadog trace ID, a u64.", + "type": "string", + "enum": [ + "datadog" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "A value from context.", + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A value from baggage.", + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "description": "A value from an environment variable.", + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + } + }, + "additionalProperties": false + }, + "subgraph": { + "description": "Attributes to include on the subgraph span. Subgraph spans contain information about the subgraph request and response and therefore contain subgraph specific attributes.", + "type": "object", + "properties": { + "attributes": { + "description": "Custom attributes that are attached to the subgraph span.", + "type": "object", + "properties": { + "subgraph.graphql.document": { + "description": "The GraphQL document being executed. Examples: * query findBookById { bookById(id: ?) { name } } Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.graphql.operation.name": { + "description": "The name of the operation being executed. Examples: * findBookById Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.graphql.operation.type": { + "description": "The type of the operation being executed. Examples: * query * subscription * mutation Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "subgraph.name": { + "description": "The name of the subgraph Examples: * products Requirement level: Required", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "type": "object", + "required": [ + "subgraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_operation_name": { + "description": "The operation name from the subgraph query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_operation_kind" + ], + "properties": { + "subgraph_operation_kind": { + "description": "The kind of the subgraph operation (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_query": { + "description": "The graphql query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_query_variable": { + "description": "The name of a subgraph query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", + "type": "object", + "required": [ + "subgraph_response_body" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_body": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_data" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_data": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_errors" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_errors": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_request_header": { + "description": "The name of a subgraph request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_response_header": { + "description": "The name of a subgraph response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_status" + ], + "properties": { + "subgraph_response_status": { + "description": "The subgraph http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_operation_name": { + "description": "The supergraph query operation name.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_kind" + ], + "properties": { + "supergraph_operation_kind": { + "description": "The supergraph query operation kind (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_query": { + "description": "The supergraph query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "supergraph_query_variable": { + "description": "The supergraph query variable name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_request_header": { + "description": "The supergraph request header name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + } + }, + "additionalProperties": false + }, + "supergraph": { + "description": "Configuration of supergraph spans. Supergraph spans contain information about the graphql request and response and therefore contain graphql specific attributes.", + "type": "object", + "properties": { + "attributes": { + "description": "Custom attributes that are attached to the supergraph span.", + "default": { + "attributes": { + "graphql.document": null, + "graphql.operation.name": null, + "graphql.operation.type": null + }, + "custom": {} + }, + "type": "object", + "properties": { + "graphql.document": { + "description": "The GraphQL document being executed. Examples: * query findBookById { bookById(id: ?) { name } } Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "graphql.operation.name": { + "description": "The name of the operation being executed. Examples: * findBookById Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + }, + "graphql.operation.type": { + "description": "The type of the operation being executed. Examples: * query * subscription * mutation Requirement level: Recommended", + "default": null, + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": { + "anyOf": [ + { + "type": "object", + "required": [ + "operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "operation_name": { + "description": "The operation name from the query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "operation_kind" + ], + "properties": { + "operation_kind": { + "description": "The operation kind from the query (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "query": { + "description": "The graphql query.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "query_variable": { + "description": "The name of a graphql query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "response_header": { + "description": "The name of the response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "tls": { + "description": "TLS related configuration options.", + "default": { + "supergraph": null, + "subgraph": { + "all": { + "certificate_authorities": null, + "client_authentication": null + }, + "subgraphs": {} + } + }, + "type": "object", + "properties": { + "subgraph": { + "description": "Configuration options pertaining to the subgraph server component.", + "default": { + "all": { + "certificate_authorities": null, + "client_authentication": null + }, + "subgraphs": {} + }, + "type": "object", + "properties": { + "all": { + "description": "options applying to all subgraphs", + "default": { + "certificate_authorities": null, + "client_authentication": null + }, + "type": "object", + "properties": { + "certificate_authorities": { + "description": "list of certificate authorities in PEM format", + "default": null, + "type": "string", + "nullable": true + }, + "client_authentication": { + "description": "client certificate authentication", + "default": null, + "type": "object", + "required": [ + "certificate_chain", + "key" + ], + "properties": { + "certificate_chain": { + "description": "list of certificates in PEM format", + "writeOnly": true, + "type": "string" + }, + "key": { + "description": "key in PEM format", + "writeOnly": true, + "type": "string" + } + }, + "additionalProperties": false, + "nullable": true + } + }, + "additionalProperties": false + }, + "subgraphs": { + "description": "per subgraph options", + "default": {}, + "type": "object", + "additionalProperties": { + "description": "Configuration options pertaining to the subgraph server component.", + "type": "object", + "properties": { + "certificate_authorities": { + "description": "list of certificate authorities in PEM format", + "default": null, + "type": "string", + "nullable": true + }, + "client_authentication": { + "description": "client certificate authentication", + "default": null, + "type": "object", + "required": [ + "certificate_chain", + "key" + ], + "properties": { + "certificate_chain": { + "description": "list of certificates in PEM format", + "writeOnly": true, + "type": "string" + }, + "key": { + "description": "key in PEM format", + "writeOnly": true, + "type": "string" + } + }, + "additionalProperties": false, + "nullable": true + } + }, + "additionalProperties": false + } + } + } + }, + "supergraph": { + "description": "TLS server configuration\n\nthis will affect the GraphQL endpoint and any other endpoint targeting the same listen address", + "default": null, + "type": "object", + "required": [ + "certificate", + "certificate_chain", + "key" + ], + "properties": { + "certificate": { + "description": "server certificate in PEM format", + "writeOnly": true, + "type": "string" + }, + "certificate_chain": { + "description": "list of certificate authorities in PEM format", + "writeOnly": true, + "type": "string" + }, + "key": { + "description": "server key in PEM format", + "writeOnly": true, + "type": "string" + } + }, + "additionalProperties": false, + "nullable": true + } + }, + "additionalProperties": false + }, + "traffic_shaping": { + "description": "Configuration for the experimental traffic shaping plugin", + "type": "object", + "properties": { + "all": { + "description": "Applied on all subgraphs", + "type": "object", + "properties": { + "compression": { + "description": "Enable compression for subgraphs (available compressions are deflate, br, gzip)", + "oneOf": [ + { + "description": "gzip", + "type": "string", + "enum": [ + "gzip" + ] + }, + { + "description": "deflate", + "type": "string", + "enum": [ + "deflate" + ] + }, + { + "description": "brotli", + "type": "string", + "enum": [ + "br" + ] + }, + { + "description": "identity", + "type": "string", + "enum": [ + "identity" + ] + } + ], + "nullable": true + }, + "deduplicate_query": { + "description": "Enable query deduplication", + "type": "boolean", + "nullable": true + }, + "experimental_http2": { + "description": "Enable HTTP2 for subgraphs", + "oneOf": [ + { + "description": "Enable HTTP2 for subgraphs", + "type": "string", + "enum": [ + "enable" + ] + }, + { + "description": "Disable HTTP2 for subgraphs", + "type": "string", + "enum": [ + "disable" + ] + }, + { + "description": "Only HTTP2 is active", + "type": "string", + "enum": [ + "http2only" + ] + } + ], + "nullable": true + }, + "experimental_retry": { + "description": "Retry configuration", + "type": "object", + "properties": { + "min_per_sec": { + "description": "minimum rate of retries allowed to accomodate clients that have just started issuing requests, or clients that do not issue many requests per window. The default value is 10", + "type": "integer", + "format": "uint32", + "minimum": 0.0, + "nullable": true + }, + "retry_mutations": { + "description": "allows request retries on mutations. This should only be activated if mutations are idempotent. Disabled by default", + "type": "boolean", + "nullable": true + }, + "retry_percent": { + "description": "percentage of calls to deposit that can be retried. This is in addition to any retries allowed for via min_per_sec. Must be between 0 and 1000, default value is 0.2", + "type": "number", + "format": "float", + "nullable": true + }, + "ttl": { + "description": "how long a single deposit should be considered. Must be between 1 and 60 seconds, default value is 10 seconds", + "default": null, + "type": "string" + } + }, + "additionalProperties": false, + "nullable": true + }, + "global_rate_limit": { + "description": "Enable global rate limiting", + "type": "object", + "required": [ + "capacity", + "interval" + ], + "properties": { + "capacity": { + "description": "Number of requests allowed", + "type": "integer", + "format": "uint64", + "minimum": 1.0 + }, + "interval": { + "description": "Per interval", + "type": "string" + } + }, + "additionalProperties": false, + "nullable": true + }, + "timeout": { + "description": "Enable timeout for incoming requests", + "default": null, + "type": "string" + } + }, + "additionalProperties": false, + "nullable": true + }, + "deduplicate_variables": { + "description": "DEPRECATED, now always enabled: Enable variable deduplication optimization when sending requests to subgraphs (https://github.com/apollographql/router/issues/87)", + "default": null, + "type": "boolean", + "nullable": true + }, + "router": { + "description": "Applied at the router level", + "type": "object", + "properties": { + "global_rate_limit": { + "description": "Enable global rate limiting", + "type": "object", + "required": [ + "capacity", + "interval" + ], + "properties": { + "capacity": { + "description": "Number of requests allowed", + "type": "integer", + "format": "uint64", + "minimum": 1.0 + }, + "interval": { + "description": "Per interval", + "type": "string" + } + }, + "additionalProperties": false, + "nullable": true + }, + "timeout": { + "description": "Enable timeout for incoming requests", + "default": null, + "type": "string" + } + }, + "additionalProperties": false, + "nullable": true + }, + "subgraphs": { + "description": "Applied on specific subgraphs", + "type": "object", + "additionalProperties": { + "description": "Traffic shaping options", + "type": "object", + "properties": { + "compression": { + "description": "Enable compression for subgraphs (available compressions are deflate, br, gzip)", + "oneOf": [ + { + "description": "gzip", + "type": "string", + "enum": [ + "gzip" + ] + }, + { + "description": "deflate", + "type": "string", + "enum": [ + "deflate" + ] + }, + { + "description": "brotli", + "type": "string", + "enum": [ + "br" + ] + }, + { + "description": "identity", + "type": "string", + "enum": [ + "identity" + ] + } + ], + "nullable": true + }, + "deduplicate_query": { + "description": "Enable query deduplication", + "type": "boolean", + "nullable": true + }, + "experimental_http2": { + "description": "Enable HTTP2 for subgraphs", + "oneOf": [ + { + "description": "Enable HTTP2 for subgraphs", + "type": "string", + "enum": [ + "enable" + ] + }, + { + "description": "Disable HTTP2 for subgraphs", + "type": "string", + "enum": [ + "disable" + ] + }, + { + "description": "Only HTTP2 is active", + "type": "string", + "enum": [ + "http2only" + ] + } + ], + "nullable": true + }, + "experimental_retry": { + "description": "Retry configuration", + "type": "object", + "properties": { + "min_per_sec": { + "description": "minimum rate of retries allowed to accomodate clients that have just started issuing requests, or clients that do not issue many requests per window. The default value is 10", + "type": "integer", + "format": "uint32", + "minimum": 0.0, + "nullable": true + }, + "retry_mutations": { + "description": "allows request retries on mutations. This should only be activated if mutations are idempotent. Disabled by default", + "type": "boolean", + "nullable": true + }, + "retry_percent": { + "description": "percentage of calls to deposit that can be retried. This is in addition to any retries allowed for via min_per_sec. Must be between 0 and 1000, default value is 0.2", + "type": "number", + "format": "float", + "nullable": true + }, + "ttl": { + "description": "how long a single deposit should be considered. Must be between 1 and 60 seconds, default value is 10 seconds", + "default": null, + "type": "string" + } + }, + "additionalProperties": false, + "nullable": true + }, + "global_rate_limit": { + "description": "Enable global rate limiting", + "type": "object", + "required": [ + "capacity", + "interval" + ], + "properties": { + "capacity": { + "description": "Number of requests allowed", + "type": "integer", + "format": "uint64", + "minimum": 1.0 + }, + "interval": { + "description": "Per interval", + "type": "string" + } + }, + "additionalProperties": false, + "nullable": true + }, + "timeout": { + "description": "Enable timeout for incoming requests", + "default": null, + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "definitions": { + "Condition_for_RouterSelector": { + "oneOf": [ + { + "description": "A condition to check a selection against a value.", + "type": "object", + "required": [ + "eq" + ], + "properties": { + "eq": { + "type": "array", + "items": { + "anyOf": [ + { + "description": "A constant value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ] + }, + { + "description": "Selector to extract a value from the pipeline.", + "anyOf": [ + { + "description": "A header from the request", + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "The request method.", + "type": "object", + "required": [ + "request_method" + ], + "properties": { + "request_method": { + "description": "The request method enabled or not", + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "description": "A header from the response", + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "The trace ID of the request.", + "type": "object", + "required": [ + "trace_id" + ], + "properties": { + "trace_id": { + "description": "The format of the trace ID.", + "oneOf": [ + { + "description": "Open Telemetry trace ID, a hex string.", + "type": "string", + "enum": [ + "open_telemetry" + ] + }, + { + "description": "Datadog trace ID, a u64.", + "type": "string", + "enum": [ + "datadog" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "A value from context.", + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A value from baggage.", + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } - ], - "nullable": true - }, - "request_header": { - "description": "The name of the request header.", + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "description": "A value from an environment variable.", + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + ] + }, + "maxItems": 2, + "minItems": 2 + } + }, + "additionalProperties": false + }, + { + "description": "A condition to check a selection against a selector.", + "type": "object", + "required": [ + "exists" + ], + "properties": { + "exists": { + "anyOf": [ + { + "description": "A header from the request", + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "The request method.", + "type": "object", + "required": [ + "request_method" + ], + "properties": { + "request_method": { + "description": "The request method enabled or not", + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "description": "A header from the response", + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "The trace ID of the request.", + "type": "object", + "required": [ + "trace_id" + ], + "properties": { + "trace_id": { + "description": "The format of the trace ID.", + "oneOf": [ + { + "description": "Open Telemetry trace ID, a hex string.", + "type": "string", + "enum": [ + "open_telemetry" + ] + }, + { + "description": "Datadog trace ID, a u64.", + "type": "string", + "enum": [ + "datadog" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "A value from context.", + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { "type": "string" } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A value from baggage.", + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, - "additionalProperties": false + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "description": "A value from an environment variable.", + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "All sub-conditions must be true.", + "type": "object", + "required": [ + "all" + ], + "properties": { + "all": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_RouterSelector" + } + } + }, + "additionalProperties": false + }, + { + "description": "At least one sub-conditions must be true.", + "type": "object", + "required": [ + "any" + ], + "properties": { + "any": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_RouterSelector" + } + } + }, + "additionalProperties": false + }, + { + "description": "The sub-condition must not be true", + "type": "object", + "required": [ + "not" + ], + "properties": { + "not": { + "$ref": "#/definitions/Condition_for_RouterSelector" + } + }, + "additionalProperties": false + }, + { + "description": "Static true condition", + "type": "string", + "enum": [ + "true" + ] + }, + { + "description": "Static false condition", + "type": "string", + "enum": [ + "false" + ] + } + ] + }, + "Condition_for_SubgraphSelector": { + "oneOf": [ + { + "description": "A condition to check a selection against a value.", + "type": "object", + "required": [ + "eq" + ], + "properties": { + "eq": { + "type": "array", + "items": { + "anyOf": [ + { + "description": "A constant value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "A header from the response", - "type": "object", - "required": [ - "response_header" - ], - "properties": { - "default": { - "description": "Optional default value.", + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ] + }, + { + "description": "Selector to extract a value from the pipeline.", + "anyOf": [ + { + "type": "object", + "required": [ + "subgraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_operation_name": { + "description": "The operation name from the subgraph query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_operation_kind" + ], + "properties": { + "subgraph_operation_kind": { + "description": "The kind of the subgraph operation (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_query": { + "description": "The graphql query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", "anyOf": [ { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "f64 values", - "type": "number", - "format": "double" + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } }, { - "description": "String values", - "type": "string" + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } }, { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } - ], - "nullable": true - }, - "response_header": { - "description": "The name of the request header.", - "type": "string" + ] } - }, - "additionalProperties": false - }, - { - "description": "A header from the response", - "type": "object", - "required": [ - "response_status" ], - "properties": { - "response_status": { - "description": "The http response status code.", - "oneOf": [ + "nullable": true + }, + "subgraph_query_variable": { + "description": "The name of a subgraph query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", + "type": "object", + "required": [ + "subgraph_response_body" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ { - "description": "The http status code.", - "type": "string", - "enum": [ - "code" - ] + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "The http status reason.", - "type": "string", - "enum": [ - "reason" - ] - } - ] - } - }, - "additionalProperties": false - }, - { - "description": "The trace ID of the request.", - "type": "object", - "required": [ - "trace_id" - ], - "properties": { - "trace_id": { - "description": "The format of the trace ID.", - "oneOf": [ + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, { - "description": "Open Telemetry trace ID, a hex string.", - "type": "string", - "enum": [ - "open_telemetry" - ] + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } }, { - "description": "Datadog trace ID, a u64.", - "type": "string", - "enum": [ - "datadog" - ] + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } ] } - }, - "additionalProperties": false - }, - { - "description": "A value from context.", - "type": "object", - "required": [ - "response_context" ], - "properties": { - "default": { - "description": "Optional default value.", + "nullable": true + }, + "subgraph_response_body": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_data" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", "anyOf": [ { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "f64 values", - "type": "number", - "format": "double" + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } }, { - "description": "String values", - "type": "string" + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } }, { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } - ], - "nullable": true + ] + } + ], + "nullable": true + }, + "subgraph_response_data": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_errors" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" }, - "response_context": { - "description": "The response context key.", - "type": "string" - } - }, - "additionalProperties": false - }, - { - "description": "A value from baggage.", - "type": "object", - "required": [ - "baggage" - ], - "properties": { - "baggage": { - "description": "The name of the baggage item.", + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", "type": "string" }, - "default": { - "description": "Optional default value.", + { + "description": "Array of homogeneous values", "anyOf": [ { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "f64 values", - "type": "number", - "format": "double" + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } }, { - "description": "String values", - "type": "string" + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } }, { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } - ], - "nullable": true + ] } - }, - "additionalProperties": false - }, - { - "description": "A value from an environment variable.", - "type": "object", - "required": [ - "env" ], - "properties": { - "default": { - "description": "Optional default value.", + "nullable": true + }, + "subgraph_response_errors": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_request_header": { + "description": "The name of a subgraph request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_response_header": { + "description": "The name of a subgraph response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_status" + ], + "properties": { + "subgraph_response_status": { + "description": "The subgraph http response status code.", + "oneOf": [ + { + "description": "The http status code.", "type": "string", - "nullable": true + "enum": [ + "code" + ] }, - "env": { - "description": "The name of the environment variable", - "type": "string" + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] } - }, - "additionalProperties": false - }, - { - "type": "string" + ] } - ] - } - } - }, - "additionalProperties": false - }, - "subgraph": { - "description": "Attributes to include on the subgraph span. Subgraph spans contain information about the subgraph request and response and therefore contain subgraph specific attributes.", - "type": "object", - "properties": { - "attributes": { - "description": "Custom attributes that are attached to the subgraph span.", - "type": "object", - "properties": { - "subgraph.graphql.document": { - "description": "The GraphQL document being executed. Examples: * query findBookById { bookById(id: ?) { name } } Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true }, - "subgraph.graphql.operation.name": { - "description": "The name of the operation being executed. Examples: * findBookById Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_operation_name": { + "description": "The supergraph query operation name.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } }, - "subgraph.graphql.operation.type": { - "description": "The type of the operation being executed. Examples: * query * subscription * mutation Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_kind" + ], + "properties": { + "supergraph_operation_kind": { + "description": "The supergraph query operation kind (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } }, - "subgraph.name": { - "description": "The name of the subgraph Examples: * products Requirement level: Required", - "default": null, - "type": "boolean", - "nullable": true - } + "additionalProperties": false }, - "additionalProperties": { - "anyOf": [ - { - "type": "object", - "required": [ - "subgraph_operation_name" - ], - "properties": { - "default": { - "description": "Optional default value.", + { + "type": "object", + "required": [ + "supergraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_query": { + "description": "The supergraph query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", "type": "string", - "nullable": true + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" }, - "subgraph_operation_name": { - "description": "The operation name from the subgraph query.", - "oneOf": [ + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ { - "description": "The raw operation name.", - "type": "string", - "enum": [ - "string" - ] + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "A hash of the operation name.", - "type": "string", - "enum": [ - "hash" - ] - } - ] - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "subgraph_operation_kind" - ], - "properties": { - "subgraph_operation_kind": { - "description": "The kind of the subgraph operation (query|mutation|subscription).", - "oneOf": [ + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, { - "description": "The raw operation kind.", - "type": "string", - "enum": [ - "string" - ] + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } ] } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "subgraph_query" ], - "properties": { - "default": { - "description": "Optional default value.", - "type": "string", - "nullable": true + "nullable": true + }, + "supergraph_query_variable": { + "description": "The supergraph query variable name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_request_header": { + "description": "The supergraph request header name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" }, - "subgraph_query": { - "description": "The graphql query to the subgraph.", - "oneOf": [ + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ { - "description": "The raw query kind.", - "type": "string", - "enum": [ - "string" - ] + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } ] } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "subgraph_query_variable" ], - "properties": { - "default": { - "description": "Optional default value.", + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", "anyOf": [ { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "f64 values", - "type": "number", - "format": "double" + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } }, { - "description": "String values", - "type": "string" + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } }, { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } - ], - "nullable": true + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" }, - "subgraph_query_variable": { - "description": "The name of a subgraph query variable.", + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", "type": "string" - } - }, - "additionalProperties": false - }, - { - "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", - "type": "object", - "required": [ - "subgraph_response_body" - ], - "properties": { - "default": { - "description": "Optional default value.", + }, + { + "description": "Array of homogeneous values", "anyOf": [ { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "f64 values", - "type": "number", - "format": "double" + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } }, { - "description": "String values", - "type": "string" + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } }, { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } - ], - "nullable": true - }, - "subgraph_response_body": { - "description": "The subgraph response body json path.", + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + ] + }, + "maxItems": 2, + "minItems": 2 + } + }, + "additionalProperties": false + }, + { + "description": "A condition to check a selection against a selector.", + "type": "object", + "required": [ + "exists" + ], + "properties": { + "exists": { + "anyOf": [ + { + "type": "object", + "required": [ + "subgraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_operation_name": { + "description": "The operation name from the subgraph query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_operation_kind" + ], + "properties": { + "subgraph_operation_kind": { + "description": "The kind of the subgraph operation (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_query": { + "description": "The graphql query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { "type": "string" } + } + ] + } + ], + "nullable": true + }, + "subgraph_query_variable": { + "description": "The name of a subgraph query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "Deprecated, use SubgraphResponseData and SubgraphResponseError instead", + "type": "object", + "required": [ + "subgraph_response_body" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "subgraph_response_data" - ], - "properties": { - "default": { - "description": "Optional default value.", - "anyOf": [ - { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" - }, - { - "description": "f64 values", - "type": "number", - "format": "double" - }, - { - "description": "String values", - "type": "string" - }, - { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] - } - ], - "nullable": true - }, - "subgraph_response_data": { - "description": "The subgraph response body json path.", - "type": "string" + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "subgraph_response_errors" - ], - "properties": { - "default": { - "description": "Optional default value.", - "anyOf": [ - { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" - }, - { - "description": "f64 values", - "type": "number", - "format": "double" - }, - { - "description": "String values", - "type": "string" - }, - { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] - } - ], - "nullable": true - }, - "subgraph_response_errors": { - "description": "The subgraph response body json path.", - "type": "string" + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "subgraph_request_header" - ], - "properties": { - "default": { - "description": "Optional default value.", - "type": "string", - "nullable": true - }, - "subgraph_request_header": { - "description": "The name of a subgraph request header.", + { + "description": "Array of strings", + "type": "array", + "items": { "type": "string" } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_body": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_data" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "subgraph_response_header" - ], - "properties": { - "default": { - "description": "Optional default value.", - "type": "string", - "nullable": true - }, - "subgraph_response_header": { - "description": "The name of a subgraph response header.", + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { "type": "string" } + } + ] + } + ], + "nullable": true + }, + "subgraph_response_data": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_errors" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "subgraph_response_status" - ], - "properties": { - "subgraph_response_status": { - "description": "The subgraph http response status code.", - "oneOf": [ - { - "description": "The http status code.", - "type": "string", - "enum": [ - "code" - ] - }, - { - "description": "The http status reason.", - "type": "string", - "enum": [ - "reason" - ] - } - ] + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "supergraph_operation_name" - ], - "properties": { - "default": { - "description": "Optional default value.", - "type": "string", - "nullable": true - }, - "supergraph_operation_name": { - "description": "The supergraph query operation name.", - "oneOf": [ - { - "description": "The raw operation name.", - "type": "string", - "enum": [ - "string" - ] - }, - { - "description": "A hash of the operation name.", - "type": "string", - "enum": [ - "hash" - ] - } - ] + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "supergraph_operation_kind" - ], - "properties": { - "supergraph_operation_kind": { - "description": "The supergraph query operation kind (query|mutation|subscription).", - "oneOf": [ - { - "description": "The raw operation kind.", - "type": "string", - "enum": [ - "string" - ] - } - ] + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "supergraph_query" - ], - "properties": { - "default": { - "description": "Optional default value.", - "type": "string", - "nullable": true - }, - "supergraph_query": { - "description": "The supergraph query to the subgraph.", - "oneOf": [ - { - "description": "The raw query kind.", - "type": "string", - "enum": [ - "string" - ] - } - ] + } + ] + } + ], + "nullable": true + }, + "subgraph_response_errors": { + "description": "The subgraph response body json path.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_request_header": { + "description": "The name of a subgraph request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "subgraph_response_header": { + "description": "The name of a subgraph response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "subgraph_response_status" + ], + "properties": { + "subgraph_response_status": { + "description": "The subgraph http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_operation_name": { + "description": "The supergraph query operation name.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_operation_kind" + ], + "properties": { + "supergraph_operation_kind": { + "description": "The supergraph query operation kind (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_query": { + "description": "The supergraph query to the subgraph.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "supergraph_query_variable" - ], - "properties": { - "default": { - "description": "Optional default value.", - "anyOf": [ - { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" - }, - { - "description": "f64 values", - "type": "number", - "format": "double" - }, - { - "description": "String values", - "type": "string" - }, - { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] - } - ], - "nullable": true - }, - "supergraph_query_variable": { - "description": "The supergraph query variable name.", - "type": "string" + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "supergraph_request_header" - ], - "properties": { - "default": { - "description": "Optional default value.", - "type": "string", - "nullable": true - }, - "supergraph_request_header": { - "description": "The supergraph request header name.", - "type": "string" + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "request_context" - ], - "properties": { - "default": { - "description": "Optional default value.", - "anyOf": [ - { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" - }, - { - "description": "f64 values", - "type": "number", - "format": "double" - }, - { - "description": "String values", - "type": "string" - }, - { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] - } - ], - "nullable": true - }, - "request_context": { - "description": "The request context key.", + { + "description": "Array of strings", + "type": "array", + "items": { "type": "string" } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "response_context" - ], - "properties": { - "default": { - "description": "Optional default value.", - "anyOf": [ - { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" - }, - { - "description": "f64 values", - "type": "number", - "format": "double" - }, - { - "description": "String values", - "type": "string" - }, - { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] - } - ], - "nullable": true - }, - "response_context": { - "description": "The response context key.", - "type": "string" + } + ] + } + ], + "nullable": true + }, + "supergraph_query_variable": { + "description": "The supergraph query variable name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "supergraph_request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "supergraph_request_header": { + "description": "The supergraph request header name.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "baggage" - ], - "properties": { - "baggage": { - "description": "The name of the baggage item.", - "type": "string" - }, - "default": { - "description": "Optional default value.", - "anyOf": [ - { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" - }, - { - "description": "f64 values", - "type": "number", - "format": "double" - }, - { - "description": "String values", - "type": "string" - }, - { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] - } - ], - "nullable": true + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "env" - ], - "properties": { - "default": { - "description": "Optional default value.", - "type": "string", - "nullable": true - }, - "env": { - "description": "The name of the environment variable", - "type": "string" + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" } }, - "additionalProperties": false - }, - { - "type": "string" - } - ] - } + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" } }, "additionalProperties": false }, - "supergraph": { - "description": "Configuration of supergraph spans. Supergraph spans contain information about the graphql request and response and therefore contain graphql specific attributes.", + { "type": "object", + "required": [ + "response_context" + ], "properties": { - "attributes": { - "description": "Custom attributes that are attached to the supergraph span.", - "default": { - "attributes": { - "graphql.document": null, - "graphql.operation.name": null, - "graphql.operation.type": null + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" }, - "custom": {} - }, - "type": "object", - "properties": { - "graphql.document": { - "description": "The GraphQL document being executed. Examples: * query findBookById { bookById(id: ?) { name } } Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true + { + "description": "i64 values", + "type": "integer", + "format": "int64" }, - "graphql.operation.name": { - "description": "The name of the operation being executed. Examples: * findBookById Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true + { + "description": "f64 values", + "type": "number", + "format": "double" }, - "graphql.operation.type": { - "description": "The type of the operation being executed. Examples: * query * subscription * mutation Requirement level: Recommended", - "default": null, - "type": "boolean", - "nullable": true + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] } - }, - "additionalProperties": { - "anyOf": [ - { - "type": "object", - "required": [ - "operation_name" - ], - "properties": { - "default": { - "description": "Optional default value.", - "type": "string", - "nullable": true - }, - "operation_name": { - "description": "The operation name from the query.", - "oneOf": [ - { - "description": "The raw operation name.", - "type": "string", - "enum": [ - "string" - ] - }, - { - "description": "A hash of the operation name.", - "type": "string", - "enum": [ - "hash" - ] - } - ] + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "operation_kind" - ], - "properties": { - "operation_kind": { - "description": "The operation kind from the query (query|mutation|subscription).", - "oneOf": [ - { - "description": "The raw operation kind.", - "type": "string", - "enum": [ - "string" - ] - } - ] + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "query" - ], - "properties": { - "default": { - "description": "Optional default value.", - "type": "string", - "nullable": true - }, - "query": { - "description": "The graphql query.", - "oneOf": [ - { - "description": "The raw query kind.", - "type": "string", - "enum": [ - "string" - ] - } - ] + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" } }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "query_variable" - ], - "properties": { - "default": { - "description": "Optional default value.", - "anyOf": [ - { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" - }, - { - "description": "f64 values", - "type": "number", - "format": "double" - }, - { - "description": "String values", - "type": "string" - }, - { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] - } - ], - "nullable": true - }, - "query_variable": { - "description": "The name of a graphql query variable.", + { + "description": "Array of strings", + "type": "array", + "items": { "type": "string" } - }, - "additionalProperties": false + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "string" + } + ] + } + }, + "additionalProperties": false + }, + { + "description": "All sub-conditions must be true.", + "type": "object", + "required": [ + "all" + ], + "properties": { + "all": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_SubgraphSelector" + } + } + }, + "additionalProperties": false + }, + { + "description": "At least one sub-conditions must be true.", + "type": "object", + "required": [ + "any" + ], + "properties": { + "any": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_SubgraphSelector" + } + } + }, + "additionalProperties": false + }, + { + "description": "The sub-condition must not be true", + "type": "object", + "required": [ + "not" + ], + "properties": { + "not": { + "$ref": "#/definitions/Condition_for_SubgraphSelector" + } + }, + "additionalProperties": false + }, + { + "description": "Static true condition", + "type": "string", + "enum": [ + "true" + ] + }, + { + "description": "Static false condition", + "type": "string", + "enum": [ + "false" + ] + } + ] + }, + "Condition_for_SupergraphSelector": { + "oneOf": [ + { + "description": "A condition to check a selection against a value.", + "type": "object", + "required": [ + "eq" + ], + "properties": { + "eq": { + "type": "array", + "items": { + "anyOf": [ + { + "description": "A constant value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } }, { - "type": "object", - "required": [ - "request_header" - ], - "properties": { - "default": { - "description": "Optional default value.", + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ] + }, + { + "description": "Selector to extract a value from the pipeline.", + "anyOf": [ + { + "type": "object", + "required": [ + "operation_name" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "operation_name": { + "description": "The operation name from the query.", + "oneOf": [ + { + "description": "The raw operation name.", "type": "string", - "nullable": true + "enum": [ + "string" + ] }, - "request_header": { - "description": "The name of the request header.", - "type": "string" + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] } - }, - "additionalProperties": false + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "operation_kind" + ], + "properties": { + "operation_kind": { + "description": "The operation kind from the query (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true }, - { - "type": "object", - "required": [ - "response_header" - ], - "properties": { - "default": { - "description": "Optional default value.", + "query": { + "description": "The graphql query.", + "oneOf": [ + { + "description": "The raw query kind.", "type": "string", - "nullable": true + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" }, - "response_header": { - "description": "The name of the response header.", + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", "type": "string" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "request_context" - ], - "properties": { - "default": { - "description": "Optional default value.", + }, + { + "description": "Array of homogeneous values", "anyOf": [ { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "f64 values", - "type": "number", - "format": "double" + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } }, { - "description": "String values", - "type": "string" + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } }, { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } - ], - "nullable": true - }, - "request_context": { - "description": "The request context key.", - "type": "string" + ] } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "response_context" ], - "properties": { - "default": { - "description": "Optional default value.", + "nullable": true + }, + "query_variable": { + "description": "The name of a graphql query variable.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "response_header": { + "description": "The name of the response header.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", "anyOf": [ { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "f64 values", - "type": "number", - "format": "double" + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } }, { - "description": "String values", - "type": "string" + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } }, { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } - ], - "nullable": true - }, - "response_context": { - "description": "The response context key.", - "type": "string" + ] } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "baggage" ], - "properties": { - "baggage": { - "description": "The name of the baggage item.", + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", "type": "string" }, - "default": { - "description": "Optional default value.", + { + "description": "Array of homogeneous values", "anyOf": [ { - "description": "bool values", - "type": "boolean" - }, - { - "description": "i64 values", - "type": "integer", - "format": "int64" + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } }, { - "description": "f64 values", - "type": "number", - "format": "double" + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } }, { - "description": "String values", - "type": "string" + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } }, { - "description": "Array of homogeneous values", - "anyOf": [ - { - "description": "Array of bools", - "type": "array", - "items": { - "type": "boolean" - } - }, - { - "description": "Array of integers", - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - { - "description": "Array of floats", - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - { - "description": "Array of strings", - "type": "array", - "items": { - "type": "string" - } - } - ] + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } } - ], - "nullable": true + ] } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "env" ], - "properties": { - "default": { - "description": "Optional default value.", - "type": "string", - "nullable": true + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" }, - "env": { - "description": "The name of the environment variable", + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] } - }, - "additionalProperties": false + ], + "nullable": true + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true }, - { + "env": { + "description": "The name of the environment variable", "type": "string" } - ] + }, + "additionalProperties": false + }, + { + "type": "string" } - } - }, - "additionalProperties": false - } + ] + } + ] }, - "additionalProperties": false + "maxItems": 2, + "minItems": 2 } }, "additionalProperties": false - } - }, - "additionalProperties": false - }, - "tls": { - "description": "TLS related configuration options.", - "default": { - "supergraph": null, - "subgraph": { - "all": { - "certificate_authorities": null, - "client_authentication": null - }, - "subgraphs": {} - } - }, - "type": "object", - "properties": { - "subgraph": { - "description": "Configuration options pertaining to the subgraph server component.", - "default": { - "all": { - "certificate_authorities": null, - "client_authentication": null - }, - "subgraphs": {} - }, + }, + { + "description": "A condition to check a selection against a selector.", "type": "object", + "required": [ + "exists" + ], "properties": { - "all": { - "description": "options applying to all subgraphs", - "default": { - "certificate_authorities": null, - "client_authentication": null - }, - "type": "object", - "properties": { - "certificate_authorities": { - "description": "list of certificate authorities in PEM format", - "default": null, - "type": "string", - "nullable": true - }, - "client_authentication": { - "description": "client certificate authentication", - "default": null, + "exists": { + "anyOf": [ + { "type": "object", "required": [ - "certificate_chain", - "key" + "operation_name" ], "properties": { - "certificate_chain": { - "description": "list of certificates in PEM format", - "writeOnly": true, - "type": "string" + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true }, - "key": { - "description": "key in PEM format", - "writeOnly": true, - "type": "string" + "operation_name": { + "description": "The operation name from the query.", + "oneOf": [ + { + "description": "The raw operation name.", + "type": "string", + "enum": [ + "string" + ] + }, + { + "description": "A hash of the operation name.", + "type": "string", + "enum": [ + "hash" + ] + } + ] } }, - "additionalProperties": false, - "nullable": true - } - }, - "additionalProperties": false - }, - "subgraphs": { - "description": "per subgraph options", - "default": {}, - "type": "object", - "additionalProperties": { - "description": "Configuration options pertaining to the subgraph server component.", - "type": "object", - "properties": { - "certificate_authorities": { - "description": "list of certificate authorities in PEM format", - "default": null, - "type": "string", - "nullable": true + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "operation_kind" + ], + "properties": { + "operation_kind": { + "description": "The operation kind from the query (query|mutation|subscription).", + "oneOf": [ + { + "description": "The raw operation kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } }, - "client_authentication": { - "description": "client certificate authentication", - "default": null, - "type": "object", - "required": [ - "certificate_chain", - "key" - ], - "properties": { - "certificate_chain": { - "description": "list of certificates in PEM format", - "writeOnly": true, - "type": "string" - }, - "key": { - "description": "key in PEM format", - "writeOnly": true, - "type": "string" - } - }, - "additionalProperties": false, - "nullable": true - } + "additionalProperties": false }, - "additionalProperties": false - } - } - } - }, - "supergraph": { - "description": "TLS server configuration\n\nthis will affect the GraphQL endpoint and any other endpoint targeting the same listen address", - "default": null, - "type": "object", - "required": [ - "certificate", - "certificate_chain", - "key" - ], - "properties": { - "certificate": { - "description": "server certificate in PEM format", - "writeOnly": true, - "type": "string" - }, - "certificate_chain": { - "description": "list of certificate authorities in PEM format", - "writeOnly": true, - "type": "string" - }, - "key": { - "description": "server key in PEM format", - "writeOnly": true, - "type": "string" - } - }, - "additionalProperties": false, - "nullable": true - } - }, - "additionalProperties": false - }, - "traffic_shaping": { - "description": "Configuration for the experimental traffic shaping plugin", - "type": "object", - "properties": { - "all": { - "description": "Applied on all subgraphs", - "type": "object", - "properties": { - "compression": { - "description": "Enable compression for subgraphs (available compressions are deflate, br, gzip)", - "oneOf": [ { - "description": "gzip", - "type": "string", - "enum": [ - "gzip" - ] + "type": "object", + "required": [ + "query" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "query": { + "description": "The graphql query.", + "oneOf": [ + { + "description": "The raw query kind.", + "type": "string", + "enum": [ + "string" + ] + } + ] + } + }, + "additionalProperties": false }, { - "description": "deflate", - "type": "string", - "enum": [ - "deflate" - ] + "type": "object", + "required": [ + "query_variable" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "query_variable": { + "description": "The name of a graphql query variable.", + "type": "string" + } + }, + "additionalProperties": false }, { - "description": "brotli", - "type": "string", - "enum": [ - "br" - ] + "type": "object", + "required": [ + "request_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "request_header": { + "description": "The name of the request header.", + "type": "string" + } + }, + "additionalProperties": false }, { - "description": "identity", - "type": "string", - "enum": [ - "identity" - ] - } - ], - "nullable": true - }, - "deduplicate_query": { - "description": "Enable query deduplication", - "type": "boolean", - "nullable": true - }, - "experimental_http2": { - "description": "Enable HTTP2 for subgraphs", - "oneOf": [ - { - "description": "Enable HTTP2 for subgraphs", - "type": "string", - "enum": [ - "enable" - ] + "type": "object", + "required": [ + "response_header" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "response_header": { + "description": "The name of the response header.", + "type": "string" + } + }, + "additionalProperties": false }, { - "description": "Disable HTTP2 for subgraphs", - "type": "string", - "enum": [ - "disable" - ] + "description": "A status from the response", + "type": "object", + "required": [ + "response_status" + ], + "properties": { + "response_status": { + "description": "The http response status code.", + "oneOf": [ + { + "description": "The http status code.", + "type": "string", + "enum": [ + "code" + ] + }, + { + "description": "The http status reason.", + "type": "string", + "enum": [ + "reason" + ] + } + ] + } + }, + "additionalProperties": false }, { - "description": "Only HTTP2 is active", - "type": "string", - "enum": [ - "http2only" - ] - } - ], - "nullable": true - }, - "experimental_retry": { - "description": "Retry configuration", - "type": "object", - "properties": { - "min_per_sec": { - "description": "minimum rate of retries allowed to accomodate clients that have just started issuing requests, or clients that do not issue many requests per window. The default value is 10", - "type": "integer", - "format": "uint32", - "minimum": 0.0, - "nullable": true + "type": "object", + "required": [ + "request_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "request_context": { + "description": "The request context key.", + "type": "string" + } + }, + "additionalProperties": false }, - "retry_mutations": { - "description": "allows request retries on mutations. This should only be activated if mutations are idempotent. Disabled by default", - "type": "boolean", - "nullable": true + { + "type": "object", + "required": [ + "response_context" + ], + "properties": { + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + }, + "response_context": { + "description": "The response context key.", + "type": "string" + } + }, + "additionalProperties": false }, - "retry_percent": { - "description": "percentage of calls to deposit that can be retried. This is in addition to any retries allowed for via min_per_sec. Must be between 0 and 1000, default value is 0.2", - "type": "number", - "format": "float", - "nullable": true + { + "type": "object", + "required": [ + "baggage" + ], + "properties": { + "baggage": { + "description": "The name of the baggage item.", + "type": "string" + }, + "default": { + "description": "Optional default value.", + "anyOf": [ + { + "description": "bool values", + "type": "boolean" + }, + { + "description": "i64 values", + "type": "integer", + "format": "int64" + }, + { + "description": "f64 values", + "type": "number", + "format": "double" + }, + { + "description": "String values", + "type": "string" + }, + { + "description": "Array of homogeneous values", + "anyOf": [ + { + "description": "Array of bools", + "type": "array", + "items": { + "type": "boolean" + } + }, + { + "description": "Array of integers", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + { + "description": "Array of floats", + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + { + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + ] + } + ], + "nullable": true + } + }, + "additionalProperties": false }, - "ttl": { - "description": "how long a single deposit should be considered. Must be between 1 and 60 seconds, default value is 10 seconds", - "default": null, - "type": "string" - } - }, - "additionalProperties": false, - "nullable": true - }, - "global_rate_limit": { - "description": "Enable global rate limiting", - "type": "object", - "required": [ - "capacity", - "interval" - ], - "properties": { - "capacity": { - "description": "Number of requests allowed", - "type": "integer", - "format": "uint64", - "minimum": 1.0 + { + "type": "object", + "required": [ + "env" + ], + "properties": { + "default": { + "description": "Optional default value.", + "type": "string", + "nullable": true + }, + "env": { + "description": "The name of the environment variable", + "type": "string" + } + }, + "additionalProperties": false }, - "interval": { - "description": "Per interval", + { "type": "string" } - }, - "additionalProperties": false, - "nullable": true - }, - "timeout": { - "description": "Enable timeout for incoming requests", - "default": null, - "type": "string" + ] } }, - "additionalProperties": false, - "nullable": true - }, - "deduplicate_variables": { - "description": "DEPRECATED, now always enabled: Enable variable deduplication optimization when sending requests to subgraphs (https://github.com/apollographql/router/issues/87)", - "default": null, - "type": "boolean", - "nullable": true + "additionalProperties": false }, - "router": { - "description": "Applied at the router level", + { + "description": "All sub-conditions must be true.", "type": "object", + "required": [ + "all" + ], "properties": { - "global_rate_limit": { - "description": "Enable global rate limiting", - "type": "object", - "required": [ - "capacity", - "interval" - ], - "properties": { - "capacity": { - "description": "Number of requests allowed", - "type": "integer", - "format": "uint64", - "minimum": 1.0 - }, - "interval": { - "description": "Per interval", - "type": "string" - } - }, - "additionalProperties": false, - "nullable": true - }, - "timeout": { - "description": "Enable timeout for incoming requests", - "default": null, - "type": "string" + "all": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_SupergraphSelector" + } } }, - "additionalProperties": false, - "nullable": true + "additionalProperties": false }, - "subgraphs": { - "description": "Applied on specific subgraphs", + { + "description": "At least one sub-conditions must be true.", "type": "object", - "additionalProperties": { - "description": "Traffic shaping options", - "type": "object", - "properties": { - "compression": { - "description": "Enable compression for subgraphs (available compressions are deflate, br, gzip)", - "oneOf": [ - { - "description": "gzip", - "type": "string", - "enum": [ - "gzip" - ] - }, - { - "description": "deflate", - "type": "string", - "enum": [ - "deflate" - ] - }, - { - "description": "brotli", - "type": "string", - "enum": [ - "br" - ] - }, - { - "description": "identity", - "type": "string", - "enum": [ - "identity" - ] - } - ], - "nullable": true - }, - "deduplicate_query": { - "description": "Enable query deduplication", - "type": "boolean", - "nullable": true - }, - "experimental_http2": { - "description": "Enable HTTP2 for subgraphs", - "oneOf": [ - { - "description": "Enable HTTP2 for subgraphs", - "type": "string", - "enum": [ - "enable" - ] - }, - { - "description": "Disable HTTP2 for subgraphs", - "type": "string", - "enum": [ - "disable" - ] - }, - { - "description": "Only HTTP2 is active", - "type": "string", - "enum": [ - "http2only" - ] - } - ], - "nullable": true - }, - "experimental_retry": { - "description": "Retry configuration", - "type": "object", - "properties": { - "min_per_sec": { - "description": "minimum rate of retries allowed to accomodate clients that have just started issuing requests, or clients that do not issue many requests per window. The default value is 10", - "type": "integer", - "format": "uint32", - "minimum": 0.0, - "nullable": true - }, - "retry_mutations": { - "description": "allows request retries on mutations. This should only be activated if mutations are idempotent. Disabled by default", - "type": "boolean", - "nullable": true - }, - "retry_percent": { - "description": "percentage of calls to deposit that can be retried. This is in addition to any retries allowed for via min_per_sec. Must be between 0 and 1000, default value is 0.2", - "type": "number", - "format": "float", - "nullable": true - }, - "ttl": { - "description": "how long a single deposit should be considered. Must be between 1 and 60 seconds, default value is 10 seconds", - "default": null, - "type": "string" - } - }, - "additionalProperties": false, - "nullable": true - }, - "global_rate_limit": { - "description": "Enable global rate limiting", - "type": "object", - "required": [ - "capacity", - "interval" - ], - "properties": { - "capacity": { - "description": "Number of requests allowed", - "type": "integer", - "format": "uint64", - "minimum": 1.0 - }, - "interval": { - "description": "Per interval", - "type": "string" - } - }, - "additionalProperties": false, - "nullable": true - }, - "timeout": { - "description": "Enable timeout for incoming requests", - "default": null, - "type": "string" + "required": [ + "any" + ], + "properties": { + "any": { + "type": "array", + "items": { + "$ref": "#/definitions/Condition_for_SupergraphSelector" } - }, - "additionalProperties": false - } + } + }, + "additionalProperties": false + }, + { + "description": "The sub-condition must not be true", + "type": "object", + "required": [ + "not" + ], + "properties": { + "not": { + "$ref": "#/definitions/Condition_for_SupergraphSelector" + } + }, + "additionalProperties": false + }, + { + "description": "Static true condition", + "type": "string", + "enum": [ + "true" + ] + }, + { + "description": "Static false condition", + "type": "string", + "enum": [ + "false" + ] } - }, - "additionalProperties": false + ] } } } diff --git a/apollo-router/src/configuration/testdata/metrics/telemetry.router.yaml b/apollo-router/src/configuration/testdata/metrics/telemetry.router.yaml index ae206ff7cf..b67bf4fc3b 100644 --- a/apollo-router/src/configuration/testdata/metrics/telemetry.router.yaml +++ b/apollo-router/src/configuration/testdata/metrics/telemetry.router.yaml @@ -44,3 +44,58 @@ telemetry: subgraph: attributes: subgraph.graphql.document: true + instruments: + router: + http.server.request.body.size: + attributes: + # Standard attributes + http.response.status_code: true + "my_attribute": + response_header: "content-type" + http.server.request.duration: + attributes: + # Standard attributes + http.response.status_code: true + http.request.method: true + # Custom attribute + "my_attribute": + response_header: "content-type" + my.request.duration: # The name of your custom instrument/metric + value: duration + type: counter + unit: s + description: "my description" + acme.request.size: # The name of your custom instrument/metric + value: + request_header: "content-length" + type: counter + unit: s + description: "my description" + + acme.request.length: # The name of your custom instrument/metric + value: + request_header: "content-length" + type: histogram + unit: s + description: "my description" + supergraph: + acme.graphql.requests: + value: unit + type: counter + unit: request + description: "supergraph requests" + attributes: + static: hello + graphql_operation_kind: + operation_kind: string + subgraph: + request_including_price1: + value: unit + type: counter + unit: request + description: "supergraph requests" + condition: + exists: + subgraph_response_data: "$.products[*].price1" + attributes: + subgraph.name: true \ No newline at end of file diff --git a/apollo-router/src/metrics/mod.rs b/apollo-router/src/metrics/mod.rs index 00c342da3a..db3487f7d1 100644 --- a/apollo-router/src/metrics/mod.rs +++ b/apollo-router/src/metrics/mod.rs @@ -185,19 +185,19 @@ pub(crate) mod test_utils { ) -> bool { let attributes = AttributeSet::from(attributes); if let Some(value) = value.to_u64() { - if self.metric_exists(name, &ty, value, &attributes) { + if self.metric_matches(name, &ty, value, &attributes) { return true; } } if let Some(value) = value.to_i64() { - if self.metric_exists(name, &ty, value, &attributes) { + if self.metric_matches(name, &ty, value, &attributes) { return true; } } if let Some(value) = value.to_f64() { - if self.metric_exists(name, &ty, value, &attributes) { + if self.metric_matches(name, &ty, value, &attributes) { return true; } } @@ -205,7 +205,7 @@ pub(crate) mod test_utils { false } - fn metric_exists( + pub(crate) fn metric_matches( &self, name: &str, ty: &MetricType, @@ -231,11 +231,47 @@ pub(crate) mod test_utils { } else if let Some(histogram) = metric.data.as_any().downcast_ref::>() { if matches!(ty, MetricType::Histogram) { - if let Some(value) = value.to_u64() { - return histogram.data_points.iter().any(|datapoint| { - datapoint.attributes == *attributes && datapoint.count == value - }); - } + return histogram.data_points.iter().any(|datapoint| { + datapoint.attributes == *attributes && datapoint.sum == value + }); + } + } + } + false + } + + pub(crate) fn metric_exists( + &self, + name: &str, + ty: MetricType, + attributes: &[KeyValue], + ) -> bool { + let attributes = AttributeSet::from(attributes); + if let Some(metric) = self.find(name) { + // Try to downcast the metric to each type of aggregation and assert that the value is correct. + if let Some(gauge) = metric.data.as_any().downcast_ref::>() { + // Find the datapoint with the correct attributes. + if matches!(ty, MetricType::Gauge) { + return gauge + .data_points + .iter() + .any(|datapoint| datapoint.attributes == attributes); + } + } else if let Some(sum) = metric.data.as_any().downcast_ref::>() { + // Note that we can't actually tell if the sum is monotonic or not, so we just check if it's a sum. + if matches!(ty, MetricType::Counter | MetricType::UpDownCounter) { + return sum + .data_points + .iter() + .any(|datapoint| datapoint.attributes == attributes); + } + } else if let Some(histogram) = metric.data.as_any().downcast_ref::>() + { + if matches!(ty, MetricType::Histogram) { + return histogram + .data_points + .iter() + .any(|datapoint| datapoint.attributes == attributes); } } } @@ -905,7 +941,7 @@ macro_rules! assert_gauge { } #[cfg(test)] -macro_rules! assert_histogram { +macro_rules! assert_histogram_sum { ($($name:ident).+, $value: expr, $($attr_key:literal = $attr_value:expr),+) => { let attributes = vec![$(opentelemetry::KeyValue::new($attr_key, $attr_value)),+]; @@ -932,11 +968,77 @@ macro_rules! assert_histogram { }; ($name:literal, $value: expr) => { - let result = crate::metrics::collect_metrics().assert($name, $value, &[]); + let result = crate::metrics::collect_metrics().assert($name, crate::metrics::test_utils::MetricType::Histogram, $value, &[]); assert_metric!(result, $name, None, Some($value.into()), &[]); }; } +#[cfg(test)] +macro_rules! assert_histogram_exists { + + ($($name:ident).+, $value: ty, $($attr_key:literal = $attr_value:expr),+) => { + let attributes = vec![$(opentelemetry::KeyValue::new($attr_key, $attr_value)),+]; + let result = crate::metrics::collect_metrics().metric_exists::<$value>(stringify!($($name).+), crate::metrics::test_utils::MetricType::Histogram, &attributes); + assert_metric!(result, $name, None, None, &attributes); + }; + + ($($name:ident).+, $value: ty, $($($attr_key:ident).+ = $attr_value:expr),+) => { + let attributes = vec![$(opentelemetry::KeyValue::new(stringify!($($attr_key).+), $attr_value)),+]; + let result = crate::metrics::collect_metrics().metric_exists::<$value>(stringify!($($name).+), crate::metrics::test_utils::MetricType::Histogram, &attributes); + assert_metric!(result, $name, None, None, &attributes); + }; + + ($name:literal, $value: ty, $($attr_key:literal = $attr_value:expr),+) => { + let attributes = vec![$(opentelemetry::KeyValue::new($attr_key, $attr_value)),+]; + let result = crate::metrics::collect_metrics().metric_exists::<$value>($name, crate::metrics::test_utils::MetricType::Histogram, &attributes); + assert_metric!(result, $name, None, None, &attributes); + }; + + ($name:literal, $value: ty, $($($attr_key:ident).+ = $attr_value:expr),+) => { + let attributes = vec![$(opentelemetry::KeyValue::new(stringify!($($attr_key).+), $attr_value)),+]; + let result = crate::metrics::collect_metrics().metric_exists::<$value>($name, crate::metrics::test_utils::MetricType::Histogram, &attributes); + assert_metric!(result, $name, None, None, &attributes); + }; + + ($name:literal, $value: ty) => { + let result = crate::metrics::collect_metrics().metric_exists::<$value>($name, crate::metrics::test_utils::MetricType::Histogram, &[]); + assert_metric!(result, $name, None, None, &[]); + }; +} + +#[cfg(test)] +macro_rules! assert_histogram_not_exists { + + ($($name:ident).+, $value: ty, $($attr_key:literal = $attr_value:expr),+) => { + let attributes = vec![$(opentelemetry::KeyValue::new($attr_key, $attr_value)),+]; + let result = crate::metrics::collect_metrics().metric_exists::<$value>(stringify!($($name).+), crate::metrics::test_utils::MetricType::Histogram, &attributes); + assert_metric!(!result, $name, None, None, &attributes); + }; + + ($($name:ident).+, $value: ty, $($($attr_key:ident).+ = $attr_value:expr),+) => { + let attributes = vec![$(opentelemetry::KeyValue::new(stringify!($($attr_key).+), $attr_value)),+]; + let result = crate::metrics::collect_metrics().metric_exists::<$value>(stringify!($($name).+), crate::metrics::test_utils::MetricType::Histogram, &attributes); + assert_metric!(!result, $name, None, None, &attributes); + }; + + ($name:literal, $value: ty, $($attr_key:literal = $attr_value:expr),+) => { + let attributes = vec![$(opentelemetry::KeyValue::new($attr_key, $attr_value)),+]; + let result = crate::metrics::collect_metrics().metric_exists::<$value>($name, crate::metrics::test_utils::MetricType::Histogram, &attributes); + assert_metric!(!result, $name, None, None, &attributes); + }; + + ($name:literal, $value: ty, $($($attr_key:ident).+ = $attr_value:expr),+) => { + let attributes = vec![$(opentelemetry::KeyValue::new(stringify!($($attr_key).+), $attr_value)),+]; + let result = crate::metrics::collect_metrics().metric_exists::<$value>($name, crate::metrics::test_utils::MetricType::Histogram, &attributes); + assert_metric!(!result, $name, None, None, &attributes); + }; + + ($name:literal, $value: ty) => { + let result = crate::metrics::collect_metrics().metric_exists::<$value>($name, crate::metrics::test_utils::MetricType::Histogram, &[]); + assert_metric!(!result, $name, None, None, &[]); + }; +} + #[cfg(test)] #[allow(unused_macros)] macro_rules! assert_metrics_snapshot { @@ -1143,7 +1245,7 @@ mod test { async fn test_u64_histogram() { async { u64_histogram!("test", "test description", 1, "attr" = "val"); - assert_histogram!("test", 1, "attr" = "val"); + assert_histogram_sum!("test", 1, "attr" = "val"); } .with_metrics() .await; @@ -1153,7 +1255,7 @@ mod test { async fn test_i64_histogram() { async { i64_histogram!("test", "test description", 1, "attr" = "val"); - assert_histogram!("test", 1, "attr" = "val"); + assert_histogram_sum!("test", 1, "attr" = "val"); } .with_metrics() .await; @@ -1163,7 +1265,7 @@ mod test { async fn test_f64_histogram() { async { f64_histogram!("test", "test description", 1.0, "attr" = "val"); - assert_histogram!("test", 1, "attr" = "val"); + assert_histogram_sum!("test", 1, "attr" = "val"); } .with_metrics() .await; @@ -1185,7 +1287,7 @@ mod test { async fn test_type_counter() { async { f64_counter!("test", "test description", 1.0, "attr" = "val"); - assert_histogram!("test", 1, "attr" = "val"); + assert_histogram_sum!("test", 1, "attr" = "val"); } .with_metrics() .await; @@ -1196,7 +1298,7 @@ mod test { async fn test_type_up_down_counter() { async { f64_up_down_counter!("test", "test description", 1.0, "attr" = "val"); - assert_histogram!("test", 1, "attr" = "val"); + assert_histogram_sum!("test", 1, "attr" = "val"); } .with_metrics() .await; @@ -1211,7 +1313,7 @@ mod test { .u64_observable_gauge("test") .with_callback(|m| m.observe(5, &[])) .init(); - assert_histogram!("test", 1, "attr" = "val"); + assert_histogram_sum!("test", 1, "attr" = "val"); } .with_metrics() .await; diff --git a/apollo-router/src/plugins/telemetry/config.rs b/apollo-router/src/plugins/telemetry/config.rs index 7de9717745..a3725a6d3f 100644 --- a/apollo-router/src/plugins/telemetry/config.rs +++ b/apollo-router/src/plugins/telemetry/config.rs @@ -88,9 +88,8 @@ pub(crate) struct Instrumentation { pub(crate) events: config_new::events::Events, /// Span configuration pub(crate) spans: config_new::spans::Spans, - #[serde(skip)] /// Instrument configuration - pub(crate) instruments: config_new::instruments::Instruments, + pub(crate) instruments: config_new::instruments::InstrumentsConfig, } /// Metrics configuration @@ -168,14 +167,14 @@ impl TryInto> for MetricView { record_min_max: true, }, ); - let mut instrument = Instrument::new().name(self.name); + let instrument = Instrument::new().name(self.name); + let mut mask = Stream::new(); if let Some(desc) = self.description { - instrument = instrument.description(desc); + mask = mask.description(desc); } if let Some(unit) = self.unit { - instrument = instrument.unit(Unit::new(unit)); + mask = mask.unit(Unit::new(unit)); } - let mut mask = Stream::new(); if let Some(aggregation) = aggregation { mask = mask.aggregation(aggregation); } diff --git a/apollo-router/src/plugins/telemetry/config_new/attributes.rs b/apollo-router/src/plugins/telemetry/config_new/attributes.rs index be3dc29216..81f99cc8cd 100644 --- a/apollo-router/src/plugins/telemetry/config_new/attributes.rs +++ b/apollo-router/src/plugins/telemetry/config_new/attributes.rs @@ -1,4 +1,3 @@ -use std::collections::LinkedList; use std::fmt::Debug; use std::net::SocketAddr; @@ -45,6 +44,7 @@ use crate::plugins::telemetry::config_new::trace_id; use crate::plugins::telemetry::config_new::DatadogId; use crate::plugins::telemetry::config_new::DefaultForLevel; use crate::plugins::telemetry::config_new::Selectors; +use crate::plugins::telemetry::otlp::TelemetryDataKind; use crate::services::router; use crate::services::router::Request; use crate::services::subgraph; @@ -102,9 +102,13 @@ pub(crate) struct RouterAttributes { } impl DefaultForLevel for RouterAttributes { - fn defaults_for_level(&mut self, requirement_level: DefaultAttributeRequirementLevel) { - self.common.defaults_for_level(requirement_level); - self.server.defaults_for_level(requirement_level); + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { + self.common.defaults_for_level(requirement_level, kind); + self.server.defaults_for_level(requirement_level, kind); } } @@ -135,7 +139,11 @@ pub(crate) struct SupergraphAttributes { } impl DefaultForLevel for SupergraphAttributes { - fn defaults_for_level(&mut self, requirement_level: DefaultAttributeRequirementLevel) { + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + _kind: TelemetryDataKind, + ) { match requirement_level { DefaultAttributeRequirementLevel::Required => {} DefaultAttributeRequirementLevel::Recommended => { @@ -186,7 +194,11 @@ pub(crate) struct SubgraphAttributes { } impl DefaultForLevel for SubgraphAttributes { - fn defaults_for_level(&mut self, requirement_level: DefaultAttributeRequirementLevel) { + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + _kind: TelemetryDataKind, + ) { match requirement_level { DefaultAttributeRequirementLevel::Required => { if self.subgraph_name.is_none() { @@ -301,7 +313,11 @@ pub(crate) struct HttpCommonAttributes { } impl DefaultForLevel for HttpCommonAttributes { - fn defaults_for_level(&mut self, requirement_level: DefaultAttributeRequirementLevel) { + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { match requirement_level { DefaultAttributeRequirementLevel::Required => { if self.error_type.is_none() { @@ -316,17 +332,26 @@ impl DefaultForLevel for HttpCommonAttributes { } DefaultAttributeRequirementLevel::Recommended => { // Recommended - if self.http_request_body_size.is_none() { - self.http_request_body_size = Some(true); - } - if self.http_response_body_size.is_none() { - self.http_response_body_size = Some(true); - } - if self.network_protocol_version.is_none() { - self.network_protocol_version = Some(true); - } - if self.network_type.is_none() { - self.network_type = Some(true); + match kind { + TelemetryDataKind::Traces => { + if self.http_request_body_size.is_none() { + self.http_request_body_size = Some(true); + } + if self.http_response_body_size.is_none() { + self.http_response_body_size = Some(true); + } + if self.network_protocol_version.is_none() { + self.network_protocol_version = Some(true); + } + if self.network_type.is_none() { + self.network_type = Some(true); + } + } + TelemetryDataKind::Metrics => { + if self.network_protocol_version.is_none() { + self.network_protocol_version = Some(true); + } + } } } DefaultAttributeRequirementLevel::None => {} @@ -430,114 +455,69 @@ pub(crate) struct HttpServerAttributes { } impl DefaultForLevel for HttpServerAttributes { - fn defaults_for_level(&mut self, requirement_level: DefaultAttributeRequirementLevel) { + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { match requirement_level { - DefaultAttributeRequirementLevel::Required => { - if self.url_scheme.is_none() { - self.url_scheme = Some(true); - } - if self.url_path.is_none() { - self.url_path = Some(true); - } - if self.url_query.is_none() { - self.url_query = Some(true); - } + DefaultAttributeRequirementLevel::Required => match kind { + TelemetryDataKind::Traces => { + if self.url_scheme.is_none() { + self.url_scheme = Some(true); + } + if self.url_path.is_none() { + self.url_path = Some(true); + } + if self.url_query.is_none() { + self.url_query = Some(true); + } - if self.http_route.is_none() { - self.http_route = Some(true); - } - } - DefaultAttributeRequirementLevel::Recommended => { - if self.client_address.is_none() { - self.client_address = Some(true); - } - if self.server_address.is_none() { - self.server_address = Some(true); + if self.http_route.is_none() { + self.http_route = Some(true); + } } - if self.server_port.is_none() && self.server_address.is_some() { - self.server_port = Some(true); + TelemetryDataKind::Metrics => { + if self.server_address.is_none() { + self.server_address = Some(true); + } + if self.server_port.is_none() && self.server_address.is_some() { + self.server_port = Some(true); + } } - if self.user_agent_original.is_none() { - self.user_agent_original = Some(true); + }, + DefaultAttributeRequirementLevel::Recommended => match kind { + TelemetryDataKind::Traces => { + if self.client_address.is_none() { + self.client_address = Some(true); + } + if self.server_address.is_none() { + self.server_address = Some(true); + } + if self.server_port.is_none() && self.server_address.is_some() { + self.server_port = Some(true); + } + if self.user_agent_original.is_none() { + self.user_agent_original = Some(true); + } } - } + TelemetryDataKind::Metrics => {} + }, DefaultAttributeRequirementLevel::None => {} } } } -/// Attributes for HTTP clients -/// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#http-client -#[derive(Deserialize, JsonSchema, Clone, Default, Debug)] -#[serde(deny_unknown_fields, default)] -pub(crate) struct HttpClientAttributes { - /// The ordinal number of request resending attempt. - /// Examples: - /// * - /// Requirement level: Recommended: if and only if request was retried. - #[serde(rename = "http.resend_count")] - http_resend_count: Option, - - /// Peer address of the network connection - IP address or Unix domain socket name. - /// Examples: - /// * 10.1.2.80 - /// * /tmp/my.sock - /// Requirement level: Recommended: If different than server.address. - #[serde(rename = "network.peer.address")] - network_peer_address: Option, - - /// Peer port number of the network connection. - /// Examples: - /// * 65123 - /// Requirement level: Recommended: If network.peer.address is set. - #[serde(rename = "network.peer.port")] - network_peer_port: Option, - - /// Host identifier of the “URI origin” HTTP request is sent to. - /// Examples: - /// * example.com - /// * 10.1.2.80 - /// * /tmp/my.sock - /// Requirement level: Required - #[serde(rename = "server.address")] - server_address: Option, - - /// Port identifier of the “URI origin” HTTP request is sent to. - /// Examples: - /// * 80 - /// * 8080 - /// * 433 - /// Requirement level: Conditionally Required - #[serde(rename = "server.port")] - server_port: Option, - - /// Absolute URL describing a network resource according to RFC3986 - /// Examples: - /// * https://www.foo.bar/search?q=OpenTelemetry#SemConv; - /// * localhost - /// Requirement level: Required - #[serde(rename = "url.full")] - url_full: Option, - - /// Value of the HTTP User-Agent header sent by the client. - /// Examples: - /// * CERN-LineMode/2.15 - /// * libwww/2.17b3 - /// Requirement level: Opt-In - #[serde(rename = "user_agent.original")] - user_agent_original: Option, -} - impl Selectors for RouterAttributes { type Request = router::Request; type Response = router::Response; - fn on_request(&self, request: &router::Request) -> LinkedList { + fn on_request(&self, request: &router::Request) -> Vec { let mut attrs = self.common.on_request(request); attrs.extend(self.server.on_request(request)); if let Some(true) = &self.trace_id { if let Some(trace_id) = trace_id() { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( Key::from_static_str("trace_id"), trace_id.to_string(), )); @@ -545,7 +525,7 @@ impl Selectors for RouterAttributes { } if let Some(true) = &self.datadog_trace_id { if let Some(trace_id) = trace_id() { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( Key::from_static_str("dd.trace_id"), trace_id.to_datadog(), )); @@ -555,20 +535,20 @@ impl Selectors for RouterAttributes { let context = Span::current().context(); let baggage = context.baggage(); for (key, (value, _)) in baggage { - attrs.push_back(KeyValue::new(key.clone(), value.clone())); + attrs.push(KeyValue::new(key.clone(), value.clone())); } } attrs } - fn on_response(&self, response: &router::Response) -> LinkedList { + fn on_response(&self, response: &router::Response) -> Vec { let mut attrs = self.common.on_response(response); attrs.extend(self.server.on_response(response)); attrs } - fn on_error(&self, error: &BoxError) -> LinkedList { + fn on_error(&self, error: &BoxError) -> Vec { let mut attrs = self.common.on_error(error); attrs.extend(self.server.on_error(error)); attrs @@ -579,10 +559,10 @@ impl Selectors for HttpCommonAttributes { type Request = router::Request; type Response = router::Response; - fn on_request(&self, request: &router::Request) -> LinkedList { - let mut attrs = LinkedList::new(); + fn on_request(&self, request: &router::Request) -> Vec { + let mut attrs = Vec::new(); if let Some(true) = &self.http_request_method { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( HTTP_REQUEST_METHOD, request.router_request.method().as_str().to_string(), )); @@ -595,7 +575,7 @@ impl Selectors for HttpCommonAttributes { .get(&CONTENT_LENGTH) .and_then(|h| h.to_str().ok()) { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( HTTP_REQUEST_BODY_SIZE, content_length.to_string(), )); @@ -603,17 +583,17 @@ impl Selectors for HttpCommonAttributes { } if let Some(true) = &self.network_protocol_name { if let Some(scheme) = request.router_request.uri().scheme() { - attrs.push_back(KeyValue::new(NETWORK_PROTOCOL_NAME, scheme.to_string())); + attrs.push(KeyValue::new(NETWORK_PROTOCOL_NAME, scheme.to_string())); } } if let Some(true) = &self.network_protocol_version { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( NETWORK_PROTOCOL_VERSION, format!("{:?}", request.router_request.version()), )); } if let Some(true) = &self.network_transport { - attrs.push_back(KeyValue::new(NETWORK_TRANSPORT, "tcp".to_string())); + attrs.push(KeyValue::new(NETWORK_TRANSPORT, "tcp".to_string())); } if let Some(true) = &self.network_type { if let Some(connection_info) = @@ -621,9 +601,9 @@ impl Selectors for HttpCommonAttributes { { if let Some(socket) = connection_info.server_address { if socket.is_ipv4() { - attrs.push_back(KeyValue::new(NETWORK_TYPE, "ipv4".to_string())); + attrs.push(KeyValue::new(NETWORK_TYPE, "ipv4".to_string())); } else if socket.is_ipv6() { - attrs.push_back(KeyValue::new(NETWORK_TYPE, "ipv6".to_string())); + attrs.push(KeyValue::new(NETWORK_TYPE, "ipv6".to_string())); } } } @@ -632,8 +612,8 @@ impl Selectors for HttpCommonAttributes { attrs } - fn on_response(&self, response: &router::Response) -> LinkedList { - let mut attrs = LinkedList::new(); + fn on_response(&self, response: &router::Response) -> Vec { + let mut attrs = Vec::new(); if let Some(true) = &self.http_response_body_size { if let Some(content_length) = response .response @@ -641,14 +621,15 @@ impl Selectors for HttpCommonAttributes { .get(&CONTENT_LENGTH) .and_then(|h| h.to_str().ok()) { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( HTTP_RESPONSE_BODY_SIZE, content_length.to_string(), )); } } + if let Some(true) = &self.http_response_status_code { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( HTTP_RESPONSE_STATUS_CODE, response.response.status().as_u16() as i64, )); @@ -656,7 +637,7 @@ impl Selectors for HttpCommonAttributes { if let Some(true) = &self.error_type { if !response.response.status().is_success() { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( ERROR_TYPE, response .response @@ -670,10 +651,10 @@ impl Selectors for HttpCommonAttributes { attrs } - fn on_error(&self, _error: &BoxError) -> LinkedList { - let mut attrs = LinkedList::new(); + fn on_error(&self, _error: &BoxError) -> Vec { + let mut attrs = Vec::new(); if let Some(true) = &self.error_type { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( ERROR_TYPE, StatusCode::INTERNAL_SERVER_ERROR .canonical_reason() @@ -681,7 +662,7 @@ impl Selectors for HttpCommonAttributes { )); } if let Some(true) = &self.http_response_status_code { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( HTTP_RESPONSE_STATUS_CODE, StatusCode::INTERNAL_SERVER_ERROR.as_u16() as i64, )); @@ -695,33 +676,33 @@ impl Selectors for HttpServerAttributes { type Request = router::Request; type Response = router::Response; - fn on_request(&self, request: &router::Request) -> LinkedList { - let mut attrs = LinkedList::new(); + fn on_request(&self, request: &router::Request) -> Vec { + let mut attrs = Vec::new(); if let Some(true) = &self.http_route { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( HTTP_ROUTE, request.router_request.uri().path().to_string(), )); } if let Some(true) = &self.client_address { if let Some(forwarded) = Self::forwarded_for(request) { - attrs.push_back(KeyValue::new(CLIENT_ADDRESS, forwarded.ip().to_string())); + attrs.push(KeyValue::new(CLIENT_ADDRESS, forwarded.ip().to_string())); } else if let Some(connection_info) = request.router_request.extensions().get::() { if let Some(socket) = connection_info.peer_address { - attrs.push_back(KeyValue::new(CLIENT_ADDRESS, socket.ip().to_string())); + attrs.push(KeyValue::new(CLIENT_ADDRESS, socket.ip().to_string())); } } } if let Some(true) = &self.client_port { if let Some(forwarded) = Self::forwarded_for(request) { - attrs.push_back(KeyValue::new(CLIENT_PORT, forwarded.port() as i64)); + attrs.push(KeyValue::new(CLIENT_PORT, forwarded.port() as i64)); } else if let Some(connection_info) = request.router_request.extensions().get::() { if let Some(socket) = connection_info.peer_address { - attrs.push_back(KeyValue::new(CLIENT_PORT, socket.port() as i64)); + attrs.push(KeyValue::new(CLIENT_PORT, socket.port() as i64)); } } } @@ -730,23 +711,23 @@ impl Selectors for HttpServerAttributes { if let Some(forwarded) = Self::forwarded_host(request).and_then(|h| h.host().map(|h| h.to_string())) { - attrs.push_back(KeyValue::new(SERVER_ADDRESS, forwarded)); + attrs.push(KeyValue::new(SERVER_ADDRESS, forwarded)); } else if let Some(connection_info) = request.router_request.extensions().get::() { if let Some(socket) = connection_info.server_address { - attrs.push_back(KeyValue::new(SERVER_ADDRESS, socket.ip().to_string())); + attrs.push(KeyValue::new(SERVER_ADDRESS, socket.ip().to_string())); } } } if let Some(true) = &self.server_port { if let Some(forwarded) = Self::forwarded_host(request).and_then(|h| h.port_u16()) { - attrs.push_back(KeyValue::new(SERVER_PORT, forwarded as i64)); + attrs.push(KeyValue::new(SERVER_PORT, forwarded as i64)); } else if let Some(connection_info) = request.router_request.extensions().get::() { if let Some(socket) = connection_info.server_address { - attrs.push_back(KeyValue::new(SERVER_PORT, socket.port() as i64)); + attrs.push(KeyValue::new(SERVER_PORT, socket.port() as i64)); } } } @@ -756,7 +737,7 @@ impl Selectors for HttpServerAttributes { request.router_request.extensions().get::() { if let Some(socket) = connection_info.server_address { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( NETWORK_LOCAL_ADDRESS, socket.ip().to_string(), )); @@ -768,7 +749,7 @@ impl Selectors for HttpServerAttributes { request.router_request.extensions().get::() { if let Some(socket) = connection_info.server_address { - attrs.push_back(KeyValue::new(NETWORK_LOCAL_PORT, socket.port() as i64)); + attrs.push(KeyValue::new(NETWORK_LOCAL_PORT, socket.port() as i64)); } } } @@ -778,7 +759,7 @@ impl Selectors for HttpServerAttributes { request.router_request.extensions().get::() { if let Some(socket) = connection_info.peer_address { - attrs.push_back(KeyValue::new(NETWORK_PEER_ADDRESS, socket.ip().to_string())); + attrs.push(KeyValue::new(NETWORK_PEER_ADDRESS, socket.ip().to_string())); } } } @@ -787,23 +768,23 @@ impl Selectors for HttpServerAttributes { request.router_request.extensions().get::() { if let Some(socket) = connection_info.peer_address { - attrs.push_back(KeyValue::new(NETWORK_PEER_PORT, socket.port() as i64)); + attrs.push(KeyValue::new(NETWORK_PEER_PORT, socket.port() as i64)); } } } let router_uri = request.router_request.uri(); if let Some(true) = &self.url_path { - attrs.push_back(KeyValue::new(URL_PATH, router_uri.path().to_string())); + attrs.push(KeyValue::new(URL_PATH, router_uri.path().to_string())); } if let Some(true) = &self.url_query { if let Some(query) = router_uri.query() { - attrs.push_back(KeyValue::new(URL_QUERY, query.to_string())); + attrs.push(KeyValue::new(URL_QUERY, query.to_string())); } } if let Some(true) = &self.url_scheme { if let Some(scheme) = router_uri.scheme_str() { - attrs.push_back(KeyValue::new(URL_SCHEME, scheme.to_string())); + attrs.push(KeyValue::new(URL_SCHEME, scheme.to_string())); } } if let Some(true) = &self.user_agent_original { @@ -813,19 +794,19 @@ impl Selectors for HttpServerAttributes { .get(&USER_AGENT) .and_then(|h| h.to_str().ok()) { - attrs.push_back(KeyValue::new(USER_AGENT_ORIGINAL, user_agent.to_string())); + attrs.push(KeyValue::new(USER_AGENT_ORIGINAL, user_agent.to_string())); } } attrs } - fn on_response(&self, _response: &router::Response) -> LinkedList { - LinkedList::default() + fn on_response(&self, _response: &router::Response) -> Vec { + Vec::default() } - fn on_error(&self, _error: &BoxError) -> LinkedList { - LinkedList::default() + fn on_error(&self, _error: &BoxError) -> Vec { + Vec::default() } } @@ -848,7 +829,7 @@ impl HttpServerAttributes { .next() } - fn forwarded_host(request: &Request) -> Option { + pub(crate) fn forwarded_host(request: &Request) -> Option { request .router_request .headers() @@ -871,11 +852,11 @@ impl Selectors for SupergraphAttributes { type Request = supergraph::Request; type Response = supergraph::Response; - fn on_request(&self, request: &supergraph::Request) -> LinkedList { - let mut attrs = LinkedList::new(); + fn on_request(&self, request: &supergraph::Request) -> Vec { + let mut attrs = Vec::new(); if let Some(true) = &self.graphql_document { if let Some(query) = &request.supergraph_request.body().query { - attrs.push_back(KeyValue::new(GRAPHQL_DOCUMENT, query.clone())); + attrs.push(KeyValue::new(GRAPHQL_DOCUMENT, query.clone())); } } if let Some(true) = &self.graphql_operation_name { @@ -884,7 +865,7 @@ impl Selectors for SupergraphAttributes { .get::<_, String>(OPERATION_NAME) .unwrap_or_default() { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( GRAPHQL_OPERATION_NAME, operation_name.clone(), )); @@ -896,7 +877,7 @@ impl Selectors for SupergraphAttributes { .get::<_, String>(OPERATION_KIND) .unwrap_or_default() { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( GRAPHQL_OPERATION_TYPE, operation_type.clone(), )); @@ -906,12 +887,12 @@ impl Selectors for SupergraphAttributes { attrs } - fn on_response(&self, _response: &supergraph::Response) -> LinkedList { - LinkedList::default() + fn on_response(&self, _response: &supergraph::Response) -> Vec { + Vec::default() } - fn on_error(&self, _error: &BoxError) -> LinkedList { - LinkedList::default() + fn on_error(&self, _error: &BoxError) -> Vec { + Vec::default() } } @@ -919,16 +900,16 @@ impl Selectors for SubgraphAttributes { type Request = subgraph::Request; type Response = subgraph::Response; - fn on_request(&self, request: &subgraph::Request) -> LinkedList { - let mut attrs = LinkedList::new(); + fn on_request(&self, request: &subgraph::Request) -> Vec { + let mut attrs = Vec::new(); if let Some(true) = &self.graphql_document { if let Some(query) = &request.subgraph_request.body().query { - attrs.push_back(KeyValue::new(SUBGRAPH_GRAPHQL_DOCUMENT, query.clone())); + attrs.push(KeyValue::new(SUBGRAPH_GRAPHQL_DOCUMENT, query.clone())); } } if let Some(true) = &self.graphql_operation_name { if let Some(op_name) = &request.subgraph_request.body().operation_name { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( SUBGRAPH_GRAPHQL_OPERATION_NAME, op_name.clone(), )); @@ -941,7 +922,7 @@ impl Selectors for SubgraphAttributes { .get::<_, String>(OPERATION_KIND) .unwrap_or_default() { - attrs.push_back(KeyValue::new( + attrs.push(KeyValue::new( SUBGRAPH_GRAPHQL_OPERATION_TYPE, operation_type.clone(), )); @@ -949,19 +930,19 @@ impl Selectors for SubgraphAttributes { } if let Some(true) = &self.subgraph_name { if let Some(subgraph_name) = &request.subgraph_name { - attrs.push_back(KeyValue::new(SUBGRAPH_NAME, subgraph_name.clone())); + attrs.push(KeyValue::new(SUBGRAPH_NAME, subgraph_name.clone())); } } attrs } - fn on_response(&self, _response: &subgraph::Response) -> LinkedList { - LinkedList::default() + fn on_response(&self, _response: &subgraph::Response) -> Vec { + Vec::default() } - fn on_error(&self, _error: &BoxError) -> LinkedList { - LinkedList::default() + fn on_error(&self, _error: &BoxError) -> Vec { + Vec::default() } } diff --git a/apollo-router/src/plugins/telemetry/config_new/conditions.rs b/apollo-router/src/plugins/telemetry/config_new/conditions.rs index f09ebb5d59..773b4a4d82 100644 --- a/apollo-router/src/plugins/telemetry/config_new/conditions.rs +++ b/apollo-router/src/plugins/telemetry/config_new/conditions.rs @@ -11,17 +11,29 @@ use crate::plugins::telemetry::config_new::Selector; pub(crate) enum Condition { /// A condition to check a selection against a value. Eq([SelectorOrValue; 2]), + /// A condition to check a selection against a selector. + Exists(T), /// All sub-conditions must be true. All(Vec>), /// At least one sub-conditions must be true. Any(Vec>), /// The sub-condition must not be true Not(Box>), + /// Static true condition + True, + /// Static false condition + False, +} + +impl Default for Condition { + fn default() -> Self { + Self::True + } } impl Condition<()> { pub(crate) fn empty() -> Condition { - Condition::Any(vec![]) + Condition::True } } @@ -40,21 +52,92 @@ impl Condition where T: Selector, { - fn evaluate(&self, request: &T::Request, response: &T::Response) -> bool { + pub(crate) fn evaluate_request(&mut self, request: &T::Request) -> Option { + match self { + Condition::Eq(eq) => match (eq[0].on_request(request), eq[1].on_request(request)) { + (None, None) => None, + (None, Some(right)) => { + eq[1] = SelectorOrValue::Value(right.into()); + None + } + (Some(left), None) => { + eq[0] = SelectorOrValue::Value(left.into()); + None + } + (Some(left), Some(right)) => { + if left == right { + *self = Condition::True; + Some(true) + } else { + Some(false) + } + } + }, + Condition::Exists(exist) => { + if exist.on_request(request).is_some() { + *self = Condition::True; + Some(true) + } else { + None + } + } + Condition::All(all) => { + if all.is_empty() { + *self = Condition::True; + return Some(true); + } + let mut response = Some(true); + for cond in all { + match cond.evaluate_request(request) { + Some(resp) => { + response = response.map(|r| resp && r); + } + None => { + response = None; + } + } + } + + response + } + Condition::Any(any) => { + if any.is_empty() { + *self = Condition::True; + return Some(true); + } + let mut response: Option = Some(false); + for cond in any { + match cond.evaluate_request(request) { + Some(resp) => { + response = response.map(|r| resp || r); + } + None => { + response = None; + } + } + } + + response + } + Condition::Not(not) => not.evaluate_request(request).map(|r| !r), + Condition::True => Some(true), + Condition::False => Some(false), + } + } + + pub(crate) fn evaluate_response(&self, response: &T::Response) -> bool { match self { Condition::Eq(eq) => { - // We don't know if the selection was for the request or result, so we try both. - let left = eq[0] - .on_request(request) - .or_else(|| eq[0].on_response(response)); - let right = eq[1] - .on_request(request) - .or_else(|| eq[1].on_response(response)); + let left = eq[0].on_response(response); + let right = eq[1].on_response(response); left == right } - Condition::All(all) => all.iter().all(|c| c.evaluate(request, response)), - Condition::Any(any) => any.iter().any(|c| c.evaluate(request, response)), - Condition::Not(not) => !not.evaluate(request, response), + Condition::Exists(exist) => exist.on_response(response).is_some(), + Condition::All(all) => all.iter().all(|c| c.evaluate_response(response)), + Condition::Any(any) => any.iter().any(|c| c.evaluate_response(response)), + Condition::Not(not) => !not.evaluate_response(response), + Condition::True => true, + Condition::False => false, } } } @@ -103,54 +186,127 @@ mod test { } } + enum TestSelectorReqRes { + Req, + Resp, + } + + impl Selector for TestSelectorReqRes { + type Request = Option; + type Response = Option; + + fn on_request(&self, request: &Self::Request) -> Option { + match self { + TestSelectorReqRes::Req => request.map(Value::I64), + TestSelectorReqRes::Resp => None, + } + } + + fn on_response(&self, response: &Self::Response) -> Option { + match self { + TestSelectorReqRes::Req => None, + TestSelectorReqRes::Resp => response.map(Value::I64), + } + } + } + + #[test] + fn test_condition_exist() { + assert_eq!( + None, + Condition::::Exists(TestSelectorReqRes::Req) + .evaluate_request(&None) + ); + assert!( + !Condition::::Exists(TestSelectorReqRes::Req) + .evaluate_response(&Some(3i64)) + ); + assert_eq!( + Some(true), + Condition::::Exists(TestSelectorReqRes::Req) + .evaluate_request(&Some(2i64)) + ); + assert!( + Condition::::Exists(TestSelectorReqRes::Resp) + .evaluate_response(&Some(3i64)) + ); + } + #[test] fn test_condition_eq() { + assert_eq!( + Some(true), + Condition::::Eq([ + SelectorOrValue::Value(1i64.into()), + SelectorOrValue::Value(1i64.into()), + ]) + .evaluate_request(&None) + ); assert!(Condition::::Eq([ SelectorOrValue::Value(1i64.into()), SelectorOrValue::Value(1i64.into()), ]) - .evaluate(&None, &None)); + .evaluate_response(&None)); assert!(!Condition::::Eq([ SelectorOrValue::Value(1i64.into()), SelectorOrValue::Value(2i64.into()), ]) - .evaluate(&None, &None)); + .evaluate_response(&None)); } #[test] fn test_condition_eq_selector() { + assert_eq!( + Some(true), + Condition::::Eq([ + SelectorOrValue::Selector(TestSelector), + SelectorOrValue::Value(1i64.into()), + ]) + .evaluate_request(&Some(1i64)) + ); + assert_eq!( + Some(true), + Condition::::Eq([ + SelectorOrValue::Value(1i64.into()), + SelectorOrValue::Selector(TestSelector), + ]) + .evaluate_request(&Some(1i64)) + ); + assert!(Condition::::Eq([ SelectorOrValue::Selector(TestSelector), - SelectorOrValue::Value(1i64.into()), - ]) - .evaluate(&Some(1i64), &None)); - assert!(Condition::::Eq([ - SelectorOrValue::Value(1i64.into()), - SelectorOrValue::Selector(TestSelector), + SelectorOrValue::Value(2i64.into()), ]) - .evaluate(&Some(1i64), &None)); + .evaluate_request(&None) + .is_none()); assert!(Condition::::Eq([ SelectorOrValue::Selector(TestSelector), SelectorOrValue::Value(2i64.into()), ]) - .evaluate(&None, &Some(2i64))); + .evaluate_response(&Some(2i64))); assert!(Condition::::Eq([ SelectorOrValue::Value(2i64.into()), SelectorOrValue::Selector(TestSelector), ]) - .evaluate(&None, &Some(2i64))); + .evaluate_response(&Some(2i64))); assert!(!Condition::::Eq([ SelectorOrValue::Selector(TestSelector), SelectorOrValue::Value(3i64.into()), ]) - .evaluate(&None, &None)); + .evaluate_response(&None)); assert!(!Condition::::Eq([ SelectorOrValue::Value(3i64.into()), SelectorOrValue::Selector(TestSelector), ]) - .evaluate(&None, &None)); + .evaluate_response(&None)); + + let mut condition = Condition::::Eq([ + SelectorOrValue::Value(3i64.into()), + SelectorOrValue::Selector(TestSelectorReqRes::Req), + ]); + assert_eq!(Some(false), condition.evaluate_request(&Some(2i64))); } #[test] @@ -159,13 +315,13 @@ mod test { SelectorOrValue::Value(1i64.into()), SelectorOrValue::Value(2i64.into()), ]))) - .evaluate(&None, &None)); + .evaluate_response(&None)); assert!(!Condition::::Not(Box::new(Condition::Eq([ SelectorOrValue::Value(1i64.into()), SelectorOrValue::Value(1i64.into()), ]))) - .evaluate(&None, &None)); + .evaluate_response(&None)); } #[test] @@ -180,7 +336,49 @@ mod test { SelectorOrValue::Value(2i64.into()), ]) ]) - .evaluate(&None, &None)); + .evaluate_response(&None)); + + let mut condition = Condition::::All(vec![ + Condition::Eq([ + SelectorOrValue::Value(1i64.into()), + SelectorOrValue::Selector(TestSelectorReqRes::Req), + ]), + Condition::Eq([ + SelectorOrValue::Value(3i64.into()), + SelectorOrValue::Selector(TestSelectorReqRes::Resp), + ]), + ]); + + assert!(condition.evaluate_request(&Some(1i64)).is_none()); + assert!(condition.evaluate_response(&Some(3i64))); + + let mut condition = Condition::::All(vec![ + Condition::Eq([ + SelectorOrValue::Value(1i64.into()), + SelectorOrValue::Selector(TestSelectorReqRes::Req), + ]), + Condition::Eq([ + SelectorOrValue::Value(3i64.into()), + SelectorOrValue::Selector(TestSelectorReqRes::Resp), + ]), + ]); + + assert!(condition.evaluate_request(&Some(1i64)).is_none()); + assert!(!condition.evaluate_response(&Some(2i64))); + + let mut condition = Condition::::All(vec![ + Condition::Eq([ + SelectorOrValue::Value(1i64.into()), + SelectorOrValue::Selector(TestSelectorReqRes::Req), + ]), + Condition::Eq([ + SelectorOrValue::Value(3i64.into()), + SelectorOrValue::Selector(TestSelectorReqRes::Req), + ]), + ]); + + assert_eq!(Some(false), condition.evaluate_request(&Some(1i64))); + assert!(!condition.evaluate_response(&Some(2i64))); assert!(!Condition::::All(vec![ Condition::Eq([ @@ -192,8 +390,9 @@ mod test { SelectorOrValue::Value(2i64.into()), ]) ]) - .evaluate(&None, &None)); + .evaluate_response(&None)); } + #[test] fn test_condition_any() { assert!(Condition::::Any(vec![ @@ -206,7 +405,7 @@ mod test { SelectorOrValue::Value(2i64.into()), ]) ]) - .evaluate(&None, &None)); + .evaluate_response(&None)); assert!(!Condition::::All(vec![ Condition::Eq([ @@ -218,6 +417,6 @@ mod test { SelectorOrValue::Value(2i64.into()), ]) ]) - .evaluate(&None, &None)); + .evaluate_response(&None)); } } diff --git a/apollo-router/src/plugins/telemetry/config_new/extendable.rs b/apollo-router/src/plugins/telemetry/config_new/extendable.rs index f365c5fb28..ae08b71539 100644 --- a/apollo-router/src/plugins/telemetry/config_new/extendable.rs +++ b/apollo-router/src/plugins/telemetry/config_new/extendable.rs @@ -1,7 +1,7 @@ use std::any::type_name; use std::collections::HashMap; -use std::collections::LinkedList; use std::fmt::Debug; +use std::sync::Arc; use opentelemetry::KeyValue; use schemars::gen::SchemaGenerator; @@ -22,6 +22,7 @@ use crate::plugins::telemetry::config_new::attributes::DefaultAttributeRequireme use crate::plugins::telemetry::config_new::DefaultForLevel; use crate::plugins::telemetry::config_new::Selector; use crate::plugins::telemetry::config_new::Selectors; +use crate::plugins::telemetry::otlp::TelemetryDataKind; /// This struct can be used as an attributes container, it has a custom JsonSchema implementation that will merge the schemas of the attributes and custom fields. #[derive(Clone, Debug)] @@ -38,8 +39,12 @@ impl DefaultForLevel for Extendable where Att: DefaultForLevel + Default, { - fn defaults_for_level(&mut self, requirement_level: DefaultAttributeRequirementLevel) { - self.attributes.defaults_for_level(requirement_level); + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { + self.attributes.defaults_for_level(requirement_level, kind); } } @@ -50,6 +55,12 @@ impl Extendable<(), ()> { { Default::default() } + pub(crate) fn empty_arc() -> Arc> + where + A: Default, + { + Default::default() + } } /// Custom Deserializer for attributes that will deserializse into a custom field if possible, but otherwise into one of the pre-defined attributes. @@ -154,7 +165,7 @@ where type Request = Request; type Response = Response; - fn on_request(&self, request: &Self::Request) -> LinkedList { + fn on_request(&self, request: &Self::Request) -> Vec { let mut attrs = self.attributes.on_request(request); let custom_attributes = self.custom.iter().filter_map(|(key, value)| { value @@ -166,7 +177,7 @@ where attrs } - fn on_response(&self, response: &Self::Response) -> LinkedList { + fn on_response(&self, response: &Self::Response) -> Vec { let mut attrs = self.attributes.on_response(response); let custom_attributes = self.custom.iter().filter_map(|(key, value)| { value @@ -178,7 +189,7 @@ where attrs } - fn on_error(&self, error: &BoxError) -> LinkedList { + fn on_error(&self, error: &BoxError) -> Vec { self.attributes.on_error(error) } } diff --git a/apollo-router/src/plugins/telemetry/config_new/instruments.rs b/apollo-router/src/plugins/telemetry/config_new/instruments.rs index 96978b1c10..76fc854b13 100644 --- a/apollo-router/src/plugins/telemetry/config_new/instruments.rs +++ b/apollo-router/src/plugins/telemetry/config_new/instruments.rs @@ -1,8 +1,26 @@ +use std::collections::HashMap; use std::fmt::Debug; +use std::sync::Arc; +use opentelemetry_api::metrics::Counter; +use opentelemetry_api::metrics::Histogram; +use opentelemetry_api::metrics::MeterProvider; +use opentelemetry_api::metrics::UpDownCounter; +use opentelemetry_api::KeyValue; +use opentelemetry_semantic_conventions::trace::HTTP_REQUEST_METHOD; +use opentelemetry_semantic_conventions::trace::SERVER_ADDRESS; +use opentelemetry_semantic_conventions::trace::SERVER_PORT; +use opentelemetry_semantic_conventions::trace::URL_SCHEME; +use parking_lot::Mutex; use schemars::JsonSchema; use serde::Deserialize; +use tokio::time::Instant; +use tower::BoxError; +use super::attributes::HttpServerAttributes; +use super::DefaultForLevel; +use super::Selector; +use crate::metrics; use crate::plugins::telemetry::config_new::attributes::DefaultAttributeRequirementLevel; use crate::plugins::telemetry::config_new::attributes::RouterAttributes; use crate::plugins::telemetry::config_new::attributes::SubgraphAttributes; @@ -12,36 +30,271 @@ use crate::plugins::telemetry::config_new::extendable::Extendable; use crate::plugins::telemetry::config_new::selectors::RouterSelector; use crate::plugins::telemetry::config_new::selectors::SubgraphSelector; use crate::plugins::telemetry::config_new::selectors::SupergraphSelector; +use crate::plugins::telemetry::config_new::Selectors; +use crate::plugins::telemetry::otlp::TelemetryDataKind; +use crate::services::router; +use crate::services::subgraph; +use crate::services::supergraph; +use crate::Context; + +const METER_NAME: &str = "apollo/router"; #[allow(dead_code)] #[derive(Clone, Deserialize, JsonSchema, Debug, Default)] #[serde(deny_unknown_fields, default)] -pub(crate) struct Instruments { - /// The attributes to include by default in instruments based on their level as specified in the otel semantic conventions and Apollo documentation. - default_attribute_requirement_level: DefaultAttributeRequirementLevel, +pub(crate) struct InstrumentsConfig { + /// The attributes and instruments to include by default in instruments based on their level as specified in the otel semantic conventions and Apollo documentation. + pub(crate) default_requirement_level: DefaultAttributeRequirementLevel, /// Router service instruments. For more information see documentation on Router lifecycle. - router: Extendable>, + pub(crate) router: + Extendable>, /// Supergraph service instruments. For more information see documentation on Router lifecycle. - supergraph: + pub(crate) supergraph: Extendable>, /// Subgraph service instruments. For more information see documentation on Router lifecycle. - subgraph: Extendable>, + pub(crate) subgraph: + Extendable>, +} + +impl InstrumentsConfig { + /// Update the defaults for spans configuration regarding the `default_attribute_requirement_level` + pub(crate) fn update_defaults(&mut self) { + self.router + .attributes + .defaults_for_levels(self.default_requirement_level, TelemetryDataKind::Metrics); + self.supergraph + .defaults_for_levels(self.default_requirement_level, TelemetryDataKind::Metrics); + self.subgraph + .defaults_for_levels(self.default_requirement_level, TelemetryDataKind::Metrics); + } + + pub(crate) fn new_router_instruments(&self) -> RouterInstruments { + let meter = metrics::meter_provider().meter(METER_NAME); + let http_server_request_duration = self + .router + .attributes + .http_server_request_duration + .is_enabled() + .then(|| CustomHistogram { + inner: Mutex::new(CustomHistogramInner { + increment: Increment::Duration(Instant::now()), + histogram: Some(meter.f64_histogram("http.server.request.duration").init()), + attributes: Vec::new(), + selector: None, + selectors: match &self.router.attributes.http_server_request_duration { + DefaultedStandardInstrument::Bool(_) + | DefaultedStandardInstrument::Unset => None, + DefaultedStandardInstrument::Extendable { attributes } => { + Some(attributes.clone()) + } + }, + }), + }); + let http_server_request_body_size = + self.router + .attributes + .http_server_request_body_size + .is_enabled() + .then(|| { + let mut nb_attributes = 0; + let selectors = match &self.router.attributes.http_server_request_body_size { + DefaultedStandardInstrument::Bool(_) + | DefaultedStandardInstrument::Unset => None, + DefaultedStandardInstrument::Extendable { attributes } => { + nb_attributes = attributes.custom.len(); + Some(attributes.clone()) + } + }; + CustomHistogram { + inner: Mutex::new(CustomHistogramInner { + increment: Increment::Custom(None), + histogram: Some( + meter.f64_histogram("http.server.request.body.size").init(), + ), + attributes: Vec::with_capacity(nb_attributes), + selector: Some(Arc::new(RouterSelector::RequestHeader { + request_header: "content-length".to_string(), + redact: None, + default: None, + })), + selectors, + }), + } + }); + let http_server_response_body_size = + self.router + .attributes + .http_server_response_body_size + .is_enabled() + .then(|| { + let mut nb_attributes = 0; + let selectors = match &self.router.attributes.http_server_response_body_size { + DefaultedStandardInstrument::Bool(_) + | DefaultedStandardInstrument::Unset => None, + DefaultedStandardInstrument::Extendable { attributes } => { + nb_attributes = attributes.custom.len(); + Some(attributes.clone()) + } + }; + + CustomHistogram { + inner: Mutex::new(CustomHistogramInner { + increment: Increment::Custom(None), + histogram: Some( + meter.f64_histogram("http.server.response.body.size").init(), + ), + attributes: Vec::with_capacity(nb_attributes), + selector: Some(Arc::new(RouterSelector::ResponseHeader { + response_header: "content-length".to_string(), + redact: None, + default: None, + })), + selectors, + }), + } + }); + let http_server_active_requests = self + .router + .attributes + .http_server_active_requests + .is_enabled() + .then(|| ActiveRequestsCounter { + inner: Mutex::new(ActiveRequestsCounterInner { + counter: Some( + meter + .i64_up_down_counter("http.server.active_requests") + .init(), + ), + attrs_config: match &self.router.attributes.http_server_active_requests { + DefaultedStandardInstrument::Bool(_) + | DefaultedStandardInstrument::Unset => Default::default(), + DefaultedStandardInstrument::Extendable { attributes } => { + attributes.clone() + } + }, + attributes: Vec::new(), + }), + }); + RouterInstruments { + http_server_request_duration, + http_server_request_body_size, + http_server_response_body_size, + http_server_active_requests, + custom: CustomInstruments::new(&self.router.custom), + } + } + + pub(crate) fn new_subgraph_instruments(&self) -> SubgraphInstruments { + let meter = metrics::meter_provider().meter(METER_NAME); + let http_client_request_duration = self + .subgraph + .attributes + .http_client_request_duration + .is_enabled() + .then(|| { + let mut nb_attributes = 0; + let selectors = match &self.subgraph.attributes.http_client_request_duration { + DefaultedStandardInstrument::Bool(_) | DefaultedStandardInstrument::Unset => { + None + } + DefaultedStandardInstrument::Extendable { attributes } => { + nb_attributes = attributes.custom.len(); + Some(attributes.clone()) + } + }; + CustomHistogram { + inner: Mutex::new(CustomHistogramInner { + increment: Increment::Duration(Instant::now()), + histogram: Some(meter.f64_histogram("http.client.request.duration").init()), + attributes: Vec::with_capacity(nb_attributes), + selector: None, + selectors, + }), + } + }); + let http_client_request_body_size = + self.subgraph + .attributes + .http_client_request_body_size + .is_enabled() + .then(|| { + let mut nb_attributes = 0; + let selectors = match &self.subgraph.attributes.http_client_request_body_size { + DefaultedStandardInstrument::Bool(_) + | DefaultedStandardInstrument::Unset => None, + DefaultedStandardInstrument::Extendable { attributes } => { + nb_attributes = attributes.custom.len(); + Some(attributes.clone()) + } + }; + CustomHistogram { + inner: Mutex::new(CustomHistogramInner { + increment: Increment::Custom(None), + histogram: Some( + meter.f64_histogram("http.client.request.body.size").init(), + ), + attributes: Vec::with_capacity(nb_attributes), + selector: Some(Arc::new(SubgraphSelector::SubgraphRequestHeader { + subgraph_request_header: "content-length".to_string(), + redact: None, + default: None, + })), + selectors, + }), + } + }); + let http_client_response_body_size = + self.subgraph + .attributes + .http_client_response_body_size + .is_enabled() + .then(|| { + let mut nb_attributes = 0; + let selectors = match &self.subgraph.attributes.http_client_response_body_size { + DefaultedStandardInstrument::Bool(_) + | DefaultedStandardInstrument::Unset => None, + DefaultedStandardInstrument::Extendable { attributes } => { + nb_attributes = attributes.custom.len(); + Some(attributes.clone()) + } + }; + CustomHistogram { + inner: Mutex::new(CustomHistogramInner { + increment: Increment::Custom(None), + histogram: Some( + meter.f64_histogram("http.client.response.body.size").init(), + ), + attributes: Vec::with_capacity(nb_attributes), + selector: Some(Arc::new(SubgraphSelector::SubgraphResponseHeader { + subgraph_response_header: "content-length".to_string(), + redact: None, + default: None, + })), + selectors, + }), + } + }); + SubgraphInstruments { + http_client_request_duration, + http_client_request_body_size, + http_client_response_body_size, + custom: CustomInstruments::new(&self.subgraph.custom), + } + } } -#[allow(dead_code)] #[derive(Clone, Deserialize, JsonSchema, Debug, Default)] #[serde(deny_unknown_fields, default)] -struct RouterInstruments { +pub(crate) struct RouterInstrumentsConfig { /// Histogram of server request duration #[serde(rename = "http.server.request.duration")] http_server_request_duration: DefaultedStandardInstrument>, - /// Gauge of active requests + /// Counter of active requests #[serde(rename = "http.server.active_requests")] - http_server_active_requests: - DefaultedStandardInstrument>, + http_server_active_requests: DefaultedStandardInstrument, /// Histogram of server request body size #[serde(rename = "http.server.request.body.size")] @@ -54,40 +307,190 @@ struct RouterInstruments { DefaultedStandardInstrument>, } -#[allow(dead_code)] -#[derive(Clone, Deserialize, JsonSchema, Debug)] +impl DefaultForLevel for RouterInstrumentsConfig { + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { + self.http_server_request_duration + .defaults_for_levels(requirement_level, kind); + self.http_server_active_requests + .defaults_for_levels(requirement_level, kind); + self.http_server_request_body_size + .defaults_for_levels(requirement_level, kind); + self.http_server_response_body_size + .defaults_for_levels(requirement_level, kind); + } +} + +#[derive(Clone, Deserialize, JsonSchema, Debug, Default)] +#[serde(deny_unknown_fields, default)] +pub(crate) struct ActiveRequestsAttributes { + #[serde(rename = "http.request.method")] + http_request_method: bool, + #[serde(rename = "server.address")] + server_address: bool, + #[serde(rename = "server.port")] + server_port: bool, + #[serde(rename = "url.scheme")] + url_scheme: bool, +} + +impl DefaultForLevel for ActiveRequestsAttributes { + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + _kind: TelemetryDataKind, + ) { + match requirement_level { + DefaultAttributeRequirementLevel::Required => { + self.http_request_method = true; + self.url_scheme = true; + } + DefaultAttributeRequirementLevel::Recommended + | DefaultAttributeRequirementLevel::None => {} + } + } +} + +#[derive(Clone, Deserialize, JsonSchema, Debug, Default)] #[serde(deny_unknown_fields, untagged)] enum DefaultedStandardInstrument { + #[default] + Unset, Bool(bool), - Extendable { attributes: T }, + Extendable { + attributes: Arc, + }, +} + +impl DefaultedStandardInstrument { + fn is_enabled(&self) -> bool { + match self { + Self::Unset => false, + Self::Bool(enabled) => *enabled, + Self::Extendable { .. } => true, + } + } +} + +impl DefaultForLevel for DefaultedStandardInstrument +where + T: DefaultForLevel + Clone + Default, +{ + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { + match self { + DefaultedStandardInstrument::Bool(enabled) if *enabled => match requirement_level { + DefaultAttributeRequirementLevel::None => {} + DefaultAttributeRequirementLevel::Required + | DefaultAttributeRequirementLevel::Recommended => { + let mut attrs = T::default(); + attrs.defaults_for_levels(requirement_level, kind); + *self = Self::Extendable { + attributes: Arc::new(attrs), + } + } + }, + DefaultedStandardInstrument::Unset => match requirement_level { + DefaultAttributeRequirementLevel::None => {} + DefaultAttributeRequirementLevel::Required + | DefaultAttributeRequirementLevel::Recommended => { + let mut attrs = T::default(); + attrs.defaults_for_levels(requirement_level, kind); + *self = Self::Extendable { + attributes: Arc::new(attrs), + } + } + }, + DefaultedStandardInstrument::Extendable { attributes } => { + Arc::make_mut(attributes).defaults_for_levels(requirement_level, kind); + } + _ => {} + } + } } -impl Default for DefaultedStandardInstrument { - fn default() -> Self { - DefaultedStandardInstrument::Bool(true) +impl Selectors for DefaultedStandardInstrument +where + T: Selectors, +{ + type Request = Request; + type Response = Response; + + fn on_request(&self, request: &Self::Request) -> Vec { + match self { + Self::Bool(_) | Self::Unset => Vec::new(), + Self::Extendable { attributes } => attributes.on_request(request), + } + } + + fn on_response(&self, response: &Self::Response) -> Vec { + match self { + Self::Bool(_) | Self::Unset => Vec::new(), + Self::Extendable { attributes } => attributes.on_response(response), + } + } + + fn on_error(&self, error: &BoxError) -> Vec { + match self { + Self::Bool(_) | Self::Unset => Vec::new(), + Self::Extendable { attributes } => attributes.on_error(error), + } } } #[allow(dead_code)] #[derive(Clone, Deserialize, JsonSchema, Debug, Default)] #[serde(deny_unknown_fields, default)] -struct SupergraphInstruments {} +pub(crate) struct SupergraphInstruments {} + +impl DefaultForLevel for SupergraphInstruments { + fn defaults_for_level( + &mut self, + _requirement_level: DefaultAttributeRequirementLevel, + _kind: TelemetryDataKind, + ) { + } +} #[allow(dead_code)] #[derive(Clone, Deserialize, JsonSchema, Debug, Default)] #[serde(deny_unknown_fields, default)] -struct SubgraphInstruments { +pub(crate) struct SubgraphInstrumentsConfig { /// Histogram of client request duration #[serde(rename = "http.client.request.duration")] - http_client_request_duration: bool, + http_client_request_duration: + DefaultedStandardInstrument>, /// Histogram of client request body size #[serde(rename = "http.client.request.body.size")] - http_client_request_body_size: bool, + http_client_request_body_size: + DefaultedStandardInstrument>, /// Histogram of client response body size #[serde(rename = "http.client.response.body.size")] - http_client_response_body_size: bool, + http_client_response_body_size: + DefaultedStandardInstrument>, +} + +impl DefaultForLevel for SubgraphInstrumentsConfig { + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { + self.http_client_request_duration + .defaults_for_level(requirement_level, kind); + self.http_client_request_body_size + .defaults_for_level(requirement_level, kind); + self.http_client_response_body_size + .defaults_for_level(requirement_level, kind); + } } #[allow(dead_code)] @@ -111,14 +514,36 @@ where unit: String, /// Attributes to include on the instrument. - #[serde(default = "Extendable::empty::")] - attributes: Extendable, + #[serde(default = "Extendable::empty_arc::")] + attributes: Arc>, /// The instrument conditions. #[serde(default = "Condition::empty::")] condition: Condition, } +impl Selectors for Instrument +where + A: Debug + Default + Selectors, + E: Debug + Selector, +{ + type Request = Request; + + type Response = Response; + + fn on_request(&self, request: &Self::Request) -> Vec { + self.attributes.on_request(request) + } + + fn on_response(&self, response: &Self::Response) -> Vec { + self.attributes.on_response(response) + } + + fn on_error(&self, error: &BoxError) -> Vec { + self.attributes.on_error(error) + } +} + #[allow(dead_code)] #[derive(Clone, Deserialize, JsonSchema, Debug)] #[serde(deny_unknown_fields, rename_all = "snake_case")] @@ -126,14 +551,12 @@ pub(crate) enum InstrumentType { /// A monotonic counter https://opentelemetry.io/docs/specs/otel/metrics/data-model/#sums Counter, - /// A counter https://opentelemetry.io/docs/specs/otel/metrics/data-model/#sums - UpDownCounter, - + // /// A counter https://opentelemetry.io/docs/specs/otel/metrics/data-model/#sums + // UpDownCounter, /// A histogram https://opentelemetry.io/docs/specs/otel/metrics/data-model/#histogram Histogram, - - /// A gauge https://opentelemetry.io/docs/specs/otel/metrics/data-model/#gauge - Gauge, + // /// A gauge https://opentelemetry.io/docs/specs/otel/metrics/data-model/#gauge + // Gauge, } #[allow(dead_code)] @@ -150,5 +573,946 @@ pub(crate) enum InstrumentValue { pub(crate) enum Standard { Duration, Unit, - Active, + // Active, +} + +pub(crate) trait Instrumented { + type Request; + type Response; + + fn on_request(&self, request: &Self::Request); + fn on_response(&self, response: &Self::Response); + fn on_error(&self, error: &BoxError, ctx: &Context); +} + +impl Instrumented for Extendable> +where + A: Default + Instrumented, + B: Default + Debug + Selectors, + E: Debug + Selector, +{ + type Request = Request; + type Response = Response; + + fn on_request(&self, request: &Self::Request) { + self.attributes.on_request(request); + } + + fn on_response(&self, response: &Self::Response) { + self.attributes.on_response(response); + } + + fn on_error(&self, error: &BoxError, ctx: &Context) { + self.attributes.on_error(error, ctx); + } +} + +impl Selectors for SubgraphInstrumentsConfig { + type Request = subgraph::Request; + type Response = subgraph::Response; + + fn on_request(&self, request: &Self::Request) -> Vec { + let mut attrs = self.http_client_request_body_size.on_request(request); + attrs.extend(self.http_client_request_duration.on_request(request)); + attrs.extend(self.http_client_response_body_size.on_request(request)); + + attrs + } + + fn on_response(&self, response: &Self::Response) -> Vec { + let mut attrs = self.http_client_request_body_size.on_response(response); + attrs.extend(self.http_client_request_duration.on_response(response)); + attrs.extend(self.http_client_response_body_size.on_response(response)); + + attrs + } + + fn on_error(&self, error: &BoxError) -> Vec { + let mut attrs = self.http_client_request_body_size.on_error(error); + attrs.extend(self.http_client_request_duration.on_error(error)); + attrs.extend(self.http_client_response_body_size.on_error(error)); + + attrs + } +} + +pub(crate) struct CustomInstruments +where + Attributes: Selectors + Default, + Select: Selector + Debug, +{ + counters: Vec>, + histograms: Vec>, +} + +impl CustomInstruments +where + Attributes: Selectors + Default + Debug + Clone, + Select: Selector + Debug + Clone, +{ + pub(crate) fn new(config: &HashMap>) -> Self { + let mut counters = Vec::new(); + let mut histograms = Vec::new(); + let meter = metrics::meter_provider().meter(METER_NAME); + + for (instrument_name, instrument) in config { + match instrument.ty { + InstrumentType::Counter => { + let (selector, increment) = match &instrument.value { + InstrumentValue::Standard(incr) => { + let incr = match incr { + Standard::Duration => Increment::Duration(Instant::now()), + Standard::Unit => Increment::Unit, + }; + (None, incr) + } + InstrumentValue::Custom(selector) => { + (Some(Arc::new(selector.clone())), Increment::Custom(None)) + } + }; + let counter = CustomCounterInner { + increment, + condition: instrument.condition.clone(), + counter: Some(meter.f64_counter(instrument_name.clone()).init()), + attributes: Vec::new(), + selector, + selectors: instrument.attributes.clone(), + }; + + counters.push(CustomCounter { + inner: Mutex::new(counter), + }) + } + InstrumentType::Histogram => { + let (selector, increment) = match &instrument.value { + InstrumentValue::Standard(incr) => { + let incr = match incr { + Standard::Duration => Increment::Duration(Instant::now()), + Standard::Unit => Increment::Unit, + }; + (None, incr) + } + InstrumentValue::Custom(selector) => { + (Some(Arc::new(selector.clone())), Increment::Custom(None)) + } + }; + let histogram = CustomHistogramInner { + increment, + histogram: Some(meter.f64_histogram(instrument_name.clone()).init()), + attributes: Vec::new(), + selector, + selectors: Some(instrument.attributes.clone()), + }; + + histograms.push(CustomHistogram { + inner: Mutex::new(histogram), + }) + } + } + } + + Self { + counters, + histograms, + } + } +} + +impl Instrumented + for CustomInstruments +where + Attributes: Selectors + Default, + Select: Selector + Debug, +{ + type Request = Request; + type Response = Response; + + fn on_request(&self, request: &Self::Request) { + for counter in &self.counters { + counter.on_request(request); + } + for histogram in &self.histograms { + histogram.on_request(request); + } + } + + fn on_response(&self, response: &Self::Response) { + for counter in &self.counters { + counter.on_response(response); + } + for histogram in &self.histograms { + histogram.on_response(response); + } + } + + fn on_error(&self, error: &BoxError, ctx: &Context) { + for counter in &self.counters { + counter.on_error(error, ctx); + } + for histogram in &self.histograms { + histogram.on_error(error, ctx); + } + } +} + +pub(crate) struct RouterInstruments { + http_server_request_duration: Option< + CustomHistogram, + >, + http_server_active_requests: Option, + http_server_request_body_size: Option< + CustomHistogram, + >, + http_server_response_body_size: Option< + CustomHistogram, + >, + custom: RouterCustomInstruments, +} + +impl Instrumented for RouterInstruments { + type Request = router::Request; + + type Response = router::Response; + + fn on_request(&self, request: &Self::Request) { + if let Some(http_server_request_duration) = &self.http_server_request_duration { + http_server_request_duration.on_request(request); + } + if let Some(http_server_active_requests) = &self.http_server_active_requests { + http_server_active_requests.on_request(request); + } + if let Some(http_server_request_body_size) = &self.http_server_request_body_size { + http_server_request_body_size.on_request(request); + } + if let Some(http_server_response_body_size) = &self.http_server_response_body_size { + http_server_response_body_size.on_request(request); + } + self.custom.on_request(request); + } + + fn on_response(&self, response: &Self::Response) { + if let Some(http_server_request_duration) = &self.http_server_request_duration { + http_server_request_duration.on_response(response); + } + if let Some(http_server_active_requests) = &self.http_server_active_requests { + http_server_active_requests.on_response(response); + } + if let Some(http_server_request_body_size) = &self.http_server_request_body_size { + http_server_request_body_size.on_response(response); + } + if let Some(http_server_response_body_size) = &self.http_server_response_body_size { + http_server_response_body_size.on_response(response); + } + self.custom.on_response(response); + } + + fn on_error(&self, error: &BoxError, ctx: &Context) { + if let Some(http_server_request_duration) = &self.http_server_request_duration { + http_server_request_duration.on_error(error, ctx); + } + if let Some(http_server_active_requests) = &self.http_server_active_requests { + http_server_active_requests.on_error(error, ctx); + } + if let Some(http_server_request_body_size) = &self.http_server_request_body_size { + http_server_request_body_size.on_error(error, ctx); + } + if let Some(http_server_response_body_size) = &self.http_server_response_body_size { + http_server_response_body_size.on_error(error, ctx); + } + self.custom.on_error(error, ctx); + } +} + +pub(crate) struct SubgraphInstruments { + http_client_request_duration: Option< + CustomHistogram< + subgraph::Request, + subgraph::Response, + SubgraphAttributes, + SubgraphSelector, + >, + >, + http_client_request_body_size: Option< + CustomHistogram< + subgraph::Request, + subgraph::Response, + SubgraphAttributes, + SubgraphSelector, + >, + >, + http_client_response_body_size: Option< + CustomHistogram< + subgraph::Request, + subgraph::Response, + SubgraphAttributes, + SubgraphSelector, + >, + >, + custom: SubgraphCustomInstruments, +} + +impl Instrumented for SubgraphInstruments { + type Request = subgraph::Request; + + type Response = subgraph::Response; + + fn on_request(&self, request: &Self::Request) { + if let Some(http_client_request_duration) = &self.http_client_request_duration { + http_client_request_duration.on_request(request); + } + if let Some(http_client_request_body_size) = &self.http_client_request_body_size { + http_client_request_body_size.on_request(request); + } + if let Some(http_client_response_body_size) = &self.http_client_response_body_size { + http_client_response_body_size.on_request(request); + } + self.custom.on_request(request); + } + + fn on_response(&self, response: &Self::Response) { + if let Some(http_client_request_duration) = &self.http_client_request_duration { + http_client_request_duration.on_response(response); + } + if let Some(http_client_request_body_size) = &self.http_client_request_body_size { + http_client_request_body_size.on_response(response); + } + if let Some(http_client_response_body_size) = &self.http_client_response_body_size { + http_client_response_body_size.on_response(response); + } + self.custom.on_response(response); + } + + fn on_error(&self, error: &BoxError, ctx: &Context) { + if let Some(http_client_request_duration) = &self.http_client_request_duration { + http_client_request_duration.on_error(error, ctx); + } + if let Some(http_client_request_body_size) = &self.http_client_request_body_size { + http_client_request_body_size.on_error(error, ctx); + } + if let Some(http_client_response_body_size) = &self.http_client_response_body_size { + http_client_response_body_size.on_error(error, ctx); + } + self.custom.on_error(error, ctx); + } +} + +pub(crate) type RouterCustomInstruments = + CustomInstruments; + +pub(crate) type SupergraphCustomInstruments = CustomInstruments< + supergraph::Request, + supergraph::Response, + SupergraphAttributes, + SupergraphSelector, +>; + +pub(crate) type SubgraphCustomInstruments = + CustomInstruments; + +// ---------------- Counter ----------------------- +enum Increment { + Unit, + Duration(Instant), + Custom(Option), +} + +struct CustomCounter +where + A: Selectors + Default, + T: Selector + Debug, +{ + inner: Mutex>, +} + +struct CustomCounterInner +where + A: Selectors + Default, + T: Selector + Debug, +{ + increment: Increment, + selector: Option>, + selectors: Arc>, + counter: Option>, + condition: Condition, + attributes: Vec, +} + +impl Instrumented for CustomCounter +where + A: Selectors + Default, + T: Selector + Debug + Debug, +{ + type Request = Request; + type Response = Response; + + fn on_request(&self, request: &Self::Request) { + let mut inner = self.inner.lock(); + if inner.condition.evaluate_request(request) == Some(false) { + return; + } + inner.attributes = inner.selectors.on_request(request).into_iter().collect(); + if let Some(selected_value) = inner.selector.as_ref().and_then(|s| s.on_request(request)) { + inner.increment = Increment::Custom(selected_value.as_str().parse::().ok()) + } + } + + fn on_response(&self, response: &Self::Response) { + let mut inner = self.inner.lock(); + if !inner.condition.evaluate_response(response) { + let _ = inner.counter.take(); + return; + } + let mut attrs: Vec = inner.selectors.on_response(response).into_iter().collect(); + attrs.append(&mut inner.attributes); + + if let Some(selected_value) = inner + .selector + .as_ref() + .and_then(|s| s.on_response(response)) + { + inner.increment = Increment::Custom(selected_value.as_str().parse::().ok()) + } + + let increment = match inner.increment { + Increment::Unit => 1f64, + Increment::Duration(instant) => instant.elapsed().as_secs_f64(), + Increment::Custom(val) => match val { + Some(incr) => incr as f64, + None => 0f64, + }, + }; + + if let Some(counter) = inner.counter.take() { + counter.add(increment, &attrs); + } + } + + fn on_error(&self, error: &BoxError, _ctx: &Context) { + let mut inner = self.inner.lock(); + let mut attrs: Vec = inner.selectors.on_error(error).into_iter().collect(); + attrs.append(&mut inner.attributes); + + let increment = match inner.increment { + Increment::Unit => 1f64, + Increment::Duration(instant) => instant.elapsed().as_secs_f64(), + Increment::Custom(val) => match val { + Some(incr) => incr as f64, + None => 0f64, + }, + }; + + if let Some(counter) = inner.counter.take() { + counter.add(increment, &attrs); + } + } +} + +impl Drop for CustomCounter +where + A: Selectors + Default, + T: Selector + Debug, +{ + fn drop(&mut self) { + // TODO add attribute error broken pipe ? cf https://github.com/apollographql/router/issues/4866 + let inner = self.inner.try_lock(); + if let Some(mut inner) = inner { + if let Some(counter) = inner.counter.take() { + let incr: f64 = match &inner.increment { + Increment::Unit => 1f64, + Increment::Duration(instant) => instant.elapsed().as_secs_f64(), + Increment::Custom(val) => match val { + Some(incr) => *incr as f64, + None => 0f64, + }, + }; + counter.add(incr, &inner.attributes); + } + } + } +} + +struct ActiveRequestsCounter { + inner: Mutex, +} + +struct ActiveRequestsCounterInner { + counter: Option>, + attrs_config: Arc, + attributes: Vec, +} + +impl Instrumented for ActiveRequestsCounter { + type Request = router::Request; + type Response = router::Response; + + fn on_request(&self, request: &Self::Request) { + let mut inner = self.inner.lock(); + if inner.attrs_config.http_request_method { + if let Some(attr) = (RouterSelector::RequestMethod { + request_method: true, + }) + .on_request(request) + { + inner + .attributes + .push(KeyValue::new(HTTP_REQUEST_METHOD, attr)); + } + } + if inner.attrs_config.server_address { + if let Some(attr) = HttpServerAttributes::forwarded_host(request) + .and_then(|h| h.host().map(|h| h.to_string())) + { + inner.attributes.push(KeyValue::new(SERVER_ADDRESS, attr)); + } + } + if inner.attrs_config.server_port { + if let Some(attr) = + HttpServerAttributes::forwarded_host(request).and_then(|h| h.port_u16()) + { + inner + .attributes + .push(KeyValue::new(SERVER_PORT, attr as i64)); + } + } + if inner.attrs_config.url_scheme { + if let Some(attr) = request.router_request.uri().scheme_str() { + inner + .attributes + .push(KeyValue::new(URL_SCHEME, attr.to_string())); + } + } + if let Some(counter) = &inner.counter { + counter.add(1, &inner.attributes); + } + } + + fn on_response(&self, _response: &Self::Response) { + let mut inner = self.inner.lock(); + if let Some(counter) = &inner.counter.take() { + counter.add(-1, &inner.attributes); + } + } + + fn on_error(&self, _error: &BoxError, _ctx: &Context) { + let mut inner = self.inner.lock(); + if let Some(counter) = &inner.counter.take() { + counter.add(-1, &inner.attributes); + } + } +} + +impl Drop for ActiveRequestsCounter { + fn drop(&mut self) { + let inner = self.inner.try_lock(); + if let Some(mut inner) = inner { + if let Some(counter) = &inner.counter.take() { + counter.add(-1, &inner.attributes); + } + } + } +} + +// ---------------- Histogram ----------------------- + +struct CustomHistogram +where + A: Selectors + Default, + T: Selector, +{ + inner: Mutex>, +} + +struct CustomHistogramInner +where + A: Selectors + Default, + T: Selector, +{ + increment: Increment, + selector: Option>, + selectors: Option>>, + histogram: Option>, + attributes: Vec, +} + +impl Instrumented for CustomHistogram +where + A: Selectors + Default, + T: Selector, +{ + type Request = Request; + type Response = Response; + + fn on_request(&self, request: &Self::Request) { + let mut inner = self.inner.lock(); + if let Some(selectors) = &inner.selectors { + inner.attributes = selectors.on_request(request).into_iter().collect(); + } + if let Some(selected_value) = inner.selector.as_ref().and_then(|s| s.on_request(request)) { + inner.increment = Increment::Custom(selected_value.as_str().parse::().ok()) + } + } + + fn on_response(&self, response: &Self::Response) { + let mut inner = self.inner.lock(); + let mut attrs: Vec = inner + .selectors + .as_ref() + .map(|s| s.on_response(response).into_iter().collect()) + .unwrap_or_default(); + attrs.append(&mut inner.attributes); + if let Some(selected_value) = inner + .selector + .as_ref() + .and_then(|s| s.on_response(response)) + { + inner.increment = Increment::Custom(selected_value.as_str().parse::().ok()) + } + + let increment = match inner.increment { + Increment::Unit => Some(1f64), + Increment::Duration(instant) => Some(instant.elapsed().as_secs_f64()), + Increment::Custom(val) => val.map(|incr| incr as f64), + }; + + if let (Some(histogram), Some(increment)) = (inner.histogram.take(), increment) { + histogram.record(increment, &attrs); + } + } + + fn on_error(&self, error: &BoxError, _ctx: &Context) { + let mut inner = self.inner.lock(); + let mut attrs: Vec = inner + .selectors + .as_ref() + .map(|s| s.on_error(error).into_iter().collect()) + .unwrap_or_default(); + attrs.append(&mut inner.attributes); + + let increment = match inner.increment { + Increment::Unit => Some(1f64), + Increment::Duration(instant) => Some(instant.elapsed().as_secs_f64()), + Increment::Custom(val) => val.map(|incr| incr as f64), + }; + + if let (Some(histogram), Some(increment)) = (inner.histogram.take(), increment) { + histogram.record(increment, &attrs); + } + } +} + +impl Drop for CustomHistogram +where + A: Selectors + Default, + T: Selector, +{ + fn drop(&mut self) { + // TODO add attribute error broken pipe ? cf https://github.com/apollographql/router/issues/4866 + let inner = self.inner.try_lock(); + if let Some(mut inner) = inner { + if let Some(histogram) = inner.histogram.take() { + let increment = match &inner.increment { + Increment::Unit => Some(1f64), + Increment::Duration(instant) => Some(instant.elapsed().as_secs_f64()), + Increment::Custom(val) => val.map(|incr| incr as f64), + }; + + if let Some(increment) = increment { + histogram.record(increment, &inner.attributes); + } + } + } + } +} + +#[cfg(test)] +mod tests { + use http::StatusCode; + use serde_json::json; + + use super::*; + use crate::context::OPERATION_KIND; + use crate::graphql; + use crate::metrics::FutureMetricsExt; + use crate::services::RouterRequest; + use crate::services::RouterResponse; + + #[tokio::test] + async fn test_router_instruments() { + async { + let config: InstrumentsConfig = serde_json::from_str( + json!({ + "router": { + "http.server.request.body.size": true, + "http.server.response.body.size": { + "attributes": { + "http.response.status_code": false, + "acme.my_attribute": { + "response_header": "x-my-header", + "default": "unknown" + } + } + }, + "acme.request.on_error": { + "value": "unit", + "type": "counter", + "unit": "error", + "description": "my description", + "condition": { + "not": { + "eq": [ + 200, + { + "response_status": "code" + } + ] + } + }, + "attributes": { + "http.response.status_code": true + } + }, + "acme.request.header_value": { + "value": { + "request_header": "x-my-header-count" + }, + "type": "counter", + "description": "my description", + "unit": "nb" + } + } + }) + .to_string() + .as_str(), + ) + .unwrap(); + + let router_instruments = config.new_router_instruments(); + let router_req = RouterRequest::fake_builder() + .header("conditional-custom", "X") + .header("x-my-header-count", "55") + .header("content-length", "35") + .header("content-type", "application/graphql") + .build() + .unwrap(); + router_instruments.on_request(&router_req); + let router_response = RouterResponse::fake_builder() + .context(router_req.context.clone()) + .status_code(StatusCode::BAD_REQUEST) + .header("content-type", "application/json") + .header("x-my-header", "TEST") + .header("content-length", "35") + .data(json!({"errors": [{"message": "nope"}]})) + .build() + .unwrap(); + router_instruments.on_response(&router_response); + + assert_counter!("acme.request.header_value", 55.0); + assert_counter!( + "acme.request.on_error", + 1.0, + "http.response.status_code" = 400 + ); + assert_histogram_sum!("http.server.request.body.size", 35.0); + assert_histogram_sum!( + "http.server.response.body.size", + 35.0, + "acme.my_attribute" = "TEST" + ); + + let router_instruments = config.new_router_instruments(); + let router_req = RouterRequest::fake_builder() + .header("content-length", "35") + .header("x-my-header-count", "5") + .header("content-type", "application/graphql") + .build() + .unwrap(); + router_instruments.on_request(&router_req); + let router_response = RouterResponse::fake_builder() + .context(router_req.context.clone()) + .status_code(StatusCode::BAD_REQUEST) + .header("content-type", "application/json") + .header("content-length", "35") + .data(json!({"errors": [{"message": "nope"}]})) + .build() + .unwrap(); + router_instruments.on_response(&router_response); + + assert_counter!("acme.request.header_value", 60.0); + assert_counter!( + "acme.request.on_error", + 2.0, + "http.response.status_code" = 400 + ); + assert_histogram_sum!("http.server.request.body.size", 70.0); + assert_histogram_sum!( + "http.server.response.body.size", + 35.0, + "acme.my_attribute" = "TEST" + ); + assert_histogram_sum!( + "http.server.response.body.size", + 35.0, + "acme.my_attribute" = "unknown" + ); + + let router_instruments = config.new_router_instruments(); + let router_req = RouterRequest::fake_builder() + .header("content-length", "35") + .header("content-type", "application/graphql") + .build() + .unwrap(); + router_instruments.on_request(&router_req); + let router_response = RouterResponse::fake_builder() + .context(router_req.context.clone()) + .status_code(StatusCode::OK) + .header("content-type", "application/json") + .header("content-length", "35") + .data(json!({"errors": [{"message": "nope"}]})) + .build() + .unwrap(); + router_instruments.on_response(&router_response); + + assert_counter!("acme.request.header_value", 60.0); + assert_counter!( + "acme.request.on_error", + 2.0, + "http.response.status_code" = 400 + ); + } + .with_metrics() + .await; + } + + #[tokio::test] + async fn test_supergraph_instruments() { + async { + let config: InstrumentsConfig = serde_json::from_str( + json!({ + "supergraph": { + "acme.request.on_error": { + "value": "unit", + "type": "counter", + "unit": "error", + "description": "my description", + "condition": { + "not": { + "eq": [ + 200, + { + "response_status": "code" + } + ] + } + } + }, + "acme.query": { + "value": "unit", + "type": "counter", + "description": "nb of queries", + "condition": { + "eq": [ + "query", + { + "operation_kind": "string" + } + ] + }, + "unit": "query", + "attributes": { + "query": { + "query": "string" + } + } + } + } + }) + .to_string() + .as_str(), + ) + .unwrap(); + + let custom_instruments = SupergraphCustomInstruments::new(&config.supergraph.custom); + let context = crate::context::Context::new(); + let _ = context.insert(OPERATION_KIND, "query".to_string()); + let supergraph_req = supergraph::Request::fake_builder() + .header("conditional-custom", "X") + .header("x-my-header-count", "55") + .header("content-length", "35") + .header("content-type", "application/graphql") + .query("{me{name}}") + .context(context.clone()) + .build() + .unwrap(); + custom_instruments.on_request(&supergraph_req); + let supergraph_response = supergraph::Response::fake_builder() + .context(supergraph_req.context.clone()) + .status_code(StatusCode::BAD_REQUEST) + .header("content-type", "application/json") + .header("x-my-header", "TEST") + .header("content-length", "35") + .errors(vec![graphql::Error::builder() + .message("nope") + .extension_code("NOPE") + .build()]) + .build() + .unwrap(); + custom_instruments.on_response(&supergraph_response); + + assert_counter!("acme.query", 1.0, query = "{me{name}}"); + assert_counter!("acme.request.on_error", 1.0); + + let custom_instruments = SupergraphCustomInstruments::new(&config.supergraph.custom); + let supergraph_req = supergraph::Request::fake_builder() + .header("content-length", "35") + .header("x-my-header-count", "5") + .header("content-type", "application/graphql") + .context(context.clone()) + .query("Subscription {me{name}}") + .build() + .unwrap(); + custom_instruments.on_request(&supergraph_req); + let supergraph_response = supergraph::Response::fake_builder() + .context(supergraph_req.context.clone()) + .status_code(StatusCode::BAD_REQUEST) + .header("content-type", "application/json") + .header("content-length", "35") + .errors(vec![graphql::Error::builder() + .message("nope") + .extension_code("NOPE") + .build()]) + .build() + .unwrap(); + custom_instruments.on_response(&supergraph_response); + + assert_counter!("acme.query", 1.0, query = "{me{name}}"); + assert_counter!("acme.request.on_error", 2.0); + + let custom_instruments = SupergraphCustomInstruments::new(&config.supergraph.custom); + let supergraph_req = supergraph::Request::fake_builder() + .header("content-length", "35") + .header("content-type", "application/graphql") + .context(context.clone()) + .query("{me{name}}") + .build() + .unwrap(); + custom_instruments.on_request(&supergraph_req); + let supergraph_response = supergraph::Response::fake_builder() + .context(supergraph_req.context.clone()) + .status_code(StatusCode::OK) + .header("content-type", "application/json") + .header("content-length", "35") + .errors(vec![graphql::Error::builder() + .message("nope") + .extension_code("NOPE") + .build()]) + .build() + .unwrap(); + custom_instruments.on_response(&supergraph_response); + + assert_counter!("acme.query", 2.0, query = "{me{name}}"); + assert_counter!("acme.request.on_error", 2.0); + } + .with_metrics() + .await; + } } diff --git a/apollo-router/src/plugins/telemetry/config_new/mod.rs b/apollo-router/src/plugins/telemetry/config_new/mod.rs index a1b0cb623c..67d758456d 100644 --- a/apollo-router/src/plugins/telemetry/config_new/mod.rs +++ b/apollo-router/src/plugins/telemetry/config_new/mod.rs @@ -1,5 +1,3 @@ -use std::collections::LinkedList; - use opentelemetry::baggage::BaggageExt; use opentelemetry::trace::TraceContextExt; use opentelemetry::trace::TraceId; @@ -9,6 +7,7 @@ use tower::BoxError; use tracing::Span; use tracing_opentelemetry::OpenTelemetrySpanExt; +use super::otlp::TelemetryDataKind; use crate::plugins::telemetry::config::AttributeValue; use crate::plugins::telemetry::config_new::attributes::DefaultAttributeRequirementLevel; @@ -27,9 +26,9 @@ pub(crate) mod spans; pub(crate) trait Selectors { type Request; type Response; - fn on_request(&self, request: &Self::Request) -> LinkedList; - fn on_response(&self, response: &Self::Response) -> LinkedList; - fn on_error(&self, error: &BoxError) -> LinkedList; + fn on_request(&self, request: &Self::Request) -> Vec; + fn on_response(&self, response: &Self::Response) -> Vec; + fn on_error(&self, error: &BoxError) -> Vec; } pub(crate) trait Selector { @@ -42,16 +41,24 @@ pub(crate) trait Selector { pub(crate) trait DefaultForLevel { /// Don't call this directly, use `defaults_for_levels` instead. - fn defaults_for_level(&mut self, requirement_level: DefaultAttributeRequirementLevel); - fn defaults_for_levels(&mut self, requirement_level: DefaultAttributeRequirementLevel) { + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ); + fn defaults_for_levels( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { match requirement_level { DefaultAttributeRequirementLevel::None => {} DefaultAttributeRequirementLevel::Required => { - self.defaults_for_level(DefaultAttributeRequirementLevel::Required) + self.defaults_for_level(DefaultAttributeRequirementLevel::Required, kind) } DefaultAttributeRequirementLevel::Recommended => { - self.defaults_for_level(DefaultAttributeRequirementLevel::Required); - self.defaults_for_level(DefaultAttributeRequirementLevel::Recommended); + self.defaults_for_level(DefaultAttributeRequirementLevel::Required, kind); + self.defaults_for_level(DefaultAttributeRequirementLevel::Recommended, kind); } } } diff --git a/apollo-router/src/plugins/telemetry/config_new/selectors.rs b/apollo-router/src/plugins/telemetry/config_new/selectors.rs index 87845f977c..300905d96a 100644 --- a/apollo-router/src/plugins/telemetry/config_new/selectors.rs +++ b/apollo-router/src/plugins/telemetry/config_new/selectors.rs @@ -82,6 +82,11 @@ pub(crate) enum RouterSelector { /// Optional default value. default: Option, }, + /// The request method. + RequestMethod { + /// The request method enabled or not + request_method: bool, + }, /// A header from the response ResponseHeader { /// The name of the request header. @@ -93,7 +98,7 @@ pub(crate) enum RouterSelector { /// Optional default value. default: Option, }, - /// A header from the response + /// A status from the response ResponseStatus { /// The http response status code. response_status: ResponseStatus, @@ -201,6 +206,11 @@ pub(crate) enum SupergraphSelector { /// Optional default value. default: Option, }, + /// A status from the response + ResponseStatus { + /// The http response status code. + response_status: ResponseStatus, + }, RequestContext { /// The request context key. request_context: String, @@ -446,6 +456,9 @@ impl Selector for RouterSelector { fn on_request(&self, request: &router::Request) -> Option { match self { + RouterSelector::RequestMethod { request_method } if *request_method => { + Some(request.router_request.method().to_string().into()) + } RouterSelector::RequestHeader { request_header, default, @@ -618,6 +631,16 @@ impl Selector for SupergraphSelector { .and_then(|h| Some(h.to_str().ok()?.to_string())) .or_else(|| default.clone()) .map(opentelemetry::Value::from), + SupergraphSelector::ResponseStatus { response_status } => match response_status { + ResponseStatus::Code => Some(opentelemetry::Value::I64( + response.response.status().as_u16() as i64, + )), + ResponseStatus::Reason => response + .response + .status() + .canonical_reason() + .map(|reason| reason.to_string().into()), + }, SupergraphSelector::ResponseContext { response_context, default, diff --git a/apollo-router/src/plugins/telemetry/config_new/spans.rs b/apollo-router/src/plugins/telemetry/config_new/spans.rs index ed1f139e07..396077e7a1 100644 --- a/apollo-router/src/plugins/telemetry/config_new/spans.rs +++ b/apollo-router/src/plugins/telemetry/config_new/spans.rs @@ -10,6 +10,7 @@ use crate::plugins::telemetry::config_new::selectors::RouterSelector; use crate::plugins::telemetry::config_new::selectors::SubgraphSelector; use crate::plugins::telemetry::config_new::selectors::SupergraphSelector; use crate::plugins::telemetry::config_new::DefaultForLevel; +use crate::plugins::telemetry::otlp::TelemetryDataKind; use crate::plugins::telemetry::span_factory::SpanMode; #[derive(Deserialize, JsonSchema, Clone, Default, Debug)] @@ -38,12 +39,18 @@ pub(crate) struct Spans { impl Spans { /// Update the defaults for spans configuration regarding the `default_attribute_requirement_level` pub(crate) fn update_defaults(&mut self) { - self.router - .defaults_for_levels(self.default_attribute_requirement_level); - self.supergraph - .defaults_for_levels(self.default_attribute_requirement_level); - self.subgraph - .defaults_for_levels(self.default_attribute_requirement_level); + self.router.defaults_for_levels( + self.default_attribute_requirement_level, + TelemetryDataKind::Traces, + ); + self.supergraph.defaults_for_levels( + self.default_attribute_requirement_level, + TelemetryDataKind::Traces, + ); + self.subgraph.defaults_for_levels( + self.default_attribute_requirement_level, + TelemetryDataKind::Traces, + ); } } @@ -55,8 +62,12 @@ pub(crate) struct RouterSpans { } impl DefaultForLevel for RouterSpans { - fn defaults_for_level(&mut self, requirement_level: DefaultAttributeRequirementLevel) { - self.attributes.defaults_for_level(requirement_level); + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { + self.attributes.defaults_for_level(requirement_level, kind); } } @@ -67,8 +78,12 @@ pub(crate) struct SupergraphSpans { pub(crate) attributes: Extendable, } impl DefaultForLevel for SupergraphSpans { - fn defaults_for_level(&mut self, requirement_level: DefaultAttributeRequirementLevel) { - self.attributes.defaults_for_level(requirement_level); + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { + self.attributes.defaults_for_level(requirement_level, kind); } } @@ -80,8 +95,12 @@ pub(crate) struct SubgraphSpans { } impl DefaultForLevel for SubgraphSpans { - fn defaults_for_level(&mut self, requirement_level: DefaultAttributeRequirementLevel) { - self.attributes.defaults_for_level(requirement_level); + fn defaults_for_level( + &mut self, + requirement_level: DefaultAttributeRequirementLevel, + kind: TelemetryDataKind, + ) { + self.attributes.defaults_for_level(requirement_level, kind); } } @@ -105,6 +124,7 @@ mod test { use crate::plugins::telemetry::config_new::spans::SupergraphSpans; use crate::plugins::telemetry::config_new::DefaultForLevel; use crate::plugins::telemetry::config_new::Selectors; + use crate::plugins::telemetry::otlp::TelemetryDataKind; use crate::services::router; use crate::services::subgraph; use crate::services::supergraph; @@ -112,7 +132,10 @@ mod test { #[test] fn test_router_spans_level_none() { let mut spans = RouterSpans::default(); - spans.defaults_for_levels(DefaultAttributeRequirementLevel::None); + spans.defaults_for_levels( + DefaultAttributeRequirementLevel::None, + TelemetryDataKind::Traces, + ); let values = spans.attributes.on_request( &router::Request::fake_builder() .method(http::Method::POST) @@ -135,7 +158,10 @@ mod test { #[test] fn test_router_spans_level_required() { let mut spans = RouterSpans::default(); - spans.defaults_for_levels(DefaultAttributeRequirementLevel::Required); + spans.defaults_for_levels( + DefaultAttributeRequirementLevel::Required, + TelemetryDataKind::Traces, + ); let values = spans.attributes.on_request( &router::Request::fake_builder() .method(http::Method::POST) @@ -158,7 +184,10 @@ mod test { #[test] fn test_router_spans_level_recommended() { let mut spans = RouterSpans::default(); - spans.defaults_for_levels(DefaultAttributeRequirementLevel::Recommended); + spans.defaults_for_levels( + DefaultAttributeRequirementLevel::Recommended, + TelemetryDataKind::Traces, + ); let values = spans.attributes.on_request( &router::Request::fake_builder() .method(http::Method::POST) @@ -181,7 +210,10 @@ mod test { #[test] fn test_supergraph_spans_level_none() { let mut spans = SupergraphSpans::default(); - spans.defaults_for_levels(DefaultAttributeRequirementLevel::None); + spans.defaults_for_levels( + DefaultAttributeRequirementLevel::None, + TelemetryDataKind::Traces, + ); let values = spans.attributes.on_request( &supergraph::Request::fake_builder() .query("query { __typename }") @@ -194,7 +226,10 @@ mod test { #[test] fn test_supergraph_spans_level_required() { let mut spans = SupergraphSpans::default(); - spans.defaults_for_levels(DefaultAttributeRequirementLevel::Required); + spans.defaults_for_levels( + DefaultAttributeRequirementLevel::Required, + TelemetryDataKind::Traces, + ); let values = spans.attributes.on_request( &supergraph::Request::fake_builder() .query("query { __typename }") @@ -207,7 +242,10 @@ mod test { #[test] fn test_supergraph_spans_level_recommended() { let mut spans = SupergraphSpans::default(); - spans.defaults_for_levels(DefaultAttributeRequirementLevel::Recommended); + spans.defaults_for_levels( + DefaultAttributeRequirementLevel::Recommended, + TelemetryDataKind::Traces, + ); let values = spans.attributes.on_request( &supergraph::Request::fake_builder() .query("query { __typename }") @@ -220,7 +258,10 @@ mod test { #[test] fn test_subgraph_spans_level_none() { let mut spans = SubgraphSpans::default(); - spans.defaults_for_levels(DefaultAttributeRequirementLevel::None); + spans.defaults_for_levels( + DefaultAttributeRequirementLevel::None, + TelemetryDataKind::Traces, + ); let values = spans.attributes.on_request( &subgraph::Request::fake_builder() .subgraph_request( @@ -241,7 +282,10 @@ mod test { #[test] fn test_subgraph_spans_level_required() { let mut spans = SubgraphSpans::default(); - spans.defaults_for_levels(DefaultAttributeRequirementLevel::Required); + spans.defaults_for_levels( + DefaultAttributeRequirementLevel::Required, + TelemetryDataKind::Traces, + ); let values = spans.attributes.on_request( &subgraph::Request::fake_builder() .subgraph_request( @@ -262,7 +306,10 @@ mod test { #[test] fn test_subgraph_spans_level_recommended() { let mut spans = SubgraphSpans::default(); - spans.defaults_for_levels(DefaultAttributeRequirementLevel::Recommended); + spans.defaults_for_levels( + DefaultAttributeRequirementLevel::Recommended, + TelemetryDataKind::Traces, + ); let values = spans.attributes.on_request( &subgraph::Request::fake_builder() .subgraph_request( diff --git a/apollo-router/src/plugins/telemetry/dynamic_attribute.rs b/apollo-router/src/plugins/telemetry/dynamic_attribute.rs index cab03565a6..42cfa60703 100644 --- a/apollo-router/src/plugins/telemetry/dynamic_attribute.rs +++ b/apollo-router/src/plugins/telemetry/dynamic_attribute.rs @@ -1,5 +1,3 @@ -use std::collections::LinkedList; - use opentelemetry::Key; use opentelemetry::KeyValue; use tracing_opentelemetry::OtelData; @@ -13,16 +11,16 @@ use super::tracing::APOLLO_PRIVATE_PREFIX; #[derive(Debug, Default)] pub(crate) struct LogAttributes { - attributes: LinkedList, + attributes: Vec, } impl LogAttributes { - pub(crate) fn attributes(&self) -> &LinkedList { + pub(crate) fn attributes(&self) -> &Vec { &self.attributes } pub(crate) fn insert(&mut self, kv: KeyValue) { - self.attributes.push_back(kv); + self.attributes.push(kv); } pub(crate) fn extend(&mut self, other: impl IntoIterator) { diff --git a/apollo-router/src/plugins/telemetry/formatters/json.rs b/apollo-router/src/plugins/telemetry/formatters/json.rs index d65165353b..0af89c2a8b 100644 --- a/apollo-router/src/plugins/telemetry/formatters/json.rs +++ b/apollo-router/src/plugins/telemetry/formatters/json.rs @@ -1,5 +1,4 @@ use std::collections::HashSet; -use std::collections::LinkedList; use std::fmt; use std::io; @@ -28,7 +27,7 @@ use crate::plugins::telemetry::formatters::to_list; #[derive(Debug)] pub(crate) struct Json { config: JsonFormat, - resource: LinkedList<(String, serde_json::Value)>, + resource: Vec<(String, serde_json::Value)>, excluded_attributes: HashSet<&'static str>, } @@ -52,7 +51,7 @@ impl Default for Json { } } -struct SerializableResources<'a>(&'a LinkedList<(String, serde_json::Value)>); +struct SerializableResources<'a>(&'a Vec<(String, serde_json::Value)>); impl<'a> serde::ser::Serialize for SerializableResources<'a> { fn serialize(&self, serializer_o: Ser) -> Result diff --git a/apollo-router/src/plugins/telemetry/formatters/mod.rs b/apollo-router/src/plugins/telemetry/formatters/mod.rs index 7302697c4e..024ac287e6 100644 --- a/apollo-router/src/plugins/telemetry/formatters/mod.rs +++ b/apollo-router/src/plugins/telemetry/formatters/mod.rs @@ -3,7 +3,6 @@ pub(crate) mod json; pub(crate) mod text; use std::collections::HashMap; -use std::collections::LinkedList; use std::fmt; use std::time::Instant; @@ -235,7 +234,7 @@ pub(crate) fn filter_metric_events(event: &tracing::Event<'_>) -> bool { }) } -pub(crate) fn to_list(resource: Resource) -> LinkedList<(String, serde_json::Value)> { +pub(crate) fn to_list(resource: Resource) -> Vec<(String, serde_json::Value)> { resource .into_iter() .map(|(k, v)| { diff --git a/apollo-router/src/plugins/telemetry/formatters/text.rs b/apollo-router/src/plugins/telemetry/formatters/text.rs index cc05bdbb61..31a1bdc488 100644 --- a/apollo-router/src/plugins/telemetry/formatters/text.rs +++ b/apollo-router/src/plugins/telemetry/formatters/text.rs @@ -1,7 +1,6 @@ #[cfg(test)] use std::collections::BTreeMap; use std::collections::HashSet; -use std::collections::LinkedList; use std::fmt; use nu_ansi_term::Color; @@ -34,7 +33,7 @@ use crate::plugins::telemetry::tracing::APOLLO_PRIVATE_PREFIX; pub(crate) struct Text { #[allow(dead_code)] timer: SystemTime, - resource: LinkedList<(String, Value)>, + resource: Vec<(String, Value)>, config: TextFormat, excluded_attributes: HashSet<&'static str>, } @@ -262,7 +261,7 @@ impl Text { pub(crate) fn format_resource( &self, writer: &mut Writer, - resource: &LinkedList<(String, Value)>, + resource: &Vec<(String, Value)>, ) -> fmt::Result { if !resource.is_empty() { let style = Style::new().dimmed(); diff --git a/apollo-router/src/plugins/telemetry/mod.rs b/apollo-router/src/plugins/telemetry/mod.rs index 05c409a013..cd82bb0c17 100644 --- a/apollo-router/src/plugins/telemetry/mod.rs +++ b/apollo-router/src/plugins/telemetry/mod.rs @@ -1,7 +1,6 @@ //! Telemetry plugin. use std::collections::BTreeMap; use std::collections::HashMap; -use std::collections::LinkedList; use std::fmt; use std::sync::Arc; use std::time::Duration; @@ -61,6 +60,10 @@ use self::config::Conf; use self::config::Sampler; use self::config::SamplerOption; use self::config::TraceIdFormat; +use self::config_new::instruments::Instrumented; +use self::config_new::instruments::RouterInstruments; +use self::config_new::instruments::SubgraphInstruments; +use self::config_new::instruments::SupergraphCustomInstruments; use self::config_new::spans::Spans; use self::metrics::apollo::studio::SingleTypeStat; use self::metrics::AttributesForwardConf; @@ -243,6 +246,7 @@ impl Plugin for Telemetry { let mut config = init.config; config.instrumentation.spans.update_defaults(); + config.instrumentation.instruments.update_defaults(); config.exporters.logging.validate()?; let field_level_instrumentation_ratio = @@ -350,6 +354,7 @@ impl Plugin for Telemetry { .router .attributes .on_request(request); + custom_attributes.extend([ KeyValue::new(CLIENT_NAME_KEY, client_name.to_string()), KeyValue::new(CLIENT_VERSION_KEY, client_version.to_string()), @@ -362,9 +367,24 @@ impl Plugin for Telemetry { ), ]); - custom_attributes + let custom_instruments: RouterInstruments = config_request + .instrumentation + .instruments + .new_router_instruments(); + custom_instruments.on_request(request); + + ( + custom_attributes, + custom_instruments, + request.context.clone(), + ) }, - move |custom_attributes: LinkedList, fut| { + move |(custom_attributes, custom_instruments, ctx): ( + Vec, + RouterInstruments, + Context, + ), + fut| { let start = Instant::now(); let config = config_later.clone(); @@ -390,6 +410,8 @@ impl Plugin for Telemetry { .attributes .on_response(response), ); + custom_instruments.on_response(response); + if expose_trace_id.enabled { let header_name = expose_trace_id .header_name @@ -421,6 +443,7 @@ impl Plugin for Telemetry { span.set_dyn_attributes( config.instrumentation.spans.router.attributes.on_error(err), ); + custom_instruments.on_error(err, &ctx); } response @@ -501,9 +524,14 @@ impl Plugin for Telemetry { move |req: &SupergraphRequest| { let custom_attributes = config.instrumentation.spans.supergraph.attributes.on_request(req); Self::populate_context(config.clone(), field_level_instrumentation_ratio, req); - (req.context.clone(), custom_attributes) + let custom_instruments = SupergraphCustomInstruments::new( + &config.instrumentation.instruments.supergraph.custom, + ); + custom_instruments.on_request(req); + + (req.context.clone(), custom_instruments, custom_attributes) }, - move |(ctx, custom_attributes): (Context, LinkedList), fut| { + move |(ctx, custom_instruments, custom_attributes): (Context, SupergraphCustomInstruments, Vec), fut| { let config = config_map_res.clone(); let sender = metrics_sender.clone(); let start = Instant::now(); @@ -513,8 +541,14 @@ impl Plugin for Telemetry { span.set_dyn_attributes(custom_attributes); let mut result: Result = fut.await; match &result { - Ok(resp) => span.set_dyn_attributes(config.instrumentation.spans.supergraph.attributes.on_response(resp)), - Err(err) => span.set_dyn_attributes(config.instrumentation.spans.supergraph.attributes.on_error(err)), + Ok(resp) => { + span.set_dyn_attributes(config.instrumentation.spans.supergraph.attributes.on_response(resp)); + custom_instruments.on_response(resp); + }, + Err(err) => { + span.set_dyn_attributes(config.instrumentation.spans.supergraph.attributes.on_error(err)); + custom_instruments.on_error(err, &ctx); + }, } result = Self::update_otel_metrics( config.clone(), @@ -585,10 +619,23 @@ impl Plugin for Telemetry { .subgraph .attributes .on_request(sub_request); + let custom_instruments = config + .instrumentation + .instruments + .new_subgraph_instruments(); + custom_instruments.on_request(sub_request); - (sub_request.context.clone(), custom_attributes) + ( + sub_request.context.clone(), + custom_instruments, + custom_attributes, + ) }, - move |(context, custom_attributes): (Context, LinkedList), + move |(context, custom_instruments, custom_attributes): ( + Context, + SubgraphInstruments, + Vec, + ), f: BoxFuture<'static, Result>| { let subgraph_attribute = subgraph_attribute.clone(); let subgraph_metrics_conf = subgraph_metrics_conf_resp.clone(); @@ -614,6 +661,7 @@ impl Plugin for Telemetry { .attributes .on_response(resp), ); + custom_instruments.on_response(resp); } Err(err) => { span.record(OTEL_STATUS_CODE, OTEL_STATUS_CODE_ERROR); @@ -621,6 +669,7 @@ impl Plugin for Telemetry { span.set_dyn_attributes( conf.instrumentation.spans.subgraph.attributes.on_error(err), ); + custom_instruments.on_error(err, &context); } } @@ -1812,6 +1861,7 @@ mod tests { use axum::headers::HeaderName; use dashmap::DashMap; + use http::header::CONTENT_TYPE; use http::HeaderMap; use http::HeaderValue; use http::StatusCode; @@ -1835,15 +1885,19 @@ mod tests { use super::apollo::ForwardHeaders; use super::Telemetry; use crate::error::FetchError; + use crate::graphql; use crate::graphql::Error; use crate::graphql::Request; use crate::http_ext; use crate::json_ext::Object; use crate::metrics::FutureMetricsExt; + use crate::plugin::test::MockRouterService; use crate::plugin::test::MockSubgraphService; use crate::plugin::test::MockSupergraphService; use crate::plugin::DynPlugin; use crate::plugins::telemetry::handle_error_internal; + use crate::services::RouterRequest; + use crate::services::RouterResponse; use crate::services::SubgraphRequest; use crate::services::SubgraphResponse; use crate::services::SupergraphRequest; @@ -1965,16 +2019,6 @@ mod tests { "status" = "200", "x-custom" = "coming_from_header" ); - assert_histogram!( - "apollo_router_http_request_duration_seconds", - 1, - "another_test" = "my_default_value", - "my_value" = 2, - "myname" = "label_value", - "renamed_value" = "my_value_set", - "status" = "200", - "x-custom" = "coming_from_header" - ); } .with_metrics() .await; @@ -2026,6 +2070,477 @@ mod tests { .await; } + #[tokio::test] + async fn test_custom_router_instruments() { + async { + let plugin = + create_plugin_with_config(include_str!("testdata/custom_instruments.router.yaml")) + .await; + + let mut mock_bad_request_service = MockRouterService::new(); + mock_bad_request_service + .expect_call() + .times(2) + .returning(move |req: RouterRequest| { + Ok(RouterResponse::fake_builder() + .context(req.context) + .status_code(StatusCode::BAD_REQUEST) + .header("content-type", "application/json") + .data(json!({"errors": [{"message": "nope"}]})) + .build() + .unwrap()) + }); + let mut bad_request_router_service = + plugin.router_service(BoxService::new(mock_bad_request_service)); + let router_req = RouterRequest::fake_builder() + .header("x-custom", "TEST") + .header("conditional-custom", "X") + .header("custom-length", "55") + .header("content-length", "55") + .header("content-type", "application/graphql"); + let _router_response = bad_request_router_service + .ready() + .await + .unwrap() + .call(router_req.build().unwrap()) + .await + .unwrap() + .next_response() + .await + .unwrap(); + + assert_counter!("acme.graphql.custom_req", 1.0); + assert_histogram_sum!( + "http.server.request.body.size", + 55.0, + "http.response.status_code" = 400, + "acme.my_attribute" = "application/json" + ); + assert_histogram_sum!("acme.request.length", 55.0); + + let router_req = RouterRequest::fake_builder() + .header("x-custom", "TEST") + .header("custom-length", "5") + .header("content-length", "5") + .header("content-type", "application/graphql"); + let _router_response = bad_request_router_service + .ready() + .await + .unwrap() + .call(router_req.build().unwrap()) + .await + .unwrap() + .next_response() + .await + .unwrap(); + assert_counter!("acme.graphql.custom_req", 1.0); + assert_histogram_sum!("acme.request.length", 60.0); + assert_histogram_sum!( + "http.server.request.body.size", + 60.0, + "http.response.status_code" = 400, + "acme.my_attribute" = "application/json" + ); + } + .with_metrics() + .await; + } + + #[tokio::test] + async fn test_custom_router_instruments_with_requirement_level() { + async { + let plugin = create_plugin_with_config(include_str!( + "testdata/custom_instruments_level.router.yaml" + )) + .await; + + let mut mock_bad_request_service = MockRouterService::new(); + mock_bad_request_service + .expect_call() + .times(2) + .returning(move |req: RouterRequest| { + Ok(RouterResponse::fake_builder() + .context(req.context) + .status_code(StatusCode::BAD_REQUEST) + .header("content-type", "application/json") + .data(json!({"errors": [{"message": "nope"}]})) + .build() + .unwrap()) + }); + let mut bad_request_router_service = + plugin.router_service(BoxService::new(mock_bad_request_service)); + let router_req = RouterRequest::fake_builder() + .header("x-custom", "TEST") + .header("conditional-custom", "X") + .header("custom-length", "55") + .header("content-length", "55") + .header("content-type", "application/graphql"); + let _router_response = bad_request_router_service + .ready() + .await + .unwrap() + .call(router_req.build().unwrap()) + .await + .unwrap() + .next_response() + .await + .unwrap(); + + assert_counter!("acme.graphql.custom_req", 1.0); + assert_histogram_sum!( + "http.server.request.body.size", + 55.0, + "acme.my_attribute" = "application/json", + "error.type" = "Bad Request", + "http.response.status_code" = 400, + "network.protocol.version" = "HTTP/1.1" + ); + assert_histogram_exists!( + "http.server.request.duration", + f64, + "error.type" = "Bad Request", + "http.response.status_code" = 400, + "network.protocol.version" = "HTTP/1.1", + "http.request.method" = "GET" + ); + assert_histogram_sum!("acme.request.length", 55.0); + + let router_req = RouterRequest::fake_builder() + .header("x-custom", "TEST") + .header("custom-length", "5") + .header("content-length", "5") + .header("content-type", "application/graphql"); + let _router_response = bad_request_router_service + .ready() + .await + .unwrap() + .call(router_req.build().unwrap()) + .await + .unwrap() + .next_response() + .await + .unwrap(); + assert_counter!("acme.graphql.custom_req", 1.0); + assert_histogram_sum!("acme.request.length", 60.0); + assert_histogram_sum!( + "http.server.request.body.size", + 60.0, + "http.response.status_code" = 400, + "acme.my_attribute" = "application/json", + "error.type" = "Bad Request", + "http.response.status_code" = 400, + "network.protocol.version" = "HTTP/1.1" + ); + } + .with_metrics() + .await; + } + + #[tokio::test] + async fn test_custom_supergraph_instruments() { + async { + let plugin = + create_plugin_with_config(include_str!("testdata/custom_instruments.router.yaml")) + .await; + + let mut mock_bad_request_service = MockSupergraphService::new(); + mock_bad_request_service.expect_call().times(3).returning( + move |req: SupergraphRequest| { + Ok(SupergraphResponse::fake_builder() + .context(req.context) + .status_code(StatusCode::BAD_REQUEST) + .header("content-type", "application/json") + .data(json!({"errors": [{"message": "nope"}]})) + .build() + .unwrap()) + }, + ); + let mut bad_request_supergraph_service = + plugin.supergraph_service(BoxService::new(mock_bad_request_service)); + let supergraph_req = SupergraphRequest::fake_builder() + .header("x-custom", "TEST") + .header("conditional-custom", "X") + .header("custom-length", "55") + .header("content-length", "55") + .header("content-type", "application/graphql") + .query("Query test { me {name} }") + .operation_name("test".to_string()); + let _router_response = bad_request_supergraph_service + .ready() + .await + .unwrap() + .call(supergraph_req.build().unwrap()) + .await + .unwrap() + .next_response() + .await + .unwrap(); + + assert_counter!( + "acme.graphql.requests", + 1.0, + "acme.my_attribute" = "application/json", + "graphql_query" = "Query test { me {name} }", + "graphql.document" = "Query test { me {name} }" + ); + + let supergraph_req = SupergraphRequest::fake_builder() + .header("x-custom", "TEST") + .header("custom-length", "5") + .header("content-length", "5") + .header("content-type", "application/graphql") + .query("Query test { me {name} }") + .operation_name("test".to_string()); + + let _router_response = bad_request_supergraph_service + .ready() + .await + .unwrap() + .call(supergraph_req.build().unwrap()) + .await + .unwrap() + .next_response() + .await + .unwrap(); + assert_counter!( + "acme.graphql.requests", + 2.0, + "acme.my_attribute" = "application/json", + "graphql_query" = "Query test { me {name} }", + "graphql.document" = "Query test { me {name} }" + ); + + let supergraph_req = SupergraphRequest::fake_builder() + .header("custom-length", "5") + .header("content-length", "5") + .header("content-type", "application/graphql") + .query("Query test { me {name} }") + .operation_name("test".to_string()); + + let _router_response = bad_request_supergraph_service + .ready() + .await + .unwrap() + .call(supergraph_req.build().unwrap()) + .await + .unwrap() + .next_response() + .await + .unwrap(); + assert_counter!( + "acme.graphql.requests", + 2.0, + "acme.my_attribute" = "application/json", + "graphql_query" = "Query test { me {name} }", + "graphql.document" = "Query test { me {name} }" + ); + } + .with_metrics() + .await; + } + + #[tokio::test] + async fn test_custom_subgraph_instruments_level() { + async { + let plugin = create_plugin_with_config(include_str!( + "testdata/custom_instruments_level.router.yaml" + )) + .await; + + let mut mock_bad_request_service = MockSubgraphService::new(); + mock_bad_request_service.expect_call().times(2).returning( + move |req: SubgraphRequest| { + let mut headers = HeaderMap::new(); + headers.insert(CONTENT_TYPE, "application/json".parse().unwrap()); + let errors = vec![ + graphql::Error::builder() + .message("nope".to_string()) + .extension_code("NOPE") + .build(), + graphql::Error::builder() + .message("nok".to_string()) + .extension_code("NOK") + .build(), + ]; + Ok(SubgraphResponse::fake_builder() + .context(req.context) + .status_code(StatusCode::BAD_REQUEST) + .headers(headers) + .errors(errors) + .build()) + }, + ); + let mut bad_request_subgraph_service = + plugin.subgraph_service("test", BoxService::new(mock_bad_request_service)); + let sub_req = http::Request::builder() + .method("POST") + .uri("http://test") + .header("x-custom", "TEST") + .header("conditional-custom", "X") + .header("custom-length", "55") + .header("content-length", "55") + .header("content-type", "application/graphql") + .body(graphql::Request::builder().query("{ me {name} }").build()) + .unwrap(); + let subgraph_req = SubgraphRequest::fake_builder() + .subgraph_request(sub_req) + .subgraph_name("test".to_string()) + .build(); + + let _router_response = bad_request_subgraph_service + .ready() + .await + .unwrap() + .call(subgraph_req) + .await + .unwrap(); + + assert_counter!( + "acme.subgraph.error_reqs", + 1.0, + graphql_error = opentelemetry::Value::Array(opentelemetry::Array::String(vec![ + "nope".into(), + "nok".into() + ])), + subgraph.name = "test" + ); + let sub_req = http::Request::builder() + .method("POST") + .uri("http://test") + .header("x-custom", "TEST") + .header("conditional-custom", "X") + .header("custom-length", "55") + .header("content-length", "55") + .header("content-type", "application/graphql") + .body(graphql::Request::builder().query("{ me {name} }").build()) + .unwrap(); + let subgraph_req = SubgraphRequest::fake_builder() + .subgraph_request(sub_req) + .subgraph_name("test".to_string()) + .build(); + + let _router_response = bad_request_subgraph_service + .ready() + .await + .unwrap() + .call(subgraph_req) + .await + .unwrap(); + assert_counter!( + "acme.subgraph.error_reqs", + 2.0, + graphql_error = opentelemetry::Value::Array(opentelemetry::Array::String(vec![ + "nope".into(), + "nok".into() + ])), + subgraph.name = "test" + ); + assert_histogram_not_exists!("http.client.request.duration", f64); + } + .with_metrics() + .await; + } + + #[tokio::test] + async fn test_custom_subgraph_instruments() { + async { + let plugin = + create_plugin_with_config(include_str!("testdata/custom_instruments.router.yaml")) + .await; + + let mut mock_bad_request_service = MockSubgraphService::new(); + mock_bad_request_service.expect_call().times(2).returning( + move |req: SubgraphRequest| { + let mut headers = HeaderMap::new(); + headers.insert(CONTENT_TYPE, "application/json".parse().unwrap()); + let errors = vec![ + graphql::Error::builder() + .message("nope".to_string()) + .extension_code("NOPE") + .build(), + graphql::Error::builder() + .message("nok".to_string()) + .extension_code("NOK") + .build(), + ]; + Ok(SubgraphResponse::fake_builder() + .context(req.context) + .status_code(StatusCode::BAD_REQUEST) + .headers(headers) + .errors(errors) + .build()) + }, + ); + let mut bad_request_subgraph_service = + plugin.subgraph_service("test", BoxService::new(mock_bad_request_service)); + let sub_req = http::Request::builder() + .method("POST") + .uri("http://test") + .header("x-custom", "TEST") + .header("conditional-custom", "X") + .header("custom-length", "55") + .header("content-length", "55") + .header("content-type", "application/graphql") + .body(graphql::Request::builder().query("{ me {name} }").build()) + .unwrap(); + let subgraph_req = SubgraphRequest::fake_builder() + .subgraph_request(sub_req) + .subgraph_name("test".to_string()) + .build(); + + let _router_response = bad_request_subgraph_service + .ready() + .await + .unwrap() + .call(subgraph_req) + .await + .unwrap(); + + assert_counter!( + "acme.subgraph.error_reqs", + 1.0, + graphql_error = opentelemetry::Value::Array(opentelemetry::Array::String(vec![ + "nope".into(), + "nok".into() + ])), + subgraph.name = "test" + ); + let sub_req = http::Request::builder() + .method("POST") + .uri("http://test") + .header("x-custom", "TEST") + .header("conditional-custom", "X") + .header("custom-length", "55") + .header("content-length", "55") + .header("content-type", "application/graphql") + .body(graphql::Request::builder().query("{ me {name} }").build()) + .unwrap(); + let subgraph_req = SubgraphRequest::fake_builder() + .subgraph_request(sub_req) + .subgraph_name("test".to_string()) + .build(); + + let _router_response = bad_request_subgraph_service + .ready() + .await + .unwrap() + .call(subgraph_req) + .await + .unwrap(); + assert_counter!( + "acme.subgraph.error_reqs", + 2.0, + graphql_error = opentelemetry::Value::Array(opentelemetry::Array::String(vec![ + "nope".into(), + "nok".into() + ])), + subgraph.name = "test" + ); + } + .with_metrics() + .await; + } + #[tokio::test] async fn test_subgraph_metrics_ok() { async { @@ -2201,15 +2716,6 @@ mod tests { "renamed_value" = "my_value_set", "status" = "400" ); - assert_histogram!( - "apollo_router_http_request_duration_seconds", - 1, - "another_test" = "my_default_value", - "error" = "400 Bad Request", - "myname" = "label_value", - "renamed_value" = "my_value_set", - "status" = "400" - ); } .with_metrics() .await; diff --git a/apollo-router/src/plugins/telemetry/otlp.rs b/apollo-router/src/plugins/telemetry/otlp.rs index 2545a148a1..e1f4dfe966 100644 --- a/apollo-router/src/plugins/telemetry/otlp.rs +++ b/apollo-router/src/plugins/telemetry/otlp.rs @@ -65,6 +65,7 @@ pub(crate) struct Config { pub(crate) temporality: Temporality, } +#[derive(Copy, Clone)] pub(crate) enum TelemetryDataKind { Traces, Metrics, diff --git a/apollo-router/src/plugins/telemetry/testdata/custom_instruments.router.yaml b/apollo-router/src/plugins/telemetry/testdata/custom_instruments.router.yaml new file mode 100644 index 0000000000..b32c4bfa44 --- /dev/null +++ b/apollo-router/src/plugins/telemetry/testdata/custom_instruments.router.yaml @@ -0,0 +1,76 @@ +telemetry: + apollo: + client_name_header: name_header + client_version_header: version_header + instrumentation: + instruments: + default_requirement_level: none + router: + http.server.request.body.size: + attributes: + # Standard attributes + http.response.status_code: true + "acme.my_attribute": + response_header: "content-type" + acme.request.duration: # The name of your custom instrument/metric + value: duration + type: counter + unit: s + description: "my description" + acme.graphql.custom_req: + value: unit + type: counter + unit: request + description: "supergraph requests" + condition: + exists: + request_header: "conditional-custom" + acme.request.size: # The name of your custom instrument/metric + value: + request_header: "custom-length" + type: counter + unit: s + condition: + all: + - eq: + - request_header: "x-custom" + - "TEST" + - eq: + - response_header: "content-type" + - "application/graphql" + description: "my description" + + acme.request.length: # The name of your custom instrument/metric + value: + request_header: "custom-length" + type: histogram + unit: s + description: "my description" + supergraph: + acme.graphql.requests: + value: unit + type: counter + unit: request + description: "supergraph requests" + attributes: + graphql.document: true + graphql_query: + query: string + "acme.my_attribute": + response_header: "content-type" + condition: + exists: + request_header: "x-custom" + subgraph: + acme.subgraph.error_reqs: + value: unit + type: counter + unit: request + description: "subgraph requests in error" + attributes: + subgraph.name: true + graphql_error: + subgraph_response_errors: "$[*].message" + condition: + exists: + subgraph_response_errors: "$[*].message" \ No newline at end of file diff --git a/apollo-router/src/plugins/telemetry/testdata/custom_instruments_level.router.yaml b/apollo-router/src/plugins/telemetry/testdata/custom_instruments_level.router.yaml new file mode 100644 index 0000000000..72cf175364 --- /dev/null +++ b/apollo-router/src/plugins/telemetry/testdata/custom_instruments_level.router.yaml @@ -0,0 +1,77 @@ +telemetry: + apollo: + client_name_header: name_header + client_version_header: version_header + instrumentation: + instruments: + default_requirement_level: recommended + router: + http.server.request.body.size: + attributes: + # Standard attributes + http.request.method: false + "acme.my_attribute": + response_header: "content-type" + acme.request.duration: # The name of your custom instrument/metric + value: duration + type: counter + unit: s + description: "my description" + acme.graphql.custom_req: + value: unit + type: counter + unit: request + description: "supergraph requests" + condition: + exists: + request_header: "conditional-custom" + acme.request.size: # The name of your custom instrument/metric + value: + request_header: "custom-length" + type: counter + unit: s + condition: + all: + - eq: + - request_header: "x-custom" + - "TEST" + - eq: + - response_header: "content-type" + - "application/graphql" + description: "my description" + + acme.request.length: # The name of your custom instrument/metric + value: + request_header: "custom-length" + type: histogram + unit: s + description: "my description" + supergraph: + acme.graphql.requests: + value: unit + type: counter + unit: request + description: "supergraph requests" + attributes: + graphql.document: true + graphql_query: + query: string + "acme.my_attribute": + response_header: "content-type" + condition: + exists: + request_header: "x-custom" + subgraph: + http.client.request.duration: false + acme.subgraph.error_reqs: + value: unit + type: counter + unit: request + description: "subgraph requests in error" + attributes: + subgraph.name: true + graphql_error: + subgraph_response_errors: "$[*].message" + condition: + exists: + subgraph_response_errors: "$[*].message" \ No newline at end of file diff --git a/apollo-router/src/plugins/telemetry/testdata/prometheus_custom_buckets_specific_metrics.router.yaml b/apollo-router/src/plugins/telemetry/testdata/prometheus_custom_buckets_specific_metrics.router.yaml index 06a868748d..c24056770f 100644 --- a/apollo-router/src/plugins/telemetry/testdata/prometheus_custom_buckets_specific_metrics.router.yaml +++ b/apollo-router/src/plugins/telemetry/testdata/prometheus_custom_buckets_specific_metrics.router.yaml @@ -8,6 +8,8 @@ telemetry: service_name: apollo-router views: - name: apollo_router_http_request_duration_seconds + unit: seconds + description: duration of the http request aggregation: histogram: buckets: diff --git a/docs/source/configuration/telemetry/exporters/metrics/prometheus.mdx b/docs/source/configuration/telemetry/exporters/metrics/prometheus.mdx index ab3f23781d..e22482dcd3 100644 --- a/docs/source/configuration/telemetry/exporters/metrics/prometheus.mdx +++ b/docs/source/configuration/telemetry/exporters/metrics/prometheus.mdx @@ -6,7 +6,7 @@ description: Configure the Prometheus metrics exporter endpoint in the Apollo Ro Enable and configure the [Prometheus](https://www.prometheus.io/) exporter for metrics in the Apollo Router. -For general tracing configuration, refer to [Router Metrics Configuration](./overview). +For general metrics configuration, refer to [Router Metrics Configuration](./overview). ## Prometheus configuration diff --git a/docs/source/configuration/telemetry/instrumentation/conditions.mdx b/docs/source/configuration/telemetry/instrumentation/conditions.mdx index 59d4f4a997..60d3d1fa26 100644 --- a/docs/source/configuration/telemetry/instrumentation/conditions.mdx +++ b/docs/source/configuration/telemetry/instrumentation/conditions.mdx @@ -6,18 +6,22 @@ description: Set conditions for when events or instruments are triggered in the -You can set conditions for when an [instrument](./instruments) should be mutated or an [event](./events) should be triggered. +You can set conditions for when an [instrument](./instruments) should be mutated should be triggered. ## Condition configuration Here is an example of a condition on a custom instrument: -```yaml title="future.router.yaml" +```yaml title="router.yaml" telemetry: instrumentation: instruments: router: my.instrument: + value: duration + type: counter + unit: s + description: "my description" # ... # This instrument will only be mutated if the condition evaluates to true condition: @@ -31,6 +35,17 @@ telemetry: - response_header: x-resp-header ``` +#### `exists` + +The `exists` condition is testing if [selectors](./selectors) is present. + +For example, the following condition checks the value of `x-req-header` exists: + +```yaml +exists: + - request_header: x-req-header +``` + #### `eq` The `eq` condition is an equality test between [selectors](./selectors) or values. @@ -105,6 +120,7 @@ The available basic conditions: | Condition | Description | |----------|----------------------------------------------------------| | `eq` | An equality test between selectors or values | +| `exist` | A check to see if the selectors value exists | | `not` | A negated equality test between selectors or values | | `all` | A list of conditions that must all be true | | `any` | A list of conditions of which at least one must be true | diff --git a/docs/source/configuration/telemetry/instrumentation/instruments.mdx b/docs/source/configuration/telemetry/instrumentation/instruments.mdx index cfd3cbce8f..cff1cfd7ff 100644 --- a/docs/source/configuration/telemetry/instrumentation/instruments.mdx +++ b/docs/source/configuration/telemetry/instrumentation/instruments.mdx @@ -6,10 +6,11 @@ description: Create and customize instruments to collect data and report measure import RouterServices from '../../../../shared/router-lifecycle-services.mdx'; + + An **instrument** is used to collect data and report measurements to a metric backend. The Apollo Router supports the following metric instruments: * Counter -* Gauge * Histogram Instruments in the router are configurable in `router.yaml` as `telemetry.instruments`. @@ -27,7 +28,7 @@ For more information, see the [OpenTelemetry semantic conventions for HTTP metri These standard instruments are configurable in `router.yaml`: -```yaml title="future.router.yaml" +```yaml title="router.yaml" telemetry: instrumentation: instruments: @@ -40,19 +41,15 @@ telemetry: Standard instruments can be customized by attaching or removing attributes. -```yaml title="future.router.yaml" +```yaml title="router.yaml" telemetry: instrumentation: instruments: - default_attribute_requirement_level: required + default_requirement_level: required router: http.server.active_requests: attributes: - # Standard attributes - http.response.status_code: false - # Custom attribute - "acme.my_attribute": - response_header: "x-my-header" + http.request.method: true ``` See the [attributes](#attributes) configuration for more information. @@ -71,7 +68,7 @@ When defining a custom instrument, make sure to reference the [OpenTelemetry sem In the example configuration below, three custom instruments are defined (`acme.request.duration`, `acme.graphql.requests`, `acme.graphql.subgraph.errors`), one for each service of the router pipeline respectively (`router`, `supergraph`, `subgraph`): -```yaml title="future.router.yaml" +```yaml title="router.yaml" telemetry: instrumentation: instruments: @@ -82,6 +79,10 @@ telemetry: type: counter unit: kb description: "my description" + condition: + eq: + - 200 + - response_status: code attributes: http.response.status_code: true "my_attribute": @@ -90,7 +91,6 @@ telemetry: supergraph: acme.graphql.requests: value: unit - event: on_error type: counter unit: count description: "supergraph requests" @@ -98,7 +98,6 @@ telemetry: subgraph: acme.graphql.subgraph.errors: value: unit - event: on_error type: counter unit: count description: "my description" @@ -119,37 +118,48 @@ Some particular guidelines to note: ### Instrument configuration -#### `default_attribute_requirement_level` +#### `default_requirement_level` -The `default_attribute_requirement_level` option sets the default attributes to attach to standard instruments, as defined by [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/otel/common/attribute-requirement-level/). +The `default_requirement_level` option sets the default attributes to attach to default standard instruments, as defined by [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/otel/common/attribute-requirement-level/). Valid values: * `required` (default) - required attributes will be attached to standard instruments by default. * `recommended` - recommended attributes will be attached to standard instruments by default. -```yaml title="future.router.yaml" +```yaml title="router.yaml" telemetry: instrumentation: instruments: # Set the default requirement level - default_attribute_requirement_level: required #highlight-line + default_requirement_level: required #highlight-line ``` Attributes can be configured individually, so that `required` attributes can be overridden or disabled. For example, `http.response.status_code` is set individually to override the standard value: -```yaml title="future.router.yaml" +```yaml title="router.yaml" telemetry: instrumentation: instruments: # Set the default requirement level - default_attribute_requirement_level: required + default_requirement_level: required router: - http.server.active_requests: + # Standard metrics + http.server.request.body.size: attributes: - # Override attributes for this instrument - network.transport: true + # Standard attributes http.response.status_code: false + # Custom attribute + "acme.my_attribute": + response_header: "x-my-header" + # Standard metrics + http.server.active_requests: + attributes: + # Standard attributes, different than other ones provides in standard metrics, custom attributes are not available on this standard metric + http.request.method: false + server.address: true + server.port: true + url.scheme: true ``` @@ -166,7 +176,7 @@ The `router`, `supergraph` and `subgraph` sections are used to define custom ins To define a custom instrument, add a new key to `router.yaml` as `telemetry.instruments..`. For example, add a custom instrument `acme.request.duration`: -```yaml title="future.router.yaml" +```yaml title="router.yaml" telemetry: instrumentation: instruments: @@ -184,7 +194,6 @@ The `value` of an instrument is the value which will be drawn from. This can be * `duration` - the duration of the pipeline service. * `unit` - the number of times the pipeline service has been executed. -* `active` - the number of in-progress requests in the pipeline service. * `custom` - a custom value extracted from the pipeline service. See [selectors](./selectors) for more information. ```yaml title="future.router.yaml" @@ -219,11 +228,9 @@ The value must be of the expected type for the instrument. For example, a counte #### `type` -Instruments come in four different types: +Instruments come in two different types: * `counter` - A monotonic counter. For example, requests served, tasks completed, or errors occurred. -* `up_down_counter` - A bidirectional counter that is modified by a delta. For example, the number of items in a queue. -* `gauge` - A value that is sampled at a specific point in time. For example, active requests or CPU usage. * `histogram` - A histogram of values. For example, request durations or response body sizes. ```yaml title="future.router.yaml" @@ -233,7 +240,7 @@ telemetry: router: acme.metric: # ... - type: counter # counter, up_down_counter, gauge, histogram + type: counter # counter, histogram ``` #### `unit` @@ -282,32 +289,44 @@ telemetry: condition: eq: - 200 - - response_header: Status + - response_status: code ``` #### `attributes` Instruments may have attributes attached to them from the router pipeline. These attributes are used to filter and group metrics in your APM. -Attributes may be drawn from [standard attributes](./standard-attributes) or [selectors](./selectors). +Attributes may be drawn from [standard attributes](./standard-attributes) or [selectors](./selectors) except for the standard metric `http.server.active_requests`. The attributes available depend on the service of the pipeline. -```yaml title="future.router.yaml" +```yaml title="router.yaml" telemetry: instrumentation: instruments: router: # Standard metrics - http.server.active_requests: + http.server.request.body.size: attributes: # Standard attributes http.response.status_code: false # Custom attribute "acme.my_attribute": response_header: "x-my-header" + # Standard metrics + http.server.active_requests: + attributes: + # Standard attributes, different than other ones provides in standard metrics, custom attributes are not available on this standard metric + http.request.method: false + server.address: true + server.port: true + url.scheme: true # Custom metric acme.metric: + value: duration + type: counter + unit: s + description: "my description" attributes: http.response.status_code: true "my_attribute": @@ -321,11 +340,11 @@ telemetry: |---------------------------------------|------------------------------------------------------------------------------|------------|----------------------------------------------| | `` | | | The name of the custom attribute. | | `` | | | The name of the custom instrument. | -| `attributes` | [standard attributes](./standard-attributes) or [selectors](./selectors) | | The attributes of the custom instrument. | -| `condition` | [conditions](./conditions) | | The a condition for mutating the instrument. | -| `default_attribute_requirement_level` | `required`\|`recommended` | `required` | The default attribute requirement level. | -| `type` | `counter`\|`up_down_counter`\|`gauge`\|`histogram` | | The name of the custom instrument. | -| `unit` | | | A unit name, for example `By` or `{request}`. | +| `attributes` | [standard attributes](./standard-attributes) or [selectors](./selectors) | | The attributes of the custom instrument. | +| `condition` | [conditions](./conditions) | | The a condition for mutating the instrument. | +| `default_requirement_level` | `required`\|`recommended` | `required` | The default attribute requirement level. | +| `type` | `counter`\|`histogram` | | The name of the custom instrument. | +| `unit` | | | A unit name, for example `By` or `{request}`.| | `description` | | | The description of the custom instrument. | -| `value` | `unit`\|`duration`\|`active`\|`` | | The value of the instrument. | +| `value` | `unit`\|`duration`\|`` | | The value of the instrument. | diff --git a/docs/source/configuration/telemetry/instrumentation/selectors.mdx b/docs/source/configuration/telemetry/instrumentation/selectors.mdx index d2749e59a2..5af6dc1bac 100644 --- a/docs/source/configuration/telemetry/instrumentation/selectors.mdx +++ b/docs/source/configuration/telemetry/instrumentation/selectors.mdx @@ -5,7 +5,7 @@ description: Extract and select data from the Apollo Router's pipeline services --- import RouterServices from '../../../../shared/router-lifecycle-services.mdx'; -A **selector** is used to extract data from the Apollo Router's request lifecycle (pipeline) services and attach them to telemetry, specifically [spans](./spans). +A **selector** is used to extract data from the Apollo Router's request lifecycle (pipeline) services and attach them to telemetry, specifically [spans](./spans), [instruments](./instruments), [conditions](./conditions). Each service of the router pipeline (`router`, `supergraph`, `subgraph`) has its own available selectors. @@ -47,8 +47,8 @@ The supergraph service is executed after query parsing but before query executio | Selector | Defaultable | Values | Description | |--------------------|-------------|-------------------------------------|--------------------------------------| | `operation_name` | Yes | | The operation name from the query | -| `operation_kind` | No | `query`\|`mutation`\|`subscription` | The operation kind from the query | -| `query` | Yes | `query`\|`hash` | The graphql query | +| `operation_kind` | No | `string` | The operation kind from the query | +| `query` | Yes | `string` | The graphql query | | `query_variable` | Yes | | The name of a graphql query variable | | `response_body` | Yes | | Json Path into the response body | | `request_header` | Yes | | The name of a request header | @@ -66,16 +66,16 @@ The subgraph service executes multiple times during query execution, with each e | Selector | Defaultable | Values | Description | |-----------------------------|-------------|-------------------------------------|---------------------------------------------------------------------------------| | `subgraph_operation_name` | Yes | | The operation name from the subgraph query | -| `subgraph_operation_kind` | No | `query`\|`mutation`\|`subscription` | The operation kind from the subgraph query | +| `subgraph_operation_kind` | No | `string` | The operation kind from the subgraph query | | `subgraph_query` | Yes | | The graphql query to the subgraph | | `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 performances) | | `subgraph_response_errors` | Yes | | Json Path into the subgraph response body errors (it might impact performances) | | `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 | | The name of a subgraph response header | +| `subgraph_response_status` | Yes | | The status of a subgraph response | | `supergraph_operation_name` | Yes | | The operation name from the supergraph query | -| `supergraph_operation_kind` | Yes | `query`\|`mutation`\|`subscription` | The operation kind from the supergraph query | +| `supergraph_operation_kind` | Yes | `string` | The operation kind from the supergraph query | | `supergraph_query` | Yes | | The graphql query to the supergraph | | `supergraph_query_variable` | Yes | | The name of a supergraph query variable | | `request_context` | Yes | | The name of a request context key |