Skip to content

Commit 7dc37e6

Browse files
authored
remove high cardinality labels and fix bug for operationName (#3179)
* fix: operationName issue when label is not present * remove high cardinality labels * fix: format * upgrade prometheus * add changeset * use major version
1 parent 266488a commit 7dc37e6

File tree

5 files changed

+19
-80
lines changed

5 files changed

+19
-80
lines changed

.changeset/dull-numbers-work.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphql-yoga/plugin-prometheus': major
3+
---
4+
5+
Removed labels that cause high cardinality

packages/plugins/prometheus/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"prom-client": "^15.0.0"
4343
},
4444
"dependencies": {
45-
"@envelop/prometheus": "^9.2.0"
45+
"@envelop/prometheus": "^9.3.1"
4646
},
4747
"devDependencies": {
4848
"prom-client": "15.0.0"

packages/plugins/prometheus/src/index.ts

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ export { createCounter, createHistogram, createSummary, FillLabelsFnParams };
1414

1515
export interface PrometheusTracingPluginConfig extends EnvelopPrometheusTracingPluginConfig {
1616
http?: boolean | ReturnType<typeof createHistogram>;
17-
httpRequestHeaders?: boolean;
18-
httpResponseHeaders?: boolean;
17+
1918
/**
2019
* The endpoint to serve metrics exposed by this plugin.
2120
* Defaults to "/metrics".
@@ -26,7 +25,6 @@ export interface PrometheusTracingPluginConfig extends EnvelopPrometheusTracingP
2625
export function usePrometheus(options: PrometheusTracingPluginConfig): Plugin {
2726
const endpoint = options.endpoint || '/metrics';
2827
const registry = options.registry || defaultRegistry;
29-
3028
let httpHistogram: ReturnType<typeof createHistogram> | undefined;
3129

3230
function labelExists(label: string) {
@@ -37,19 +35,13 @@ export function usePrometheus(options: PrometheusTracingPluginConfig): Plugin {
3735
}
3836

3937
if (options.http) {
40-
const labelNames = ['url', 'method', 'statusCode', 'statusText'];
38+
const labelNames = ['method', 'statusCode'];
4139
if (labelExists('operationName')) {
4240
labelNames.push('operationName');
4341
}
4442
if (labelExists('operationType')) {
4543
labelNames.push('operationType');
4644
}
47-
if (options.httpRequestHeaders) {
48-
labelNames.push('requestHeaders');
49-
}
50-
if (options.httpResponseHeaders) {
51-
labelNames.push('responseHeaders');
52-
}
5345
httpHistogram =
5446
typeof options.http === 'object'
5547
? options.http
@@ -62,28 +54,15 @@ export function usePrometheus(options: PrometheusTracingPluginConfig): Plugin {
6254
}),
6355
fillLabelsFn(params, { request, response }) {
6456
const labels: Record<string, string> = {
65-
operationName: params.operationName || 'Anonymous',
66-
url: request.url,
6757
method: request.method,
6858
statusCode: response.status,
69-
statusText: response.statusText,
7059
};
7160
if (labelExists('operationType') && params.operationType) {
7261
labels.operationType = params.operationType;
7362
}
7463
if (labelExists('operationName')) {
7564
labels.operationName = params.operationName || 'Anonymous';
7665
}
77-
if (options.httpRequestHeaders) {
78-
labels.requestHeaders = JSON.stringify(
79-
Object.fromEntries(request.headers.entries()),
80-
);
81-
}
82-
if (options.httpResponseHeaders) {
83-
labels.responseHeaders = JSON.stringify(
84-
Object.fromEntries(response.headers.entries()),
85-
);
86-
}
8766
return labels;
8867
},
8968
});

packages/plugins/prometheus/tests/prometheus.spec.ts

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ describe('Prometheus', () => {
1818
afterEach(() => {
1919
registry.clear();
2020
});
21-
it('http flag should work and do not send headers by default', async () => {
21+
it('http flag should work', async () => {
2222
const yoga = createYoga({
2323
schema,
2424
plugins: [
@@ -47,21 +47,20 @@ describe('Prometheus', () => {
4747
expect(metrics).toContain('graphql_yoga_http_duration_bucket');
4848
expect(metrics).toContain('operationName="TestProm"');
4949
expect(metrics).toContain('operationType="query"');
50-
expect(metrics).toContain('url="http://localhost:4000/graphql"');
5150
expect(metrics).toContain('method="POST"');
5251
expect(metrics).toContain('statusCode="200"');
53-
expect(metrics).toContain('statusText="OK"');
54-
expect(metrics).not.toContain('requestHeaders');
55-
expect(metrics).not.toContain('x-test=test');
5652
});
57-
it('httpRequestHeaders should work', async () => {
53+
it('labels should be excluded', async () => {
5854
const yoga = createYoga({
5955
schema,
6056
plugins: [
6157
usePrometheus({
6258
http: true,
63-
httpRequestHeaders: true,
6459
registry,
60+
labels: {
61+
operationName: false,
62+
operationType: false,
63+
},
6564
}),
6665
],
6766
});
@@ -82,54 +81,12 @@ describe('Prometheus', () => {
8281
await result.text();
8382
const metrics = await registry.metrics();
8483
expect(metrics).toContain('graphql_yoga_http_duration_bucket');
85-
expect(metrics).toContain('operationName="TestProm"');
86-
expect(metrics).toContain('operationType="query"');
87-
expect(metrics).toContain('url="http://localhost:4000/graphql"');
88-
expect(metrics).toContain('method="POST"');
89-
expect(metrics).toContain('statusCode="200"');
90-
expect(metrics).toContain('statusText="OK"');
91-
expect(metrics).toContain(
92-
'requestHeaders="{\\"content-type\\":\\"application/json\\",\\"x-test\\":\\"test\\",\\"content-length\\":\\"82\\"}"}',
93-
);
94-
});
95-
it('httpResponseHeaders should work', async () => {
96-
const yoga = createYoga({
97-
schema,
98-
plugins: [
99-
usePrometheus({
100-
http: true,
101-
httpResponseHeaders: true,
102-
registry,
103-
}),
104-
],
105-
});
106-
const result = await yoga.fetch('http://localhost:4000/graphql', {
107-
method: 'POST',
108-
headers: {
109-
'Content-Type': 'application/json',
110-
'x-test': 'test',
111-
},
112-
body: JSON.stringify({
113-
query: /* GraphQL */ `
114-
query TestProm {
115-
hello
116-
}
117-
`,
118-
}),
119-
});
120-
await result.text();
121-
const metrics = await registry.metrics();
122-
expect(metrics).toContain('graphql_yoga_http_duration_bucket');
123-
expect(metrics).toContain('operationName="TestProm"');
124-
expect(metrics).toContain('operationType="query"');
125-
expect(metrics).toContain('url="http://localhost:4000/graphql"');
84+
expect(metrics).not.toContain('operationName="TestProm"');
85+
expect(metrics).not.toContain('operationType="query"');
12686
expect(metrics).toContain('method="POST"');
12787
expect(metrics).toContain('statusCode="200"');
128-
expect(metrics).toContain('statusText="OK"');
129-
expect(metrics).toContain(
130-
`responseHeaders="{\\"content-type\\":\\"application/json; charset=utf-8\\",\\"content-length\\":\\"33\\"}"}`,
131-
);
13288
});
89+
13390
it('endpoint should work', async () => {
13491
const yoga = createYoga({
13592
schema,
@@ -162,9 +119,7 @@ describe('Prometheus', () => {
162119
expect(metrics).toContain('graphql_yoga_http_duration_bucket');
163120
expect(metrics).toContain('operationName="TestProm"');
164121
expect(metrics).toContain('operationType="query"');
165-
expect(metrics).toContain('url="http://localhost:4000/graphql"');
166122
expect(metrics).toContain('method="POST"');
167123
expect(metrics).toContain('statusCode="200"');
168-
expect(metrics).toContain('statusText="OK"');
169124
});
170125
});

website/src/pages/docs/integrations/integration-with-bun.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ const yoga = createYoga({
4040
})
4141

4242
const server = Bun.serve({
43-
fetch: yoga,
44-
});
43+
fetch: yoga
44+
})
4545

4646
console.info(
4747
`Server is running on ${new URL(

0 commit comments

Comments
 (0)