From 143dccc97a519e322f2a4632ed8b7db6dd791eab Mon Sep 17 00:00:00 2001 From: Coenen Benjamin Date: Tue, 2 Apr 2024 11:11:58 +0200 Subject: [PATCH] Add support of instruments in configuration for telemetry (#4771) 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. It can be conditional, get values from selectors like headers, context, body. And the metrics can 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) Fixes #4319 --------- Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- .changesets/feat_bnjjj_feat_4319.md | 43 + apollo-router/src/configuration/metrics.rs | 8 + ...__test__metrics@telemetry.router.yaml.snap | 6 +- ...nfiguration__tests__schema_generation.snap | 20118 ++++++++++++++-- .../testdata/metrics/telemetry.router.yaml | 55 + apollo-router/src/metrics/mod.rs | 136 +- apollo-router/src/plugins/telemetry/config.rs | 11 +- .../telemetry/config_new/attributes.rs | 327 +- .../telemetry/config_new/conditions.rs | 261 +- .../telemetry/config_new/extendable.rs | 23 +- .../telemetry/config_new/instruments.rs | 1426 +- .../src/plugins/telemetry/config_new/mod.rs | 27 +- .../plugins/telemetry/config_new/selectors.rs | 25 +- .../src/plugins/telemetry/config_new/spans.rs | 89 +- .../plugins/telemetry/dynamic_attribute.rs | 8 +- .../src/plugins/telemetry/formatters/json.rs | 5 +- .../src/plugins/telemetry/formatters/mod.rs | 3 +- .../src/plugins/telemetry/formatters/text.rs | 5 +- apollo-router/src/plugins/telemetry/mod.rs | 562 +- apollo-router/src/plugins/telemetry/otlp.rs | 1 + .../testdata/custom_instruments.router.yaml | 76 + .../custom_instruments_level.router.yaml | 77 + ...ustom_buckets_specific_metrics.router.yaml | 2 + .../exporters/metrics/prometheus.mdx | 2 +- .../telemetry/instrumentation/conditions.mdx | 20 +- .../telemetry/instrumentation/instruments.mdx | 93 +- .../telemetry/instrumentation/selectors.mdx | 12 +- 27 files changed, 20921 insertions(+), 2500 deletions(-) create mode 100644 .changesets/feat_bnjjj_feat_4319.md create mode 100644 apollo-router/src/plugins/telemetry/testdata/custom_instruments.router.yaml create mode 100644 apollo-router/src/plugins/telemetry/testdata/custom_instruments_level.router.yaml 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 |