UNPKG

@envelop/prometheus

Version:

This plugin tracks the complete execution flow, and reports metrics using Prometheus tracing (based on `prom-client`).

152 lines (122 loc) 4.96 kB
## `@envelop/prometheus` This plugin tracks the complete execution flow, and reports metrics using Prometheus tracing (based on `prom-client`). You can opt-in to collect tracing from the following phases: - Successful requests (`requestCount`) - Request summary (`requestSummary`) - errors (categorized by `phase`) - resolvers tracing and runtime - deprecated fields usage - count of graphql operations - `parse` execution time - `validate` execution time - `contextBuilding` execution time - `execute` execution time > You can also customize each phase reporter, and add custom metadata and labels to the metrics. ## Getting Started ``` yarn add prom-client @envelop/prometheus ``` ## Usage Example ```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({ // 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 }) ] }) ``` > Note: 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. ### 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. ### Custom `prom-client` instances Each tracing field supports custom `prom-client` objects, and custom `labels` a 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.