Skip to content

Commit

Permalink
[plugin/prometheus] fix labels not filled properly on invalid operati…
Browse files Browse the repository at this point in the history
…ons (#3278)
  • Loading branch information
EmrysMyrddin authored May 17, 2024
1 parent 02c839f commit edf3737
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 35 deletions.
5 changes: 5 additions & 0 deletions .changeset/rotten-chefs-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-yoga/plugin-prometheus': patch
---

Fix labels not filled properly on invalid operations
24 changes: 12 additions & 12 deletions packages/plugins/prometheus/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import {

export {
CounterAndLabels,
FillLabelsFnParams,
HistogramAndLabels,
SummaryAndLabels,
createCounter,
createHistogram,
createSummary,
FillLabelsFnParams,
HistogramAndLabels,
SummaryAndLabels,
};

export interface PrometheusTracingPluginConfig extends EnvelopPrometheusTracingPluginConfig {
Expand Down Expand Up @@ -101,15 +101,15 @@ export function usePrometheus(options: PrometheusTracingPluginConfig): Plugin {
}
return undefined;
},
onExecute({ args }) {
const operationAST = getOperationAST(args.document, args.operationName);
const operationType = operationAST?.operation;
const operationName = operationAST?.name?.value;
paramsByRequest.set(args.contextValue.request, {
document: args.document,
operationName,
operationType,
});
onParse() {
return ({ result: document, context: { params, request } }) => {
const operationAST = getOperationAST(document, params.operationName);
paramsByRequest.set(request, {
document,
operationName: operationAST?.name?.value,
operationType: operationAST?.operation,
});
};
},
onResponse({ request, response, serverContext }) {
const start = startByRequest.get(request);
Expand Down
34 changes: 34 additions & 0 deletions packages/plugins/prometheus/tests/prometheus.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,38 @@ describe('Prometheus', () => {
registry,
});
});

it('should emit metric with all labels on invalid operations', async () => {
const yoga = createYoga({
schema,
plugins: [
usePrometheus({
http: true,
registry,
}),
],
});
const result = await yoga.fetch('http://localhost:4000/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/graphql+json',
Accept: 'application/graphql-response+json',
},
body: JSON.stringify({
query: /* GraphQL */ `
query TestProm {
hello_DOES_NOT_EXIST
}
`,
}),
});
await result.text();
expect(result.status).toBe(400);
const metrics = await registry.metrics();
expect(metrics).toContain('graphql_yoga_http_duration_bucket');
expect(metrics).toContain('operationType="query"');
expect(metrics).toContain('method="POST"');
expect(metrics).toContain('statusCode="400"');
expect(metrics).toContain('operationName="TestProm"');
});
});
46 changes: 23 additions & 23 deletions website/src/pages/docs/features/automatic-persisted-queries.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -124,32 +124,32 @@ For external stores the `set` and `get` properties on the store can also return
Instead of raising an error, returning undefined or null will allow the server to continue to
respond to requests if the store goes down.

```ts filename="Automatic Persisted Operations with a redis store" {16}
import Keyv from "keyv";

const store = new Keyv("redis://user:pass@localhost:6379");

useAPQ({
store: {
async get(key) {
try {
return await store.get(key);
} catch(e) {
console.error(`Error while fetching the operation: ${key}`, e);
}
},
async set(key, value) {
try {
return await store.set(key, value);
} catch(e) {
console.error(`Error while saving the operation: ${key}`, e);
}
```ts filename="Automatic Persisted Operations with a redis store" {16}
import Keyv from 'keyv'

const store = new Keyv('redis://user:pass@localhost:6379')

useAPQ({
store: {
async get(key) {
try {
return await store.get(key)
} catch (e) {
console.error(`Error while fetching the operation: ${key}`, e)
}
},
async set(key, value) {
try {
return await store.set(key, value)
} catch (e) {
console.error(`Error while saving the operation: ${key}`, e)
}
}
})
```
</Callout>
}
})
```

</Callout>

## Configure Error responses

Expand Down

0 comments on commit edf3737

Please sign in to comment.