utils.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import {t, tct} from 'sentry/locale';
  2. import {
  3. SamplingConditionLogicalInner,
  4. SamplingInnerName,
  5. SamplingInnerOperator,
  6. SamplingRule,
  7. } from 'sentry/types/sampling';
  8. import {getInnerNameLabel} from '../../utils';
  9. import {Conditions} from './conditions';
  10. import {TruncatedLabel} from './truncatedLabel';
  11. type Condition = React.ComponentProps<typeof Conditions>['conditions'][0];
  12. export function getMatchFieldPlaceholder(category: SamplingInnerName | string) {
  13. switch (category) {
  14. case SamplingInnerName.TRACE_USER_SEGMENT:
  15. return t('ex. paid, common (Multiline)');
  16. case SamplingInnerName.TRACE_ENVIRONMENT:
  17. return t('ex. prod, dev');
  18. case SamplingInnerName.TRACE_RELEASE:
  19. return t('ex. 1*, [I3].[0-9].*');
  20. default:
  21. return undefined;
  22. }
  23. }
  24. export function getNewCondition(condition: Condition): SamplingConditionLogicalInner {
  25. const newValue = (condition.match ?? '')
  26. .split('\n')
  27. .filter(match => !!match.trim())
  28. .map(match => match.trim());
  29. if (condition.category === SamplingInnerName.TRACE_RELEASE) {
  30. return {
  31. op: SamplingInnerOperator.GLOB_MATCH,
  32. name: condition.category,
  33. value: newValue,
  34. };
  35. }
  36. return {
  37. op: SamplingInnerOperator.EQUAL,
  38. // TODO(sampling): remove the cast
  39. name: condition.category as
  40. | SamplingInnerName.TRACE_ENVIRONMENT
  41. | SamplingInnerName.TRACE_USER_SEGMENT,
  42. value: newValue,
  43. options: {
  44. ignoreCase: true,
  45. },
  46. };
  47. }
  48. const unexpectedErrorMessage = t('An internal error occurred while saving sampling rule');
  49. type ResponseJSONDetailed = {
  50. detail: string[];
  51. };
  52. type ResponseJSON = {
  53. dynamicSampling?: {
  54. rules: Array<Partial<SamplingRule>>;
  55. };
  56. };
  57. export function getErrorMessage(
  58. error: {
  59. responseJSON?: ResponseJSON | ResponseJSONDetailed;
  60. },
  61. currentRuleIndex: number
  62. ) {
  63. const detailedErrorResponse = (error.responseJSON as undefined | ResponseJSONDetailed)
  64. ?.detail;
  65. if (detailedErrorResponse) {
  66. // This is a temp solution until we enable error rules again, therefore it does not need translation
  67. return detailedErrorResponse[0];
  68. }
  69. const errorResponse = error.responseJSON as undefined | ResponseJSON;
  70. if (!errorResponse) {
  71. return unexpectedErrorMessage;
  72. }
  73. const responseErrors = errorResponse.dynamicSampling?.rules[currentRuleIndex] ?? {};
  74. const [type, _value] = Object.entries(responseErrors)[0];
  75. if (type === 'sampleRate') {
  76. return {
  77. type: 'sampleRate',
  78. message: t('Ensure this value is a floating number between 0 and 100'),
  79. };
  80. }
  81. return unexpectedErrorMessage;
  82. }
  83. export function getTagKey(condition: Condition) {
  84. switch (condition.category) {
  85. case SamplingInnerName.TRACE_RELEASE:
  86. return 'release';
  87. case SamplingInnerName.TRACE_ENVIRONMENT:
  88. return 'environment';
  89. default:
  90. return undefined;
  91. }
  92. }
  93. export const distributedTracesConditions = [
  94. SamplingInnerName.TRACE_RELEASE,
  95. SamplingInnerName.TRACE_ENVIRONMENT,
  96. SamplingInnerName.TRACE_USER_SEGMENT,
  97. ];
  98. export function generateConditionCategoriesOptions(
  99. conditionCategories: SamplingInnerName[]
  100. ): [SamplingInnerName, string][] {
  101. const sortedConditionCategories = conditionCategories
  102. // sort dropdown options alphabetically based on display labels
  103. .sort((a, b) => getInnerNameLabel(a).localeCompare(getInnerNameLabel(b)));
  104. // massage into format that select component understands
  105. return sortedConditionCategories.map(innerName => [
  106. innerName,
  107. getInnerNameLabel(innerName),
  108. ]);
  109. }
  110. export function formatCreateTagLabel(label: string) {
  111. return tct('Add "[newLabel]"', {
  112. newLabel: <TruncatedLabel value={label} />,
  113. });
  114. }