Skip to content

Commit 2631251

Browse files
authored
feat(core): Add plugin options as tags (#113)
Add a subset of our plugin options as tags to Sentry events. Obviously, we cannot send all options but we have to be careful to only send insensitive data, such as if an optional step (e.g. `deploy`) was selected or not. Going forward, we can use this data to evaluate which options are used and for debugging issues. Also add some tests
1 parent 624c156 commit 2631251

File tree

3 files changed

+131
-2
lines changed

3 files changed

+131
-2
lines changed

packages/bundler-plugin-core/src/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ import {
1010
uploadSourceMaps,
1111
} from "./sentry/releasePipeline";
1212
import "@sentry/tracing";
13-
import { addSpanToTransaction, captureMinimalError, makeSentryClient } from "./sentry/telemetry";
13+
import {
14+
addPluginOptionTags,
15+
addSpanToTransaction,
16+
captureMinimalError,
17+
makeSentryClient,
18+
} from "./sentry/telemetry";
1419
import { Span, Transaction } from "@sentry/types";
1520
import { createLogger, Logger } from "./sentry/logger";
1621
import { InternalOptions, normalizeUserOptions, validateOptions } from "./options-mapping";
@@ -90,6 +95,7 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
9095
"https://[email protected]/6690737",
9196
internalOptions.telemetry
9297
);
98+
addPluginOptionTags(internalOptions, sentryHub);
9399

94100
const logger = createLogger({
95101
hub: sentryHub,

packages/bundler-plugin-core/src/sentry/telemetry.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
NodeClient,
88
} from "@sentry/node";
99
import { Span } from "@sentry/tracing";
10+
import { InternalOptions } from "../options-mapping";
1011
import { BuildContext } from "../types";
1112

1213
export function makeSentryClient(
@@ -76,3 +77,43 @@ export function captureMinimalError(error: unknown | Error, hub: Hub) {
7677

7778
hub.captureException(sentryError);
7879
}
80+
81+
export function addPluginOptionTags(options: InternalOptions, hub: Hub) {
82+
const {
83+
cleanArtifacts,
84+
finalize,
85+
setCommits,
86+
injectReleasesMap,
87+
dryRun,
88+
errorHandler,
89+
deploy,
90+
include,
91+
} = options;
92+
93+
hub.setTag("include", include.length > 1 ? "multiple-entries" : "single-entry");
94+
95+
// Optional release pipeline steps
96+
if (cleanArtifacts) {
97+
hub.setTag("clean-artifacts", true);
98+
}
99+
if (setCommits) {
100+
hub.setTag("set-commits", setCommits.auto === true ? "auto" : "manual");
101+
}
102+
if (finalize) {
103+
hub.setTag("finalize-release", true);
104+
}
105+
if (deploy) {
106+
hub.setTag("add-deploy", true);
107+
}
108+
109+
// Miscelaneous options
110+
if (dryRun) {
111+
hub.setTag("dry-run", true);
112+
}
113+
if (injectReleasesMap) {
114+
hub.setTag("inject-releases-map", true);
115+
}
116+
if (errorHandler) {
117+
hub.setTag("error-handler", "custom");
118+
}
119+
}

packages/bundler-plugin-core/test/sentry/telemetry.test.ts

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Hub } from "@sentry/node";
2-
import { captureMinimalError } from "../../src/sentry/telemetry";
2+
import { InternalOptions } from "../../src/options-mapping";
3+
import { addPluginOptionTags, captureMinimalError } from "../../src/sentry/telemetry";
34

45
describe("captureMinimalError", () => {
56
const mockedHub = {
@@ -57,3 +58,84 @@ describe("captureMinimalError", () => {
5758
});
5859
});
5960
});
61+
62+
describe("addPluginOptionTags", () => {
63+
const mockedHub = {
64+
setTag: jest.fn(),
65+
};
66+
67+
const defaultOptions: Partial<InternalOptions> = {
68+
include: [],
69+
};
70+
71+
beforeEach(() => {
72+
jest.resetAllMocks();
73+
});
74+
75+
it("should set include tag according to number of entries (single entry)", () => {
76+
addPluginOptionTags(defaultOptions as unknown as InternalOptions, mockedHub as unknown as Hub);
77+
expect(mockedHub.setTag).toHaveBeenCalledWith("include", "single-entry");
78+
});
79+
it("should set include tag according to number of entries (multiple entries)", () => {
80+
addPluginOptionTags(
81+
{ include: [{}, {}, {}] } as unknown as InternalOptions,
82+
mockedHub as unknown as Hub
83+
);
84+
expect(mockedHub.setTag).toHaveBeenCalledWith("include", "multiple-entries");
85+
});
86+
87+
it("should set deploy tag to true if the deploy option is specified", () => {
88+
addPluginOptionTags(
89+
{ ...defaultOptions, deploy: { env: "production" } } as unknown as InternalOptions,
90+
mockedHub as unknown as Hub
91+
);
92+
expect(mockedHub.setTag).toHaveBeenCalledWith("add-deploy", true);
93+
});
94+
95+
it("should set errorHandler tag to `custom` if the errorHandler option is specified", () => {
96+
addPluginOptionTags(
97+
// eslint-disable-next-line @typescript-eslint/no-empty-function
98+
{ ...defaultOptions, errorHandler: () => {} } as unknown as InternalOptions,
99+
mockedHub as unknown as Hub
100+
);
101+
expect(mockedHub.setTag).toHaveBeenCalledWith("error-handler", "custom");
102+
});
103+
104+
it.each([
105+
["auto", { auto: true }],
106+
["manual", { repo: "", commit: "" }],
107+
])(
108+
`should set setCommits tag to %s if the setCommits option is %s`,
109+
(expectedValue, commitOptions) => {
110+
addPluginOptionTags(
111+
{ ...defaultOptions, setCommits: commitOptions } as unknown as InternalOptions,
112+
mockedHub as unknown as Hub
113+
);
114+
expect(mockedHub.setTag).toHaveBeenCalledWith("set-commits", expectedValue);
115+
}
116+
);
117+
118+
it("sets all simple tags correctly", () => {
119+
addPluginOptionTags(
120+
{
121+
...defaultOptions,
122+
cleanArtifacts: true,
123+
finalize: true,
124+
injectReleasesMap: true,
125+
dryRun: true,
126+
} as unknown as InternalOptions,
127+
mockedHub as unknown as Hub
128+
);
129+
130+
expect(mockedHub.setTag).toHaveBeenCalledWith("clean-artifacts", true);
131+
expect(mockedHub.setTag).toHaveBeenCalledWith("finalize-release", true);
132+
expect(mockedHub.setTag).toHaveBeenCalledWith("inject-releases-map", true);
133+
expect(mockedHub.setTag).toHaveBeenCalledWith("dry-run", true);
134+
});
135+
136+
it("shouldn't set any tags other than include if no opional options are specified", () => {
137+
addPluginOptionTags(defaultOptions as unknown as InternalOptions, mockedHub as unknown as Hub);
138+
expect(mockedHub.setTag).toHaveBeenCalledTimes(1);
139+
expect(mockedHub.setTag).toHaveBeenCalledWith("include", "single-entry");
140+
});
141+
});

0 commit comments

Comments
 (0)