mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
206 lines
5.5 KiB
TypeScript
206 lines
5.5 KiB
TypeScript
import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
|
|
import type {
|
|
Docs,
|
|
DocsParams,
|
|
OnboardingConfig,
|
|
} from 'sentry/components/onboarding/gettingStartedDoc/types';
|
|
import {getUploadSourceMapsStep} from 'sentry/components/onboarding/gettingStartedDoc/utils';
|
|
import {getJSServerMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
|
|
import {ProductSolution} from 'sentry/components/onboarding/productSelection';
|
|
import {t, tct} from 'sentry/locale';
|
|
import type {ProductSelectionMap} from 'sentry/utils/gettingStartedDocs/node';
|
|
import {
|
|
getDefaultNodeImports,
|
|
getInstallConfig,
|
|
} from 'sentry/utils/gettingStartedDocs/node';
|
|
|
|
type Params = DocsParams;
|
|
|
|
const productSelection = (params: Params): ProductSelectionMap => {
|
|
return {
|
|
[ProductSolution.ERROR_MONITORING]: true,
|
|
[ProductSolution.PROFILING]: params.isProfilingSelected,
|
|
[ProductSolution.PERFORMANCE_MONITORING]: params.isPerformanceSelected,
|
|
[ProductSolution.SESSION_REPLAY]: params.isReplaySelected,
|
|
};
|
|
};
|
|
|
|
const getSdkSetupSnippet = (params: Params) => `
|
|
${getDefaultNodeImports({productSelection: productSelection(params)}).join('\n')}
|
|
import { stripUrlQueryAndFragment } from "@sentry/utils";
|
|
import Koa from "koa";
|
|
|
|
const app = new Koa();
|
|
|
|
Sentry.init({
|
|
dsn: "${params.dsn}",
|
|
integrations: [${
|
|
params.isPerformanceSelected
|
|
? `
|
|
// Automatically instrument Node.js libraries and frameworks
|
|
...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(),`
|
|
: ''
|
|
}${
|
|
params.isProfilingSelected
|
|
? `
|
|
new ProfilingIntegration(),`
|
|
: ''
|
|
}
|
|
],${
|
|
params.isPerformanceSelected
|
|
? `
|
|
// Performance Monitoring
|
|
tracesSampleRate: 1.0, // Capture 100% of the transactions`
|
|
: ''
|
|
}${
|
|
params.isProfilingSelected
|
|
? `
|
|
// Set sampling rate for profiling - this is relative to tracesSampleRate
|
|
profilesSampleRate: 1.0,`
|
|
: ''
|
|
}
|
|
});${
|
|
params.isPerformanceSelected
|
|
? `
|
|
|
|
const requestHandler = (ctx, next) => {
|
|
return new Promise((resolve, reject) => {
|
|
Sentry.runWithAsyncContext(async () => {
|
|
const hub = Sentry.getCurrentHub();
|
|
hub.configureScope((scope) =>
|
|
scope.addEventProcessor((event) =>
|
|
Sentry.addRequestDataToEvent(event, ctx.request, {
|
|
include: {
|
|
user: false,
|
|
},
|
|
})
|
|
)
|
|
);
|
|
|
|
try {
|
|
await next();
|
|
} catch (err) {
|
|
reject(err);
|
|
}
|
|
resolve();
|
|
});
|
|
});
|
|
};
|
|
|
|
// This tracing middleware creates a transaction per request
|
|
const tracingMiddleWare = async (ctx, next) => {
|
|
const reqMethod = (ctx.method || "").toUpperCase();
|
|
const reqUrl = ctx.url && stripUrlQueryAndFragment(ctx.url);
|
|
|
|
// Connect to trace of upstream app
|
|
let traceparentData;
|
|
if (ctx.request.get("sentry-trace")) {
|
|
traceparentData = Sentry.extractTraceparentData(
|
|
ctx.request.get("sentry-trace")
|
|
);
|
|
}
|
|
|
|
const transaction = Sentry.startTransaction({
|
|
name: \`\${reqMethod} \${reqUrl}\`,
|
|
op: "http.server",
|
|
...traceparentData,
|
|
});
|
|
|
|
ctx.__sentry_transaction = transaction;
|
|
|
|
// We put the transaction on the scope so users can attach children to it
|
|
Sentry.getCurrentHub().configureScope((scope) => {
|
|
scope.setSpan(transaction);
|
|
});
|
|
|
|
ctx.res.on("finish", () => {
|
|
// Push \`transaction.finish\` to the next event loop so open spans have a chance to finish before the transaction closes
|
|
setImmediate(() => {
|
|
// If you're using koa router, set the matched route as transaction name
|
|
if (ctx._matchedRoute) {
|
|
const mountPath = ctx.mountPath || "";
|
|
transaction.setName(\`\${reqMethod} \${mountPath}\${ctx._matchedRoute}\`);
|
|
}
|
|
transaction.setHttpStatus(ctx.status);
|
|
transaction.finish();
|
|
});
|
|
});
|
|
|
|
await next();
|
|
};
|
|
|
|
app.use(requestHandler);
|
|
app.use(tracingMiddleWare);`
|
|
: ''
|
|
}
|
|
|
|
// Send errors to Sentry
|
|
app.on("error", (err, ctx) => {
|
|
Sentry.withScope((scope) => {
|
|
scope.addEventProcessor((event) => {
|
|
return Sentry.addRequestDataToEvent(event, ctx.request);
|
|
});
|
|
Sentry.captureException(err);
|
|
});
|
|
});
|
|
|
|
app.listen(3000);`;
|
|
|
|
const getVerifySnippet = () => `
|
|
app.use(async function () {
|
|
throw new Error("My first Sentry error!");
|
|
});
|
|
`;
|
|
|
|
const onboarding: OnboardingConfig = {
|
|
install: params => [
|
|
{
|
|
type: StepType.INSTALL,
|
|
description: t('Add the Sentry Node SDK as a dependency:'),
|
|
configurations: getInstallConfig(params, {
|
|
additionalPackages: params.isPerformanceSelected ? ['@sentry/utils'] : [],
|
|
}),
|
|
},
|
|
],
|
|
configure: params => [
|
|
{
|
|
type: StepType.CONFIGURE,
|
|
description: tct(
|
|
"Initialize Sentry as early as possible in your application's lifecycle, for example in your [code:index.ts/js] entry point:",
|
|
{code: <code />}
|
|
),
|
|
configurations: [
|
|
{
|
|
language: 'javascript',
|
|
code: getSdkSetupSnippet(params),
|
|
},
|
|
],
|
|
},
|
|
getUploadSourceMapsStep({
|
|
guideLink: 'https://docs.sentry.io/platforms/node/guides/koa/sourcemaps/',
|
|
...params,
|
|
}),
|
|
],
|
|
verify: () => [
|
|
{
|
|
type: StepType.VERIFY,
|
|
description: t(
|
|
"This snippet contains an intentional error and can be used as a test to make sure that everything's working as expected."
|
|
),
|
|
configurations: [
|
|
{
|
|
language: 'javascript',
|
|
code: getVerifySnippet(),
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
|
|
const docs: Docs = {
|
|
onboarding,
|
|
customMetricsOnboarding: getJSServerMetricsOnboarding(),
|
|
};
|
|
|
|
export default docs;
|