-
Notifications
You must be signed in to change notification settings - Fork 575
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add documentation for prometheus plugin
- Loading branch information
1 parent
a517979
commit e4fdacf
Showing
1 changed file
with
177 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
--- | ||
description: How to monitor your GraphQL server using Prometheus. | ||
--- | ||
|
||
import { Callout } from '@theguild/components' | ||
|
||
# Monitoring | ||
|
||
Once in production, it's important to monitor your GraphQL server. | ||
|
||
A common way to monitor your server is by using Prometheus, a popular, free and open-source | ||
monitoring system. | ||
|
||
## Getting Started | ||
|
||
To get started, you need to install the `@graphql-yoga/plugin-prometheus` package. | ||
|
||
This plugin tracks the complete execution flow, and reports metrics using Prometheus tracing (based | ||
on `prom-client`). | ||
|
||
```sh npm2yarn | ||
npm i prom-client @graphql-yoga/plugin-prometheus | ||
``` | ||
|
||
You can then add the plugin to your GraphQL server: | ||
|
||
```ts | ||
import { execute, parse, specifiedRules, subscribe, validate } from 'graphql' | ||
import { envelop, useEngine } from '@envelop/core' | ||
import { usePrometheus } from '@envelop/prometheus' | ||
|
||
const getEnveloped = envelop({ | ||
plugins: [ | ||
useEngine({ parse, validate, specifiedRules, execute, subscribe }), | ||
// ... other plugins ... | ||
usePrometheus({ | ||
endpoint: '/metrics', // optional, default is `/metrics`, you can disable it by setting it to `false` if registry is configured in "push" mode | ||
// all optional, and by default, all set to false, please opt-in to the metrics you wish to get | ||
requestCount: true, // requires `execute` to be true as well | ||
requestSummary: true, // requires `execute` to be true as well | ||
parse: true, | ||
validate: true, | ||
contextBuilding: true, | ||
execute: true, | ||
errors: true, | ||
resolvers: true, // requires "execute" to be `true` as well | ||
resolversWhitelist: ['Mutation.*', 'Query.user'], // reports metrics als for these resolvers, leave `undefined` to report all fields | ||
deprecatedFields: true, | ||
registry: myRegistry // If you are using a custom prom-client registry, please set it here | ||
}) | ||
] | ||
}) | ||
``` | ||
|
||
<Callout type="warning"> | ||
Tracing resolvers using `resolvers: true` might have a performance impact on your GraphQL runtime. | ||
Please consider to test it locally first and then decide if it's needed. | ||
</Callout> | ||
|
||
Now, you can access the metrics by visiting the `/metrics` endpoint of your server. | ||
|
||
You can then configure Prometheus to scrape the metrics from your server by using this URL. | ||
|
||
## Configuration | ||
|
||
### Available metrics | ||
|
||
You can opt-in to collect tracing from the following phases: | ||
|
||
- HTTP request process time (`http`) | ||
- Graphql successful requests (`requestCount`) | ||
- Graphql request summary (`requestSummary`) | ||
- `errors` (categorized by `phase`) | ||
- `resolvers` tracing and runtime | ||
- deprecated fields usage (`deprecatedFields`) | ||
- `parse` execution time | ||
- `validate` execution time | ||
- `contextBuilding` execution time | ||
- `execute` execution time | ||
- `subscribe` execution time | ||
- count of schema changes (`schemaChangeCount`) | ||
|
||
> You can also customize each phase reporter, and add custom metadata and labels to the metrics. | ||
### Custom registry | ||
|
||
You can customize the `prom-client` `Registry` object if you are using a custom one, by passing it | ||
along with the configuration object: | ||
|
||
```ts | ||
import { execute, parse, specifiedRules, subscribe, validate } from 'graphql' | ||
import { Registry } from 'prom-client' | ||
import { envelop, useEngine } from '@envelop/core' | ||
|
||
const myRegistry = new Registry() | ||
|
||
const getEnveloped = envelop({ | ||
plugins: [ | ||
useEngine({ parse, validate, specifiedRules, execute, subscribe }), | ||
// ... other plugins ... | ||
usePrometheus({ | ||
// ... config ... | ||
registry: myRegistry | ||
}) | ||
] | ||
}) | ||
``` | ||
|
||
> Note: if you are using custom `prom-client` instances, you need to make sure to pass your registry | ||
> there as well. | ||
### Introspection | ||
|
||
If you wish to disable introspection logging, you can use `skipIntrospection: true` in your config | ||
object. | ||
|
||
### Customize metrics options and labels | ||
|
||
Each metric can be configured and custom `labels` can be added to provide more metadata. You can | ||
create a custom extraction function for every `Histogram` / `Summary` / `Counter`: | ||
|
||
```ts | ||
import { execute, parse, specifiedRules, subscribe, validate } from 'graphql' | ||
import { Histogram, register as registry } from 'prom-client' | ||
import { envelop, useEngine } from '@envelop/core' | ||
import { createHistogram, usePrometheus } from '@envelop/prometheus' | ||
|
||
const getEnveloped = envelop({ | ||
plugins: [ | ||
useEngine({ parse, validate, specifiedRules, execute, subscribe }), | ||
// ... other plugins ... | ||
usePrometheus({ | ||
// all optional, and by default, all set to false, please opt-in to the metrics you wish to get | ||
parse: createHistogram({ | ||
registry: registry // make sure to add your custom registry, if you are not using the default one | ||
histogram: new Histogram({ | ||
name: 'my_custom_name', | ||
help: 'HELP ME', | ||
labelNames: ['opText'] as const, | ||
}), | ||
fillLabelsFn: params => { | ||
// if you wish to fill your `labels` with metadata, you can use the params in order to get access to things like DocumentNode, operationName, operationType, `error` (for error metrics) and `info` (for resolvers metrics) | ||
return { | ||
opText: print(params.document) | ||
} | ||
} | ||
}) | ||
}) | ||
] | ||
}) | ||
``` | ||
|
||
## Caveats | ||
|
||
Due to Prometheus client API limitations, if this plugin is initialized multiple times, only the | ||
metrics configuration of the first initialization will be applied. | ||
|
||
If necessary, use a different registry instance for each plugin instance, or clear the registry | ||
before plugin initialization. | ||
|
||
```ts | ||
function usePrometheusWithRegistry() { | ||
// create a new registry instance for each plugin instance | ||
const registry = new Registry() | ||
|
||
// or just clear the registry if you use only on plugin instance at a time | ||
registry.clear() | ||
|
||
return usePrometheus({ | ||
registry, | ||
... | ||
}) | ||
} | ||
``` | ||
|
||
Keep in mind that this implies potential data loss in pull mode if some data is produced between | ||
last pull and the re-initialization of the plugin. |