feat(core): add operation-level sample rates to the usage plugin#8181
feat(core): add operation-level sample rates to the usage plugin#8181ChaoyangS wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces operation-level sample rates to the usage plugin via the new sampleRates option. The review feedback suggests avoiding the non-null assertion operator (!) in sampling.ts by destructuring properties and leveraging TypeScript's control flow analysis to narrow the type of regex automatically.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const rules = config.rates.map(rate => { | ||
| const hasName = typeof rate.name === 'string'; | ||
| const hasRegex = rate.regex instanceof RegExp; | ||
|
|
||
| if (hasName === hasRegex) { | ||
| throw new Error( | ||
| 'Expected usage.sampleRates entry to define exactly one of "name" or "regex".', | ||
| ); | ||
| } | ||
|
|
||
| if (rate.sampleRate > 1 || rate.sampleRate < 0) { | ||
| throw new Error( | ||
| `Expected usage.sampleRates sampleRate to be 0 <= x <= 1, received ${rate.sampleRate}`, | ||
| ); | ||
| } | ||
|
|
||
| const matches = hasRegex | ||
| ? (operationName: string) => rate.regex!.test(operationName) | ||
| : (operationName: string) => operationName === rate.name; | ||
|
|
||
| return { matches, sampleRate: rate.sampleRate }; | ||
| }); |
There was a problem hiding this comment.
Avoid using the non-null assertion operator (!) outside of test files, as it can lead to subtle bugs. We can destructure the properties from rate and let TypeScript's control flow analysis narrow the type of regex automatically when checking regex instanceof RegExp.
const rules = config.rates.map(rate => {
const { name, regex, sampleRate } = rate;
const hasName = typeof name === 'string';
const hasRegex = regex instanceof RegExp;
if (hasName === hasRegex) {
throw new Error(
'Expected usage.sampleRates entry to define exactly one of "name" or "regex".',
);
}
if (sampleRate > 1 || sampleRate < 0) {
throw new Error(
'Expected usage.sampleRates sampleRate to be 0 <= x <= 1, received ' + sampleRate,
);
}
const matches = regex instanceof RegExp
? (operationName: string) => regex.test(operationName)
: (operationName: string) => operationName === name;
return { matches, sampleRate };
});References
- Avoid using the non-null assertion operator (
!) outside of test files, as it can lead to subtle bugs.
Background
Hive's usage plugin currently supports a single global
sampleRate, applieduniformly to every operation. For systems that mix very high-volume and
low-volume operations this forces a bad trade-off: a low global rate to control
quota cost causes low-volume operations to be missed entirely, while a high rate
to keep visibility into rare operations overpays by reporting all the
high-volume traffic.
This PR adds operation-level sample rates so high-volume operations can be
sampled aggressively while low-volume operations stay at (or near) 100%
visibility.
Resolves #3556.
Description
Adds a new declarative
sampleRatesoption toHiveUsagePluginOptionsin@graphql-hive/core(the client/agent library used by the integrations).packages/libraries/core/src/client/types.ts— newOperationSampleRatetype (
nameorregex+sampleRate) and thesampleRates?: OperationSampleRate[]option.
packages/libraries/core/src/client/sampling.ts— newoperationSampling()factory returning a
shouldInclude(context)function: first matching rule wins,unmatched operations fall back to the global
sampleRate. Rules are validatedeagerly (exactly one of
name/regex; rate within0..1).packages/libraries/core/src/client/usage.ts— wiressampleRatesinto theexisting
shouldIncludeselection, preserving precedence:exclude>sampler>sampleRates> globalsampleRate. Fully backwardcompatible (option is optional; default behavior unchanged).
tests/sampling.spec.ts) and an end-to-end usage test(
tests/usage.spec.ts), plus a runnable demo (demo/operation-sample-rates.ts).@graphql-hive/core,minor).