Skip to content

Commit

Permalink
feat: allow adding keys from the context to the breadcrumb (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
DiederikvandenB authored Feb 25, 2020
1 parent e78f1e0 commit 15ea217
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 1 deletion.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ const defaultOptions = {
/**
* Include context keys as extra data in the breadcrumb. Accepts dot notation.
* The data is stringified and formatted. Can be used to include headers for instance.
* Note that this option is not yet implemented.
*/
includeContextKeys: [],
},
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@sentry/types": "^5.12.4",
"apollo-link": "^1.2.13",
"deepmerge": "^4.2.2",
"dot-prop": "^5.2.0",
"graphql": "^14.6.0"
},
"devDependencies": {
Expand Down
18 changes: 18 additions & 0 deletions src/Operation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Operation as ApolloOperation } from 'apollo-link';
import dotProp from 'dot-prop';

import { ApolloLinkSentry } from './types';
import { isEmpty } from './utils';
Expand Down Expand Up @@ -82,4 +83,21 @@ export class Operation {
? this.operation.query?.loc.source.body
: undefined
);

/**
* Get a set of keys from the context using dot notation
* @param {string[]} keys
* @returns {{[p: string]: any} | undefined}
*/
public getContextKeys = (keys: string[]): { [s: string]: any } | undefined => {
const context = this.operation.getContext();

const find = keys
.map((key): object | undefined => ({ [key]: dotProp.get(context, key) }))
.reduce((a: object, b: any): object => ({ ...a, ...b }), {});

return !isEmpty(find)
? find
: undefined;
};
}
16 changes: 16 additions & 0 deletions src/OperationsBreadcrumb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,22 @@ export class OperationsBreadcrumb {
return this;
};

/**
* Set the breadcrumb's context
* @param {object | undefined} context
* @returns {OperationsBreadcrumb}
*/
addContext = (context: object | undefined): OperationsBreadcrumb => {
if (isEmpty(context)) return this;

this.breadcrumb.data = {
...this.breadcrumb.data,
context: stringifyObject(context),
};

return this;
};

/**
* Set the breadcrumb's response data
* @param {object | undefined} response
Expand Down
5 changes: 5 additions & 0 deletions src/SentryLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const defaultOptions: ApolloLinkSentry.Options = {
includeVariables: false,
includeResponse: false,
includeError: false,
includeContextKeys: [],
},
};

Expand Down Expand Up @@ -98,6 +99,10 @@ export class SentryLink extends ApolloLink {
if (this.options.breadcrumb?.includeVariables) {
breadcrumb.addVariables(operation.variables);
}

if (this.options?.breadcrumb?.includeContextKeys?.length) {
breadcrumb.addContext(operation.getContextKeys(this.options.breadcrumb.includeContextKeys));
}
};

/**
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export namespace ApolloLinkSentry {
cache?: string,
response?: string,
error?: string,
context?: string,
}
}
}
Expand All @@ -26,6 +27,7 @@ export namespace ApolloLinkSentry {
includeVariables?: boolean;
includeResponse?: boolean;
includeError?: boolean;
includeContextKeys?: string[];
}

export interface Options {
Expand Down
11 changes: 11 additions & 0 deletions tests/Operation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,15 @@ describe('Operation', () => {
const query = OperationStub.query.loc?.source.body;
expect(operation['getQuery']()).toEqual(query);
});

it('should be possible to get context keys', () => {
const operation = new Operation(OperationStub);
const { headers } = OperationStub.getContext();

const keys = ['headers', 'someOtherContext.lorem.ipsum'];
const context = operation['getContextKeys'](keys);

expect(context?.headers).toEqual(headers);
expect(context?.['someOtherContext.lorem.ipsum']).toBeTruthy();
});
});
9 changes: 9 additions & 0 deletions tests/OperationsBreadcrumb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ describe('OperationsBreadcrumb', () => {
expect(data?.variables).toBe(stringifyObject(variables));
});

it('should be possible to set the context', () => {
const context = { headers: { 'X-Debug': true } };

const breadcrumb = new OperationsBreadcrumb();
const { data } = breadcrumb.addContext(context)['breadcrumb'];

expect(data?.context).toBe(stringifyObject(context));
});

it('should be possible to add a response', () => {
const response = { status: 200, data: { success: true } };

Expand Down
17 changes: 17 additions & 0 deletions tests/SentryLink.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,5 +261,22 @@ describe('SentryLink', () => {

expect(originalReport.fingerprint).toBeUndefined();
});

test('should add context keys to the breadcrumb', () => {
const keys = ['headers', 'someOtherContext.lorem.ipsum'];
const link = new SentryLink({ breadcrumb: { includeContextKeys: keys } });
const breadcrumb = new OperationsBreadcrumb();
const operation = new Operation(OperationStub);
const context = operation['getContextKeys'](keys);

link.fillBreadcrumb(breadcrumb, operation);
link.attachBreadcrumbToSentry(breadcrumb);
Sentry.captureException(new Error('Error'));

const [report] = testkit.reports();
const [crumb] = report.breadcrumbs;

expect(crumb.data?.context).toBe(stringifyObject(context));
});
});
});
10 changes: 10 additions & 0 deletions tests/stubs/Operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,16 @@ const operation: Operation = {
freezeResults: false,
},
},
headers: {
'App-Impersonation-Key': 'a0cb2511-d7b1-47a2-ad59-da06bf2f1a10',
},
someOtherContext: {
lorem: {
ipsum: {
dorem: true,
},
},
},
}),

setContext: (): any => {},
Expand Down

0 comments on commit 15ea217

Please sign in to comment.