11import {
22 PrometheusTracingPluginConfig as EnvelopPrometheusTracingPluginConfig ,
33 usePrometheus as useEnvelopPrometheus ,
4+ createCounter ,
5+ createHistogram ,
6+ createSummary ,
7+ FillLabelsFnParams ,
48} from '@envelop/prometheus'
9+ import { getOperationAST } from 'graphql'
510import { Plugin } from 'graphql-yoga'
611import { Histogram , register as defaultRegistry } from 'prom-client'
712
13+ export { createCounter , createHistogram , createSummary , FillLabelsFnParams }
14+
815export interface PrometheusTracingPluginConfig
916 extends EnvelopPrometheusTracingPluginConfig {
10- http ?: boolean | EnvelopPrometheusTracingPluginConfig [ 'execute' ]
17+ http ?: boolean | ReturnType < typeof createHistogram >
18+ httpRequestHeaders ?: boolean
19+ httpResponseHeaders ?: boolean
1120 /**
1221 * The endpoint to serve metrics exposed by this plugin.
1322 * Defaults to "/metrics".
@@ -27,21 +36,61 @@ export function usePrometheus(options: PrometheusTracingPluginConfig): Plugin {
2736 const endpoint = options . endpoint || '/metrics'
2837 const registry = options . registry || defaultRegistry
2938
30- const httpHistogram = new Histogram ( {
31- name : 'graphql_yoga_http_duration' ,
32- help : 'Time spent on HTTP connection' ,
33- labelNames : [
39+ let httpHistogram : ReturnType < typeof createHistogram > | undefined
40+
41+ if ( options . http ) {
42+ const labelNames = [
3443 'url' ,
3544 'method' ,
36- 'requestHeaders' ,
3745 'statusCode' ,
3846 'statusText' ,
39- 'responseHeaders' ,
40- ] ,
41- registers : [ registry ] ,
42- } )
47+ 'operationName' ,
48+ 'operationType' ,
49+ ]
50+ if ( options . httpRequestHeaders ) {
51+ labelNames . push ( 'requestHeaders' )
52+ }
53+ if ( options . httpResponseHeaders ) {
54+ labelNames . push ( 'responseHeaders' )
55+ }
56+ httpHistogram =
57+ typeof options . http === 'object'
58+ ? options . http
59+ : createHistogram ( {
60+ histogram : new Histogram ( {
61+ name : 'graphql_yoga_http_duration' ,
62+ help : 'Time spent on HTTP connection' ,
63+ labelNames,
64+ registers : [ registry ] ,
65+ } ) ,
66+ fillLabelsFn ( params , { request, response } ) {
67+ const labels : Record < string , string > = {
68+ operationName : params . operationName || 'Anonymous' ,
69+ url : request . url ,
70+ method : request . method ,
71+ statusCode : response . status ,
72+ statusText : response . statusText ,
73+ }
74+ if ( params ?. operationType ) {
75+ labels . operationType = params . operationType
76+ }
77+ if ( options . httpRequestHeaders ) {
78+ labels . requestHeaders = JSON . stringify (
79+ headersToObj ( request . headers ) ,
80+ )
81+ }
82+ if ( options . httpResponseHeaders ) {
83+ labels . responseHeaders = JSON . stringify (
84+ headersToObj ( response . headers ) ,
85+ )
86+ }
87+ return labels
88+ } ,
89+ } )
90+ }
4391
4492 const startByRequest = new WeakMap < Request , number > ( )
93+ const paramsByRequest = new WeakMap < Request , FillLabelsFnParams > ( )
4594
4695 return {
4796 onPluginInit ( { addPlugin } ) {
@@ -59,19 +108,27 @@ export function usePrometheus(options: PrometheusTracingPluginConfig): Plugin {
59108 endResponse ( response )
60109 }
61110 } ,
62- onResponse ( { request, response } ) {
111+ onExecute ( { args } ) {
112+ const operationAST = getOperationAST ( args . document , args . operationName )
113+ const operationType = operationAST ?. operation
114+ const operationName = operationAST ?. name ?. value
115+ paramsByRequest . set ( args . contextValue . request , {
116+ document : args . document ,
117+ operationName,
118+ operationType,
119+ } )
120+ } ,
121+ onResponse ( { request, response, serverContext } ) {
63122 const start = startByRequest . get ( request )
64123 if ( start ) {
65124 const duration = Date . now ( ) - start
66- httpHistogram . observe (
67- {
68- url : request . url ,
69- method : request . method ,
70- requestHeaders : JSON . stringify ( headersToObj ( request . headers ) ) ,
71- statusCode : response . status ,
72- statusText : response . statusText ,
73- responseHeaders : JSON . stringify ( headersToObj ( response . headers ) ) ,
74- } ,
125+ const params = paramsByRequest . get ( request )
126+ httpHistogram ?. histogram . observe (
127+ httpHistogram . fillLabelsFn ( params || { } , {
128+ ...serverContext ,
129+ request,
130+ response,
131+ } ) ,
75132 duration ,
76133 )
77134 }
0 commit comments