index.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import {ParseResult, parseSearch, Token} from 'sentry/components/searchSyntax/parser';
  2. import {Organization} from 'sentry/types';
  3. import {FieldKey, getFieldDefinition} from 'sentry/utils/fields';
  4. import {
  5. ON_DEMAND_METRICS_SUPPORTED_TAGS,
  6. STANDARD_SEARCH_FIELD_KEYS,
  7. } from 'sentry/utils/onDemandMetrics/constants';
  8. function isStandardSearchFilterKey(key: FieldKey): boolean {
  9. return STANDARD_SEARCH_FIELD_KEYS.has(key);
  10. }
  11. function isOnDemandSupportedFilterKey(key: FieldKey): boolean {
  12. return ON_DEMAND_METRICS_SUPPORTED_TAGS.has(key);
  13. }
  14. function isCustomTag(key: FieldKey): boolean {
  15. return !getFieldDefinition(key);
  16. }
  17. export function createOnDemandFilterWarning(warning: React.ReactNode) {
  18. return (key: string) => {
  19. const fieldKey = key as FieldKey;
  20. if (isCustomTag(fieldKey)) {
  21. return warning;
  22. }
  23. if (!isStandardSearchFilterKey(fieldKey) && isOnDemandSupportedFilterKey(fieldKey)) {
  24. return warning;
  25. }
  26. return null;
  27. };
  28. }
  29. export function isOnDemandQueryString(query: string): boolean {
  30. const tokens = parseSearch(query);
  31. if (!tokens) {
  32. return false;
  33. }
  34. const searchFilterKeys = getSearchFilterKeys(tokens);
  35. const isStandardSearch = searchFilterKeys.every(isStandardSearchFilterKey);
  36. const isOnDemandSupportedSearch = searchFilterKeys.some(key =>
  37. ON_DEMAND_METRICS_SUPPORTED_TAGS.has(key)
  38. );
  39. const hasCustomTags = searchFilterKeys.some(isCustomTag);
  40. return !isStandardSearch && (isOnDemandSupportedSearch || hasCustomTags);
  41. }
  42. type SearchFilterKey = FieldKey | null;
  43. function getSearchFilterKeys(tokens: ParseResult): FieldKey[] {
  44. try {
  45. return getTokenKeys(tokens).filter(Boolean) as FieldKey[];
  46. } catch (e) {
  47. return [];
  48. }
  49. }
  50. function getTokenKeys(tokens: ParseResult): SearchFilterKey[] {
  51. return tokens.flatMap(getTokenKey);
  52. }
  53. function getTokenKey(token): SearchFilterKey[] | SearchFilterKey {
  54. if (token.type === Token.LOGIC_GROUP) {
  55. return getTokenKeys(token.inner);
  56. }
  57. if (token.type === Token.FILTER) {
  58. return token.key.value;
  59. }
  60. return null;
  61. }
  62. const EXTRAPOLATED_AREA_STRIPE_IMG =
  63. 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAABkAQMAAACFAjPUAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAZQTFRFpKy5SVlzL3npZAAAAA9JREFUeJxjsD/AMIqIQwBIyGOd43jaDwAAAABJRU5ErkJggg==';
  64. export const extrapolatedAreaStyle = {
  65. color: {
  66. repeat: 'repeat',
  67. image: EXTRAPOLATED_AREA_STRIPE_IMG,
  68. rotation: 0.785,
  69. scaleX: 0.5,
  70. },
  71. opacity: 1.0,
  72. };
  73. export function hasOnDemandMetricAlertFeature(organization: Organization) {
  74. return organization.features.includes('on-demand-metrics-extraction');
  75. }
  76. export function hasOnDemandMetricWidgetFeature(organization: Organization) {
  77. return (
  78. organization.features.includes('on-demand-metrics-extraction') &&
  79. organization.features.includes('on-demand-metrics-extraction-experimental')
  80. );
  81. }