sentry-instrumentation.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import type {Span} from '@sentry/core';
  2. import os from 'node:os';
  3. import type webpack from 'webpack';
  4. const {SENTRY_INSTRUMENTATION, GITHUB_SHA, GITHUB_REF} = process.env;
  5. const IS_CI = !!GITHUB_SHA;
  6. const PLUGIN_NAME = 'SentryInstrumentation';
  7. const GB_BYTE = 1073741824;
  8. class SentryInstrumentation {
  9. Sentry = require('@sentry/node');
  10. hasInitializedBuild: boolean = false;
  11. spans: Record<string, Span> = {};
  12. constructor() {
  13. // Only run if SENTRY_INSTRUMENTATION` is set or when in ci,
  14. // only in the javascript suite that runs webpack
  15. if (!SENTRY_INSTRUMENTATION) {
  16. return;
  17. }
  18. this.Sentry.init({
  19. dsn: 'https://3d282d186d924374800aa47006227ce9@sentry.io/2053674',
  20. environment: IS_CI ? 'ci' : 'local',
  21. tracesSampleRate: 1.0,
  22. });
  23. this.withCITags();
  24. this.withOSPlatformTags();
  25. this.spans['initial-build'] = this.Sentry.startInactiveSpan({
  26. op: 'webpack-build',
  27. name: 'initial-build',
  28. });
  29. }
  30. withCITags() {
  31. if (IS_CI) {
  32. this.Sentry.setTag('branch', GITHUB_REF);
  33. }
  34. }
  35. withOSPlatformTags() {
  36. this.Sentry.setTag('platform', os.platform());
  37. this.Sentry.setTag('arch', os.arch());
  38. const cpus = os.cpus();
  39. this.Sentry.setTag(
  40. 'cpu',
  41. cpus?.length ? `${cpus[0]!.model} (cores: ${cpus.length})}` : 'N/A'
  42. );
  43. }
  44. measureInitialBuildTime(startTime: number, endTime: number) {
  45. const initialBuildSpan = this.spans['initial-build'];
  46. if (!initialBuildSpan) {
  47. return;
  48. }
  49. const that = this;
  50. this.Sentry.withActiveSpan(initialBuildSpan, () => {
  51. that.Sentry.startInactiveSpan({
  52. op: 'build',
  53. name: 'webpack build',
  54. attributes: {
  55. os: `${os.platform()} ${os.arch()} v${os.release()}`,
  56. memory: os.freemem()
  57. ? `${os.freemem() / GB_BYTE} / ${os.totalmem() / GB_BYTE} GB (${
  58. (os.freemem() / os.totalmem()) * 100
  59. }% free)`
  60. : 'N/A',
  61. loadavg: os.loadavg(),
  62. },
  63. startTime,
  64. }).end(endTime);
  65. });
  66. initialBuildSpan.end();
  67. delete this.spans['initial-build'];
  68. this.hasInitializedBuild = true;
  69. }
  70. apply(compiler: webpack.Compiler) {
  71. compiler.hooks.done.tapAsync(PLUGIN_NAME, async ({startTime, endTime}, done) => {
  72. this.measureInitialBuildTime(startTime / 1000, endTime / 1000);
  73. await this.Sentry.flush();
  74. done();
  75. });
  76. }
  77. }
  78. export default SentryInstrumentation;