Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .changesets/feat_rreg_additional_connector_instrument_selectors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
### Additional Connector Custom Instrument Selectors ([PR #8045](https://github.com/apollographql/router/pull/8045))

This adds new [custom instrument selectors](https://www.apollographql.com/docs/graphos/routing/observability/telemetry/instrumentation/selectors#connector) for Connectors and enhances some existing selectors. The new selectors are:
- `supergraph_operation_name`
- The supergraph's operation name
- `supergraph_operation_kind`
- The supergraph's operation type (e.g. `query`, `mutation`, `subscription`)
- `request_context`
- Takes the value of the given key on the request context
- `connector_on_response_error`
- Returns true when the response does not meet the `is_successful` condition. Or, if that condition is not set,
returns true when the response has a non-200 status code

These selectors were modified to add additional functionality:
- `connector_request_mapping_problems`
- Adds a new `boolean` variant that will return `true` when a mapping problem exists on the request
- `connector_response_mapping_problems`
- Adds a new `boolean` variant that will return `true` when a mapping problem exists on the response

By [@rregitsky](https://github.com/rregitsky) in https://github.com/apollographql/router/pull/8045
4 changes: 2 additions & 2 deletions .changesets/feat_rreg_experimental_subgraph_metrics.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
### [Subgraph Insights] Experimental Apollo Subgraph Fetch Histogram ([PR #8013](https://github.com/apollographql/router/pull/8013))
### [Subgraph Insights] Experimental Apollo Subgraph Fetch Histogram ([PR #8013](https://github.com/apollographql/router/pull/8013), [PR #8045](https://github.com/apollographql/router/pull/8045))

This change adds a new, experimental histogram to capture subgraph fetch duration for GraphOS. This will
eventually be used to power subgraph-level insights in Apollo Studio.
Expand All @@ -15,4 +15,4 @@ The new instrument is only sent to GraphOS and is not available in 3rd-party OTe
customizable. Users requiring a customizable alternative can use the existing `http.client.request.duration`
instrument, which measures the same value.

By [@rregitsky](https://github.com/rregitsky) in https://github.com/apollographql/router/pull/8013
By [@rregitsky](https://github.com/rregitsky) in https://github.com/apollographql/router/pull/8013 and https://github.com/apollographql/router/pull/8045
Original file line number Diff line number Diff line change
Expand Up @@ -2175,6 +2175,68 @@ snapshot_kind: text
"connector_response_mapping_problems"
],
"type": "object"
},
{
"additionalProperties": false,
"properties": {
"default": {
"$ref": "#/definitions/AttributeValue",
"description": "#/definitions/AttributeValue",
"nullable": true
},
"request_context": {
"description": "The request context key.",
"type": "string"
}
},
"required": [
"request_context"
],
"type": "object"
},
{
"additionalProperties": false,
"properties": {
"default": {
"description": "Optional default value.",
"nullable": true,
"type": "string"
},
"supergraph_operation_name": {
"$ref": "#/definitions/OperationName",
"description": "#/definitions/OperationName"
}
},
"required": [
"supergraph_operation_name"
],
"type": "object"
},
{
"additionalProperties": false,
"properties": {
"supergraph_operation_kind": {
"$ref": "#/definitions/OperationKind",
"description": "#/definitions/OperationKind"
}
},
"required": [
"supergraph_operation_kind"
],
"type": "object"
},
{
"additionalProperties": false,
"properties": {
"connector_on_response_error": {
"description": "Boolean set to true if the response's `is_successful` condition is false. If this is not set, returns true when the response contains a non-200 status code",
"type": "boolean"
}
},
"required": [
"connector_on_response_error"
],
"type": "object"
}
]
},
Expand Down Expand Up @@ -4400,11 +4462,29 @@ snapshot_kind: text
"type": "object"
},
"MappingProblems": {
"enum": [
"problems",
"count"
],
"type": "string"
"oneOf": [
{
"description": "String representation of all problems",
"enum": [
"problems"
],
"type": "string"
},
{
"description": "The count of mapping problems",
"enum": [
"count"
],
"type": "string"
},
{
"description": "Whether there are any mapping problems",
"enum": [
"boolean"
],
"type": "string"
}
]
},
"MetricAggregation": {
"oneOf": [
Expand Down
166 changes: 151 additions & 15 deletions apollo-router/src/plugins/telemetry/config_new/apollo/instruments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ use crate::plugins::telemetry::GRAPHQL_OPERATION_NAME_ATTRIBUTE;
use crate::plugins::telemetry::GRAPHQL_OPERATION_TYPE_ATTRIBUTE;
use crate::plugins::telemetry::apollo::Config;
use crate::plugins::telemetry::config_new::attributes::StandardAttribute;
use crate::plugins::telemetry::config_new::connector::ConnectorRequest;
use crate::plugins::telemetry::config_new::connector::ConnectorResponse;
use crate::plugins::telemetry::config_new::connector::attributes::ConnectorAttributes;
use crate::plugins::telemetry::config_new::connector::selectors::ConnectorSelector;
use crate::plugins::telemetry::config_new::extendable::Extendable;
use crate::plugins::telemetry::config_new::instruments::APOLLO_ROUTER_OPERATIONS_FETCH_DURATION;
use crate::plugins::telemetry::config_new::instruments::CustomHistogram;
Expand All @@ -43,6 +47,18 @@ pub(crate) struct ApolloSubgraphInstruments {
>,
}

pub(crate) struct ApolloConnectorInstruments {
pub(crate) apollo_router_operations_fetch_duration: Option<
CustomHistogram<
ConnectorRequest,
ConnectorResponse,
(),
ConnectorAttributes,
ConnectorSelector,
>,
>,
}

impl ApolloSubgraphInstruments {
pub(crate) fn new(
static_instruments: Arc<HashMap<String, StaticInstrument>>,
Expand Down Expand Up @@ -127,21 +143,7 @@ impl ApolloSubgraphInstruments {
}

pub(crate) fn new_builtin() -> HashMap<String, StaticInstrument> {
let meter = metrics::meter_provider().meter(METER_NAME);
let mut static_instruments = HashMap::with_capacity(1);

static_instruments.insert(
APOLLO_ROUTER_OPERATIONS_FETCH_DURATION.to_string(),
StaticInstrument::Histogram(
meter
.f64_histogram(APOLLO_ROUTER_OPERATIONS_FETCH_DURATION)
.with_unit("s")
.with_description("Duration of a subgraph fetch.")
.init(),
),
);

static_instruments
create_subgraph_and_connector_shared_static_instruments()
}
}

Expand Down Expand Up @@ -174,3 +176,137 @@ impl Instrumented for ApolloSubgraphInstruments {
}
}
}

impl ApolloConnectorInstruments {
pub(crate) fn new(
static_instruments: Arc<HashMap<String, StaticInstrument>>,
apollo_config: Config,
) -> Self {
let selectors = Extendable {
attributes: ConnectorAttributes::builder()
.subgraph_name(StandardAttribute::Bool(true))
.build(),
custom: HashMap::from([
(
APOLLO_CLIENT_NAME_ATTRIBUTE.to_string(),
ConnectorSelector::RequestContext {
request_context: CLIENT_NAME.to_string(),
redact: None,
default: None,
},
),
(
APOLLO_CLIENT_VERSION_ATTRIBUTE.to_string(),
ConnectorSelector::RequestContext {
request_context: CLIENT_VERSION.to_string(),
redact: None,
default: None,
},
),
(
GRAPHQL_OPERATION_NAME_ATTRIBUTE.to_string(),
ConnectorSelector::SupergraphOperationName {
supergraph_operation_name: OperationName::String,
redact: None,
default: None,
},
),
(
GRAPHQL_OPERATION_TYPE_ATTRIBUTE.to_string(),
ConnectorSelector::SupergraphOperationKind {
supergraph_operation_kind: OperationKind::String,
},
),
(
APOLLO_OPERATION_ID_ATTRIBUTE.to_string(),
ConnectorSelector::RequestContext {
request_context: APOLLO_OPERATION_ID.to_string(),
redact: None,
default: None,
},
),
(
APOLLO_HAS_ERRORS_ATTRIBUTE.to_string(),
ConnectorSelector::OnResponseError {
connector_on_response_error: true,
},
),
]),
};
let attribute_count = selectors.custom.len() + 1; // 1 for subgraph_name on attributes

let apollo_router_operations_fetch_duration =
apollo_config.experimental_subgraph_metrics.then(|| {
CustomHistogram::builder()
.increment(Increment::Duration(Instant::now()))
.attributes(Vec::with_capacity(attribute_count))
.selectors(Arc::new(selectors))
.histogram(static_instruments
.get(APOLLO_ROUTER_OPERATIONS_FETCH_DURATION)
.expect(
"cannot get apollo static instrument for subgraph; this should not happen",
)
.as_histogram()
.cloned()
.expect(
"cannot convert apollo instrument to histogram for subgraph; this should not happen",
)
)
.build()
});

Self {
apollo_router_operations_fetch_duration,
}
}

pub(crate) fn new_builtin() -> HashMap<String, StaticInstrument> {
create_subgraph_and_connector_shared_static_instruments()
}
}

impl Instrumented for ApolloConnectorInstruments {
type Request = ConnectorRequest;
type Response = ConnectorResponse;
type EventResponse = ();

fn on_request(&self, request: &Self::Request) {
if let Some(apollo_router_operations_fetch_duration) =
&self.apollo_router_operations_fetch_duration
{
apollo_router_operations_fetch_duration.on_request(request);
}
}

fn on_response(&self, response: &Self::Response) {
if let Some(apollo_router_operations_fetch_duration) =
&self.apollo_router_operations_fetch_duration
{
apollo_router_operations_fetch_duration.on_response(response);
}
}

fn on_error(&self, error: &BoxError, ctx: &Context) {
if let Some(apollo_router_operations_fetch_duration) =
&self.apollo_router_operations_fetch_duration
{
apollo_router_operations_fetch_duration.on_error(error, ctx);
}
}
}

fn create_subgraph_and_connector_shared_static_instruments() -> HashMap<String, StaticInstrument> {
let meter = metrics::meter_provider().meter(METER_NAME);
let mut static_instruments = HashMap::with_capacity(1);
static_instruments.insert(
APOLLO_ROUTER_OPERATIONS_FETCH_DURATION.to_string(),
StaticInstrument::Histogram(
meter
.f64_histogram(APOLLO_ROUTER_OPERATIONS_FETCH_DURATION)
.with_unit("s")
.with_description("Duration of a subgraph fetch.")
.init(),
),
);
static_instruments
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const CONNECTOR_HTTP_METHOD: Key = Key::from_static_str("connector.http.method")
const CONNECTOR_SOURCE_NAME: Key = Key::from_static_str("connector.source.name");
const CONNECTOR_URL_TEMPLATE: Key = Key::from_static_str("connector.url.template");

#[derive(Deserialize, JsonSchema, Clone, Default, Debug)]
#[derive(Deserialize, JsonSchema, Clone, Default, Debug, buildstructor::Builder)]
#[serde(deny_unknown_fields, default)]
pub(crate) struct ConnectorAttributes {
/// The name of the subgraph containing the connector
Expand Down
Loading