Skip to content

Commit

Permalink
feat(telemetry): add error section in custom attributes configuration (
Browse files Browse the repository at this point in the history
…#1443)

Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
  • Loading branch information
bnjjj authored Aug 1, 2022
1 parent 79a2080 commit 0f226d7
Show file tree
Hide file tree
Showing 5 changed files with 316 additions and 19 deletions.
22 changes: 22 additions & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,28 @@ By [@Geal](https://github.com/Geal) in https://github.com/apollographql/router/p

## 🚀 Features

### Add support of error section in telemetry to add custom attributes ([PR #1443](https://github.com/apollographql/router/pull/1443))

The telemetry is now able to hook at the error stage if router or a subgraph is returning an error. Here is an example of configuration:

```yaml
telemetry:
metrics:
prometheus:
enabled: true
common:
attributes:
subgraph:
all:
errors: # Only works if it's a valid GraphQL error
include_messages: true # Will include the error message in a message attribute
extensions: # Include extension data
- name: subgraph_error_extended_type # Name of the attribute
path: .type # JSON query path to fetch data from extensions
```
By [@bnjjj](https://github.com/bnjjj) in https://github.com/apollographql/router/pull/1443
### Experimental support for the `@defer` directive ([PR #1182](https://github.com/apollographql/router/pull/1182))

The router can now understand the `@defer` directive, used to tag parts of a query so the response is split into
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ expression: "&schema"
"type": "object",
"properties": {
"context": {
"description": "Configuration to forward values from the context custom attributes/labels in metrics",
"description": "Configuration to forward values from the context to custom attributes/labels in metrics",
"type": "array",
"items": {
"description": "Configuration to forward context values in metric attributes/labels",
Expand All @@ -497,8 +497,47 @@ expression: "&schema"
},
"nullable": true
},
"errors": {
"description": "Configuration to forward values from the error to custom attributes/labels in metrics",
"type": "object",
"properties": {
"extensions": {
"description": "Forward extensions values as custom attributes/labels in metrics",
"type": "array",
"items": {
"description": "Configuration to forward body values in metric attributes/labels",
"type": "object",
"required": [
"name",
"path"
],
"properties": {
"default": {
"type": "string",
"nullable": true
},
"name": {
"type": "string"
},
"path": {
"type": "string"
}
},
"additionalProperties": false
},
"nullable": true
},
"include_messages": {
"description": "Will include the error message in a \"message\" attribute",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false,
"nullable": true
},
"request": {
"description": "Configuration to forward headers or body values from the request custom attributes/labels in metrics",
"description": "Configuration to forward headers or body values from the request to custom attributes/labels in metrics",
"type": "object",
"properties": {
"body": {
Expand Down Expand Up @@ -576,7 +615,7 @@ expression: "&schema"
"nullable": true
},
"response": {
"description": "Configuration to forward headers or body values from the response custom attributes/labels in metrics",
"description": "Configuration to forward headers or body values from the response to custom attributes/labels in metrics",
"type": "object",
"properties": {
"body": {
Expand Down Expand Up @@ -687,7 +726,7 @@ expression: "&schema"
"type": "object",
"properties": {
"context": {
"description": "Configuration to forward values from the context custom attributes/labels in metrics",
"description": "Configuration to forward values from the context to custom attributes/labels in metrics",
"type": "array",
"items": {
"description": "Configuration to forward context values in metric attributes/labels",
Expand All @@ -712,8 +751,47 @@ expression: "&schema"
},
"nullable": true
},
"errors": {
"description": "Configuration to forward values from the error to custom attributes/labels in metrics",
"type": "object",
"properties": {
"extensions": {
"description": "Forward extensions values as custom attributes/labels in metrics",
"type": "array",
"items": {
"description": "Configuration to forward body values in metric attributes/labels",
"type": "object",
"required": [
"name",
"path"
],
"properties": {
"default": {
"type": "string",
"nullable": true
},
"name": {
"type": "string"
},
"path": {
"type": "string"
}
},
"additionalProperties": false
},
"nullable": true
},
"include_messages": {
"description": "Will include the error message in a \"message\" attribute",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false,
"nullable": true
},
"request": {
"description": "Configuration to forward headers or body values from the request custom attributes/labels in metrics",
"description": "Configuration to forward headers or body values from the request to custom attributes/labels in metrics",
"type": "object",
"properties": {
"body": {
Expand Down Expand Up @@ -791,7 +869,7 @@ expression: "&schema"
"nullable": true
},
"response": {
"description": "Configuration to forward headers or body values from the response custom attributes/labels in metrics",
"description": "Configuration to forward headers or body values from the response to custom attributes/labels in metrics",
"type": "object",
"properties": {
"body": {
Expand Down Expand Up @@ -900,7 +978,7 @@ expression: "&schema"
"type": "object",
"properties": {
"context": {
"description": "Configuration to forward values from the context custom attributes/labels in metrics",
"description": "Configuration to forward values from the context to custom attributes/labels in metrics",
"type": "array",
"items": {
"description": "Configuration to forward context values in metric attributes/labels",
Expand All @@ -925,8 +1003,47 @@ expression: "&schema"
},
"nullable": true
},
"errors": {
"description": "Configuration to forward values from the error to custom attributes/labels in metrics",
"type": "object",
"properties": {
"extensions": {
"description": "Forward extensions values as custom attributes/labels in metrics",
"type": "array",
"items": {
"description": "Configuration to forward body values in metric attributes/labels",
"type": "object",
"required": [
"name",
"path"
],
"properties": {
"default": {
"type": "string",
"nullable": true
},
"name": {
"type": "string"
},
"path": {
"type": "string"
}
},
"additionalProperties": false
},
"nullable": true
},
"include_messages": {
"description": "Will include the error message in a \"message\" attribute",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false,
"nullable": true
},
"request": {
"description": "Configuration to forward headers or body values from the request custom attributes/labels in metrics",
"description": "Configuration to forward headers or body values from the request to custom attributes/labels in metrics",
"type": "object",
"properties": {
"body": {
Expand Down Expand Up @@ -1004,7 +1121,7 @@ expression: "&schema"
"nullable": true
},
"response": {
"description": "Configuration to forward headers or body values from the response custom attributes/labels in metrics",
"description": "Configuration to forward headers or body values from the response to custom attributes/labels in metrics",
"type": "object",
"properties": {
"body": {
Expand Down
75 changes: 72 additions & 3 deletions apollo-router/src/plugins/telemetry/metrics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use serde_json::Value;
use tower::util::BoxService;
use tower::BoxError;

use crate::error::FetchError;
use crate::graphql::Request;
use crate::http_ext;
use crate::plugin::serde::deserialize_header_name;
Expand Down Expand Up @@ -67,12 +68,14 @@ pub(crate) struct AttributesForwardConf {
/// Configuration to insert custom attributes/labels in metrics
#[serde(rename = "static")]
pub(crate) insert: Option<Vec<Insert>>,
/// Configuration to forward headers or body values from the request custom attributes/labels in metrics
/// Configuration to forward headers or body values from the request to custom attributes/labels in metrics
pub(crate) request: Option<Forward>,
/// Configuration to forward headers or body values from the response custom attributes/labels in metrics
/// Configuration to forward headers or body values from the response to custom attributes/labels in metrics
pub(crate) response: Option<Forward>,
/// Configuration to forward values from the context custom attributes/labels in metrics
/// Configuration to forward values from the context to custom attributes/labels in metrics
pub(crate) context: Option<Vec<ContextForward>>,
/// Configuration to forward values from the error to custom attributes/labels in metrics
pub(crate) errors: Option<ErrorsForward>,
}

#[derive(Clone, JsonSchema, Deserialize, Debug)]
Expand All @@ -92,6 +95,16 @@ pub(crate) struct Forward {
pub(crate) body: Option<Vec<BodyForward>>,
}

#[derive(Debug, Clone, Deserialize, JsonSchema, Default)]
#[serde(deny_unknown_fields)]
pub(crate) struct ErrorsForward {
/// Will include the error message in a "message" attribute
#[serde(default)]
pub(crate) include_messages: bool,
/// Forward extensions values as custom attributes/labels in metrics
pub(crate) extensions: Option<Vec<BodyForward>>,
}

#[derive(Clone, JsonSchema, Deserialize, Debug)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
#[serde(untagged)]
Expand Down Expand Up @@ -192,6 +205,55 @@ impl Forward {
}
}

impl ErrorsForward {
pub(crate) fn merge(&mut self, to_merge: Self) {
match (&mut self.extensions, to_merge.extensions) {
(Some(extensions), Some(extensions_to_merge)) => {
extensions.extend(extensions_to_merge);
}
(None, Some(extensions_to_merge)) => {
self.extensions = Some(extensions_to_merge);
}
_ => {}
}
self.include_messages = to_merge.include_messages;
}

pub(crate) fn get_attributes_from_error(&self, err: &BoxError) -> HashMap<String, String> {
let mut attributes = HashMap::new();
if let Some(fetch_error) = err
.source()
.and_then(|e| e.downcast_ref::<FetchError>())
.or_else(|| err.downcast_ref::<FetchError>())
{
let gql_error = fetch_error.to_graphql_error(None);
// Include error message
if self.include_messages {
attributes.insert("message".to_string(), gql_error.message);
}
// Extract data from extensions
if let Some(extensions_fw) = &self.extensions {
for ext_fw in extensions_fw {
let output = ext_fw.path.execute(&gql_error.extensions).unwrap();
if let Some(val) = output {
if let Value::String(val_str) = val {
attributes.insert(ext_fw.name.clone(), val_str);
} else {
attributes.insert(ext_fw.name.clone(), val.to_string());
}
} else if let Some(default_val) = &ext_fw.default {
attributes.insert(ext_fw.name.clone(), default_val.clone());
}
}
}
} else if self.include_messages {
attributes.insert("message".to_string(), err.to_string());
}

attributes
}
}

impl AttributesForwardConf {
pub(crate) async fn get_attributes_from_router_response(
&self,
Expand Down Expand Up @@ -385,6 +447,13 @@ impl AttributesForwardConf {

attributes
}

pub(crate) fn get_attributes_from_error(&self, err: &BoxError) -> HashMap<String, String> {
self.errors
.as_ref()
.map(|e| e.get_attributes_from_error(err))
.unwrap_or_default()
}
}

fn string_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
Expand Down
Loading

0 comments on commit 0f226d7

Please sign in to comment.