@odigos/ui-kit 0.0.33 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/lib/components/dropdown/index.d.ts +1 -0
  3. package/lib/components/input/index.d.ts +1 -1
  4. package/lib/components/input-table/index.d.ts +3 -11
  5. package/lib/components/input-table/map-columns-to-fields/index.d.ts +15 -0
  6. package/lib/components/input-table/types.d.ts +15 -0
  7. package/lib/components.js +9 -9
  8. package/lib/constants.js +1 -1
  9. package/lib/containers/action-form/custom-fields/add-cluster-info.d.ts +1 -1
  10. package/lib/containers/action-form/custom-fields/delete-attributes.d.ts +1 -1
  11. package/lib/containers/action-form/custom-fields/error-sampler.d.ts +1 -1
  12. package/lib/containers/action-form/custom-fields/k8s-attributes.d.ts +1 -1
  13. package/lib/containers/action-form/custom-fields/latency-sampler.d.ts +1 -1
  14. package/lib/containers/action-form/custom-fields/pii-masking.d.ts +1 -1
  15. package/lib/containers/action-form/custom-fields/probabilistic-sampler.d.ts +1 -1
  16. package/lib/containers/action-form/custom-fields/rename-attributes.d.ts +1 -1
  17. package/lib/containers/action-form/custom-fields/service-name-sampler.d.ts +5 -0
  18. package/lib/containers/action-form/custom-fields/span-attribute-sampler.d.ts +5 -0
  19. package/lib/containers/instrumentation-rule-drawer/build-card.d.ts +1 -1
  20. package/lib/containers.js +339 -131
  21. package/lib/functions/get-action-icon/index.d.ts +2 -2
  22. package/lib/functions/index.d.ts +1 -0
  23. package/lib/functions/numbers-only/index.d.ts +1 -0
  24. package/lib/functions.js +5 -5
  25. package/lib/hooks.js +3 -3
  26. package/lib/icons.js +7 -7
  27. package/lib/{index-f8FRaVkE.js → index--RecCPGA.js} +1 -1
  28. package/lib/{index-Iq7U_fzb.js → index-BBjwRlta.js} +4 -4
  29. package/lib/{index-BQQZyvRz.js → index-BWZT-ipR.js} +1 -1
  30. package/lib/{index-BedCNcwV.js → index-BZq0yNL-.js} +88 -43
  31. package/lib/{index-Do3CYz7N.js → index-Bd8ZAEvq.js} +1 -1
  32. package/lib/{index-CNfdJ1X8.js → index-CIKkezVt.js} +1 -1
  33. package/lib/{index-B_Gl6Qa6.js → index-ChYtqgBW.js} +9 -3
  34. package/lib/{index-1N9wymEq.js → index-Cq8NT9Hr.js} +1 -1
  35. package/lib/{index-CVH8Q8Sl.js → index-DJGe2YeC.js} +29 -12
  36. package/lib/{index-CaAOgaiC.js → index-a_WA-82O.js} +2 -2
  37. package/lib/{index-BjVl4-os.js → index-ovjVbVQq.js} +4 -4
  38. package/lib/snippets.js +8 -8
  39. package/lib/store.js +1 -1
  40. package/lib/theme.js +1 -1
  41. package/lib/types/actions/index.d.ts +137 -41
  42. package/lib/types/common/index.d.ts +4 -16
  43. package/lib/types.js +78 -20
  44. package/lib/{useSourceSelectionFormData-DiwzViqL.js → useSourceSelectionFormData-DBNf1uEe.js} +41 -23
  45. package/lib/{useTransition-B0eagOib.js → useTransition-dZ92VxT2.js} +1 -1
  46. package/package.json +12 -12
package/lib/containers.js CHANGED
@@ -1,27 +1,27 @@
1
1
  import React, { useState, useEffect, forwardRef, useRef, useImperativeHandle, useMemo, memo, useContext, createContext, useCallback, useLayoutEffect, Fragment } from 'react';
2
2
  import styled, { css } from 'styled-components';
3
- import { T as Theme, h as usePendingStore, g as useNotificationStore, b as useDrawerStore, c as useEntityStore, A as ACTION_OPTIONS, k as getActionIcon, f as useModalStore, d as useFilterStore, M as MONITORS_OPTIONS, s as styleInject, i as useSelectedStore, e as useInstrumentStore, m as getInstrumentationRuleIcon, a as useDataStreamStore, l as getEntityId, j as useSetupStore, I as INSTRUMENTATION_RULE_OPTIONS, u as useDarkMode } from './index-CVH8Q8Sl.js';
3
+ import { T as Theme, h as usePendingStore, g as useNotificationStore, b as useDrawerStore, c as useEntityStore, A as ACTION_OPTIONS, k as getActionIcon, f as useModalStore, d as useFilterStore, M as MONITORS_OPTIONS, s as styleInject, i as useSelectedStore, e as useInstrumentStore, m as getInstrumentationRuleIcon, a as useDataStreamStore, l as getEntityId, j as useSetupStore, I as INSTRUMENTATION_RULE_OPTIONS, u as useDarkMode } from './index-DJGe2YeC.js';
4
4
  import { a as DISPLAY_TITLES, B as BUTTON_TEXTS, F as FORM_ALERTS } from './index-mOgS3e5E.js';
5
- import { ActionType, EntityTypes, StatusType, Crud, OtherStatus, NodeTypes, AddNodeTypes, EdgeTypes, FieldTypes, SignalType, CodeAttributesKeyTypes, HeadersCollectionKeyTypes, PayloadCollectionKeyTypes, InstrumentationRuleType } from './types.js';
6
- import { f as DataCardFieldTypes, o as FieldLabel, C as Checkbox, n as FieldError, u as Input, w as InputTable, K as KeyValueInputsList, v as InputList, V as Text, O as Segment, L as SectionTitle, i as DocsButton, y as MonitorsCheckboxes, W as TextArea, j as Drawer, d as ConditionDetails, D as DataCard, a0 as FlexColumn, M as Modal, N as NavigationButtons, a4 as ModalBody, J as NotificationNote, a as AutocompleteInput, h as Divider, R as Status, $ as FlexRow, Y as Tooltip, r as IconWrapped, z as MonitorsIcons, a5 as TableContainer, a6 as TableTitleWrap, q as IconTitleBadge, a7 as TableWrap, x as InteractiveTable, a1 as CenterThis, G as NoDataFound, Z as TraceLoader, b as Badge, E as ExtendArrow, a2 as VerticalScroll, P as SelectionButton, B as Button, m as Dropdown, a8 as getDefaultExportFromCjs, F as FadeLoader, g as DataTab, Q as SkeletonLoader, X as Toggle, A as AddButton$1, U as Stepper, I as IconButton, e as DataCardFields, s as IconsNav, p as IconGroup } from './index-BedCNcwV.js';
5
+ import { ActionType, ActionKeyTypes, InputTypes, FieldTypes, EntityTypes, StatusType, Crud, OtherStatus, NodeTypes, AddNodeTypes, EdgeTypes, SignalType, HeadersCollectionKeyTypes, CodeAttributesKeyTypes, PayloadCollectionKeyTypes, InstrumentationRuleType } from './types.js';
6
+ import { f as DataCardFieldTypes, o as FieldLabel, C as Checkbox, n as FieldError, u as Input, w as InputTable, K as KeyValueInputsList, v as InputList, V as Text, O as Segment, L as SectionTitle, i as DocsButton, y as MonitorsCheckboxes, W as TextArea, j as Drawer, d as ConditionDetails, D as DataCard, a0 as FlexColumn, M as Modal, N as NavigationButtons, a4 as ModalBody, J as NotificationNote, a as AutocompleteInput, h as Divider, R as Status, $ as FlexRow, Y as Tooltip, r as IconWrapped, z as MonitorsIcons, a5 as TableContainer, a6 as TableTitleWrap, q as IconTitleBadge, a7 as TableWrap, x as InteractiveTable, a1 as CenterThis, G as NoDataFound, Z as TraceLoader, b as Badge, E as ExtendArrow, a2 as VerticalScroll, P as SelectionButton, B as Button, m as Dropdown, a8 as getDefaultExportFromCjs, F as FadeLoader, g as DataTab, Q as SkeletonLoader, X as Toggle, A as AddButton$1, U as Stepper, I as IconButton, e as DataCardFields, s as IconsNav, p as IconGroup } from './index-BZq0yNL-.js';
7
7
  import { i as isEmpty, s as safeJsonParse } from './index-BV85P9UP.js';
8
- import { i as CheckCircledIcon, O as OdigosLogo } from './index-Do3CYz7N.js';
9
- import { C as CrossCircledIcon, O as OdigosLogoText, a as OverviewIcon, F as FilterIcon, D as DataStreamsIcon, N as NotificationIcon, S as SlackLogo, K as KeyIcon, T as TerminalIcon } from './index-f8FRaVkE.js';
10
- import { u as useActionFormData, a as useClickNode, c as useDataStreamFormData, d as useDestinationFormData, b as useClickNotification, e as useSourceFormData, f as useSourceSelectionFormData } from './useSourceSelectionFormData-DiwzViqL.js';
11
- import { d as useKeyDown, e as useOnClickOutside, u as useContainerSize, c as useInstrumentationRuleFormData, g as useTransition, f as useTimeAgo, a as useCopy } from './useTransition-B0eagOib.js';
12
- import { E as EditIcon } from './index-BQQZyvRz.js';
13
- import { T as TrashIcon, S as SearchIcon, P as PlusIcon$1, f as CheckIcon, A as ArrowIcon, a as CopyIcon, g as CrossIcon } from './index-CNfdJ1X8.js';
14
- import { D as DeleteWarning, C as CancelWarning } from './index-CaAOgaiC.js';
15
- import { m as mapConditions, b as getStatusIcon, c as capitalizeFirstLetter } from './index-B_Gl6Qa6.js';
16
- import { f as filterActions, i as getConditionsBooleans, n as getEntityLabel, m as getEntityIcon, x as sleep$1, p as getPlatformIcon, q as getPlatformLabel, h as formatBytes, k as getContainersIcons, r as getValueForRange, l as getDestinationIcon, w as mapExportedSignals, g as filterSourcesByStream, e as filterSources, b as filterDestinationsByStream, a as filterDestinations, v as mapDestinationFieldsForDisplay, c as compareCondition, t as getYamlFieldsForDestination, d as deepClone, o as getMetricForEntity, s as getWorkloadId, j as getContainersInstrumentedCount, u as isOverTime } from './index-Iq7U_fzb.js';
8
+ import { i as CheckCircledIcon, O as OdigosLogo } from './index-Bd8ZAEvq.js';
9
+ import { C as CrossCircledIcon, O as OdigosLogoText, a as OverviewIcon, F as FilterIcon, D as DataStreamsIcon, N as NotificationIcon, S as SlackLogo, K as KeyIcon, T as TerminalIcon } from './index--RecCPGA.js';
10
+ import { u as useActionFormData, a as useClickNode, c as useDataStreamFormData, d as useDestinationFormData, b as useClickNotification, e as useSourceFormData, f as useSourceSelectionFormData } from './useSourceSelectionFormData-DBNf1uEe.js';
11
+ import { d as useKeyDown, e as useOnClickOutside, u as useContainerSize, c as useInstrumentationRuleFormData, g as useTransition, f as useTimeAgo, a as useCopy } from './useTransition-dZ92VxT2.js';
12
+ import { E as EditIcon } from './index-BWZT-ipR.js';
13
+ import { T as TrashIcon, S as SearchIcon, P as PlusIcon$1, f as CheckIcon, A as ArrowIcon, a as CopyIcon, g as CrossIcon } from './index-CIKkezVt.js';
14
+ import { D as DeleteWarning, C as CancelWarning } from './index-a_WA-82O.js';
15
+ import { m as mapConditions, b as getStatusIcon, c as capitalizeFirstLetter } from './index-ChYtqgBW.js';
16
+ import { f as filterActions, i as getConditionsBooleans, n as getEntityLabel, m as getEntityIcon, x as sleep$1, p as getPlatformIcon, q as getPlatformLabel, h as formatBytes, k as getContainersIcons, r as getValueForRange, l as getDestinationIcon, w as mapExportedSignals, g as filterSourcesByStream, e as filterSources, b as filterDestinationsByStream, a as filterDestinations, v as mapDestinationFieldsForDisplay, c as compareCondition, t as getYamlFieldsForDestination, d as deepClone, o as getMetricForEntity, s as getWorkloadId, j as getContainersInstrumentedCount, u as isOverTime } from './index-BBjwRlta.js';
17
17
  import { createPortal } from 'react-dom';
18
- import { N as NoteBackToSummary, E as EditButton } from './index-BjVl4-os.js';
18
+ import { N as NoteBackToSummary, E as EditButton } from './index-ovjVbVQq.js';
19
19
  import { D as DESTINATION_CATEGORIES } from './index-Dqief9td.js';
20
- import { a6 as RulesIcon, a7 as SourcesIcon, a3 as ActionsIcon, a4 as DestinationsIcon } from './index-1N9wymEq.js';
20
+ import { a6 as RulesIcon, a7 as SourcesIcon, a3 as ActionsIcon, a4 as DestinationsIcon } from './index-Cq8NT9Hr.js';
21
21
  import './index-CnZlllYu.js';
22
22
 
23
23
  const buildCard$3 = (action) => {
24
- const { type, spec: { actionName, notes, signals, disabled, collectContainerAttributes, collectReplicaSetAttributes, collectWorkloadId, collectClusterId, labelsAttributes, annotationsAttributes, clusterAttributes, attributeNamesToDelete, renames, piiCategories, fallbackSamplingRatio, samplingPercentage, endpointsFilters, }, } = action;
24
+ const { type, spec: { actionName, notes, signals, disabled, collectContainerAttributes, collectReplicaSetAttributes, collectWorkloadId, collectClusterId, labelsAttributes, annotationsAttributes, clusterAttributes, attributeNamesToDelete, renames, piiCategories, fallbackSamplingRatio, samplingPercentage, endpointsFilters, servicesNameFilters, attributeFilters, }, } = action;
25
25
  const arr = [
26
26
  { title: DISPLAY_TITLES.TYPE, value: type },
27
27
  { type: DataCardFieldTypes.ActiveStatus, title: DISPLAY_TITLES.STATUS, value: String(!disabled) },
@@ -101,14 +101,39 @@ const buildCard$3 = (action) => {
101
101
  str += `Service Name: ${serviceName}\n`;
102
102
  str += `HTTP Route: ${httpRoute}\n`;
103
103
  str += `Min. Latency: ${minimumLatencyThreshold}\n`;
104
- str += `Sampling Ratio: ${fallbackSamplingRatio}`;
104
+ str += `Fallback Sampling Ratio: ${fallbackSamplingRatio}`;
105
105
  arr.push({ title: `Endpoint${endpointsFilters.length > 1 ? ` #${idx + 1}` : ''}`, value: str });
106
106
  });
107
107
  }
108
+ if (type === ActionType.ServiceNameSampler) {
109
+ servicesNameFilters?.forEach(({ serviceName, samplingRatio, fallbackSamplingRatio }, idx) => {
110
+ let str = '';
111
+ str += `Service Name: ${serviceName}\n`;
112
+ str += `Sampling Ratio: ${samplingRatio}\n`;
113
+ str += `Fallback Sampling Ratio: ${fallbackSamplingRatio}`;
114
+ arr.push({ title: `Filter${servicesNameFilters.length > 1 ? ` #${idx + 1}` : ''}`, value: str });
115
+ });
116
+ }
117
+ if (type === ActionType.SpanAttributeSampler) {
118
+ attributeFilters?.forEach(({ serviceName, attributeKey, fallbackSamplingRatio, condition }, idx) => {
119
+ let str = '';
120
+ str += `Service Name: ${serviceName}\n`;
121
+ str += `Attribute Key: ${attributeKey}\n`;
122
+ str += `Fallback Sampling Ratio: ${fallbackSamplingRatio}\n`;
123
+ const conditionKey = Object.keys(condition)[0];
124
+ str += `Condition: ${conditionKey}\n`;
125
+ str += `Operation: ${condition[conditionKey]?.operation}\n`;
126
+ str += `Expected Value: ${condition[conditionKey]?.expectedValue}`;
127
+ if (conditionKey === 'jsonCondition') {
128
+ str += `\nJSON Path: ${condition[conditionKey].jsonPath}`;
129
+ }
130
+ arr.push({ title: `Filter${attributeFilters.length > 1 ? ` #${idx + 1}` : ''}`, value: str });
131
+ });
132
+ }
108
133
  return arr;
109
134
  };
110
135
 
111
- const KEY$6 = 'piiCategories';
136
+ const KEY$8 = ActionKeyTypes.PiiCategories;
112
137
  const ListContainer$2 = styled.div `
113
138
  display: flex;
114
139
  flex-direction: row;
@@ -127,18 +152,18 @@ const PII_OPTIONS = [
127
152
  },
128
153
  ];
129
154
  const PiiMasking = ({ value, setValue, formErrors }) => {
130
- const errorMessage = formErrors[KEY$6];
131
- const mappedValue = value[KEY$6] || [];
155
+ const errorMessage = formErrors[KEY$8];
156
+ const mappedValue = value[KEY$8] || [];
132
157
  const [isLastSelection, setIsLastSelection] = useState(mappedValue.length === 1);
133
158
  const handleChange = (id, isAdd) => {
134
159
  const arr = isAdd ? [...mappedValue, id] : mappedValue.filter((str) => str !== id);
135
- setValue(KEY$6, arr);
160
+ setValue(KEY$8, arr);
136
161
  setIsLastSelection(arr.length === 1);
137
162
  };
138
163
  useEffect(() => {
139
164
  if (!mappedValue.length) {
140
165
  const arr = PII_OPTIONS.map(({ id }) => id);
141
- setValue(KEY$6, arr);
166
+ setValue(KEY$8, arr);
142
167
  setIsLastSelection(PII_OPTIONS.length === 1);
143
168
  }
144
169
  // eslint-disable-next-line
@@ -149,140 +174,316 @@ const PiiMasking = ({ value, setValue, formErrors }) => {
149
174
  !!errorMessage && React.createElement(FieldError, null, errorMessage)));
150
175
  };
151
176
 
152
- const KEY$5 = 'fallbackSamplingRatio', MIN$1 = 0, MAX$1 = 100;
177
+ const KEY$7 = ActionKeyTypes.FallbackSamplingRatio, MIN$1 = 0, MAX$1 = 100;
153
178
  const ErrorSampler = ({ value, setValue, formErrors }) => {
154
- const errorMessage = formErrors[KEY$5];
155
- const mappedValue = value[KEY$5];
156
- const handleChange = (val) => setValue(KEY$5, Math.max(MIN$1, Math.min(Number(val), MAX$1)) || MIN$1);
157
- return (React.createElement(Input, { title: 'Fallback sampling ratio', required: true, type: 'number', min: MIN$1, max: MAX$1, value: !isEmpty(mappedValue) ? String(mappedValue) : '', onChange: ({ target: { value: v } }) => handleChange(v), errorMessage: errorMessage }));
179
+ const errorMessage = formErrors[KEY$7];
180
+ const mappedValue = value[KEY$7];
181
+ const handleChange = (val) => setValue(KEY$7, Math.max(MIN$1, Math.min(Number(val), MAX$1)) || MIN$1);
182
+ return (React.createElement(Input, { title: 'Fallback sampling ratio', required: true, type: InputTypes.Number, min: MIN$1, max: MAX$1, value: !isEmpty(mappedValue) ? String(mappedValue) : '', onChange: ({ target: { value: v } }) => handleChange(v), errorMessage: errorMessage }));
158
183
  };
159
184
 
185
+ const LABEL_COLUMNS = [
186
+ {
187
+ title: 'Label Key',
188
+ keyName: 'labelKey',
189
+ placeholder: 'app.kubernetes.io/name',
190
+ required: true,
191
+ },
192
+ {
193
+ title: 'Attribute Key',
194
+ keyName: 'attributeKey',
195
+ placeholder: 'app.kubernetes.name',
196
+ required: true,
197
+ },
198
+ ];
199
+ const ANNOTATION_COLUMNS = [
200
+ {
201
+ title: 'Annotation Key',
202
+ keyName: 'annotationKey',
203
+ placeholder: 'kubectl.kubernetes.io/restartedAt',
204
+ required: true,
205
+ },
206
+ {
207
+ title: 'Attribute Key',
208
+ keyName: 'attributeKey',
209
+ placeholder: 'kubectl.kubernetes.restartedAt',
210
+ required: true,
211
+ },
212
+ ];
160
213
  const K8sAttributes = ({ value, setValue, formErrors }) => {
161
214
  useEffect(() => {
162
- if (!value.collectContainerAttributes && !value.collectWorkloadId && !value.collectReplicaSetAttributes && !value.collectClusterId && !value.labelsAttributes?.length && !value.annotationsAttributes?.length) {
163
- setValue('collectContainerAttributes', true);
164
- setValue('collectReplicaSetAttributes', true);
165
- setValue('collectWorkloadId', true);
166
- setValue('collectClusterId', true);
167
- setValue('labelsAttributes', []);
168
- setValue('annotationsAttributes', []);
215
+ if (!value[ActionKeyTypes.CollectContainerAttributes] &&
216
+ !value[ActionKeyTypes.CollectReplicaSetAttributes] &&
217
+ !value[ActionKeyTypes.CollectWorkloadId] &&
218
+ !value[ActionKeyTypes.CollectClusterId] &&
219
+ !value[ActionKeyTypes.LabelsAttributes]?.length &&
220
+ !value[ActionKeyTypes.AnnotationsAttributes]?.length) {
221
+ setValue(ActionKeyTypes.CollectContainerAttributes, true);
222
+ setValue(ActionKeyTypes.CollectReplicaSetAttributes, true);
223
+ setValue(ActionKeyTypes.CollectWorkloadId, true);
224
+ setValue(ActionKeyTypes.CollectClusterId, true);
225
+ setValue(ActionKeyTypes.LabelsAttributes, []);
226
+ setValue(ActionKeyTypes.AnnotationsAttributes, []);
169
227
  }
170
228
  // eslint-disable-next-line
171
229
  }, []);
172
230
  return (React.createElement(React.Fragment, null,
173
- React.createElement(Checkbox, { title: 'Collect Container Attributes', value: value['collectContainerAttributes'] || false, onChange: (bool) => setValue('collectContainerAttributes', bool), errorMessage: formErrors['collectContainerAttributes'] }),
174
- React.createElement(Checkbox, { title: 'Collect ReplicaSet Attributes', value: value['collectReplicaSetAttributes'] || false, onChange: (bool) => setValue('collectReplicaSetAttributes', bool), errorMessage: formErrors['collectReplicaSetAttributes'] }),
175
- React.createElement(Checkbox, { title: 'Collect Workload ID', value: value['collectWorkloadId'] || false, onChange: (bool) => setValue('collectWorkloadId', bool), errorMessage: formErrors['collectWorkloadId'] }),
176
- React.createElement(Checkbox, { title: 'Collect Cluster ID', value: value['collectClusterId'] || false, onChange: (bool) => setValue('collectClusterId', bool), errorMessage: formErrors['collectClusterId'] }),
177
- React.createElement(InputTable, { columns: [
178
- {
179
- title: 'Label Key',
180
- keyName: 'labelKey',
181
- placeholder: 'app.kubernetes.io/name',
182
- required: true,
183
- },
184
- {
185
- title: 'Attribute Key',
186
- keyName: 'attributeKey',
187
- placeholder: 'app.kubernetes.name',
188
- required: true,
189
- },
190
- ], value: value['labelsAttributes'] || [], onChange: (arr) => setValue('labelsAttributes', arr), errorMessage: formErrors['labelsAttributes'] }),
191
- React.createElement(InputTable, { columns: [
192
- {
193
- title: 'Annotation Key',
194
- keyName: 'annotationKey',
195
- placeholder: 'kubectl.kubernetes.io/restartedAt',
196
- required: true,
197
- },
198
- {
199
- title: 'Attribute Key',
200
- keyName: 'attributeKey',
201
- placeholder: 'kubectl.kubernetes.restartedAt',
202
- required: true,
203
- },
204
- ], value: value['annotationsAttributes'] || [], onChange: (arr) => setValue('annotationsAttributes', arr), errorMessage: formErrors['annotationsAttributes'] })));
231
+ React.createElement(Checkbox, { title: 'Collect Container Attributes', value: value[ActionKeyTypes.CollectContainerAttributes] || false, onChange: (bool) => setValue(ActionKeyTypes.CollectContainerAttributes, bool), errorMessage: formErrors[ActionKeyTypes.CollectContainerAttributes] }),
232
+ React.createElement(Checkbox, { title: 'Collect ReplicaSet Attributes', value: value[ActionKeyTypes.CollectReplicaSetAttributes] || false, onChange: (bool) => setValue(ActionKeyTypes.CollectReplicaSetAttributes, bool), errorMessage: formErrors[ActionKeyTypes.CollectReplicaSetAttributes] }),
233
+ React.createElement(Checkbox, { title: 'Collect Workload ID', value: value[ActionKeyTypes.CollectWorkloadId] || false, onChange: (bool) => setValue(ActionKeyTypes.CollectWorkloadId, bool), errorMessage: formErrors[ActionKeyTypes.CollectWorkloadId] }),
234
+ React.createElement(Checkbox, { title: 'Collect Cluster ID', value: value[ActionKeyTypes.CollectClusterId] || false, onChange: (bool) => setValue(ActionKeyTypes.CollectClusterId, bool), errorMessage: formErrors[ActionKeyTypes.CollectClusterId] }),
235
+ React.createElement(InputTable, { columns: LABEL_COLUMNS, value: value[ActionKeyTypes.LabelsAttributes] || [], onChange: (arr) => setValue(ActionKeyTypes.LabelsAttributes, arr), errorMessage: formErrors[ActionKeyTypes.LabelsAttributes] }),
236
+ React.createElement(InputTable, { columns: ANNOTATION_COLUMNS, value: value[ActionKeyTypes.AnnotationsAttributes] || [], onChange: (arr) => setValue(ActionKeyTypes.AnnotationsAttributes, arr), errorMessage: formErrors[ActionKeyTypes.AnnotationsAttributes] })));
205
237
  };
206
238
 
207
- const KEY$4 = 'endpointsFilters';
239
+ const KEY$6 = ActionKeyTypes.EndpointsFilters;
240
+ const COLUMNS$2 = [
241
+ {
242
+ title: 'Service',
243
+ keyName: 'serviceName',
244
+ placeholder: 'e.g. my-service',
245
+ tooltip: 'Service name: The rule applies to a specific service name. Only traces originating from this service’s root span will be considered.',
246
+ required: true,
247
+ },
248
+ {
249
+ title: 'HTTP route',
250
+ keyName: 'httpRoute',
251
+ placeholder: 'e.g. /api/v1/users',
252
+ tooltip: 'HTTP route: The specific HTTP route prefix to match for sampling. Only traces with routes beginning with this prefix will be considered. For instance, configuring /buy will also match /buy/product.',
253
+ required: true,
254
+ },
255
+ {
256
+ title: 'Threshold',
257
+ keyName: 'minimumLatencyThreshold',
258
+ placeholder: 'e.g. 1000',
259
+ tooltip: 'Minimum latency threshold (ms): Specifies the minimum latency in milliseconds; traces with latency below this threshold are ignored.',
260
+ required: true,
261
+ type: InputTypes.Number,
262
+ },
263
+ {
264
+ title: 'Fallback',
265
+ keyName: 'fallbackSamplingRatio',
266
+ placeholder: 'e.g. 100',
267
+ tooltip: 'Fallback sampling ratio: Specifies the percentage of traces that meet the service/http_route filter but fall below the threshold that you still want to retain. For example, if a rule is set for service A and http_route B with a minimum latency threshold of 1 second, you might still want to keep some traces below this threshold. Setting the ratio to 20% ensures that 20% of these traces will be retained.',
268
+ required: true,
269
+ type: InputTypes.Number,
270
+ },
271
+ ];
208
272
  const LatencySampler = ({ value, setValue, formErrors }) => {
209
- const errorMessage = formErrors[KEY$4];
210
- const mappedValue = value[KEY$4] || [];
211
- const handleChange = (arr) => setValue(KEY$4, arr);
212
- return (React.createElement(InputTable, { columns: [
213
- {
214
- title: 'Service',
215
- keyName: 'serviceName',
216
- placeholder: 'Choose service',
217
- required: true,
218
- tooltip: 'Service name: The rule applies to a specific service name. Only traces originating from this service’s root span will be considered.',
219
- },
220
- {
221
- title: 'HTTP route',
222
- keyName: 'httpRoute',
223
- placeholder: 'e.g. /api/v1/users',
224
- required: true,
225
- tooltip: 'HTTP route: The specific HTTP route prefix to match for sampling. Only traces with routes beginning with this prefix will be considered. For instance, configuring /buy will also match /buy/product.',
226
- },
227
- {
228
- title: 'Threshold',
229
- keyName: 'minimumLatencyThreshold',
230
- placeholder: 'e.g. 1000',
231
- required: true,
232
- type: 'number',
233
- tooltip: 'Minimum latency threshold (ms): Specifies the minimum latency in milliseconds; traces with latency below this threshold are ignored.',
234
- },
235
- {
236
- title: 'Fallback',
237
- keyName: 'fallbackSamplingRatio',
238
- placeholder: 'e.g. 20',
239
- required: true,
240
- type: 'number',
241
- tooltip: 'Fallback sampling ratio: Specifies the percentage of traces that meet the service/http_route filter but fall below the threshold that you still want to retain. For example, if a rule is set for service A and http_route B with a minimum latency threshold of 1 second, you might still want to keep some traces below this threshold. Setting the ratio to 20% ensures that 20% of these traces will be retained.',
242
- },
243
- ], value: mappedValue, onChange: handleChange, errorMessage: errorMessage }));
273
+ const errorMessage = formErrors[KEY$6];
274
+ const mappedValue = value[KEY$6] || [];
275
+ const handleChange = (arr) => {
276
+ const mapped = arr.map(({ serviceName, httpRoute, minimumLatencyThreshold, fallbackSamplingRatio }) => {
277
+ const row = {
278
+ serviceName,
279
+ httpRoute,
280
+ minimumLatencyThreshold: Number(minimumLatencyThreshold),
281
+ fallbackSamplingRatio: Number(fallbackSamplingRatio),
282
+ };
283
+ return row;
284
+ });
285
+ setValue(KEY$6, mapped);
286
+ };
287
+ return React.createElement(InputTable, { columns: COLUMNS$2, value: mappedValue, onChange: handleChange, errorMessage: errorMessage });
244
288
  };
245
289
 
246
- const KEY$3 = 'clusterAttributes';
290
+ const KEY$5 = ActionKeyTypes.ClusterAttributes;
247
291
  const AddClusterInfo = ({ value, setValue, formErrors }) => {
248
- const errorMessage = formErrors[KEY$3];
249
- const mappedValue = value[KEY$3]?.map((obj) => ({
292
+ const errorMessage = formErrors[KEY$5];
293
+ const mappedValue = value[KEY$5]?.map((obj) => ({
250
294
  key: obj.attributeName,
251
295
  value: obj.attributeStringValue,
252
296
  })) || [];
253
- const handleChange = (arr) => setValue(KEY$3, arr.map((obj) => ({
297
+ const handleChange = (arr) => setValue(KEY$5, arr.map((obj) => ({
254
298
  attributeName: obj.key,
255
299
  attributeStringValue: obj.value,
256
300
  })));
257
301
  return React.createElement(KeyValueInputsList, { title: 'Resource Attributes', value: mappedValue, onChange: handleChange, required: true, errorMessage: errorMessage });
258
302
  };
259
303
 
260
- const KEY$2 = 'attributeNamesToDelete';
304
+ const KEY$4 = ActionKeyTypes.AttributeNamesToDelete;
261
305
  const DeleteAttributes = ({ value, setValue, formErrors }) => {
262
- const errorMessage = formErrors[KEY$2];
263
- const mappedValue = value[KEY$2] || [];
264
- const handleChange = (arr) => setValue(KEY$2, arr);
306
+ const errorMessage = formErrors[KEY$4];
307
+ const mappedValue = value[KEY$4] || [];
308
+ const handleChange = (arr) => setValue(KEY$4, arr);
265
309
  return React.createElement(InputList, { title: 'Attributes to delete', value: mappedValue, onChange: handleChange, required: true, errorMessage: errorMessage });
266
310
  };
267
311
 
268
- const KEY$1 = 'renames';
312
+ const KEY$3 = ActionKeyTypes.Renames;
269
313
  const RenameAttributes = ({ value, setValue, formErrors }) => {
270
- const errorMessage = formErrors[KEY$1];
271
- const mappedValue = Object.entries(value[KEY$1] || {}).map(([k, v]) => ({ key: k, value: v }));
314
+ const errorMessage = formErrors[KEY$3];
315
+ const mappedValue = Object.entries(value[KEY$3] || {}).map(([k, v]) => ({ key: k, value: v }));
272
316
  const handleChange = (arr) => {
273
317
  const payload = {};
274
318
  arr.forEach((obj) => (payload[obj.key] = obj.value));
275
- setValue(KEY$1, payload);
319
+ setValue(KEY$3, payload);
276
320
  };
277
321
  return React.createElement(KeyValueInputsList, { title: 'Attributes to rename', value: mappedValue, onChange: handleChange, required: true, errorMessage: errorMessage });
278
322
  };
279
323
 
280
- const KEY = 'samplingPercentage', MIN = 0, MAX = 100;
324
+ const KEY$2 = ActionKeyTypes.ServicesNameFilters;
325
+ const COLUMNS$1 = [
326
+ {
327
+ title: 'Service Name',
328
+ keyName: 'serviceName',
329
+ placeholder: 'e.g. my-service',
330
+ tooltip: 'Specifies the service name to search within the trace (Across all available spans).',
331
+ required: true,
332
+ },
333
+ {
334
+ title: 'Sampling Ratio',
335
+ keyName: 'samplingRatio',
336
+ placeholder: 'e.g. 10',
337
+ tooltip: 'Specifies the sample rate for all traces.',
338
+ required: true,
339
+ type: InputTypes.Number,
340
+ },
341
+ {
342
+ title: 'Fallback Sampling Ratio',
343
+ keyName: 'fallbackSamplingRatio',
344
+ placeholder: 'e.g. 100',
345
+ tooltip: 'Specifies the percentage of traces that don’t meet the service name filter and that you still like to retain.',
346
+ required: true,
347
+ type: InputTypes.Number,
348
+ },
349
+ ];
350
+ const ServiceNameSampler = ({ value, setValue, formErrors }) => {
351
+ const errorMessage = formErrors[KEY$2];
352
+ const mappedValue = value[KEY$2] || [];
353
+ const handleChange = (arr) => {
354
+ const mapped = arr.map(({ serviceName, samplingRatio, fallbackSamplingRatio }) => {
355
+ const row = {
356
+ serviceName,
357
+ samplingRatio: Number(samplingRatio),
358
+ fallbackSamplingRatio: Number(fallbackSamplingRatio),
359
+ };
360
+ return row;
361
+ });
362
+ setValue(KEY$2, mapped);
363
+ };
364
+ return React.createElement(InputTable, { columns: COLUMNS$1, value: mappedValue, onChange: handleChange, errorMessage: errorMessage });
365
+ };
366
+
367
+ const KEY$1 = ActionKeyTypes.SamplingPercentage, MIN = 0, MAX = 100;
281
368
  const ProbabilisticSampler = ({ value, setValue, formErrors }) => {
369
+ const errorMessage = formErrors[KEY$1];
370
+ const mappedValue = value[KEY$1];
371
+ const handleChange = (val) => setValue(KEY$1, Math.max(MIN, Math.min(Number(val), MAX)) || MIN);
372
+ return (React.createElement(Input, { title: 'Sampling percentage', required: true, type: InputTypes.Number, min: MIN, max: MAX, value: !isEmpty(mappedValue) ? String(mappedValue) : '', onChange: ({ target: { value: v } }) => handleChange(v), errorMessage: errorMessage }));
373
+ };
374
+
375
+ const KEY = ActionKeyTypes.AttributeFilters;
376
+ const COLUMNS = [
377
+ {
378
+ title: 'Service Name',
379
+ keyName: 'serviceName',
380
+ placeholder: 'e.g. my-service',
381
+ tooltip: 'Specifies the service name to search within the trace (across all available spans).',
382
+ required: true,
383
+ },
384
+ {
385
+ title: 'Attribute Key',
386
+ keyName: 'attributeKey',
387
+ placeholder: 'e.g. http.request.method',
388
+ tooltip: 'Specifies the attribute key inside of the span.',
389
+ required: true,
390
+ },
391
+ {
392
+ title: 'Fallback Sampling Ratio',
393
+ keyName: 'fallbackSamplingRatio',
394
+ placeholder: 'e.g. 100',
395
+ tooltip: 'Specifies the percentage of traces that don’t meet the service name filter and that you still like to retain.',
396
+ required: true,
397
+ type: InputTypes.Number,
398
+ },
399
+ {
400
+ title: 'Condition',
401
+ keyName: 'condition',
402
+ tooltip: 'An object representing the filters for span attributes filters.',
403
+ required: true,
404
+ componentType: FieldTypes.Dropdown,
405
+ options: [
406
+ { id: 'stringCondition', value: 'String Condition' },
407
+ { id: 'numberCondition', value: 'Number Condition' },
408
+ { id: 'booleanCondition', value: 'Boolean Condition' },
409
+ { id: 'jsonCondition', value: 'JSON Condition' },
410
+ ],
411
+ },
412
+ {
413
+ title: 'Operation',
414
+ keyName: 'operation',
415
+ tooltip: 'Specifies the operation to run against the attribute.',
416
+ required: true,
417
+ componentType: FieldTypes.Dropdown,
418
+ options: [
419
+ { id: 'exists', value: 'Exists' },
420
+ { id: 'equals', value: 'Equals' },
421
+ { id: 'not_equals', value: 'Not Equals' },
422
+ { id: 'contains', value: 'Contains' },
423
+ { id: 'not_contains', value: 'Not Contains' },
424
+ { id: 'regex', value: 'Regex' },
425
+ { id: 'greater_than', value: 'Greater Than' },
426
+ { id: 'less_than', value: 'Less Than' },
427
+ { id: 'greater_than_or_equal', value: 'Greater Than Or Equal' },
428
+ { id: 'less_than_or_equal', value: 'Less Than Or Equal' },
429
+ { id: 'is_valid_json', value: 'Is Valid JSON' },
430
+ { id: 'is_invalid_json', value: 'Is Invalid JSON' },
431
+ { id: 'jsonpath_exists', value: 'JSON Path Exists' },
432
+ { id: 'key_equals', value: 'Key Equals' },
433
+ { id: 'key_not_equals', value: 'Key Not Equals' },
434
+ ],
435
+ },
436
+ {
437
+ title: 'Expected Value',
438
+ keyName: 'expectedValue',
439
+ placeholder: 'e.g. GET',
440
+ tooltip: 'The values to test the attribute against.',
441
+ required: true,
442
+ },
443
+ {
444
+ title: 'JSON Path',
445
+ keyName: 'jsonPath',
446
+ placeholder: 'e.g. $.user.role',
447
+ tooltip: 'An expression used to navigate the JSON structure.',
448
+ required: false,
449
+ renderCondition: (row) => row.condition === 'jsonCondition',
450
+ },
451
+ ];
452
+ const SpanAttributeSampler = ({ value, setValue, formErrors }) => {
282
453
  const errorMessage = formErrors[KEY];
283
- const mappedValue = value[KEY];
284
- const handleChange = (val) => setValue(KEY, Math.max(MIN, Math.min(Number(val), MAX)) || MIN);
285
- return (React.createElement(Input, { title: 'Sampling percentage', required: true, type: 'number', min: MIN, max: MAX, value: !isEmpty(mappedValue) ? String(mappedValue) : '', onChange: ({ target: { value: v } }) => handleChange(v), errorMessage: errorMessage }));
454
+ const mappedValue = (value[KEY] || []).map(({ serviceName, attributeKey, fallbackSamplingRatio, condition }) => {
455
+ const conditionKey = Object.entries(condition).filter(([k, v]) => v)[0][0];
456
+ return {
457
+ serviceName,
458
+ attributeKey,
459
+ fallbackSamplingRatio,
460
+ condition: conditionKey,
461
+ operation: condition[conditionKey]?.operation,
462
+ expectedValue: condition[conditionKey]?.expectedValue,
463
+ jsonPath: condition[conditionKey]?.jsonPath,
464
+ };
465
+ });
466
+ const handleChange = (arr) => {
467
+ const mapped = arr.map(({ serviceName, attributeKey, fallbackSamplingRatio, condition, operation, expectedValue, jsonPath }) => {
468
+ const row = {
469
+ serviceName,
470
+ attributeKey,
471
+ fallbackSamplingRatio: Number(fallbackSamplingRatio),
472
+ condition: {
473
+ [condition]: {
474
+ operation,
475
+ expectedValue,
476
+ },
477
+ },
478
+ };
479
+ if (jsonPath) {
480
+ row.condition[condition].jsonPath = jsonPath;
481
+ }
482
+ return row;
483
+ });
484
+ setValue(KEY, mapped);
485
+ };
486
+ return React.createElement(InputTable, { columns: COLUMNS, value: mappedValue, onChange: handleChange, errorMessage: errorMessage, limitFieldsPerRow: 3 });
286
487
  };
287
488
 
288
489
  const componentsMap$1 = {
@@ -294,6 +495,8 @@ const componentsMap$1 = {
294
495
  [ActionType.ErrorSampler]: ErrorSampler,
295
496
  [ActionType.ProbabilisticSampler]: ProbabilisticSampler,
296
497
  [ActionType.LatencySampler]: LatencySampler,
498
+ [ActionType.ServiceNameSampler]: ServiceNameSampler,
499
+ [ActionType.SpanAttributeSampler]: SpanAttributeSampler,
297
500
  };
298
501
  const CustomFields$1 = ({ actionType, value, setValue, formErrors }) => {
299
502
  if (!actionType)
@@ -7115,8 +7318,8 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
7115
7318
  // from stays the same
7116
7319
  ...previousConnection,
7117
7320
  isValid,
7118
- to: closestHandle && isValid
7119
- ? rendererPointToPoint({ x: closestHandle.x, y: closestHandle.y }, transform)
7321
+ to: result.toHandle && isValid
7322
+ ? rendererPointToPoint({ x: result.toHandle.x, y: result.toHandle.y }, transform)
7120
7323
  : position,
7121
7324
  toHandle: result.toHandle,
7122
7325
  toPosition: isValid && result.toHandle ? result.toHandle.position : oppositePosition[fromHandle.position],
@@ -7216,7 +7419,7 @@ function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId
7216
7419
  ? (isTarget && handleType === 'source') || (!isTarget && handleType === 'target')
7217
7420
  : handleNodeId !== fromNodeId || handleId !== fromHandleId);
7218
7421
  result.isValid = isValid && isValidConnection(connection);
7219
- result.toHandle = getHandle(handleNodeId, handleType, handleId, nodeLookup, connectionMode, false);
7422
+ result.toHandle = getHandle(handleNodeId, handleType, handleId, nodeLookup, connectionMode, true);
7220
7423
  }
7221
7424
  return result;
7222
7425
  }
@@ -9017,11 +9220,12 @@ keyCode = null, options = { target: defaultDoc, actInsideInputWithModifier: true
9017
9220
  return [[], []];
9018
9221
  }, [keyCode]);
9019
9222
  useEffect(() => {
9020
- const target = options?.target || defaultDoc;
9223
+ const target = options?.target ?? defaultDoc;
9224
+ const actInsideInputWithModifier = options?.actInsideInputWithModifier ?? true;
9021
9225
  if (keyCode !== null) {
9022
9226
  const downHandler = (event) => {
9023
9227
  modifierPressed.current = event.ctrlKey || event.metaKey || event.shiftKey || event.altKey;
9024
- const preventAction = (!modifierPressed.current || (modifierPressed.current && !options.actInsideInputWithModifier)) &&
9228
+ const preventAction = (!modifierPressed.current || (modifierPressed.current && !actInsideInputWithModifier)) &&
9025
9229
  isInputDOMNode(event);
9026
9230
  if (preventAction) {
9027
9231
  return false;
@@ -9806,7 +10010,6 @@ function useReactFlow() {
9806
10010
  }
9807
10011
 
9808
10012
  const selected = (item) => item.selected;
9809
- const deleteKeyOptions = { actInsideInputWithModifier: false };
9810
10013
  const win$1 = typeof window !== 'undefined' ? window : undefined;
9811
10014
  /**
9812
10015
  * Hook for handling global key events.
@@ -9816,7 +10019,7 @@ const win$1 = typeof window !== 'undefined' ? window : undefined;
9816
10019
  function useGlobalKeyHandler({ deleteKeyCode, multiSelectionKeyCode, }) {
9817
10020
  const store = useStoreApi();
9818
10021
  const { deleteElements } = useReactFlow();
9819
- const deleteKeyPressed = useKeyPress(deleteKeyCode, deleteKeyOptions);
10022
+ const deleteKeyPressed = useKeyPress(deleteKeyCode, { actInsideInputWithModifier: false });
9820
10023
  const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode, { target: win$1 });
9821
10024
  useEffect(() => {
9822
10025
  if (deleteKeyPressed) {
@@ -14814,7 +15017,7 @@ const DestinationTable = ({ metrics, maxHeight, maxWidth }) => {
14814
15017
  };
14815
15018
 
14816
15019
  const buildCard$1 = (rule) => {
14817
- const { type, ruleName, notes, disabled, profileName, payloadCollection, codeAttributes } = rule;
15020
+ const { type, ruleName, notes, disabled, profileName, payloadCollection, codeAttributes, headersCollection } = rule;
14818
15021
  const arr = [
14819
15022
  { title: DISPLAY_TITLES.TYPE, value: type },
14820
15023
  { type: DataCardFieldTypes.ActiveStatus, title: DISPLAY_TITLES.STATUS, value: String(!disabled) },
@@ -14823,20 +15026,25 @@ const buildCard$1 = (rule) => {
14823
15026
  { title: DISPLAY_TITLES.MANAGED_BY_PROFILE, value: profileName },
14824
15027
  { type: DataCardFieldTypes.Divider },
14825
15028
  ];
14826
- if (!!payloadCollection) {
15029
+ if (payloadCollection) {
14827
15030
  const str = Object.entries(payloadCollection)
14828
- .filter(([key, val]) => !!val)
15031
+ .filter(([key, val]) => val)
14829
15032
  .map(([key, val]) => key)
14830
15033
  .join(', ');
14831
- if (!!str)
15034
+ if (str)
14832
15035
  arr.push({ title: 'Collect', value: str });
14833
15036
  }
14834
- if (!!codeAttributes) {
15037
+ if (codeAttributes) {
14835
15038
  const str = Object.entries(codeAttributes)
14836
- .filter(([key, val]) => !!val)
15039
+ .filter(([key, val]) => val)
14837
15040
  .map(([key, val]) => key)
14838
15041
  .join(', ');
14839
- if (!!str)
15042
+ if (str)
15043
+ arr.push({ title: 'Collect', value: str });
15044
+ }
15045
+ if (headersCollection) {
15046
+ const str = (headersCollection[HeadersCollectionKeyTypes.HeaderKeys] || []).filter((val) => val).join(', ');
15047
+ if (str)
14840
15048
  arr.push({ title: 'Collect', value: str });
14841
15049
  }
14842
15050
  return arr;
@@ -1,2 +1,2 @@
1
- import { ActionType, type SVG } from '@/types';
2
- export declare const getActionIcon: (type: ActionType | "sampler" | "attributes") => SVG;
1
+ import { ActionCategory, ActionType, type SVG } from '@/types';
2
+ export declare const getActionIcon: (type: ActionType | ActionCategory) => SVG;
@@ -36,6 +36,7 @@ export * from './is-time-elapsed';
36
36
  export * from './map-conditions';
37
37
  export * from './map-destination-fields-for-display';
38
38
  export * from './map-exported-signals';
39
+ export * from './numbers-only';
39
40
  export * from './parse-json-string-to-pretty-string';
40
41
  export * from './remove-empty-values-from-object';
41
42
  export * from './safe-json-parse';
@@ -0,0 +1 @@
1
+ export declare const numbersOnly: (value: string) => string;