Update exclude arg to accept RegExp (#3555) (#3608)

Co-authored-by: Mina Kong <35077931+kongMina@users.noreply.github.com>
This commit is contained in:
Kamil Kisiela 2023-12-14 09:47:50 +01:00 committed by GitHub
parent a7ba40bf9e
commit daf9eaa4b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 141 additions and 4 deletions

View file

@ -0,0 +1,5 @@
---
"@graphql-hive/client": minor
---
Changed `exclude` argument type to accept RegEX

View file

@ -67,9 +67,9 @@ export interface HiveUsagePluginOptions {
*/
ttl?: number;
/**
* A list of operations (by name) to be ignored by Hive.
* A list of operations (by name or regular expression) that should be excluded from reporting.
*/
exclude?: string[];
exclude?: Array<string | RegExp>;
/**
* Sample rate to determine sampling.
* 0.0 = 0% chance of being sent

View file

@ -177,9 +177,14 @@ export function createUsage(pluginOptions: HivePluginOptions): UsageCollector {
) as OperationDefinitionNode;
providedOperationName = args.operationName || rootOperation.name?.value;
const operationName = providedOperationName || 'anonymous';
// Check if operationName is a match with any string or regex in excludeSet
const isMatch = Array.from(excludeSet).some(excludingValue =>
excludingValue instanceof RegExp
? excludingValue.test(operationName)
: operationName === excludingValue,
);
if (
!excludeSet.has(operationName) &&
!isMatch &&
shouldInclude({
operationName,
document,

View file

@ -556,3 +556,130 @@ test('should send data to Hive at least once when using atLeastOnceSampler', asy
const operations = report.operations;
expect(operations).toHaveLength(2); // two operations
});
test('should not send excluded operation name data to Hive', async () => {
const logger = {
error: vi.fn(),
info: vi.fn(),
};
const token = 'Token';
let report: Report = {
size: 0,
map: {},
operations: [],
};
const http = nock('http://localhost')
.post('/200')
.once()
.reply((_, _body) => {
report = _body as any;
return [200];
});
const hive = createHive({
enabled: true,
debug: true,
agent: {
timeout: 500,
maxRetries: 0,
logger,
},
token,
selfHosting: {
graphqlEndpoint: 'http://localhost/graphql',
applicationUrl: 'http://localhost/',
usageEndpoint: 'http://localhost/200',
},
usage: {
exclude: ['deleteProjectShouldntBeIncluded', new RegExp('ExcludeThis$')],
},
});
const collect = hive.collectUsage();
await waitFor(2000);
collect(
{
schema,
document: op,
operationName: 'deleteProjectExcludeThis',
},
{},
);
collect(
{
schema,
document: op,
operationName: 'deleteProjectShouldntBeIncluded',
},
{},
);
collect(
{
schema,
document: op,
operationName: 'deleteProject',
},
{},
);
collect(
{
schema,
document: op2,
operationName: 'getProject',
},
{},
);
await hive.dispose();
await waitFor(1000);
http.done();
expect(logger.error).not.toHaveBeenCalled();
expect(logger.info).toHaveBeenCalledWith(`[hive][usage] Sending (queue 2) (attempt 1)`);
expect(logger.info).toHaveBeenCalledWith(`[hive][usage] Sent!`);
// Map
expect(report.size).toEqual(2);
expect(Object.keys(report.map)).toHaveLength(2);
const key = Object.keys(report.map)[0];
const record = report.map[key];
// operation
expect(record.operation).toMatch('mutation deleteProject');
expect(record.operationName).toMatch('deleteProject');
// fields
expect(record.fields).toMatchInlineSnapshot(`
[
Mutation.deleteProject,
Mutation.deleteProject.selector,
DeleteProjectPayload.selector,
ProjectSelector.organization,
ProjectSelector.project,
DeleteProjectPayload.deletedProject,
Project.id,
Project.cleanId,
Project.name,
Project.type,
ProjectSelectorInput.organization,
ID,
ProjectSelectorInput.project,
]
`);
// Operations
const operations = report.operations;
expect(operations).toHaveLength(2); // two operations
const operation = operations[0];
expect(operation.operationMapKey).toEqual(key);
expect(operation.timestamp).toEqual(expect.any(Number));
// execution
expect(operation.execution.duration).toBeGreaterThanOrEqual(1500 * 1_000_000); // >=1500ms in microseconds
expect(operation.execution.duration).toBeLessThan(3000 * 1_000_000); // <3000ms
expect(operation.execution.errorsTotal).toBe(0);
expect(operation.execution.errors).toHaveLength(0);
expect(operation.execution.ok).toBe(true);
});