sampling.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. Object.defineProperty(exports, '__esModule', { value: true });
  2. const utils = require('@sentry/utils');
  3. const debugBuild = require('../debug-build.js');
  4. const semanticAttributes = require('../semanticAttributes.js');
  5. const hasTracingEnabled = require('../utils/hasTracingEnabled.js');
  6. const spanUtils = require('../utils/spanUtils.js');
  7. /**
  8. * Makes a sampling decision for the given transaction and stores it on the transaction.
  9. *
  10. * Called every time a transaction is created. Only transactions which emerge with a `sampled` value of `true` will be
  11. * sent to Sentry.
  12. *
  13. * This method muttes the given `transaction` and will set the `sampled` value on it.
  14. * It returns the same transaction, for convenience.
  15. */
  16. function sampleTransaction(
  17. transaction,
  18. options,
  19. samplingContext,
  20. ) {
  21. // nothing to do if tracing is not enabled
  22. if (!hasTracingEnabled.hasTracingEnabled(options)) {
  23. // eslint-disable-next-line deprecation/deprecation
  24. transaction.sampled = false;
  25. return transaction;
  26. }
  27. // if the user has forced a sampling decision by passing a `sampled` value in their transaction context, go with that
  28. // eslint-disable-next-line deprecation/deprecation
  29. if (transaction.sampled !== undefined) {
  30. // eslint-disable-next-line deprecation/deprecation
  31. transaction.setAttribute(semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, Number(transaction.sampled));
  32. return transaction;
  33. }
  34. // we would have bailed already if neither `tracesSampler` nor `tracesSampleRate` nor `enableTracing` were defined, so one of these should
  35. // work; prefer the hook if so
  36. let sampleRate;
  37. if (typeof options.tracesSampler === 'function') {
  38. sampleRate = options.tracesSampler(samplingContext);
  39. transaction.setAttribute(semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, Number(sampleRate));
  40. } else if (samplingContext.parentSampled !== undefined) {
  41. sampleRate = samplingContext.parentSampled;
  42. } else if (typeof options.tracesSampleRate !== 'undefined') {
  43. sampleRate = options.tracesSampleRate;
  44. transaction.setAttribute(semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, Number(sampleRate));
  45. } else {
  46. // When `enableTracing === true`, we use a sample rate of 100%
  47. sampleRate = 1;
  48. transaction.setAttribute(semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, sampleRate);
  49. }
  50. // Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The
  51. // only valid values are booleans or numbers between 0 and 1.)
  52. if (!isValidSampleRate(sampleRate)) {
  53. debugBuild.DEBUG_BUILD && utils.logger.warn('[Tracing] Discarding transaction because of invalid sample rate.');
  54. // eslint-disable-next-line deprecation/deprecation
  55. transaction.sampled = false;
  56. return transaction;
  57. }
  58. // if the function returned 0 (or false), or if `tracesSampleRate` is 0, it's a sign the transaction should be dropped
  59. if (!sampleRate) {
  60. debugBuild.DEBUG_BUILD &&
  61. utils.logger.log(
  62. `[Tracing] Discarding transaction because ${
  63. typeof options.tracesSampler === 'function'
  64. ? 'tracesSampler returned 0 or false'
  65. : 'a negative sampling decision was inherited or tracesSampleRate is set to 0'
  66. }`,
  67. );
  68. // eslint-disable-next-line deprecation/deprecation
  69. transaction.sampled = false;
  70. return transaction;
  71. }
  72. // Now we roll the dice. Math.random is inclusive of 0, but not of 1, so strict < is safe here. In case sampleRate is
  73. // a boolean, the < comparison will cause it to be automatically cast to 1 if it's true and 0 if it's false.
  74. // eslint-disable-next-line deprecation/deprecation
  75. transaction.sampled = Math.random() < (sampleRate );
  76. // if we're not going to keep it, we're done
  77. // eslint-disable-next-line deprecation/deprecation
  78. if (!transaction.sampled) {
  79. debugBuild.DEBUG_BUILD &&
  80. utils.logger.log(
  81. `[Tracing] Discarding transaction because it's not included in the random sample (sampling rate = ${Number(
  82. sampleRate,
  83. )})`,
  84. );
  85. return transaction;
  86. }
  87. debugBuild.DEBUG_BUILD &&
  88. // eslint-disable-next-line deprecation/deprecation
  89. utils.logger.log(`[Tracing] starting ${transaction.op} transaction - ${spanUtils.spanToJSON(transaction).description}`);
  90. return transaction;
  91. }
  92. /**
  93. * Checks the given sample rate to make sure it is valid type and value (a boolean, or a number between 0 and 1).
  94. */
  95. function isValidSampleRate(rate) {
  96. // we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck
  97. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  98. if (utils.isNaN(rate) || !(typeof rate === 'number' || typeof rate === 'boolean')) {
  99. debugBuild.DEBUG_BUILD &&
  100. utils.logger.warn(
  101. `[Tracing] Given sample rate is invalid. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify(
  102. rate,
  103. )} of type ${JSON.stringify(typeof rate)}.`,
  104. );
  105. return false;
  106. }
  107. // in case sampleRate is a boolean, it will get automatically cast to 1 if it's true and 0 if it's false
  108. if (rate < 0 || rate > 1) {
  109. debugBuild.DEBUG_BUILD &&
  110. utils.logger.warn(`[Tracing] Given sample rate is invalid. Sample rate must be between 0 and 1. Got ${rate}.`);
  111. return false;
  112. }
  113. return true;
  114. }
  115. exports.sampleTransaction = sampleTransaction;
  116. //# sourceMappingURL=sampling.js.map