mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-22 01:40:32 +01:00
Compare commits
32 Commits
refactor/i
...
feat/cloud
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e00584634 | ||
|
|
dca8887de5 | ||
|
|
7d6a59882d | ||
|
|
819879ecc7 | ||
|
|
3ab7ab612c | ||
|
|
3d9ab97856 | ||
|
|
4e6384c0c1 | ||
|
|
9c6656d6b9 | ||
|
|
5c54a2537c | ||
|
|
b05d16242a | ||
|
|
fb2edfd770 | ||
|
|
34a2767396 | ||
|
|
43c72b8f4d | ||
|
|
95be5f12f3 | ||
|
|
ce141576d6 | ||
|
|
fab7fd001f | ||
|
|
02634894d9 | ||
|
|
83f1070b8a | ||
|
|
147005077c | ||
|
|
d720f76819 | ||
|
|
d76e15d444 | ||
|
|
dc1a5cce76 | ||
|
|
37c97528f3 | ||
|
|
6a8e6e94e9 | ||
|
|
5c480272f3 | ||
|
|
ab26fd3d8c | ||
|
|
80c0801b2e | ||
|
|
bd190b8d88 | ||
|
|
7e5f5bfac4 | ||
|
|
7f72ca19d3 | ||
|
|
231229d73e | ||
|
|
bb88cde296 |
@@ -1,315 +0,0 @@
|
||||
# antd `Input` → `@signozhq/ui/input` Migration — Affected Files & Verification
|
||||
|
||||
## What changed
|
||||
|
||||
For each file listed below, the import was rewritten:
|
||||
|
||||
```diff
|
||||
- import { Input, ...rest } from 'antd';
|
||||
+ import { Input } from '@signozhq/ui/input';
|
||||
+ import { ...rest } from 'antd';
|
||||
```
|
||||
|
||||
Only the plain antd `<Input>` component was migrated. The following are **not** migrated and continue to use antd:
|
||||
|
||||
- `Input.TextArea` / `Input.Password` / `Input.Search` / `Input.Group`
|
||||
- `InputNumber`
|
||||
- `<Input>` with `addonBefore`, `addonAfter`, `allowClear`, `bordered`, `status="error"`, or `size="small|middle|large"` props
|
||||
- `InputRef` (typed refs)
|
||||
|
||||
No JSX usages of `<Input>` were touched — only the import source was swapped. The component contract (`value`, `onChange`, `placeholder`, `disabled`, `type`, `prefix`, `suffix`, etc.) matches between the two libraries for the cases migrated here.
|
||||
|
||||
---
|
||||
|
||||
## Reverted after TypeScript errors — 4 files (kept on antd, marked with TODO)
|
||||
|
||||
These files were initially migrated, then reverted because `@signozhq/ui` `Input` does not expose the props they need. Each one carries a `TODO(@signozhq/ui-input)` comment above the antd import.
|
||||
|
||||
| File | Blocker |
|
||||
|---|---|
|
||||
| `frontend/src/container/MetricsExplorer/Inspect/MetricTimeAggregation.tsx` | Uses `onWheel` on `<Input type="number">` to blur on scroll. Not exposed on `@signozhq/ui/input`. |
|
||||
| `frontend/src/container/NewWidget/RightContainer/ContextLinks/UpdateContextLinks.tsx` | URL `<Input>` uses `spellCheck="false"` (along with `autoCorrect`, `autoCapitalize`). `spellCheck` not exposed. |
|
||||
| `frontend/src/container/PipelinePage/PipelineListsView/AddNewProcessor/FormFields/CSVInput.tsx` | Spreads antd `InputProps` (`{...otherProps}`) onto `<Input>`. `size: SizeType` clashes with `@signozhq/ui` Input's numeric `size`. |
|
||||
| `frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/styles.ts` | The `styled(Input)` wrapper is consumed in `Duration/index.tsx` with `addonAfter="ms"`. Not exposed. |
|
||||
|
||||
---
|
||||
|
||||
## Migrated files — 51 total
|
||||
|
||||
Grouped by the route/page that renders them. Visit each route after the migration and confirm the input still:
|
||||
|
||||
1. Renders with the expected layout/spacing
|
||||
2. Accepts keyboard input and reflects controlled `value`
|
||||
3. Fires `onChange` correctly (search filters, form submissions still work)
|
||||
4. Shows placeholder text
|
||||
5. Disables/enables as expected
|
||||
6. Form validation (`Form.Item rules`) still shows errors
|
||||
|
||||
### Alerts — Create / Edit Alert (`/alerts/new`, `/alerts/edit`)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/container/CreateAlertV2/AlertCondition/ThresholdItem.tsx` | Threshold name + threshold value + recovery threshold inputs in the Alert Condition card |
|
||||
| `frontend/src/container/CreateAlertV2/EvaluationSettings/AdvancedOptions.tsx` | Advanced Options collapse inside Evaluation Settings |
|
||||
| `frontend/src/container/CreateAlertV2/EvaluationSettings/EvaluationWindowPopover/EvaluationWindowDetails.tsx` | Evaluation Window popover (numeric value + unit) |
|
||||
| `frontend/src/container/CreateAlertV2/EvaluationSettings/TimeInput/TimeInput.tsx` | HH:MM:SS time input shared in Evaluation Settings |
|
||||
| `frontend/src/container/CreateAlertV2/NotificationSettings/NotificationSettings.tsx` | Re-notification interval input |
|
||||
|
||||
### Alert Channels (`/settings/channels/new`, `/settings/channels/edit/:channelId`)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/container/FormAlertChannels/index.tsx` | Channel name + send-resolved / common fields |
|
||||
| `frontend/src/container/FormAlertChannels/Settings/Email.tsx` | "To" email field of the Email channel form |
|
||||
| `frontend/src/container/FormAlertChannels/Settings/Webhook.tsx` | Webhook URL / username / password fields |
|
||||
|
||||
### Routing Policies (`/settings/channels` → routing policies tab)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/container/RoutingPolicies/RoutingPolicies.tsx` | Search box on the routing policies list |
|
||||
|
||||
### Organization Settings (`/settings/org-settings`)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/container/OrganizationSettings/InviteTeamMembers/index.tsx` | Email + name fields in the "Invite team members" form (used by the invite-members flow) |
|
||||
|
||||
### Members (`/settings/members`)
|
||||
|
||||
_None directly migrated this round_ — already on `@signozhq/ui/input`.
|
||||
|
||||
### Planned Downtime (`/settings/channels` → Planned Downtime, or `/planned-downtime` depending on plan)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/container/PlannedDowntime/PlannedDowntime.tsx` | "Search downtime" text input above the list |
|
||||
|
||||
### Licenses (`/licenses`)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/container/Licenses/ApplyLicenseForm.tsx` | License key text input on the apply-license form |
|
||||
|
||||
### Dashboards — list, detail, widget editor
|
||||
|
||||
| File | Where the input shows up | Route |
|
||||
|---|---|---|
|
||||
| `frontend/src/container/ListOfDashboard/DashboardsList.tsx` | Main "Search by name, description, or tags…" input on the dashboards list | `/dashboard` |
|
||||
| `frontend/src/container/ListOfDashboard/RequestDashboardBtn.tsx` | "Request dashboard" modal input | `/dashboard` |
|
||||
| `frontend/src/container/ListOfDashboard/DashboardTemplates/DashboardTemplatesModal.tsx` | Templates modal search input | `/dashboard` (open templates) |
|
||||
| `frontend/src/container/DashboardContainer/DashboardDescription/index.tsx` | Dashboard description editor name field | `/dashboard/:dashboardId` |
|
||||
| `frontend/src/container/GridCardLayout/GridCardLayout.tsx` | Section / row name inline edit | `/dashboard/:dashboardId` |
|
||||
| `frontend/src/container/DashboardContainer/visualization/components/ChartManager/ChartManager.tsx` | Chart manager search input | `/dashboard/:dashboardId` |
|
||||
| `frontend/src/container/NewWidget/LeftContainer/ExplorerColumnsRenderer.tsx` | Column-config inputs in the widget editor's left panel | `/dashboard/:dashboardId/:widgetId` |
|
||||
|
||||
### Logs (`/logs/logs-explorer`, `/logs/pipelines`)
|
||||
|
||||
| File | Where the input shows up | Route |
|
||||
|---|---|---|
|
||||
| `frontend/src/container/LogsFilters/index.tsx` | Logs filter sidebar search input | `/logs/logs-explorer` |
|
||||
| `frontend/src/container/LogsSearchFilter/SearchFields/QueryBuilder/QueryBuilder.tsx` | Query-builder field value inputs in the legacy logs search | `/logs/logs-explorer` |
|
||||
| `frontend/src/container/LogDetailedView/Overview.tsx` | Log details drawer Overview tab inputs (severity / body filters) | `/logs/logs-explorer` (open a log) |
|
||||
| `frontend/src/container/PipelinePage/PipelineListsView/AddNewProcessor/ProcessorForm.tsx` | Add-new-processor form fields | `/logs/pipelines` |
|
||||
| `frontend/src/container/PipelinePage/PipelineListsView/AddNewProcessor/FormFields/JsonFlattening.tsx` | JSON-flattening processor form | `/logs/pipelines` |
|
||||
| `frontend/src/container/PipelinePage/PipelineListsView/AddNewPipeline/FormFields/NameInput.tsx` | "Pipeline name" field in the new-pipeline form | `/logs/pipelines` |
|
||||
|
||||
### Traces (`/traces-explorer`, trace details, funnels)
|
||||
|
||||
| File | Where the input shows up | Route |
|
||||
|---|---|---|
|
||||
| `frontend/src/container/Trace/Search/AllTags/Tag/TagKey.tsx` | Tag-key autocomplete input in the legacy trace search | `/trace` |
|
||||
| `frontend/src/container/Trace/TraceGraphFilter/index.tsx` | Trace-graph filter search/value input | `/trace` |
|
||||
| `frontend/src/container/SpanDetailsDrawer/SpanDetailsDrawer.tsx` | "Search resource attributes" input in the span details drawer | `/traces-explorer` → open span |
|
||||
| `frontend/src/container/SpanDetailsDrawer/Attributes/Attributes.tsx` | Span details drawer → Attributes search | `/traces-explorer` → open span |
|
||||
| `frontend/src/container/SpanDetailsDrawer/Events/Events.tsx` | Span details drawer → Events search | `/traces-explorer` → open span |
|
||||
| `frontend/src/container/TraceWaterfall/AddSpanToFunnelModal/AddSpanToFunnelModal.tsx` | "Add span to funnel" modal name input (legacy waterfall) | `/trace/:id` |
|
||||
| `frontend/src/pages/TraceDetailsV3/SpanDetailsPanel/SpanPercentile/SpanPercentilePanel.tsx` | Percentile filter input in span details v3 | `/trace/:id` (v3) |
|
||||
| `frontend/src/pages/TraceDetailsV3/TraceWaterfall/AddSpanToFunnelModal/AddSpanToFunnelModal.tsx` | "Add span to funnel" modal in v3 waterfall | `/trace/:id` (v3) |
|
||||
| `frontend/src/pages/TracesFunnels/components/SearchBar/SearchBar.tsx` | Search box on the funnels list page | `/traces/funnels` |
|
||||
| `frontend/src/pages/TracesFunnels/components/RenameFunnel/RenameFunnel.tsx` | Rename-funnel modal input | `/traces/funnels` |
|
||||
|
||||
### Saved Views (`/logs/saved-views`, `/traces/saved-views`)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/components/ExplorerCard/SaveViewWithName.tsx` | "Save view with name" inline input on the explorer save flow |
|
||||
| `frontend/src/container/ExplorerOptions/ExplorerOptions.tsx` | "e.g. External http method view" — name input in the Save View modal across explorers |
|
||||
| `frontend/src/pages/SaveView/index.tsx` | Rename saved view input on the saved-views list |
|
||||
|
||||
### Metrics Explorer (`/metrics-explorer`)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/container/MetricsExplorer/MetricDetails/Metadata.tsx` | Metadata edit inputs in metric details |
|
||||
|
||||
### Messaging Queues (`/messaging-queues`)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/pages/MessagingQueues/MQDetails/DropRateView/EvaluationTimeSelector.tsx` | Evaluation time selector inside Drop Rate view |
|
||||
|
||||
### Integrations (`/integrations`)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/container/Integrations/CloudIntegration/AmazonWebServices/RegionForm/RenderConnectionParams.tsx` | Connection-params text fields in AWS cloud integration setup |
|
||||
|
||||
### Ingestion Settings (`/settings/ingestion-settings`)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/container/IngestionSettings/MultiIngestionSettings.tsx` | "Search for ingestion key…" + add/edit ingestion-key name fields. `<InputNumber>` usages in this file still come from antd. |
|
||||
|
||||
### Onboarding (`/get-started/*`, `/onboarding`)
|
||||
|
||||
| File | Where the input shows up |
|
||||
|---|---|
|
||||
| `frontend/src/container/OnboardingContainer/Steps/DataSource/DataSource.tsx` | Custom data source name input |
|
||||
| `frontend/src/container/OnboardingContainer/Steps/EnvironmentDetails/EnvironmentDetails.tsx` | Environment details (env name / app name) inputs |
|
||||
|
||||
### Other shared components (rendered on multiple routes)
|
||||
|
||||
| File | Where it shows up |
|
||||
|---|---|
|
||||
| `frontend/src/components/CustomTimePicker/TimezonePicker.tsx` | Timezone search input inside the global custom time picker — visible on dashboards, logs, traces, alerts header |
|
||||
| `frontend/src/components/InputWithLabel/InputWithLabel.tsx` | Generic labeled-input wrapper — used in invite flows, threshold editing, etc. |
|
||||
| `frontend/src/components/QuickFilters/QuickFiltersSettings/QuickFiltersSettings.tsx` | "Search filters" input inside the Quick Filters settings drawer (logs/traces/infra/metrics quick-filters) |
|
||||
| `frontend/src/components/QuickFilters/FilterRenderers/Checkbox/Checkbox.tsx` | Search box at the top of each checkbox-style quick filter |
|
||||
| `frontend/src/container/QueryTable/Drilldown/BreakoutOptions.tsx` | "Breakout by" attribute search input in the query-table drilldown menu (dashboards, alerts) |
|
||||
| `frontend/src/components/LogsFormatOptionsMenu/LogsFormatOptionsMenu.tsx` | "Search…" input inside the "Add column" picker in the logs format options menu (rendered on `/logs/logs-explorer`). `<InputNumber>` for max-line config still comes from antd. |
|
||||
|
||||
### `styled(Input)` wrappers — `.ts` style files
|
||||
|
||||
These wrap the now-`@signozhq/ui` `Input` with styled-components. CSS selectors target the descendant `<input>` element so behavior should be unchanged, but visually re-verify on the routes below.
|
||||
|
||||
| File | Verification route |
|
||||
|---|---|
|
||||
| `frontend/src/container/Version/styles.ts` | Status page `/status` — confirm input width = 183px |
|
||||
|
||||
> `Trace/Filters/Panel/PanelBody/Duration/styles.ts` was attempted and reverted — see the "Reverted" section at the top.
|
||||
|
||||
---
|
||||
|
||||
## Smoke-test checklist
|
||||
|
||||
A short loop that covers the bulk of what changed:
|
||||
|
||||
1. **Alerts → New alert** (`/alerts/new`) — add a threshold, type a name + value, switch evaluation window unit, expand Advanced Options, set time input, save.
|
||||
2. **Channels → New channel** (`/settings/channels/new`) — pick Email, fill the "to" field; pick Webhook, fill URL.
|
||||
3. **Dashboards** — open a dashboard, edit a panel (`/dashboard/:dashboardId/:widgetId`) → set context-link label/URL/params, edit explorer columns. Then on the list page (`/dashboard`) open the Templates modal and the "Request dashboard" modal.
|
||||
4. **Logs Explorer** (`/logs/logs-explorer`) — type into the sidebar filter search, open a log row → Overview tab.
|
||||
5. **Logs Pipelines** (`/logs/pipelines`) — open "Add new pipeline" and "Add new processor", switch processor type to JSON Flattening / CSV.
|
||||
6. **Traces Explorer** (`/traces-explorer`) — open a span, search inside Attributes + Events tabs.
|
||||
7. **Trace details V3** (`/trace/:id`) — open the percentile panel, open "Add span to funnel".
|
||||
8. **Funnels list** (`/traces/funnels`) — type in the search bar, rename a funnel.
|
||||
9. **Saved Views** (`/logs/saved-views`, `/traces/saved-views`) — rename a view; from an explorer, "Save view as…".
|
||||
10. **Metrics Explorer** (`/metrics-explorer/explorer`) — open Inspect → time aggregation; open metric details → Metadata tab.
|
||||
11. **Integrations → AWS** — open AWS cloud integration → Region form.
|
||||
12. **Onboarding** (`/get-started`) — pick "Custom" data source, fill env/app names.
|
||||
13. **Custom time picker** — open the global time picker anywhere, switch to "Custom" → type in the timezone search.
|
||||
14. **Quick filters** — on `/logs/logs-explorer` or `/traces-explorer`, open the quick-filter settings drawer and search inside.
|
||||
15. **Org settings → Invite members** (`/settings/org-settings`) — open invite flow, fill email + name.
|
||||
16. **Planned downtime** — search the list.
|
||||
17. **Licenses** (`/licenses`) — paste a license key in the input.
|
||||
|
||||
For each: confirm typing, controlled value, placeholder, disabled state, and form-validation error display all behave the same as before.
|
||||
|
||||
---
|
||||
|
||||
## Skipped (still on antd) — 61 files
|
||||
|
||||
After the migration, 61 files still import `Input` from antd. None of them use a plain `<Input>` that can be migrated — each one is kept on antd for one of the reasons below.
|
||||
|
||||
Kept on antd because they use features the `@signozhq/ui` `Input` does not expose. No action required unless these are migrated separately later.
|
||||
|
||||
**Use `Input.TextArea` / `Input.Password` / `Input.Search` / `Input.Group`:**
|
||||
`CreateAlertV2/EvaluationSettings/EvaluationCadence/EvaluationCadence.tsx`,
|
||||
`CreateAlertV2/EvaluationSettings/EvaluationCadence/EvaluationCadenceDetails.tsx`,
|
||||
`CreateAlertV2/NotificationSettings/NotificationMessage.tsx`,
|
||||
`QueryBuilder/components/Formula/Formula.tsx`,
|
||||
`OptionsMenu/AddColumnField/index.tsx`,
|
||||
`LogsSearchFilter/index.tsx`,
|
||||
`RoutingPolicies/RoutingPolicyDetails.tsx`,
|
||||
`DashboardContainer/DashboardSettings/DashboardVariableSettings/VariableItem/VariableItem.tsx`,
|
||||
`DashboardContainer/DashboardSettings/General/index.tsx`,
|
||||
`FormAlertChannels/Settings/MsTeams.tsx`,
|
||||
`MySettings/UserInfo/index.tsx`,
|
||||
`Login/index.tsx`,
|
||||
`PipelinePage/PipelineListsView/AddNewPipeline/FormFields/DescriptionTextArea.tsx`,
|
||||
`components/HeaderRightSection/FeedbackModal.tsx`,
|
||||
`pages/TracesFunnelDetails/components/FunnelConfiguration/AddFunnelStepDetailsModal.tsx`,
|
||||
`pages/TracesFunnelDetails/components/FunnelConfiguration/AddFunnelDescriptionModal.tsx`,
|
||||
`pages/TracesExplorer/Filter/SectionContent.tsx`.
|
||||
|
||||
**Destructure `const { TextArea/Search } = Input`:**
|
||||
`Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx`,
|
||||
`Trace/Filters/Panel/PanelBody/SearchTraceID/index.tsx`,
|
||||
`Trace/Search/styles.ts`,
|
||||
`ListAlertRules/ListAlert.tsx`,
|
||||
`FormAlertRules/styles.ts`,
|
||||
`FormAlertChannels/Settings/Opsgenie.tsx`,
|
||||
`FormAlertChannels/Settings/Pager.tsx`,
|
||||
`FormAlertChannels/Settings/Slack.tsx`,
|
||||
`NewWidget/RightContainer/SettingSections/GeneralSettingsSection/GeneralSettingsSection.tsx`,
|
||||
`AnomalyAlertEvaluationView/AnomalyAlertEvaluationView.tsx`.
|
||||
|
||||
**`InputNumber` co-used:**
|
||||
`NewWidget/RightContainer/Threshold/Threshold.tsx`,
|
||||
`components/LogsFormatOptionsMenu/LogsFormatOptionsMenu.tsx`.
|
||||
|
||||
**Typed `InputRef`:**
|
||||
`DashboardContainer/DashboardVariablesSelection/TextboxVariableInput.tsx`,
|
||||
`NewWidget/RightContainer/SettingSections/GeneralSettingsSection/GeneralSettingsSection.tsx`,
|
||||
`PipelinePage/components/TagInput.tsx`,
|
||||
`components/OverflowInputToolTip/OverflowInputToolTip.tsx`,
|
||||
`components/CustomTimePicker/CustomTimePicker.tsx`,
|
||||
`components/Input/index.tsx`,
|
||||
`pages/AlertDetails/AlertHeader/ActionButtons/RenameModal.tsx`,
|
||||
`LogsSearchFilter/index.tsx`.
|
||||
|
||||
**Use `addonBefore` / `addonAfter`:**
|
||||
`QueryBuilder/components/Query/Query.tsx`,
|
||||
`QueryBuilder/components/Formula/Formula.tsx`,
|
||||
`GridCardLayout/GridCard/FullView/index.tsx`,
|
||||
`GridCardLayout/WidgetHeader/index.tsx`,
|
||||
`OnboardingV2Container/InviteTeamMembers/InviteTeamMembers.tsx`,
|
||||
`NewWidget/LeftContainer/QuerySection/QueryBuilder/ClickHouse/query.tsx`,
|
||||
`NewWidget/LeftContainer/QuerySection/QueryBuilder/promQL/query.tsx`,
|
||||
`components/Input/index.tsx`,
|
||||
`pages/TracesExplorer/Filter/DurationSection.tsx`.
|
||||
|
||||
**Use `allowClear`:**
|
||||
`Trace/Search/AllTags/Tag/TagKey.tsx` _(migrated — `allowClear` was only used elsewhere)_,
|
||||
`ServiceTable/Filter/FilterDropdown.tsx`,
|
||||
`ServiceApplication/Filter/FilterDropdown.tsx`,
|
||||
`LogsSearchFilter/index.tsx`,
|
||||
`MetricsExplorer/MetricDetails/AllAttributesValue.tsx`,
|
||||
`GridCardLayout/GridCard/FullView/index.tsx`,
|
||||
`NewWidget/RightContainer/SettingSections/GeneralSettingsSection/GeneralSettingsSection.tsx`,
|
||||
`AnomalyAlertEvaluationView/AnomalyAlertEvaluationView.tsx`,
|
||||
`AllError/index.tsx`,
|
||||
`PipelinePage/Layouts/Pipeline/PipelinesSearchSection.tsx`,
|
||||
`lib/uPlotV2/components/Legend/Legend.tsx`.
|
||||
|
||||
**Use `bordered`, `status`, or `size="small|middle|large"`:**
|
||||
`OrganizationSettings/DisplayName/index.tsx` (size, status),
|
||||
`FormAlertRules/labels/index.tsx` (bordered),
|
||||
`DashboardContainer/DashboardVariablesSelection/TextboxVariableInput.tsx` (bordered),
|
||||
`MetricsExplorer/MetricDetails/AllAttributes.tsx` (size),
|
||||
`MetricsExplorer/MetricDetails/AllAttributesValue.tsx` (size),
|
||||
`AllError/index.tsx` (size),
|
||||
`components/CustomTimePicker/CustomTimePicker.tsx` (status),
|
||||
`QueryBuilder/components/Query/Query.tsx` (size),
|
||||
`QueryBuilder/components/Formula/Formula.tsx` (size),
|
||||
`NewWidget/LeftContainer/QuerySection/QueryBuilder/ClickHouse/query.tsx` (size),
|
||||
`NewWidget/LeftContainer/QuerySection/QueryBuilder/promQL/query.tsx` (size).
|
||||
|
||||
**`styled(Input)` in `.ts` style files (DOM structure differs):**
|
||||
`Trace/Filters/Panel/PanelBody/Duration/styles.ts`,
|
||||
`Version/styles.ts`.
|
||||
|
||||
**Aliased-only `Input as X` (no plain `<Input>`):**
|
||||
`ResetPassword/index.tsx`.
|
||||
|
||||
**Already on `@signozhq/ui/input`** (no diff this round): Retention, AuthnOIDC/SAML/Google + their helper sections (ClaimMapping, RoleMapping, AttributeMapping, DomainMapping), ForgotPassword, IntegrationsHeader, OnboardingQuestionaire (Invite + AboutSigNoz), AIAssistant/ChatInput, ServiceAccountsSettings, MembersSettings, ServiceAccountDrawer (EditKey + AddKey), InviteMembersModal, EditMemberDrawer, RolesSettings + CreateRoleModal, SignUp, plus the rest of the `@signozhq/ui/input` adopters listed in `git grep "@signozhq/ui/input"`.
|
||||
@@ -115,7 +115,7 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
func(ps factory.ProviderSettings, q querier.Querier, a analytics.Analytics) querier.Handler {
|
||||
return querier.NewHandler(ps, q, a)
|
||||
},
|
||||
func(_ sqlstore.SQLStore, _ global.Global, _ zeus.Zeus, _ gateway.Gateway, _ licensing.Licensing, _ serviceaccount.Module, _ cloudintegration.Config) (cloudintegration.Module, error) {
|
||||
func(_ sqlstore.SQLStore, _ dashboard.Module, _ global.Global, _ zeus.Zeus, _ gateway.Gateway, _ licensing.Licensing, _ serviceaccount.Module, _ cloudintegration.Config) (cloudintegration.Module, error) {
|
||||
return implcloudintegration.NewModule(), nil
|
||||
},
|
||||
func(c cache.Cache, am alertmanager.Alertmanager, ss sqlstore.SQLStore, ts telemetrystore.TelemetryStore, ms telemetrytypes.MetadataStore, p prometheus.Prometheus, og organization.Getter, rsh rulestatehistory.Module, q querier.Querier, qp queryparser.QueryParser) factory.NamedMap[factory.ProviderFactory[ruler.Ruler, ruler.Config]] {
|
||||
|
||||
@@ -167,7 +167,7 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
communityHandler := querier.NewHandler(ps, q, a)
|
||||
return eequerier.NewHandler(ps, q, communityHandler)
|
||||
},
|
||||
func(sqlStore sqlstore.SQLStore, global global.Global, zeus zeus.Zeus, gateway gateway.Gateway, licensing licensing.Licensing, serviceAccount serviceaccount.Module, config cloudintegration.Config) (cloudintegration.Module, error) {
|
||||
func(sqlStore sqlstore.SQLStore, dashboardModule dashboard.Module, global global.Global, zeus zeus.Zeus, gateway gateway.Gateway, licensing licensing.Licensing, serviceAccount serviceaccount.Module, config cloudintegration.Config) (cloudintegration.Module, error) {
|
||||
defStore := pkgcloudintegration.NewServiceDefinitionStore()
|
||||
awsCloudProviderModule, err := implcloudprovider.NewAWSCloudProvider(defStore)
|
||||
if err != nil {
|
||||
@@ -179,7 +179,7 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
cloudintegrationtypes.CloudProviderTypeAzure: azureCloudProviderModule,
|
||||
}
|
||||
|
||||
return implcloudintegration.NewModule(pkgcloudintegration.NewStore(sqlStore), global, zeus, gateway, licensing, serviceAccount, cloudProvidersMap, config)
|
||||
return implcloudintegration.NewModule(pkgcloudintegration.NewStore(sqlStore), dashboardModule, global, zeus, gateway, licensing, serviceAccount, cloudProvidersMap, config)
|
||||
},
|
||||
func(c cache.Cache, am alertmanager.Alertmanager, ss sqlstore.SQLStore, ts telemetrystore.TelemetryStore, ms telemetrytypes.MetadataStore, p prometheus.Prometheus, og organization.Getter, rsh rulestatehistory.Module, q querier.Querier, qp queryparser.QueryParser) factory.NamedMap[factory.ProviderFactory[ruler.Ruler, ruler.Config]] {
|
||||
return factory.MustNewNamedMap(signozruler.NewFactory(c, am, ss, ts, ms, p, og, rsh, q, qp, eerules.PrepareTaskFunc, eerules.TestNotification))
|
||||
|
||||
@@ -2689,7 +2689,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesClusterRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -2759,7 +2758,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesDaemonSetRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -2829,7 +2827,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesDeploymentRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -2908,7 +2905,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesHostRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -2984,7 +2980,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesJobRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -3032,7 +3027,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesNamespaceRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -3110,7 +3104,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesNodeRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -3209,7 +3202,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -3554,7 +3546,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesStatefulSetRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -3615,7 +3606,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesVolumeRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
|
||||
@@ -54,11 +54,6 @@ func (provider *awscloudprovider) GetServiceDefinition(ctx context.Context, serv
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// override cloud integration dashboard id
|
||||
for index, dashboard := range serviceDef.Assets.Dashboards {
|
||||
serviceDef.Assets.Dashboards[index].ID = cloudintegrationtypes.GetCloudIntegrationDashboardID(cloudintegrationtypes.CloudProviderTypeAWS, serviceID.StringValue(), dashboard.ID)
|
||||
}
|
||||
|
||||
return serviceDef, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,6 @@ func (provider *azurecloudprovider) GetServiceDefinition(ctx context.Context, se
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// override cloud integration dashboard id.
|
||||
for index, dashboard := range serviceDef.Assets.Dashboards {
|
||||
serviceDef.Assets.Dashboards[index].ID = cloudintegrationtypes.GetCloudIntegrationDashboardID(cloudintegrationtypes.CloudProviderTypeAzure, serviceID.StringValue(), dashboard.ID)
|
||||
}
|
||||
|
||||
return serviceDef, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package implcloudintegration
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
@@ -11,6 +10,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/global"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/cloudintegrationtypes"
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
type module struct {
|
||||
store cloudintegrationtypes.Store
|
||||
dashboardModule dashboard.Module
|
||||
gateway gateway.Gateway
|
||||
zeus zeus.Zeus
|
||||
licensing licensing.Licensing
|
||||
@@ -34,6 +35,7 @@ type module struct {
|
||||
|
||||
func NewModule(
|
||||
store cloudintegrationtypes.Store,
|
||||
dashboardModule dashboard.Module,
|
||||
global global.Global,
|
||||
zeus zeus.Zeus,
|
||||
gateway gateway.Gateway,
|
||||
@@ -44,6 +46,7 @@ func NewModule(
|
||||
) (cloudintegration.Module, error) {
|
||||
return &module{
|
||||
store: store,
|
||||
dashboardModule: dashboardModule,
|
||||
global: global,
|
||||
zeus: zeus,
|
||||
gateway: gateway,
|
||||
@@ -254,7 +257,41 @@ func (module *module) DisconnectAccount(ctx context.Context, orgID valuer.UUID,
|
||||
return errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
return module.store.RemoveAccount(ctx, orgID, accountID, provider)
|
||||
return module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
services, err := module.store.ListServices(ctx, accountID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sharedServices, err := module.store.ListSharedServices(ctx, orgID, provider, accountID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, svc := range services {
|
||||
svcCfg, err := cloudintegrationtypes.NewServiceConfigFromJSON(provider, svc.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !svcCfg.IsMetricsEnabled(provider) {
|
||||
continue
|
||||
}
|
||||
|
||||
if cloudintegrationtypes.IsServiceSharedWithMetricsEnabled(provider, sharedServices[svc.Type]) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := module.deprovisionDashboards(ctx, orgID, provider, svc.Type); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := module.store.DeleteServicesByCloudIntegrationID(ctx, orgID, accountID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return module.store.RemoveAccount(ctx, orgID, accountID, provider)
|
||||
})
|
||||
}
|
||||
|
||||
func (module *module) ListServicesMetadata(ctx context.Context, orgID valuer.UUID, provider cloudintegrationtypes.CloudProviderType, integrationID valuer.UUID) ([]*cloudintegrationtypes.ServiceMetadata, error) {
|
||||
@@ -331,12 +368,16 @@ func (module *module) GetService(ctx context.Context, orgID valuer.UUID, service
|
||||
|
||||
integrationService = cloudintegrationtypes.NewCloudIntegrationServiceFromStorable(storedService, serviceConfig)
|
||||
}
|
||||
|
||||
if err := module.enrichDashboardIDs(ctx, orgID, provider, serviceID, serviceDefinition); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return cloudintegrationtypes.NewService(*serviceDefinition, integrationService), nil
|
||||
}
|
||||
|
||||
func (module *module) CreateService(ctx context.Context, orgID valuer.UUID, service *cloudintegrationtypes.CloudIntegrationService, provider cloudintegrationtypes.CloudProviderType) error {
|
||||
func (module *module) CreateService(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, service *cloudintegrationtypes.CloudIntegrationService, provider cloudintegrationtypes.CloudProviderType) error {
|
||||
_, err := module.licensing.GetActive(ctx, orgID)
|
||||
if err != nil {
|
||||
return errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
@@ -357,10 +398,21 @@ func (module *module) CreateService(ctx context.Context, orgID valuer.UUID, serv
|
||||
return err
|
||||
}
|
||||
|
||||
return module.store.CreateService(ctx, cloudintegrationtypes.NewStorableCloudIntegrationService(service, string(configJSON)))
|
||||
metricsEnabled := service.Config.IsMetricsEnabled(provider)
|
||||
storableService := cloudintegrationtypes.NewStorableCloudIntegrationService(service, string(configJSON))
|
||||
|
||||
return module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
if err := module.store.CreateService(ctx, storableService); err != nil {
|
||||
return err
|
||||
}
|
||||
if metricsEnabled {
|
||||
return module.provisionDashboards(ctx, orgID, createdBy, creator, provider, service, serviceDefinition)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (module *module) UpdateService(ctx context.Context, orgID valuer.UUID, integrationService *cloudintegrationtypes.CloudIntegrationService, provider cloudintegrationtypes.CloudProviderType) error {
|
||||
func (module *module) UpdateService(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, integrationService *cloudintegrationtypes.CloudIntegrationService, provider cloudintegrationtypes.CloudProviderType) error {
|
||||
_, err := module.licensing.GetActive(ctx, orgID)
|
||||
if err != nil {
|
||||
return errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
@@ -381,43 +433,28 @@ func (module *module) UpdateService(ctx context.Context, orgID valuer.UUID, inte
|
||||
return err
|
||||
}
|
||||
|
||||
metricsEnabled := integrationService.Config.IsMetricsEnabled(provider)
|
||||
storableService := cloudintegrationtypes.NewStorableCloudIntegrationService(integrationService, string(configJSON))
|
||||
|
||||
return module.store.UpdateService(ctx, storableService)
|
||||
}
|
||||
|
||||
func (module *module) GetDashboardByID(ctx context.Context, orgID valuer.UUID, id string) (*dashboardtypes.Dashboard, error) {
|
||||
_, err := module.licensing.GetActive(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
_, _, _, err = cloudintegrationtypes.ParseCloudIntegrationDashboardID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
allDashboards, err := module.listDashboards(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, d := range allDashboards {
|
||||
if d.ID == id {
|
||||
return d, nil
|
||||
return module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
if err := module.store.UpdateService(ctx, storableService); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New(errors.TypeNotFound, cloudintegrationtypes.ErrCodeCloudIntegrationNotFound, "cloud integration dashboard not found")
|
||||
}
|
||||
if metricsEnabled {
|
||||
return module.provisionDashboards(ctx, orgID, createdBy, creator, provider, integrationService, serviceDefinition)
|
||||
}
|
||||
|
||||
func (module *module) ListDashboards(ctx context.Context, orgID valuer.UUID) ([]*dashboardtypes.Dashboard, error) {
|
||||
_, err := module.licensing.GetActive(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
}
|
||||
sharedServices, err := module.store.ListSharedServices(ctx, orgID, provider, integrationService.CloudIntegrationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cloudintegrationtypes.IsServiceSharedWithMetricsEnabled(provider, sharedServices[integrationService.Type]) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return module.listDashboards(ctx, orgID)
|
||||
return module.deprovisionDashboards(ctx, orgID, provider, integrationService.Type)
|
||||
})
|
||||
}
|
||||
|
||||
func (module *module) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
||||
@@ -493,52 +530,73 @@ func (module *module) getOrCreateAPIKey(ctx context.Context, orgID valuer.UUID,
|
||||
return factorAPIKey.Key, nil
|
||||
}
|
||||
|
||||
func (module *module) listDashboards(ctx context.Context, orgID valuer.UUID) ([]*dashboardtypes.Dashboard, error) {
|
||||
var allDashboards []*dashboardtypes.Dashboard
|
||||
// provisionDashboards creates dashboard and integration_dashboard rows for each dashboard in the service definition.
|
||||
// Must be called within a transaction (ctx carries the tx).
|
||||
func (module *module) provisionDashboards(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, provider cloudintegrationtypes.CloudProviderType, service *cloudintegrationtypes.CloudIntegrationService, serviceDefinition *cloudintegrationtypes.ServiceDefinition) error {
|
||||
// TODO: DB calls are in for loop, can be optimized later.
|
||||
for _, dashboard := range serviceDefinition.Assets.Dashboards {
|
||||
slug := cloudintegrationtypes.IntegrationDashboardSlug(provider, service.Type, dashboard.ID)
|
||||
|
||||
for provider := range module.cloudProvidersMap {
|
||||
cloudProvider, err := module.getCloudProvider(provider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
existing, err := module.store.GetIntegrationDashboardBySlug(ctx, orgID, cloudintegrationtypes.IntegrationDashboardProviderCloudIntegration, slug)
|
||||
if err != nil && !errors.Ast(err, errors.TypeNotFound) {
|
||||
return err
|
||||
}
|
||||
if existing != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
connectedAccounts, err := module.store.ListConnectedAccounts(ctx, orgID, provider)
|
||||
createdDashboard, err := module.dashboardModule.Create(ctx, orgID, createdBy, creator, dashboardtypes.SourceIntegration, dashboardtypes.PostableDashboard(dashboard.Definition))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
for _, storableAccount := range connectedAccounts {
|
||||
storedServices, err := module.store.ListServices(ctx, storableAccount.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, storedSvc := range storedServices {
|
||||
serviceConfig, err := cloudintegrationtypes.NewServiceConfigFromJSON(provider, storedSvc.Config)
|
||||
if err != nil || !serviceConfig.IsMetricsEnabled(provider) {
|
||||
continue
|
||||
}
|
||||
|
||||
svcDef, err := cloudProvider.GetServiceDefinition(ctx, storedSvc.Type)
|
||||
if err != nil || svcDef == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
dashboards := cloudintegrationtypes.GetDashboardsFromAssets(
|
||||
storedSvc.Type.StringValue(),
|
||||
orgID,
|
||||
provider,
|
||||
storableAccount.CreatedAt,
|
||||
svcDef.Assets,
|
||||
)
|
||||
allDashboards = append(allDashboards, dashboards...)
|
||||
}
|
||||
integrationDashboard := cloudintegrationtypes.NewStorableIntegrationDashboard(createdDashboard.ID, cloudintegrationtypes.IntegrationDashboardProviderCloudIntegration, slug)
|
||||
if err := module.store.CreateIntegrationDashboard(ctx, integrationDashboard); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(allDashboards, func(i, j int) bool {
|
||||
return allDashboards[i].ID < allDashboards[j].ID
|
||||
})
|
||||
|
||||
return allDashboards, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// deprovisionDashboards deletes all dashboard and integration_dashboard rows for the given service.
|
||||
// make sure to call this within a transaction.
|
||||
func (module *module) deprovisionDashboards(ctx context.Context, orgID valuer.UUID, provider cloudintegrationtypes.CloudProviderType, serviceID cloudintegrationtypes.ServiceID) error {
|
||||
slugPrefix := cloudintegrationtypes.IntegrationDashboardSlugPrefix(provider, serviceID)
|
||||
rows, err := module.store.ListIntegrationDashboardsBySlugPrefix(ctx, orgID, cloudintegrationtypes.IntegrationDashboardProviderCloudIntegration, slugPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, row := range rows {
|
||||
dashID, err := valuer.NewUUID(row.DashboardID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := module.store.DeleteIntegrationDashboardBySlug(ctx, orgID, cloudintegrationtypes.IntegrationDashboardProviderCloudIntegration, row.Slug); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := module.dashboardModule.DeleteUnsafe(ctx, orgID, dashID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// enrichDashboardIDs replaces the raw dashboard name in each Dashboard.ID with the provisioned UUID.
|
||||
// TODO: remove this hack and send idiomatic response to client.
|
||||
func (module *module) enrichDashboardIDs(ctx context.Context, orgID valuer.UUID, provider cloudintegrationtypes.CloudProviderType, serviceID cloudintegrationtypes.ServiceID, serviceDefinition *cloudintegrationtypes.ServiceDefinition) error {
|
||||
for i, d := range serviceDefinition.Assets.Dashboards {
|
||||
slug := cloudintegrationtypes.IntegrationDashboardSlug(provider, serviceID, d.ID)
|
||||
row, err := module.store.GetIntegrationDashboardBySlug(ctx, orgID, cloudintegrationtypes.IntegrationDashboardProviderCloudIntegration, slug)
|
||||
if err != nil {
|
||||
if errors.Ast(err, errors.TypeNotFound) {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
serviceDefinition.Assets.Dashboards[i].ID = row.DashboardID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -162,24 +162,11 @@ func (module *module) Delete(ctx context.Context, orgID valuer.UUID, id valuer.U
|
||||
return errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "dashboard is locked, please unlock the dashboard to be delete it")
|
||||
}
|
||||
|
||||
err = module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
err := module.store.DeletePublic(ctx, id.String())
|
||||
if err != nil && !errors.Ast(err, errors.TypeNotFound) {
|
||||
return err
|
||||
}
|
||||
return module.delete(ctx, orgID, id)
|
||||
}
|
||||
|
||||
err = module.store.Delete(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
func (module *module) DeleteUnsafe(ctx context.Context, orgID, id valuer.UUID) error {
|
||||
return module.delete(ctx, orgID, id)
|
||||
}
|
||||
|
||||
func (module *module) DeletePublic(ctx context.Context, orgID valuer.UUID, dashboardID valuer.UUID) error {
|
||||
@@ -221,8 +208,8 @@ func (module *module) Collect(ctx context.Context, orgID valuer.UUID) (map[strin
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func (module *module) Create(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, data dashboardtypes.PostableDashboard) (*dashboardtypes.Dashboard, error) {
|
||||
return module.pkgDashboardModule.Create(ctx, orgID, createdBy, creator, data)
|
||||
func (module *module) Create(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, source dashboardtypes.Source, data dashboardtypes.PostableDashboard) (*dashboardtypes.Dashboard, error) {
|
||||
return module.pkgDashboardModule.Create(ctx, orgID, createdBy, creator, source, data)
|
||||
}
|
||||
|
||||
func (module *module) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*dashboardtypes.Dashboard, error) {
|
||||
@@ -244,3 +231,12 @@ func (module *module) Update(ctx context.Context, orgID valuer.UUID, id valuer.U
|
||||
func (module *module) LockUnlock(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, isAdmin bool, lock bool) error {
|
||||
return module.pkgDashboardModule.LockUnlock(ctx, orgID, id, updatedBy, isAdmin, lock)
|
||||
}
|
||||
|
||||
func (module *module) delete(ctx context.Context, orgID, id valuer.UUID) error {
|
||||
return module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
if err := module.store.DeletePublic(ctx, id.String()); err != nil && !errors.Ast(err, errors.TypeNotFound) {
|
||||
return err
|
||||
}
|
||||
return module.store.Delete(ctx, orgID, id)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3488,9 +3488,9 @@ export interface InframonitoringtypesClustersDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesClusterRecordDTO[] | null;
|
||||
records: InframonitoringtypesClusterRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3566,9 +3566,9 @@ export interface InframonitoringtypesDaemonSetsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesDaemonSetRecordDTO[] | null;
|
||||
records: InframonitoringtypesDaemonSetRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3644,9 +3644,9 @@ export interface InframonitoringtypesDeploymentsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesDeploymentRecordDTO[] | null;
|
||||
records: InframonitoringtypesDeploymentRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3730,9 +3730,9 @@ export interface InframonitoringtypesHostsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesHostRecordDTO[] | null;
|
||||
records: InframonitoringtypesHostRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3816,9 +3816,9 @@ export interface InframonitoringtypesJobsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesJobRecordDTO[] | null;
|
||||
records: InframonitoringtypesJobRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3866,9 +3866,9 @@ export interface InframonitoringtypesNamespacesDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesNamespaceRecordDTO[] | null;
|
||||
records: InframonitoringtypesNamespaceRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3933,9 +3933,9 @@ export interface InframonitoringtypesNodesDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesNodeRecordDTO[] | null;
|
||||
records: InframonitoringtypesNodeRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -4017,9 +4017,9 @@ export interface InframonitoringtypesPodsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesPodRecordDTO[] | null;
|
||||
records: InframonitoringtypesPodRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -4437,9 +4437,9 @@ export interface InframonitoringtypesStatefulSetsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesStatefulSetRecordDTO[] | null;
|
||||
records: InframonitoringtypesStatefulSetRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -4506,9 +4506,9 @@ export interface InframonitoringtypesVolumesDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesVolumeRecordDTO[] | null;
|
||||
records: InframonitoringtypesVolumeRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Input } from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
import { TimezonePickerShortcuts } from 'constants/shortcuts/TimezonePickerShortcuts';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Card, Form } from 'antd';
|
||||
import { Card, Form, Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button } from 'antd';
|
||||
import { Button, Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import { X } from '@signozhq/icons';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, InputNumber, Popover, Tooltip } from 'antd';
|
||||
import { Button, Input, InputNumber, Popover, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import cx from 'classnames';
|
||||
|
||||
@@ -13,7 +13,7 @@ export function NoAuthBanner(): JSX.Element {
|
||||
Impersonation mode: authentication is disabled. Anyone with access to this
|
||||
instance has admin privileges.{' '}
|
||||
<a
|
||||
href="https://signoz.io/docs/manage/administrator-guide/configuration/no-auth-mode/"
|
||||
href="https://signoz.io/docs/manage/administrator-guide/configuration/impersonation-mode/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable sonarjs/no-identical-functions */
|
||||
import { Fragment, useMemo, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Checkbox, Skeleton } from 'antd';
|
||||
import { Button, Checkbox, Input, Skeleton } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import { removeKeysFromExpression } from 'components/QueryBuilderV2/utils';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button } from 'antd';
|
||||
import { Button, Input } from 'antd';
|
||||
import { Check, TableColumnsSplit, X } from '@signozhq/icons';
|
||||
import { Filter as FilterType } from 'types/api/quickFilters/getCustomFilters';
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Select, Tooltip } from 'antd';
|
||||
import { Button, Input, Select, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { CircleX, Trash } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Collapse } from 'antd';
|
||||
import { Collapse, Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
import { useCreateAlertState } from '../context';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Select } from 'antd';
|
||||
import { Input, Select } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
import { ADVANCED_OPTIONS_TIME_UNIT_OPTIONS } from '../../context/constants';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Input } from 'antd';
|
||||
|
||||
import './TimeInput.scss';
|
||||
|
||||
export interface TimeInputProps {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Select } from 'antd';
|
||||
import { Input, Select } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
import { useCreateAlertState } from '../context';
|
||||
|
||||
@@ -16,8 +16,7 @@ import {
|
||||
Plus,
|
||||
X,
|
||||
} from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Card, Modal, Popover, Tag, Tooltip } from 'antd';
|
||||
import { Button, Card, Input, Modal, Popover, Tag, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import ConfigureIcon from 'assets/Integrations/ConfigureIcon';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button } from 'antd';
|
||||
import { Button, Input } from 'antd';
|
||||
import { PrecisionOption, PrecisionOptionsEnum } from 'components/Graph/types';
|
||||
import { ResizeTable } from 'components/ResizeTable';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
|
||||
@@ -19,11 +19,11 @@ import {
|
||||
Info,
|
||||
} from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import {
|
||||
Button,
|
||||
ColorPicker,
|
||||
Divider,
|
||||
Input,
|
||||
Modal,
|
||||
RefSelectProps,
|
||||
Select,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form } from 'antd';
|
||||
import { Form, Input } from 'antd';
|
||||
|
||||
import { EmailChannel } from '../../CreateAlertChannels/config';
|
||||
|
||||
function EmailForm({ setSelectedConfig }: EmailFormProps): JSX.Element {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form } from 'antd';
|
||||
import { Form, Input } from 'antd';
|
||||
import { MarkdownRenderer } from 'components/MarkdownRenderer/MarkdownRenderer';
|
||||
|
||||
import { WebhookChannel } from '../../CreateAlertChannels/config';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Dispatch, ReactElement, SetStateAction } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form, FormInstance, Select, Switch } from 'antd';
|
||||
import { Form, FormInstance, Input, Select, Switch } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import type { Store } from 'antd/lib/form/interface';
|
||||
import ROUTES from 'constants/routes';
|
||||
|
||||
@@ -6,8 +6,7 @@ import { useIsFetching } from 'react-query';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Form, Modal } from 'antd';
|
||||
import { Button, Form, Input, Modal } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
|
||||
@@ -5,12 +5,12 @@ import { useCopyToClipboard } from 'react-use';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import {
|
||||
Col,
|
||||
Collapse,
|
||||
DatePicker,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Modal,
|
||||
Row,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form } from 'antd';
|
||||
import { Form, Input } from 'antd';
|
||||
import { CloudintegrationtypesCredentialsDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
|
||||
function RenderConnectionFields({
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Form } from 'antd';
|
||||
import { Button, Form, Input } from 'antd';
|
||||
import apply from 'api/v3/licenses/post';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
import { ChangeEvent, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Modal } from 'antd';
|
||||
import { Button, Input, Modal } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import ApacheIcon from 'assets/CustomIcons/ApacheIcon';
|
||||
import DockerIcon from 'assets/CustomIcons/DockerIcon';
|
||||
|
||||
@@ -12,11 +12,11 @@ import { useTranslation } from 'react-i18next';
|
||||
import { generatePath } from 'react-router-dom';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import {
|
||||
Button,
|
||||
Dropdown,
|
||||
Flex,
|
||||
Input,
|
||||
MenuProps,
|
||||
Modal,
|
||||
Popover,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LoaderCircle, Check } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Space } from 'antd';
|
||||
import { Button, Input, Space } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
|
||||
@@ -2,8 +2,7 @@ import { ReactNode, useState } from 'react';
|
||||
import MEditor, { EditorProps, Monaco } from '@monaco-editor/react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Collapse, Divider, Switch, Tag } from 'antd';
|
||||
import { Collapse, Divider, Input, Switch, Tag } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { AddToQueryHOCProps } from 'components/Logs/AddToQueryHOC';
|
||||
import { ChangeViewFunctionType } from 'container/ExplorerOptions/types';
|
||||
|
||||
@@ -2,8 +2,7 @@ import { ChangeEvent, useCallback, useState } from 'react';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { CirclePlus, X } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Col } from 'antd';
|
||||
import { Col, Input } from 'antd';
|
||||
import CategoryHeading from 'components/Logs/CategoryHeading';
|
||||
import { fieldSearchFilter } from 'lib/logs/fieldSearch';
|
||||
import { AppState } from 'store/reducers';
|
||||
|
||||
@@ -2,8 +2,7 @@ import { useCallback, useMemo, useState } from 'react';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { SquareX, X } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Select } from 'antd';
|
||||
import { Button, Input, Select } from 'antd';
|
||||
import CategoryHeading from 'components/Logs/CategoryHeading';
|
||||
import {
|
||||
ConditionalOperators,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
// TODO(@signozhq/ui-input): migrate this <Input> once @signozhq/ui Input
|
||||
// supports the `onWheel` handler (used to blur on scroll for number inputs).
|
||||
import { Input, Select } from 'antd';
|
||||
import { Select } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { TIME_AGGREGATION_OPTIONS } from './constants';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useQueryClient } from 'react-query';
|
||||
import type { TableColumnsType as ColumnsType } from 'antd';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Collapse, Select, Spin } from 'antd';
|
||||
import { Button, Collapse, Input, Select, Spin } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import {
|
||||
|
||||
@@ -127,6 +127,12 @@
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding-bottom: 16px;
|
||||
|
||||
.password-error-text {
|
||||
font-size: var(--font-size-xs);
|
||||
color: var(--bg-cherry-400);
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-color-picker-trigger {
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Input, Modal } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import {
|
||||
updateMyPassword,
|
||||
useUpdateMyUserV2,
|
||||
} from 'api/generated/services/users';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { toast } from '@signozhq/ui/sonner';
|
||||
import { Check, FileTerminal, Mail, User } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { useErrorModal } from 'providers/ErrorModalProvider';
|
||||
import APIError from 'types/api/error';
|
||||
import { ErrorV2Resp } from 'types/api';
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
import '../MySettings.styles.scss';
|
||||
import './UserInfo.styles.scss';
|
||||
|
||||
function UserInfo(): JSX.Element {
|
||||
const { user, org, updateUser } = useAppContext();
|
||||
const { t } = useTranslation(['routes', 'settings', 'common']);
|
||||
|
||||
const { notifications } = useNotifications();
|
||||
const { showErrorModal } = useErrorModal();
|
||||
const { mutateAsync: updateMyUser } = useUpdateMyUserV2();
|
||||
|
||||
const [currentPassword, setCurrentPassword] = useState<string>('');
|
||||
@@ -47,6 +49,8 @@ function UserInfo(): JSX.Element {
|
||||
|
||||
const hideResetPasswordModal = (): void => {
|
||||
setIsResetPasswordModalOpen(false);
|
||||
setCurrentPassword('');
|
||||
setUpdatePassword('');
|
||||
};
|
||||
|
||||
const onChangePasswordClickHandler = async (): Promise<void> => {
|
||||
@@ -57,27 +61,29 @@ function UserInfo(): JSX.Element {
|
||||
newPassword: updatePassword,
|
||||
oldPassword: currentPassword,
|
||||
});
|
||||
notifications.success({
|
||||
message: t('success', {
|
||||
ns: 'common',
|
||||
}),
|
||||
});
|
||||
toast.success('Password updated successfully');
|
||||
hideResetPasswordModal();
|
||||
setIsLoading(false);
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
notifications.error({
|
||||
message: (error as APIError).error.error.code,
|
||||
description: (error as APIError).error.error.message,
|
||||
});
|
||||
try {
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
} catch (apiError) {
|
||||
showErrorModal(apiError as APIError);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const passwordsMatch =
|
||||
currentPassword.length > 0 &&
|
||||
updatePassword.length > 0 &&
|
||||
currentPassword === updatePassword;
|
||||
|
||||
const isResetPasswordDisabled =
|
||||
isLoading ||
|
||||
currentPassword.length === 0 ||
|
||||
updatePassword.length === 0 ||
|
||||
currentPassword === updatePassword;
|
||||
passwordsMatch;
|
||||
|
||||
const onSaveHandler = async (): Promise<void> => {
|
||||
void logEvent('Account Settings: Name Updated', {
|
||||
@@ -94,11 +100,7 @@ function UserInfo(): JSX.Element {
|
||||
setIsLoading(true);
|
||||
await updateMyUser({ data: { displayName: changedName } });
|
||||
|
||||
notifications.success({
|
||||
message: t('success', {
|
||||
ns: 'common',
|
||||
}),
|
||||
});
|
||||
toast.success('Name updated successfully');
|
||||
updateUser({
|
||||
...user,
|
||||
displayName: changedName,
|
||||
@@ -106,10 +108,11 @@ function UserInfo(): JSX.Element {
|
||||
setIsLoading(false);
|
||||
hideUpdateNameModal();
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
try {
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
} catch (apiError) {
|
||||
showErrorModal(apiError as APIError);
|
||||
}
|
||||
}
|
||||
setIsLoading(false);
|
||||
};
|
||||
@@ -166,7 +169,7 @@ function UserInfo(): JSX.Element {
|
||||
type="primary"
|
||||
icon={<Check size={16} />}
|
||||
onClick={onSaveHandler}
|
||||
disabled={isLoading}
|
||||
loading={isLoading}
|
||||
data-testid="update-name-btn"
|
||||
>
|
||||
Update name
|
||||
@@ -178,7 +181,11 @@ function UserInfo(): JSX.Element {
|
||||
<Input
|
||||
placeholder="e.g. John Doe"
|
||||
value={changedName}
|
||||
disabled={isLoading}
|
||||
onChange={(e): void => setChangedName(e.target.value)}
|
||||
onPressEnter={(): void => {
|
||||
void onSaveHandler();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
@@ -188,6 +195,7 @@ function UserInfo(): JSX.Element {
|
||||
title={<span className="title">Reset password</span>}
|
||||
open={isResetPasswordModalOpen}
|
||||
closable
|
||||
destroyOnClose
|
||||
onCancel={hideResetPasswordModal}
|
||||
footer={[
|
||||
<Button
|
||||
@@ -197,7 +205,8 @@ function UserInfo(): JSX.Element {
|
||||
}`}
|
||||
icon={<Check size={16} />}
|
||||
onClick={onChangePasswordClickHandler}
|
||||
disabled={isLoading || isResetPasswordDisabled}
|
||||
loading={isLoading}
|
||||
disabled={isResetPasswordDisabled}
|
||||
data-testid="reset-password-btn"
|
||||
>
|
||||
Reset password
|
||||
@@ -218,6 +227,11 @@ function UserInfo(): JSX.Element {
|
||||
type="password"
|
||||
autoComplete="off"
|
||||
visibilityToggle
|
||||
onPressEnter={(): void => {
|
||||
if (!isResetPasswordDisabled) {
|
||||
void onChangePasswordClickHandler();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -235,7 +249,18 @@ function UserInfo(): JSX.Element {
|
||||
type="password"
|
||||
autoComplete="off"
|
||||
visibilityToggle={false}
|
||||
status={passwordsMatch ? 'error' : ''}
|
||||
onPressEnter={(): void => {
|
||||
if (!isResetPasswordDisabled) {
|
||||
void onChangePasswordClickHandler();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{passwordsMatch && (
|
||||
<span className="password-error-text">
|
||||
New password must be different from current password
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@@ -8,11 +8,23 @@ import {
|
||||
waitFor,
|
||||
within,
|
||||
} from 'tests/test-utils';
|
||||
import APIError from 'types/api/error';
|
||||
import { toast } from '@signozhq/ui/sonner';
|
||||
|
||||
const toggleThemeFunction = jest.fn();
|
||||
const logEventFunction = jest.fn();
|
||||
const copyToClipboardFn = jest.fn();
|
||||
const editUserFn = jest.fn();
|
||||
const updateMyPasswordFn = jest.fn();
|
||||
const showErrorModalFn = jest.fn();
|
||||
|
||||
jest.mock('@signozhq/ui/sonner', () => ({
|
||||
...jest.requireActual('@signozhq/ui/sonner'),
|
||||
toast: {
|
||||
success: jest.fn(),
|
||||
error: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('react-use', () => ({
|
||||
__esModule: true,
|
||||
@@ -24,12 +36,21 @@ jest.mock('react-use', () => ({
|
||||
|
||||
jest.mock('api/generated/services/users', () => ({
|
||||
...jest.requireActual('api/generated/services/users'),
|
||||
updateMyPassword: (...args: unknown[]): Promise<unknown> =>
|
||||
updateMyPasswordFn(...args),
|
||||
useUpdateMyUserV2: jest.fn(() => ({
|
||||
mutateAsync: (...args: unknown[]): Promise<unknown> => editUserFn(...args),
|
||||
isLoading: false,
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('providers/ErrorModalProvider', () => ({
|
||||
...jest.requireActual('providers/ErrorModalProvider'),
|
||||
useErrorModal: jest.fn(() => ({
|
||||
showErrorModal: showErrorModalFn,
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('hooks/useDarkMode', () => ({
|
||||
__esModule: true,
|
||||
useIsDarkMode: jest.fn(() => true),
|
||||
@@ -65,12 +86,12 @@ const NEW_PASSWORD_TEST_ID = 'new-password-textbox';
|
||||
const UPDATE_NAME_BUTTON_TEST_ID = 'update-name-btn';
|
||||
const RESET_PASSWORD_BUTTON_TEST_ID = 'reset-password-btn';
|
||||
const UPDATE_NAME_BUTTON_TEXT = 'Update name';
|
||||
const PASSWORD_VALIDATION_MESSAGE_TEST_ID = 'password-validation-message';
|
||||
|
||||
describe('MySettings Flows', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
editUserFn.mockResolvedValue({});
|
||||
updateMyPasswordFn.mockResolvedValue({});
|
||||
render(<MySettingsContainer />);
|
||||
});
|
||||
|
||||
@@ -152,9 +173,7 @@ describe('MySettings Flows', () => {
|
||||
fireEvent.click(modalUpdateNameButton);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(successNotification).toHaveBeenCalledWith({
|
||||
message: 'success',
|
||||
}),
|
||||
expect(toast.success).toHaveBeenCalledWith('Name updated successfully'),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -181,22 +200,131 @@ describe('MySettings Flows', () => {
|
||||
expect(screen.getByTestId(NEW_PASSWORD_TEST_ID)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should display validation error if password is less than 8 characters', async () => {
|
||||
it('Should show inline error when new password matches current password', async () => {
|
||||
const resetPasswordButtons = screen.getAllByText(RESET_PASSWORD_BUTTON_TEXT);
|
||||
fireEvent.click(resetPasswordButtons[0]);
|
||||
|
||||
const currentPasswordTextbox = screen.getByTestId(CURRENT_PASSWORD_TEST_ID);
|
||||
act(() => {
|
||||
fireEvent.change(currentPasswordTextbox, { target: { value: '123' } });
|
||||
fireEvent.change(screen.getByTestId(CURRENT_PASSWORD_TEST_ID), {
|
||||
target: { value: 'samePassword1' },
|
||||
});
|
||||
fireEvent.change(screen.getByTestId(NEW_PASSWORD_TEST_ID), {
|
||||
target: { value: 'samePassword1' },
|
||||
});
|
||||
});
|
||||
|
||||
expect(
|
||||
screen.getByText('New password must be different from current password'),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByTestId(RESET_PASSWORD_BUTTON_TEST_ID)).toBeDisabled();
|
||||
});
|
||||
|
||||
it('Should hide inline error when passwords are changed to be different', async () => {
|
||||
const resetPasswordButtons = screen.getAllByText(RESET_PASSWORD_BUTTON_TEXT);
|
||||
fireEvent.click(resetPasswordButtons[0]);
|
||||
|
||||
act(() => {
|
||||
fireEvent.change(screen.getByTestId(CURRENT_PASSWORD_TEST_ID), {
|
||||
target: { value: 'samePassword1' },
|
||||
});
|
||||
fireEvent.change(screen.getByTestId(NEW_PASSWORD_TEST_ID), {
|
||||
target: { value: 'samePassword1' },
|
||||
});
|
||||
});
|
||||
|
||||
act(() => {
|
||||
fireEvent.change(screen.getByTestId(NEW_PASSWORD_TEST_ID), {
|
||||
target: { value: 'differentPassword1' },
|
||||
});
|
||||
});
|
||||
|
||||
expect(
|
||||
screen.queryByText('New password must be different from current password'),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should show error modal when password reset API returns an error', async () => {
|
||||
updateMyPasswordFn.mockRejectedValue(
|
||||
new Error('Current password is incorrect'),
|
||||
);
|
||||
|
||||
const resetPasswordButtons = screen.getAllByText(RESET_PASSWORD_BUTTON_TEXT);
|
||||
fireEvent.click(resetPasswordButtons[0]);
|
||||
|
||||
act(() => {
|
||||
fireEvent.change(screen.getByTestId(CURRENT_PASSWORD_TEST_ID), {
|
||||
target: { value: 'oldPassword1' },
|
||||
});
|
||||
fireEvent.change(screen.getByTestId(NEW_PASSWORD_TEST_ID), {
|
||||
target: { value: 'newPassword1' },
|
||||
});
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByTestId(RESET_PASSWORD_BUTTON_TEST_ID));
|
||||
|
||||
await waitFor(() => {
|
||||
// Use getByTestId for the validation message (if present in your modal/component)
|
||||
if (screen.queryByTestId(PASSWORD_VALIDATION_MESSAGE_TEST_ID)) {
|
||||
expect(
|
||||
screen.getByTestId(PASSWORD_VALIDATION_MESSAGE_TEST_ID),
|
||||
).toBeInTheDocument();
|
||||
}
|
||||
expect(showErrorModalFn).toHaveBeenCalledWith(expect.any(APIError));
|
||||
});
|
||||
});
|
||||
|
||||
it('Should show success toast and close modal on successful password reset', async () => {
|
||||
const resetPasswordButtons = screen.getAllByText(RESET_PASSWORD_BUTTON_TEXT);
|
||||
fireEvent.click(resetPasswordButtons[0]);
|
||||
|
||||
act(() => {
|
||||
fireEvent.change(screen.getByTestId(CURRENT_PASSWORD_TEST_ID), {
|
||||
target: { value: 'oldPassword1' },
|
||||
});
|
||||
fireEvent.change(screen.getByTestId(NEW_PASSWORD_TEST_ID), {
|
||||
target: { value: 'newPassword1' },
|
||||
});
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByTestId(RESET_PASSWORD_BUTTON_TEST_ID));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(toast.success).toHaveBeenCalledWith('Password updated successfully');
|
||||
expect(
|
||||
screen.queryByTestId(CURRENT_PASSWORD_TEST_ID),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('Should clear password fields when modal is cancelled', async () => {
|
||||
const resetPasswordButtons = screen.getAllByText(RESET_PASSWORD_BUTTON_TEXT);
|
||||
fireEvent.click(resetPasswordButtons[0]);
|
||||
|
||||
act(() => {
|
||||
fireEvent.change(screen.getByTestId(CURRENT_PASSWORD_TEST_ID), {
|
||||
target: { value: 'somePassword' },
|
||||
});
|
||||
fireEvent.change(screen.getByTestId(NEW_PASSWORD_TEST_ID), {
|
||||
target: { value: 'otherPassword' },
|
||||
});
|
||||
});
|
||||
|
||||
expect(screen.getByTestId(CURRENT_PASSWORD_TEST_ID)).toHaveValue(
|
||||
'somePassword',
|
||||
);
|
||||
|
||||
// Close the modal
|
||||
const closeButton = document.querySelector(
|
||||
'.reset-password-modal .ant-modal-close',
|
||||
) as HTMLElement;
|
||||
fireEvent.click(closeButton);
|
||||
|
||||
// Reopen the modal
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.queryByTestId(CURRENT_PASSWORD_TEST_ID),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getAllByText(RESET_PASSWORD_BUTTON_TEXT)[0]);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId(CURRENT_PASSWORD_TEST_ID)).toHaveValue('');
|
||||
expect(screen.getByTestId(NEW_PASSWORD_TEST_ID)).toHaveValue('');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
DropResult,
|
||||
} from 'react-beautiful-dnd';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Divider, Dropdown, MenuProps, Tooltip } from 'antd';
|
||||
import { Button, Divider, Dropdown, Input, MenuProps, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { FieldDataType } from 'api/v5/v5';
|
||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
// TODO(@signozhq/ui-input): migrate <Input> once @signozhq/ui Input
|
||||
// supports the `spellCheck` prop on the URL input below.
|
||||
import { Button, Col, Form, Input, Input as AntInput, Row } from 'antd';
|
||||
import { Button, Col, Form, Input as AntInput, Input, Row } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { CONTEXT_LINK_FIELDS } from 'container/NewWidget/RightContainer/ContextLinks/constants';
|
||||
import {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Blocks, Check, LoaderCircle } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Card, Form, Select, Space } from 'antd';
|
||||
import { Button, Card, Form, Input, Select, Space } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Check, Server, LoaderCircle } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Card, Form, Space } from 'antd';
|
||||
import { Button, Card, Form, Input, Space } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Plus, Trash2 } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Form, FormInstance, Select, Space } from 'antd';
|
||||
import { Button, Form, FormInstance, Input, Select, Space } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { requireErrorMessage } from 'utils/form/requireErrorMessage';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form } from 'antd';
|
||||
import { Form, Input } from 'antd';
|
||||
|
||||
import { ProcessorFormField } from '../../AddNewProcessor/config';
|
||||
import { formValidationRules } from '../../config';
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { ChangeEventHandler, useState } from 'react';
|
||||
// TODO(@signozhq/ui-input): migrate to @signozhq/ui Input once the antd
|
||||
// `InputProps` spread (`size`, etc.) is no longer needed on this wrapper.
|
||||
import { Input, InputProps } from 'antd';
|
||||
|
||||
function CSVInput({ value, onChange, ...otherProps }: InputProps): JSX.Element {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Info } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Flex, Form, Space, Switch, Tooltip } from 'antd';
|
||||
import { Flex, Form, Input, Space, Switch, Tooltip } from 'antd';
|
||||
import { ProcessorData } from 'types/api/pipeline/def';
|
||||
|
||||
import { PREDEFINED_MAPPING } from '../config';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Form, Select, Space, Switch } from 'antd';
|
||||
import { Form, Input, Select, Space, Switch } from 'antd';
|
||||
import { ModalFooterTitle } from 'container/PipelinePage/styles';
|
||||
import { ProcessorData } from 'types/api/pipeline/def';
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@ import React, { ChangeEvent, useEffect, useState } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Plus, Search } from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Flex, Form, Tooltip } from 'antd';
|
||||
import { Button, Flex, Form, Input, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import {
|
||||
useDeleteDowntimeScheduleByID,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Skeleton } from 'antd';
|
||||
import { Input, Skeleton } from 'antd';
|
||||
import { getKeySuggestions } from 'api/querySuggestions/getKeySuggestions';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
import { QUERY_BUILDER_KEY_TYPES } from 'constants/antlrQueryConstants';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { ChangeEvent, useMemo } from 'react';
|
||||
import { Plus, Search } from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Flex, Tooltip } from 'antd';
|
||||
import { Button, Flex, Input, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { USER_ROLES } from 'types/roles';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import CopyClipboardHOC from 'components/Logs/CopyClipboardHOC';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Collapse, Modal } from 'antd';
|
||||
import { Collapse, Input, Modal } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { getYAxisFormattedValue } from 'components/Graph/yAxisConfig';
|
||||
import { Diamond } from '@signozhq/icons';
|
||||
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Input,
|
||||
Modal,
|
||||
Select,
|
||||
Skeleton,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// TODO(@signozhq/ui-input): migrate this styled(Input) once @signozhq/ui
|
||||
// Input supports `addonAfter` (the consumer renders `<InputComponent addonAfter="ms">`).
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const DurationText = styled.div`
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
import { useQuery } from 'react-query';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { AutoComplete } from 'antd';
|
||||
import { AutoComplete, Input } from 'antd';
|
||||
import getTagFilters from 'api/trace/getTagFilter';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
@@ -2,8 +2,7 @@ import { useMemo, useState } from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { AutoComplete, Space } from 'antd';
|
||||
import { AutoComplete, Input, Space } from 'antd';
|
||||
import getTagFilters from 'api/trace/getTagFilter';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ChangeEvent, useEffect, useMemo, useState } from 'react';
|
||||
import { ArrowLeft, Check, Loader, Plus, Search } from '@signozhq/icons';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Spin } from 'antd';
|
||||
import { Button, Input, Spin } from 'antd';
|
||||
import cx from 'classnames';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
import SignozModal from 'components/SignozModal/SignozModal';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Input } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const InputComponent = styled(Input)`
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Select } from 'antd';
|
||||
import { Input, Select } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
import './DropRateView.styles.scss';
|
||||
|
||||
@@ -3,8 +3,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { ColorPicker, Modal, Table, TableProps } from 'antd';
|
||||
import { ColorPicker, Input, Modal, Table, TableProps } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Checkbox, Select, Skeleton } from 'antd';
|
||||
import { Checkbox, Input, Select, Skeleton } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ChangeEvent, useEffect, useMemo, useState } from 'react';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Spin } from 'antd';
|
||||
import { Input, Spin } from 'antd';
|
||||
import cx from 'classnames';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
import SignozModal from 'components/SignozModal/SignozModal';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { useQueryClient } from 'react-query';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Input } from 'antd';
|
||||
import SignozModal from 'components/SignozModal/SignozModal';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import { useRenameFunnel } from 'hooks/TracesFunnels/useFunnels';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Button, Popover, Tooltip } from 'antd';
|
||||
import { Button, Input, Popover, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { ArrowDownWideNarrow, Check, Plus, Search } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||
citypes "github.com/SigNoz/signoz/pkg/types/cloudintegrationtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
@@ -43,23 +42,14 @@ type Module interface {
|
||||
GetService(ctx context.Context, orgID valuer.UUID, serviceID citypes.ServiceID, provider citypes.CloudProviderType, integrationID valuer.UUID) (*citypes.Service, error)
|
||||
|
||||
// CreateService creates a new service for a cloud integration account.
|
||||
CreateService(ctx context.Context, orgID valuer.UUID, service *citypes.CloudIntegrationService, provider citypes.CloudProviderType) error
|
||||
CreateService(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, service *citypes.CloudIntegrationService, provider citypes.CloudProviderType) error
|
||||
|
||||
// UpdateService updates cloud integration service
|
||||
UpdateService(ctx context.Context, orgID valuer.UUID, service *citypes.CloudIntegrationService, provider citypes.CloudProviderType) error
|
||||
UpdateService(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, service *citypes.CloudIntegrationService, provider citypes.CloudProviderType) error
|
||||
|
||||
// AgentCheckIn is called by agent to send heartbeat and get latest config in response.
|
||||
AgentCheckIn(ctx context.Context, orgID valuer.UUID, provider citypes.CloudProviderType, req *citypes.AgentCheckInRequest) (*citypes.AgentCheckInResponse, error)
|
||||
|
||||
// GetDashboardByID returns dashboard JSON for a given dashboard id.
|
||||
// this only returns the dashboard when the service (embedded in dashboard id) is enabled
|
||||
// in the org for any cloud integration account
|
||||
GetDashboardByID(ctx context.Context, orgID valuer.UUID, id string) (*dashboardtypes.Dashboard, error)
|
||||
|
||||
// ListDashboards returns list of dashboards across all connected cloud integration accounts
|
||||
// for enabled services in the org. This list gets added to dashboard list page
|
||||
ListDashboards(ctx context.Context, orgID valuer.UUID) ([]*dashboardtypes.Dashboard, error)
|
||||
|
||||
statsreporter.StatsCollector
|
||||
}
|
||||
|
||||
|
||||
@@ -380,7 +380,7 @@ func (handler *handler) UpdateService(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err = handler.module.CreateService(ctx, orgID, cloudIntegrationService, provider)
|
||||
err = handler.module.CreateService(ctx, orgID, claims.Email, valuer.MustNewUUID(claims.IdentityID()), cloudIntegrationService, provider)
|
||||
} else {
|
||||
err = svc.CloudIntegrationService.Update(provider, serviceID, req.Config)
|
||||
if err != nil {
|
||||
@@ -388,7 +388,7 @@ func (handler *handler) UpdateService(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err = handler.module.UpdateService(ctx, orgID, svc.CloudIntegrationService, provider)
|
||||
err = handler.module.UpdateService(ctx, orgID, claims.Email, valuer.MustNewUUID(claims.IdentityID()), svc.CloudIntegrationService, provider)
|
||||
}
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/types/cloudintegrationtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
@@ -45,7 +44,7 @@ func (module *module) DisconnectAccount(ctx context.Context, orgID valuer.UUID,
|
||||
return errors.New(errors.TypeUnsupported, cloudintegrationtypes.ErrCodeUnsupported, "disconnect account is not supported")
|
||||
}
|
||||
|
||||
func (module *module) CreateService(ctx context.Context, orgID valuer.UUID, service *cloudintegrationtypes.CloudIntegrationService, provider cloudintegrationtypes.CloudProviderType) error {
|
||||
func (module *module) CreateService(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, service *cloudintegrationtypes.CloudIntegrationService, provider cloudintegrationtypes.CloudProviderType) error {
|
||||
return errors.New(errors.TypeUnsupported, cloudintegrationtypes.ErrCodeUnsupported, "create service is not supported")
|
||||
}
|
||||
|
||||
@@ -57,7 +56,7 @@ func (module *module) ListServicesMetadata(ctx context.Context, orgID valuer.UUI
|
||||
return nil, errors.New(errors.TypeUnsupported, cloudintegrationtypes.ErrCodeUnsupported, "list services metadata is not supported")
|
||||
}
|
||||
|
||||
func (module *module) UpdateService(ctx context.Context, orgID valuer.UUID, service *cloudintegrationtypes.CloudIntegrationService, provider cloudintegrationtypes.CloudProviderType) error {
|
||||
func (module *module) UpdateService(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, service *cloudintegrationtypes.CloudIntegrationService, provider cloudintegrationtypes.CloudProviderType) error {
|
||||
return errors.New(errors.TypeUnsupported, cloudintegrationtypes.ErrCodeUnsupported, "update service is not supported")
|
||||
}
|
||||
|
||||
@@ -69,14 +68,6 @@ func (module *module) AgentCheckIn(ctx context.Context, orgID valuer.UUID, provi
|
||||
return nil, errors.New(errors.TypeUnsupported, cloudintegrationtypes.ErrCodeUnsupported, "agent check-in is not supported")
|
||||
}
|
||||
|
||||
func (module *module) GetDashboardByID(ctx context.Context, orgID valuer.UUID, id string) (*dashboardtypes.Dashboard, error) {
|
||||
return nil, errors.New(errors.TypeUnsupported, cloudintegrationtypes.ErrCodeUnsupported, "get dashboard by ID is not supported")
|
||||
}
|
||||
|
||||
func (module *module) ListDashboards(ctx context.Context, orgID valuer.UUID) ([]*dashboardtypes.Dashboard, error) {
|
||||
return nil, errors.New(errors.TypeUnsupported, cloudintegrationtypes.ErrCodeUnsupported, "list dashboards is not supported")
|
||||
}
|
||||
|
||||
func (module *module) Collect(context.Context, valuer.UUID) (map[string]any, error) {
|
||||
return nil, errors.New(errors.TypeUnsupported, cloudintegrationtypes.ErrCodeUnsupported, "stats collection is not supported")
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types/cloudintegrationtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
@@ -186,6 +187,41 @@ func (store *store) ListServices(ctx context.Context, cloudIntegrationID valuer.
|
||||
return services, nil
|
||||
}
|
||||
|
||||
func (store *store) ListSharedServices(ctx context.Context, orgID valuer.UUID, provider cloudintegrationtypes.CloudProviderType, cloudIntegrationID valuer.UUID) (map[cloudintegrationtypes.ServiceID][]*cloudintegrationtypes.StorableCloudIntegrationService, error) {
|
||||
// Subquery: service types that belong to the given account
|
||||
ownTypes := store.store.BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
TableExpr("cloud_integration_service").
|
||||
ColumnExpr("type").
|
||||
Where("cloud_integration_id = ?", cloudIntegrationID)
|
||||
|
||||
var services []*cloudintegrationtypes.StorableCloudIntegrationService
|
||||
err := store.
|
||||
store.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
TableExpr("cloud_integration_service AS cis").
|
||||
ColumnExpr("cis.*").
|
||||
Join("JOIN cloud_integration AS ci ON ci.id = cis.cloud_integration_id").
|
||||
Where("ci.org_id = ?", orgID).
|
||||
Where("ci.provider = ?", provider).
|
||||
Where("ci.removed_at IS NULL").
|
||||
Where("ci.account_id IS NOT NULL").
|
||||
Where("ci.last_agent_report IS NOT NULL").
|
||||
Where("cis.cloud_integration_id != ?", cloudIntegrationID).
|
||||
Where("cis.type IN (?)", ownTypes).
|
||||
Scan(ctx, &services)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[cloudintegrationtypes.ServiceID][]*cloudintegrationtypes.StorableCloudIntegrationService)
|
||||
for _, svc := range services {
|
||||
result[svc.Type] = append(result[svc.Type], svc)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (store *store) CreateService(ctx context.Context, service *cloudintegrationtypes.StorableCloudIntegrationService) error {
|
||||
_, err := store.
|
||||
store.
|
||||
@@ -200,6 +236,24 @@ func (store *store) CreateService(ctx context.Context, service *cloudintegration
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) DeleteServicesByCloudIntegrationID(ctx context.Context, orgID, cloudIntegrationID valuer.UUID) error {
|
||||
cte := store.store.BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
TableExpr("cloud_integration_service AS cis_inner").
|
||||
ColumnExpr("cis_inner.id").
|
||||
Join("JOIN cloud_integration AS ci ON cis_inner.cloud_integration_id = ci.id").
|
||||
Where("ci.org_id = ?", orgID).
|
||||
Where("cis_inner.cloud_integration_id = ?", cloudIntegrationID)
|
||||
|
||||
_, err := store.store.BunDBCtx(ctx).
|
||||
NewDelete().
|
||||
Model(new(cloudintegrationtypes.StorableCloudIntegrationService)).
|
||||
With("target", cte).
|
||||
Where("id IN (SELECT id FROM target)").
|
||||
Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
func (store *store) UpdateService(ctx context.Context, service *cloudintegrationtypes.StorableCloudIntegrationService) error {
|
||||
_, err := store.
|
||||
store.
|
||||
@@ -213,6 +267,62 @@ func (store *store) UpdateService(ctx context.Context, service *cloudintegration
|
||||
return err
|
||||
}
|
||||
|
||||
func (store *store) CreateIntegrationDashboard(ctx context.Context, integrationDashboard *cloudintegrationtypes.StorableIntegrationDashboard) error {
|
||||
_, err := store.store.BunDBCtx(ctx).NewInsert().Model(integrationDashboard).Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
func (store *store) GetIntegrationDashboardBySlug(ctx context.Context, orgID valuer.UUID, provider cloudintegrationtypes.IntegrationDashboardProviderType, slug string) (*cloudintegrationtypes.StorableIntegrationDashboard, error) {
|
||||
integrationDashboard := new(cloudintegrationtypes.StorableIntegrationDashboard)
|
||||
err := store.store.BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(integrationDashboard).
|
||||
Join("JOIN dashboard AS d ON storable_integration_dashboard.dashboard_id = d.id").
|
||||
Where("d.org_id = ?", orgID).
|
||||
Where("storable_integration_dashboard.provider = ?", provider).
|
||||
Where("storable_integration_dashboard.slug = ?", slug).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.store.WrapNotFoundErrf(err, errors.CodeNotFound, "integration dashboard with slug %s not found", slug)
|
||||
}
|
||||
return integrationDashboard, nil
|
||||
}
|
||||
|
||||
func (store *store) ListIntegrationDashboardsBySlugPrefix(ctx context.Context, orgID valuer.UUID, provider cloudintegrationtypes.IntegrationDashboardProviderType, slugPrefix string) ([]*cloudintegrationtypes.StorableIntegrationDashboard, error) {
|
||||
var integrationDashboards []*cloudintegrationtypes.StorableIntegrationDashboard
|
||||
err := store.store.BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(&integrationDashboards).
|
||||
Join("JOIN dashboard AS d ON storable_integration_dashboard.dashboard_id = d.id").
|
||||
Where("d.org_id = ?", orgID).
|
||||
Where("storable_integration_dashboard.provider = ?", provider).
|
||||
Where("storable_integration_dashboard.slug LIKE ?", slugPrefix+"%").
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return integrationDashboards, nil
|
||||
}
|
||||
|
||||
func (store *store) DeleteIntegrationDashboardBySlug(ctx context.Context, orgID valuer.UUID, provider cloudintegrationtypes.IntegrationDashboardProviderType, slug string) error {
|
||||
cte := store.store.BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
TableExpr("integration_dashboard AS id_inner").
|
||||
ColumnExpr("id_inner.id").
|
||||
Join("JOIN dashboard AS d ON id_inner.dashboard_id = d.id").
|
||||
Where("d.org_id = ?", orgID).
|
||||
Where("id_inner.provider = ?", provider).
|
||||
Where("id_inner.slug = ?", slug)
|
||||
|
||||
_, err := store.store.BunDBCtx(ctx).
|
||||
NewDelete().
|
||||
Model(new(cloudintegrationtypes.StorableIntegrationDashboard)).
|
||||
With("target", cte).
|
||||
Where("id IN (SELECT id FROM target)").
|
||||
Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
func (store *store) RunInTx(ctx context.Context, cb func(ctx context.Context) error) error {
|
||||
return store.store.RunInTxCtx(ctx, nil, func(ctx context.Context) error {
|
||||
return cb(ctx)
|
||||
|
||||
@@ -34,7 +34,7 @@ type Module interface {
|
||||
// deletes the public sharing config and disables public sharing for the dashboard
|
||||
DeletePublic(context.Context, valuer.UUID, valuer.UUID) error
|
||||
|
||||
Create(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, data dashboardtypes.PostableDashboard) (*dashboardtypes.Dashboard, error)
|
||||
Create(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, source dashboardtypes.Source, data dashboardtypes.PostableDashboard) (*dashboardtypes.Dashboard, error)
|
||||
|
||||
Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*dashboardtypes.Dashboard, error)
|
||||
|
||||
@@ -46,6 +46,9 @@ type Module interface {
|
||||
|
||||
Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
||||
|
||||
// DeleteUnsafe deletes a dashboard bypassing the guards. Intended for internal system callers.
|
||||
DeleteUnsafe(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
||||
|
||||
GetByMetricNames(ctx context.Context, orgID valuer.UUID, metricNames []string) (map[string][]map[string]string, error)
|
||||
|
||||
statsreporter.StatsCollector
|
||||
|
||||
@@ -60,7 +60,7 @@ func (handler *handler) Create(rw http.ResponseWriter, r *http.Request) {
|
||||
dashboardMigrator.Migrate(ctx, req)
|
||||
}
|
||||
|
||||
dashboard, err := handler.module.Create(ctx, orgID, claims.Email, valuer.MustNewUUID(claims.IdentityID()), req)
|
||||
dashboard, err := handler.module.Create(ctx, orgID, claims.Email, valuer.MustNewUUID(claims.IdentityID()), dashboardtypes.SourceUser, req)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
|
||||
@@ -37,8 +37,8 @@ func NewModule(store dashboardtypes.Store, settings factory.ProviderSettings, an
|
||||
}
|
||||
}
|
||||
|
||||
func (module *module) Create(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, postableDashboard dashboardtypes.PostableDashboard) (*dashboardtypes.Dashboard, error) {
|
||||
dashboard, err := dashboardtypes.NewDashboard(orgID, createdBy, dashboardtypes.SourceUser, postableDashboard)
|
||||
func (module *module) Create(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, source dashboardtypes.Source, postableDashboard dashboardtypes.PostableDashboard) (*dashboardtypes.Dashboard, error) {
|
||||
dashboard, err := dashboardtypes.NewDashboard(orgID, createdBy, source, postableDashboard)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -161,6 +161,10 @@ func (module *module) Delete(ctx context.Context, orgID valuer.UUID, id valuer.U
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *module) DeleteUnsafe(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error {
|
||||
return module.store.Delete(ctx, orgID, id)
|
||||
}
|
||||
|
||||
func (module *module) GetByMetricNames(ctx context.Context, orgID valuer.UUID, metricNames []string) (map[string][]map[string]string, error) {
|
||||
dashboards, err := module.List(ctx, orgID)
|
||||
if err != nil {
|
||||
|
||||
@@ -21,7 +21,7 @@ func NewStore(sqlstore sqlstore.SQLStore) dashboardtypes.Store {
|
||||
func (store *store) Create(ctx context.Context, storabledashboard *dashboardtypes.StorableDashboard) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDB().
|
||||
BunDBCtx(ctx).
|
||||
NewInsert().
|
||||
Model(storabledashboard).
|
||||
Exec(ctx)
|
||||
|
||||
@@ -63,7 +63,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/cloudintegrationtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/featuretypes"
|
||||
@@ -1113,20 +1112,7 @@ func (aH *APIHandler) Get(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
dashboard := new(dashboardtypes.Dashboard)
|
||||
|
||||
if _, _, _, err := cloudintegrationtypes.ParseCloudIntegrationDashboardID(id); err == nil {
|
||||
cloudIntegrationDashboard, err := aH.Signoz.Modules.CloudIntegration.GetDashboardByID(ctx, orgID, id)
|
||||
if err != nil && !errorsV2.Ast(err, errorsV2.TypeLicenseUnavailable) {
|
||||
render.Error(rw, errorsV2.Wrapf(err, errorsV2.TypeInternal, errorsV2.CodeInternal, "failed to get dashboard"))
|
||||
return
|
||||
}
|
||||
|
||||
if cloudIntegrationDashboard == nil {
|
||||
render.Error(rw, errorsV2.Newf(errorsV2.TypeNotFound, errorsV2.CodeNotFound, "dashboard not found"))
|
||||
return
|
||||
}
|
||||
|
||||
dashboard = cloudIntegrationDashboard
|
||||
} else if aH.IntegrationsController.IsInstalledIntegrationDashboardID(id) {
|
||||
if aH.IntegrationsController.IsInstalledIntegrationDashboardID(id) {
|
||||
integrationDashboard, apiErr := aH.IntegrationsController.GetInstalledIntegrationDashboardById(ctx, orgID, id)
|
||||
if apiErr != nil {
|
||||
render.Error(rw, errorsV2.Wrapf(apiErr, errorsV2.TypeInternal, errorsV2.CodeInternal, "failed to get dashboard"))
|
||||
@@ -1189,15 +1175,6 @@ func (aH *APIHandler) List(rw http.ResponseWriter, r *http.Request) {
|
||||
dashboards = append(dashboards, installedIntegrationDashboards...)
|
||||
}
|
||||
|
||||
cloudIntegrationDashboards, err := aH.Signoz.Modules.CloudIntegration.ListDashboards(ctx, orgID)
|
||||
if err != nil {
|
||||
if !errors.Ast(err, errorsV2.TypeLicenseUnavailable) {
|
||||
aH.logger.ErrorContext(ctx, "failed to get dashboards for cloud integrations", errors.Attr(err))
|
||||
}
|
||||
} else {
|
||||
dashboards = append(dashboards, cloudIntegrationDashboards...)
|
||||
}
|
||||
|
||||
gettableDashboards, err := dashboardtypes.NewGettableDashboardsFromDashboards(dashboards)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
|
||||
@@ -205,6 +205,7 @@ func NewSQLMigrationProviderFactories(
|
||||
sqlmigration.NewAddRoleCRUDTuplesFactory(sqlstore),
|
||||
sqlmigration.NewAddIntegrationDashboardFactory(sqlstore, sqlschema),
|
||||
sqlmigration.NewAddSourceToDashboardFactory(sqlstore, sqlschema),
|
||||
sqlmigration.NewMigrateCloudIntegrationDashboardsFactory(sqlstore),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ func New(
|
||||
auditorProviderFactories func(licensing.Licensing) factory.NamedMap[factory.ProviderFactory[auditor.Auditor, auditor.Config]],
|
||||
meterReporterProviderFactories func(context.Context, factory.ProviderSettings, flagger.Flagger, licensing.Licensing, telemetrystore.TelemetryStore, retention.Getter, organization.Getter, zeus.Zeus) (factory.NamedMap[factory.ProviderFactory[meterreporter.Reporter, meterreporter.Config]], string),
|
||||
querierHandlerCallback func(factory.ProviderSettings, querier.Querier, analytics.Analytics) querier.Handler,
|
||||
cloudIntegrationCallback func(sqlstore.SQLStore, global.Global, zeus.Zeus, gateway.Gateway, licensing.Licensing, serviceaccount.Module, cloudintegration.Config) (cloudintegration.Module, error),
|
||||
cloudIntegrationCallback func(sqlstore.SQLStore, dashboard.Module, global.Global, zeus.Zeus, gateway.Gateway, licensing.Licensing, serviceaccount.Module, cloudintegration.Config) (cloudintegration.Module, error),
|
||||
rulerProviderFactories func(cache.Cache, alertmanager.Alertmanager, sqlstore.SQLStore, telemetrystore.TelemetryStore, telemetrytypes.MetadataStore, prometheus.Prometheus, organization.Getter, rulestatehistory.Module, querier.Querier, queryparser.QueryParser) factory.NamedMap[factory.ProviderFactory[ruler.Ruler, ruler.Config]],
|
||||
) (*SigNoz, error) {
|
||||
// Initialize instrumentation
|
||||
@@ -458,7 +458,7 @@ func New(
|
||||
|
||||
serviceAccount := implserviceaccount.NewModule(implserviceaccount.NewStore(sqlstore), authz, cache, analytics, providerSettings, config.ServiceAccount)
|
||||
|
||||
cloudIntegrationModule, err := cloudIntegrationCallback(sqlstore, global, zeus, gateway, licensing, serviceAccount, config.CloudIntegration)
|
||||
cloudIntegrationModule, err := cloudIntegrationCallback(sqlstore, dashboard, global, zeus, gateway, licensing, serviceAccount, config.CloudIntegration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
284
pkg/sqlmigration/086_migrate_ci_dashboards.go
Normal file
284
pkg/sqlmigration/086_migrate_ci_dashboards.go
Normal file
@@ -0,0 +1,284 @@
|
||||
package sqlmigration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/migrate"
|
||||
)
|
||||
|
||||
//go:embed 086_migrate_ci_dashboards
|
||||
var cloudIntegrationDashboardFiles embed.FS
|
||||
|
||||
var (
|
||||
cloudProviderAWS = valuer.NewString("aws")
|
||||
cloudProviderAzure = valuer.NewString("azure")
|
||||
integrationSource = valuer.NewString("integration")
|
||||
cloudIntegrationProvider = valuer.NewString("cloud_integration")
|
||||
)
|
||||
|
||||
type migrateCloudIntegrationDashboards struct {
|
||||
sqlstore sqlstore.SQLStore
|
||||
}
|
||||
|
||||
type cloudIntegrationAccountRow struct {
|
||||
bun.BaseModel `bun:"table:cloud_integration"`
|
||||
|
||||
ID string `bun:"id"`
|
||||
OrgID string `bun:"org_id"`
|
||||
Provider string `bun:"provider"`
|
||||
}
|
||||
|
||||
type cloudIntegrationServiceRow struct {
|
||||
bun.BaseModel `bun:"table:cloud_integration_service"`
|
||||
|
||||
Type string `bun:"type"`
|
||||
Config string `bun:"config"`
|
||||
CloudIntegrationID string `bun:"cloud_integration_id"`
|
||||
}
|
||||
|
||||
type cloudIntegrationAWSServiceConfig struct {
|
||||
Metrics *cloudIntegrationMetricsConfig `json:"metrics"`
|
||||
}
|
||||
|
||||
type cloudIntegrationAzureServiceConfig struct {
|
||||
Metrics *cloudIntegrationMetricsConfig `json:"metrics"`
|
||||
}
|
||||
|
||||
type cloudIntegrationMetricsConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type cloudIntegrationDashboardRow struct {
|
||||
bun.BaseModel `bun:"table:dashboard"`
|
||||
|
||||
ID string `bun:"id,pk,type:text"`
|
||||
CreatedAt time.Time `bun:"created_at"`
|
||||
UpdatedAt time.Time `bun:"updated_at"`
|
||||
CreatedBy *string `bun:"created_by,type:text"`
|
||||
UpdatedBy *string `bun:"updated_by,type:text"`
|
||||
Data string `bun:"data,type:text"`
|
||||
Locked bool `bun:"locked"`
|
||||
OrgID string `bun:"org_id,type:text"`
|
||||
Source string `bun:"source,type:text"`
|
||||
}
|
||||
|
||||
type cloudIntegrationAccountMeta struct {
|
||||
orgID string
|
||||
provider string
|
||||
}
|
||||
|
||||
type cloudIntegrationOrgService struct {
|
||||
orgID string
|
||||
provider string
|
||||
serviceID string
|
||||
}
|
||||
|
||||
type integrationDashboardRow struct {
|
||||
bun.BaseModel `bun:"table:integration_dashboard"`
|
||||
|
||||
ID string `bun:"id,pk,type:text"`
|
||||
DashboardID string `bun:"dashboard_id,type:text"`
|
||||
Provider string `bun:"provider,type:text"`
|
||||
Slug string `bun:"slug,type:text"`
|
||||
CreatedAt time.Time `bun:"created_at"`
|
||||
UpdatedAt time.Time `bun:"updated_at"`
|
||||
}
|
||||
|
||||
func NewMigrateCloudIntegrationDashboardsFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] {
|
||||
return factory.NewProviderFactory(
|
||||
// migrate_cloud_integration_dashboards name is intentionally kept short to avoid hitting identifier length limits
|
||||
factory.MustNewName("migrate_ci_dashboards"),
|
||||
func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) {
|
||||
return &migrateCloudIntegrationDashboards{sqlstore: sqlstore}, nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (m *migrateCloudIntegrationDashboards) Register(migrations *migrate.Migrations) error {
|
||||
return migrations.Register(m.Up, m.Down)
|
||||
}
|
||||
|
||||
func (m *migrateCloudIntegrationDashboards) Up(ctx context.Context, db *bun.DB) error {
|
||||
dashboardDefs, err := m.loadDashboardDefs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tx, err := db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
var accounts []*cloudIntegrationAccountRow
|
||||
if err := tx.NewSelect().
|
||||
Model(&accounts).
|
||||
Where("removed_at IS NULL").
|
||||
Where("account_id IS NOT NULL").
|
||||
Scan(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
accountsMap := make(map[string]cloudIntegrationAccountMeta, len(accounts))
|
||||
for _, a := range accounts {
|
||||
accountsMap[a.ID] = cloudIntegrationAccountMeta{orgID: a.OrgID, provider: a.Provider}
|
||||
}
|
||||
|
||||
var services []*cloudIntegrationServiceRow
|
||||
if err := tx.NewSelect().Model(&services).Scan(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
seen := make(map[string]struct{})
|
||||
var toProvision []cloudIntegrationOrgService
|
||||
|
||||
for _, svc := range services {
|
||||
meta, ok := accountsMap[svc.CloudIntegrationID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if !m.isMetricsEnabled(svc.Config, meta.provider) {
|
||||
continue
|
||||
}
|
||||
|
||||
key := fmt.Sprintf("%s|%s|%s", meta.orgID, meta.provider, svc.Type)
|
||||
if _, dup := seen[key]; dup {
|
||||
continue
|
||||
}
|
||||
seen[key] = struct{}{}
|
||||
toProvision = append(toProvision, cloudIntegrationOrgService{
|
||||
orgID: meta.orgID,
|
||||
provider: meta.provider,
|
||||
serviceID: svc.Type,
|
||||
})
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
for _, service := range toProvision {
|
||||
serviceDashboards, ok := dashboardDefs[service.provider][service.serviceID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for dashName, dashboardJSON := range serviceDashboards {
|
||||
slug := fmt.Sprintf("%s-%s-%s", service.provider, service.serviceID, dashName)
|
||||
|
||||
count, err := tx.NewSelect().
|
||||
TableExpr("integration_dashboard AS id").
|
||||
Join("JOIN dashboard AS d ON id.dashboard_id = d.id").
|
||||
Where("d.org_id = ?", service.orgID).
|
||||
Where("id.provider = ?", "cloud_integration").
|
||||
Where("id.slug = ?", slug).
|
||||
Count(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if count > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
dashID := valuer.GenerateUUID().StringValue()
|
||||
|
||||
dashRow := &cloudIntegrationDashboardRow{
|
||||
ID: dashID,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
Data: string(dashboardJSON),
|
||||
Locked: true,
|
||||
OrgID: service.orgID,
|
||||
Source: integrationSource.StringValue(),
|
||||
}
|
||||
if _, err := tx.NewInsert().Model(dashRow).Exec(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
intRow := &integrationDashboardRow{
|
||||
ID: valuer.GenerateUUID().StringValue(),
|
||||
DashboardID: dashID,
|
||||
Provider: cloudIntegrationProvider.StringValue(),
|
||||
Slug: slug,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if _, err := tx.NewInsert().Model(intRow).Exec(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (m *migrateCloudIntegrationDashboards) Down(context.Context, *bun.DB) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *migrateCloudIntegrationDashboards) loadDashboardDefs() (map[string]map[string]map[string]json.RawMessage, error) {
|
||||
result := make(map[string]map[string]map[string]json.RawMessage)
|
||||
|
||||
err := fs.WalkDir(cloudIntegrationDashboardFiles, "086_migrate_ci_dashboards", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() || filepath.Ext(path) != ".json" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// path: 086_cloud_integration_dashboards/{provider}/{service}/{file}.json
|
||||
rel := strings.TrimPrefix(path, "086_migrate_ci_dashboards/")
|
||||
parts := strings.SplitN(rel, "/", 3)
|
||||
if len(parts) != 3 {
|
||||
return nil
|
||||
}
|
||||
provider := parts[0]
|
||||
serviceID := parts[1]
|
||||
dashName := strings.TrimSuffix(parts[2], ".json")
|
||||
|
||||
data, err := cloudIntegrationDashboardFiles.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if result[provider] == nil {
|
||||
result[provider] = make(map[string]map[string]json.RawMessage)
|
||||
}
|
||||
if result[provider][serviceID] == nil {
|
||||
result[provider][serviceID] = make(map[string]json.RawMessage)
|
||||
}
|
||||
result[provider][serviceID][dashName] = json.RawMessage(data)
|
||||
return nil
|
||||
})
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (m *migrateCloudIntegrationDashboards) isMetricsEnabled(configJSON string, provider string) bool {
|
||||
switch provider {
|
||||
case cloudProviderAWS.String():
|
||||
cfg := new(cloudIntegrationAWSServiceConfig)
|
||||
if err := json.Unmarshal([]byte(configJSON), cfg); err != nil {
|
||||
return false
|
||||
}
|
||||
return cfg.Metrics != nil && cfg.Metrics.Enabled
|
||||
case cloudProviderAzure.String():
|
||||
cfg := new(cloudIntegrationAzureServiceConfig)
|
||||
if err := json.Unmarshal([]byte(configJSON), cfg); err != nil {
|
||||
return false
|
||||
}
|
||||
return cfg.Metrics != nil && cfg.Metrics.Enabled
|
||||
}
|
||||
return false
|
||||
}
|
||||
1887
pkg/sqlmigration/086_migrate_ci_dashboards/aws/alb/overview.json
Normal file
1887
pkg/sqlmigration/086_migrate_ci_dashboards/aws/alb/overview.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
1446
pkg/sqlmigration/086_migrate_ci_dashboards/aws/ec2/overview.json
Normal file
1446
pkg/sqlmigration/086_migrate_ci_dashboards/aws/ec2/overview.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
851
pkg/sqlmigration/086_migrate_ci_dashboards/aws/ecs/overview.json
Normal file
851
pkg/sqlmigration/086_migrate_ci_dashboards/aws/ecs/overview.json
Normal file
@@ -0,0 +1,851 @@
|
||||
{
|
||||
"description": "View key AWS ECS metrics with an out of the box dashboard.\n",
|
||||
"image":"data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20width%3D%2280px%22%20height%3D%2280px%22%20viewBox%3D%220%200%2080%2080%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%3C!--%20Generator%3A%20Sketch%2064%20(93537)%20-%20https%3A%2F%2Fsketch.com%20--%3E%3Ctitle%3EIcon-Architecture%2F64%2FArch_Amazon-Elastic-Container-Service_64%3C%2Ftitle%3E%3Cdesc%3ECreated%20with%20Sketch.%3C%2Fdesc%3E%3Cdefs%3E%3ClinearGradient%20x1%3D%220%25%22%20y1%3D%22100%25%22%20x2%3D%22100%25%22%20y2%3D%220%25%22%20id%3D%22linearGradient-1%22%3E%3Cstop%20stop-color%3D%22%23C8511B%22%20offset%3D%220%25%22%3E%3C%2Fstop%3E%3Cstop%20stop-color%3D%22%23FF9900%22%20offset%3D%22100%25%22%3E%3C%2Fstop%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Cg%20id%3D%22Icon-Architecture%2F64%2FArch_Amazon-Elastic-Container-Service_64%22%20stroke%3D%22none%22%20stroke-width%3D%221%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cg%20id%3D%22Icon-Architecture-BG%2F64%2FContainers%22%20fill%3D%22url(%23linearGradient-1)%22%3E%3Crect%20id%3D%22Rectangle%22%20x%3D%220%22%20y%3D%220%22%20width%3D%2280%22%20height%3D%2280%22%3E%3C%2Frect%3E%3C%2Fg%3E%3Cpath%20d%3D%22M64%2C48.2340095%20L56%2C43.4330117%20L56%2C32.0000169%20C56%2C31.6440171%2055.812%2C31.3150172%2055.504%2C31.1360173%20L44%2C24.4260204%20L44%2C14.7520248%20L64%2C26.5710194%20L64%2C48.2340095%20Z%20M65.509%2C25.13902%20L43.509%2C12.139026%20C43.199%2C11.9560261%2042.818%2C11.9540261%2042.504%2C12.131026%20C42.193%2C12.3090259%2042%2C12.6410257%2042%2C13.0000256%20L42%2C25.0000201%20C42%2C25.3550199%2042.189%2C25.6840198%2042.496%2C25.8640197%20L54%2C32.5740166%20L54%2C44.0000114%20C54%2C44.3510113%2054.185%2C44.6770111%2054.486%2C44.857011%20L64.486%2C50.8570083%20C64.644%2C50.9520082%2064.822%2C51%2065%2C51%20C65.17%2C51%2065.34%2C50.9570082%2065.493%2C50.8700083%20C65.807%2C50.6930084%2066%2C50.3600085%2066%2C50%20L66%2C26.0000196%20C66%2C25.6460198%2065.814%2C25.31902%2065.509%2C25.13902%20L65.509%2C25.13902%20Z%20M40.445%2C66.863001%20L17%2C54.3990067%20L17%2C26.5710194%20L37%2C14.7520248%20L37%2C24.4510204%20L26.463%2C31.1560173%20C26.175%2C31.3400172%2026%2C31.6580171%2026%2C32.0000169%20L26%2C49.0000091%20C26%2C49.373009%2026.208%2C49.7150088%2026.538%2C49.8870087%20L39.991%2C56.8870055%20C40.28%2C57.0370055%2040.624%2C57.0380055%2040.912%2C56.8880055%20L53.964%2C50.1440086%20L61.996%2C54.9640064%20L40.445%2C66.863001%20Z%20M64.515%2C54.1420068%20L54.515%2C48.1420095%20C54.217%2C47.9640096%2053.849%2C47.9520096%2053.541%2C48.1120095%20L40.455%2C54.8730065%20L28%2C48.3930094%20L28%2C32.5490167%20L38.537%2C25.8440197%20C38.825%2C25.6600198%2039%2C25.3420199%2039%2C25.0000201%20L39%2C13.0000256%20C39%2C12.6410257%2038.808%2C12.3090259%2038.496%2C12.131026%20C38.184%2C11.9540261%2037.802%2C11.9560261%2037.491%2C12.139026%20L15.491%2C25.13902%20C15.187%2C25.31902%2015%2C25.6460198%2015%2C26.0000196%20L15%2C55%20C15%2C55.3690062%2015.204%2C55.7090061%2015.53%2C55.883006%20L39.984%2C68.8830001%20C40.131%2C68.961%2040.292%2C69%2040.453%2C69%20C40.62%2C69%2040.786%2C68.958%2040.937%2C68.8750001%20L64.484%2C55.875006%20C64.797%2C55.7020061%2064.993%2C55.3750062%2065.0001416%2C55.0180064%20C65.006%2C54.6600066%2064.821%2C54.3260067%2064.515%2C54.1420068%20L64.515%2C54.1420068%20Z%22%20id%3D%22Amazon-Elastic-Container-Service_Icon_64_Squid%22%20fill%3D%22%23FFFFFF%22%3E%3C%2Fpath%3E%3C%2Fg%3E%3C%2Fsvg%3E",
|
||||
"layout": [
|
||||
{
|
||||
"h": 6,
|
||||
"i": "f78becf8-0328-48b4-84b6-ff4dac325940",
|
||||
"moved": false,
|
||||
"static": false,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"h": 6,
|
||||
"i": "2b4eac06-b426-4f78-b874-2e1734c4104b",
|
||||
"moved": false,
|
||||
"static": false,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"h": 6,
|
||||
"i": "5bea2bc0-13a2-4937-bccb-60ffe8a43ad5",
|
||||
"moved": false,
|
||||
"static": false,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"h": 6,
|
||||
"i": "6fac67b0-50ec-4b43-ac4b-320a303d0369",
|
||||
"moved": false,
|
||||
"static": false,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 6
|
||||
}
|
||||
],
|
||||
"panelMap": {},
|
||||
"tags": [],
|
||||
"title": "AWS ECS Overview",
|
||||
"uploadedGrafana": false,
|
||||
"variables": {
|
||||
"51f4fa2b-89c7-47c2-9795-f32cffaab985": {
|
||||
"allSelected": false,
|
||||
"customValue": "",
|
||||
"description": "AWS Account ID",
|
||||
"id": "51f4fa2b-89c7-47c2-9795-f32cffaab985",
|
||||
"key": "51f4fa2b-89c7-47c2-9795-f32cffaab985",
|
||||
"modificationUUID": "7b814d17-8fff-4ed6-a4ea-90e3b1a97584",
|
||||
"multiSelect": false,
|
||||
"name": "Account",
|
||||
"order": 0,
|
||||
"queryValue": "SELECT DISTINCT JSONExtractString(labels, 'cloud.account.id') AS `cloud.account.id`\nFROM signoz_metrics.distributed_time_series_v4_1day\nWHERE metric_name = 'aws_ECS_MemoryUtilization_max' GROUP BY `cloud.account.id`",
|
||||
"showALLOption": false,
|
||||
"sort": "DISABLED",
|
||||
"textboxValue": "",
|
||||
"type": "QUERY"
|
||||
},
|
||||
"9faf0f4b-b245-4b3c-83a3-60cfa76dfeb0": {
|
||||
"allSelected": false,
|
||||
"customValue": "",
|
||||
"description": "Account Region",
|
||||
"id": "9faf0f4b-b245-4b3c-83a3-60cfa76dfeb0",
|
||||
"key": "9faf0f4b-b245-4b3c-83a3-60cfa76dfeb0",
|
||||
"modificationUUID": "3b5f499b-22a3-4c8a-847c-8d3811c9e6b2",
|
||||
"multiSelect": false,
|
||||
"name": "Region",
|
||||
"order": 1,
|
||||
"queryValue": "SELECT DISTINCT JSONExtractString(labels, 'cloud.region') AS region\nFROM signoz_metrics.distributed_time_series_v4_1day\nWHERE metric_name = 'aws_ECS_MemoryUtilization_max' AND JSONExtractString(labels, 'cloud.account.id') IN {{.Account}} GROUP BY region",
|
||||
"showALLOption": false,
|
||||
"sort": "ASC",
|
||||
"textboxValue": "",
|
||||
"type": "QUERY"
|
||||
},
|
||||
"bfbdbcbe-a168-4d81-b108-36339e249116": {
|
||||
"allSelected": true,
|
||||
"customValue": "",
|
||||
"description": "ECS Cluster Name",
|
||||
"id": "bfbdbcbe-a168-4d81-b108-36339e249116",
|
||||
"key": "bfbdbcbe-a168-4d81-b108-36339e249116",
|
||||
"modificationUUID": "9fb0d63c-ac6c-497d-82b3-17d95944e245",
|
||||
"multiSelect": true,
|
||||
"name": "Cluster",
|
||||
"order": 2,
|
||||
"queryValue": "SELECT DISTINCT JSONExtractString(labels, 'ClusterName') AS cluster\nFROM signoz_metrics.distributed_time_series_v4_1day\nWHERE metric_name = 'aws_ECS_MemoryUtilization_max' AND JSONExtractString(labels, 'cloud.account.id') IN {{.Account}} AND JSONExtractString(labels, 'cloud.region') IN {{.Region}}\nGROUP BY cluster",
|
||||
"showALLOption": true,
|
||||
"sort": "ASC",
|
||||
"textboxValue": "",
|
||||
"type": "QUERY"
|
||||
}
|
||||
},
|
||||
"version": "v4",
|
||||
"widgets": [
|
||||
{
|
||||
"bucketCount": 30,
|
||||
"bucketWidth": 0,
|
||||
"columnUnits": {},
|
||||
"description": "",
|
||||
"fillSpans": false,
|
||||
"id": "f78becf8-0328-48b4-84b6-ff4dac325940",
|
||||
"isLogScale": false,
|
||||
"isStacked": false,
|
||||
"mergeAllActiveQueries": false,
|
||||
"nullZeroValues": "zero",
|
||||
"opacity": "1",
|
||||
"panelTypes": "graph",
|
||||
"query": {
|
||||
"builder": {
|
||||
"queryData": [
|
||||
{
|
||||
"aggregateAttribute": {
|
||||
"dataType": "float64",
|
||||
"id": "aws_ECS_MemoryUtilization_max--float64--Gauge--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "aws_ECS_MemoryUtilization_max",
|
||||
"type": "Gauge"
|
||||
},
|
||||
"aggregateOperator": "max",
|
||||
"dataSource": "metrics",
|
||||
"disabled": false,
|
||||
"expression": "A",
|
||||
"filters": {
|
||||
"items": [
|
||||
{
|
||||
"id": "26ac617d",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.region--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.region",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Region"
|
||||
},
|
||||
{
|
||||
"id": "57172ed9",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.account.id--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.account.id",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Account"
|
||||
},
|
||||
{
|
||||
"id": "49b9f85e",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "ClusterName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ClusterName",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "in",
|
||||
"value": [
|
||||
"$Cluster"
|
||||
]
|
||||
}
|
||||
],
|
||||
"op": "AND"
|
||||
},
|
||||
"functions": [],
|
||||
"groupBy": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "ServiceName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ServiceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "ClusterName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ClusterName",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"having": [],
|
||||
"legend": "{{ServiceName}} ({{ClusterName}})",
|
||||
"limit": null,
|
||||
"orderBy": [],
|
||||
"queryName": "A",
|
||||
"reduceTo": "avg",
|
||||
"spaceAggregation": "max",
|
||||
"stepInterval": 60,
|
||||
"timeAggregation": "max"
|
||||
}
|
||||
],
|
||||
"queryFormulas": []
|
||||
},
|
||||
"clickhouse_sql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"id": "56068fdd-d523-4117-92fa-87c6518ad07c",
|
||||
"promql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"queryType": "builder"
|
||||
},
|
||||
"selectedLogFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "body",
|
||||
"type": ""
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "timestamp",
|
||||
"type": ""
|
||||
}
|
||||
],
|
||||
"selectedTracesFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "serviceName--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "serviceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "name--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "name",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "float64",
|
||||
"id": "durationNano--float64--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "durationNano",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "httpMethod--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "httpMethod",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "responseStatusCode--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "responseStatusCode",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"softMax": 0,
|
||||
"softMin": 0,
|
||||
"stackedBarChart": false,
|
||||
"thresholds": [],
|
||||
"timePreferance": "GLOBAL_TIME",
|
||||
"title": "Maximum Memory Utilization",
|
||||
"yAxisUnit": "none"
|
||||
},
|
||||
{
|
||||
"bucketCount": 30,
|
||||
"bucketWidth": 0,
|
||||
"columnUnits": {},
|
||||
"description": "",
|
||||
"fillSpans": false,
|
||||
"id": "2b4eac06-b426-4f78-b874-2e1734c4104b",
|
||||
"isLogScale": false,
|
||||
"isStacked": false,
|
||||
"mergeAllActiveQueries": false,
|
||||
"nullZeroValues": "zero",
|
||||
"opacity": "1",
|
||||
"panelTypes": "graph",
|
||||
"query": {
|
||||
"builder": {
|
||||
"queryData": [
|
||||
{
|
||||
"aggregateAttribute": {
|
||||
"dataType": "float64",
|
||||
"id": "aws_ECS_MemoryUtilization_min--float64--Gauge--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "aws_ECS_MemoryUtilization_min",
|
||||
"type": "Gauge"
|
||||
},
|
||||
"aggregateOperator": "min",
|
||||
"dataSource": "metrics",
|
||||
"disabled": false,
|
||||
"expression": "A",
|
||||
"filters": {
|
||||
"items": [
|
||||
{
|
||||
"id": "cd4b8848",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.region--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.region",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Region"
|
||||
},
|
||||
{
|
||||
"id": "aa5115c6",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.account.id--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.account.id",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Account"
|
||||
},
|
||||
{
|
||||
"id": "f60677b6",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "ClusterName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ClusterName",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "in",
|
||||
"value": [
|
||||
"$Cluster"
|
||||
]
|
||||
}
|
||||
],
|
||||
"op": "AND"
|
||||
},
|
||||
"functions": [],
|
||||
"groupBy": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "ServiceName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ServiceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "ClusterName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ClusterName",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"having": [],
|
||||
"legend": "{{ServiceName}} ({{ClusterName}})",
|
||||
"limit": null,
|
||||
"orderBy": [],
|
||||
"queryName": "A",
|
||||
"reduceTo": "avg",
|
||||
"spaceAggregation": "min",
|
||||
"stepInterval": 60,
|
||||
"timeAggregation": "min"
|
||||
}
|
||||
],
|
||||
"queryFormulas": []
|
||||
},
|
||||
"clickhouse_sql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"id": "fb19342e-cbde-40d8-b12f-ad108698356b",
|
||||
"promql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"queryType": "builder"
|
||||
},
|
||||
"selectedLogFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "body",
|
||||
"type": ""
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "timestamp",
|
||||
"type": ""
|
||||
}
|
||||
],
|
||||
"selectedTracesFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "serviceName--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "serviceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "name--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "name",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "float64",
|
||||
"id": "durationNano--float64--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "durationNano",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "httpMethod--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "httpMethod",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "responseStatusCode--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "responseStatusCode",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"softMax": 0,
|
||||
"softMin": 0,
|
||||
"stackedBarChart": false,
|
||||
"thresholds": [],
|
||||
"timePreferance": "GLOBAL_TIME",
|
||||
"title": "Minimum Memory Utilization",
|
||||
"yAxisUnit": "none"
|
||||
},
|
||||
{
|
||||
"bucketCount": 30,
|
||||
"bucketWidth": 0,
|
||||
"columnUnits": {},
|
||||
"description": "",
|
||||
"fillSpans": false,
|
||||
"id": "5bea2bc0-13a2-4937-bccb-60ffe8a43ad5",
|
||||
"isLogScale": false,
|
||||
"isStacked": false,
|
||||
"mergeAllActiveQueries": false,
|
||||
"nullZeroValues": "zero",
|
||||
"opacity": "1",
|
||||
"panelTypes": "graph",
|
||||
"query": {
|
||||
"builder": {
|
||||
"queryData": [
|
||||
{
|
||||
"aggregateAttribute": {
|
||||
"dataType": "float64",
|
||||
"id": "aws_ECS_CPUUtilization_max--float64--Gauge--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "aws_ECS_CPUUtilization_max",
|
||||
"type": "Gauge"
|
||||
},
|
||||
"aggregateOperator": "max",
|
||||
"dataSource": "metrics",
|
||||
"disabled": false,
|
||||
"expression": "A",
|
||||
"filters": {
|
||||
"items": [
|
||||
{
|
||||
"id": "2c13c8ee",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.region--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.region",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Region"
|
||||
},
|
||||
{
|
||||
"id": "f489f6a8",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.account.id--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.account.id",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Account"
|
||||
},
|
||||
{
|
||||
"id": "94012320",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "ClusterName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ClusterName",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "in",
|
||||
"value": [
|
||||
"$Cluster"
|
||||
]
|
||||
}
|
||||
],
|
||||
"op": "AND"
|
||||
},
|
||||
"functions": [],
|
||||
"groupBy": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "ServiceName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ServiceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "ClusterName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ClusterName",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"having": [],
|
||||
"legend": "{{ServiceName}} ({{ClusterName}})",
|
||||
"limit": null,
|
||||
"orderBy": [],
|
||||
"queryName": "A",
|
||||
"reduceTo": "avg",
|
||||
"spaceAggregation": "max",
|
||||
"stepInterval": 60,
|
||||
"timeAggregation": "max"
|
||||
}
|
||||
],
|
||||
"queryFormulas": []
|
||||
},
|
||||
"clickhouse_sql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"id": "273e0a76-c780-4b9a-9b03-2649d4227173",
|
||||
"promql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"queryType": "builder"
|
||||
},
|
||||
"selectedLogFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "body",
|
||||
"type": ""
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "timestamp",
|
||||
"type": ""
|
||||
}
|
||||
],
|
||||
"selectedTracesFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "serviceName--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "serviceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "name--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "name",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "float64",
|
||||
"id": "durationNano--float64--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "durationNano",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "httpMethod--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "httpMethod",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "responseStatusCode--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "responseStatusCode",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"softMax": 0,
|
||||
"softMin": 0,
|
||||
"stackedBarChart": false,
|
||||
"thresholds": [],
|
||||
"timePreferance": "GLOBAL_TIME",
|
||||
"title": "Maximum CPU Utilization",
|
||||
"yAxisUnit": "none"
|
||||
},
|
||||
{
|
||||
"bucketCount": 30,
|
||||
"bucketWidth": 0,
|
||||
"columnUnits": {},
|
||||
"description": "",
|
||||
"fillSpans": false,
|
||||
"id": "6fac67b0-50ec-4b43-ac4b-320a303d0369",
|
||||
"isLogScale": false,
|
||||
"isStacked": false,
|
||||
"mergeAllActiveQueries": false,
|
||||
"nullZeroValues": "zero",
|
||||
"opacity": "1",
|
||||
"panelTypes": "graph",
|
||||
"query": {
|
||||
"builder": {
|
||||
"queryData": [
|
||||
{
|
||||
"aggregateAttribute": {
|
||||
"dataType": "float64",
|
||||
"id": "aws_ECS_CPUUtilization_min--float64--Gauge--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "aws_ECS_CPUUtilization_min",
|
||||
"type": "Gauge"
|
||||
},
|
||||
"aggregateOperator": "min",
|
||||
"dataSource": "metrics",
|
||||
"disabled": false,
|
||||
"expression": "A",
|
||||
"filters": {
|
||||
"items": [
|
||||
{
|
||||
"id": "758ba906",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.region--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.region",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Region"
|
||||
},
|
||||
{
|
||||
"id": "4ffe6bf7",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.account.id--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.account.id",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Account"
|
||||
},
|
||||
{
|
||||
"id": "53d98059",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "ClusterName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ClusterName",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "in",
|
||||
"value": [
|
||||
"$Cluster"
|
||||
]
|
||||
}
|
||||
],
|
||||
"op": "AND"
|
||||
},
|
||||
"functions": [],
|
||||
"groupBy": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "ServiceName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ServiceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "ClusterName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "ClusterName",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"having": [],
|
||||
"legend": "{{ServiceName}} ({{ClusterName}})",
|
||||
"limit": null,
|
||||
"orderBy": [],
|
||||
"queryName": "A",
|
||||
"reduceTo": "avg",
|
||||
"spaceAggregation": "min",
|
||||
"stepInterval": 60,
|
||||
"timeAggregation": "min"
|
||||
}
|
||||
],
|
||||
"queryFormulas": []
|
||||
},
|
||||
"clickhouse_sql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"id": "c89482b3-5a98-4e2c-be0d-ef036d7dac05",
|
||||
"promql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"queryType": "builder"
|
||||
},
|
||||
"selectedLogFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "body",
|
||||
"type": ""
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "timestamp",
|
||||
"type": ""
|
||||
}
|
||||
],
|
||||
"selectedTracesFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "serviceName--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "serviceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "name--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "name",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "float64",
|
||||
"id": "durationNano--float64--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "durationNano",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "httpMethod--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "httpMethod",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "responseStatusCode--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "responseStatusCode",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"softMax": 0,
|
||||
"softMin": 0,
|
||||
"stackedBarChart": false,
|
||||
"thresholds": [],
|
||||
"timePreferance": "GLOBAL_TIME",
|
||||
"title": "Minimum CPU Utilization",
|
||||
"yAxisUnit": "none"
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
1748
pkg/sqlmigration/086_migrate_ci_dashboards/aws/eks/overview.json
Normal file
1748
pkg/sqlmigration/086_migrate_ci_dashboards/aws/eks/overview.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1547
pkg/sqlmigration/086_migrate_ci_dashboards/aws/lambda/overview.json
Normal file
1547
pkg/sqlmigration/086_migrate_ci_dashboards/aws/lambda/overview.json
Normal file
File diff suppressed because it is too large
Load Diff
1189
pkg/sqlmigration/086_migrate_ci_dashboards/aws/msk/overview.json
Normal file
1189
pkg/sqlmigration/086_migrate_ci_dashboards/aws/msk/overview.json
Normal file
File diff suppressed because one or more lines are too long
1945
pkg/sqlmigration/086_migrate_ci_dashboards/aws/rds/overview.json
Normal file
1945
pkg/sqlmigration/086_migrate_ci_dashboards/aws/rds/overview.json
Normal file
File diff suppressed because it is too large
Load Diff
818
pkg/sqlmigration/086_migrate_ci_dashboards/aws/sns/overview.json
Normal file
818
pkg/sqlmigration/086_migrate_ci_dashboards/aws/sns/overview.json
Normal file
@@ -0,0 +1,818 @@
|
||||
{
|
||||
"description": "View key AWS SNS metrics with an out of the box dashboard.",
|
||||
"image": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iODBweCIgaGVpZ2h0PSI4MHB4IiB2aWV3Qm94PSIwIDAgODAgODAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDY0ICg5MzUzNykgLSBodHRwczovL3NrZXRjaC5jb20gLS0+CiAgICA8dGl0bGU+SWNvbi1BcmNoaXRlY3R1cmUvNjQvQXJjaF9BV1MtU2ltcGxlLU5vdGlmaWNhdGlvbi1TZXJ2aWNlXzY0PC90aXRsZT4KICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPgogICAgPGRlZnM+CiAgICAgICAgPGxpbmVhckdyYWRpZW50IHgxPSIwJSIgeTE9IjEwMCUiIHgyPSIxMDAlIiB5Mj0iMCUiIGlkPSJsaW5lYXJHcmFkaWVudC0xIj4KICAgICAgICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iI0IwMDg0RCIgb2Zmc2V0PSIwJSI+PC9zdG9wPgogICAgICAgICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjRkY0RjhCIiBvZmZzZXQ9IjEwMCUiPjwvc3RvcD4KICAgICAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPC9kZWZzPgogICAgPGcgaWQ9Ikljb24tQXJjaGl0ZWN0dXJlLzY0L0FyY2hfQVdTLVNpbXBsZS1Ob3RpZmljYXRpb24tU2VydmljZV82NCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPGcgaWQ9Ikljb24tQXJjaGl0ZWN0dXJlLUJHLzY0L0FwcGxpY2F0aW9uLUludGVncmF0aW9uIiBmaWxsPSJ1cmwoI2xpbmVhckdyYWRpZW50LTEpIj4KICAgICAgICAgICAgPHJlY3QgaWQ9IlJlY3RhbmdsZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjgwIj48L3JlY3Q+CiAgICAgICAgPC9nPgogICAgICAgIDxwYXRoIGQ9Ik0xNywzOCBDMTguMTAzLDM4IDE5LDM4Ljg5NyAxOSw0MCBDMTksNDEuMTAzIDE4LjEwMyw0MiAxNyw0MiBDMTUuODk3LDQyIDE1LDQxLjEwMyAxNSw0MCBDMTUsMzguODk3IDE1Ljg5NywzOCAxNywzOCBMMTcsMzggWiBNNDEsNjQgQzI5LjMxNCw2NCAxOS4yODksNTUuNDY2IDE3LjE5NCw0My45OCBDMTguOTY1LDQzLjg5NCAyMC40MjcsNDIuNjU5IDIwLjg1Nyw0MSBMMjcsNDEgTDI3LDM5IEwyMC44NTcsMzkgQzIwLjQyNywzNy4zNDIgMTguOTY2LDM2LjEwNyAxNy4xOTUsMzYuMDIgQzE5LjI4NSwyNC43MSAyOS41MTEsMTYgNDEsMTYgQzQ1LjMxMywxNiA0OS44MzIsMTcuNjIyIDU0LjQyOSwyMC44MjEgTDU1LjU3MSwxOS4xNzkgQzUwLjYzMywxNS43NDMgNDUuNzMsMTQgNDEsMTQgQzI4LjI3LDE0IDE2Ljk0OSwyMy44NjUgMTUuMDYzLDM2LjUyMSBDMTMuODM5LDM3LjIwNyAxMywzOC41IDEzLDQwIEMxMyw0MS41IDEzLjgzOSw0Mi43OTMgMTUuMDYzLDQzLjQ3OCBDMTYuOTcsNTYuMzQxIDI4LjA1Niw2NiA0MSw2NiBDNDYuNDA3LDY2IDUxLjk0Miw2NC4xNTcgNTYuNTg1LDYwLjgxMSBMNTUuNDE1LDU5LjE4OSBDNTEuMTEsNjIuMjkyIDQ1Ljk5MSw2NCA0MSw2NCBMNDEsNjQgWiBNMzAuMTAxLDM2LjQ0MiBDMzEuOTU1LDM2Ljg5NSAzNC4yNzUsMzcgMzYsMzcgQzM3LjY0MiwzNyAzOS44MjMsMzYuOTA1IDQxLjYyOSwzNi41MDYgTDM3LjEwNSw0NS41NTMgQzM3LjAzNiw0NS42OTEgMzcsNDUuODQ1IDM3LDQ2IEwzNyw1MC40NTMgQzM2LjE5OSw1MC45NjQgMzQuODMzLDUxLjgxMiAzNCw1MS45ODYgTDM0LDQ2IEMzNCw0NS44NjggMzMuOTc0LDQ1LjczNyAzMy45MjMsNDUuNjE1IEwzMC4xMDEsMzYuNDQyIFogTTM2LDMzIEM0MC4wMjUsMzMgNDIuMTc0LDMzLjYwNCA0Mi44NDEsMzQgQzQyLjE3NCwzNC4zOTYgNDAuMDI1LDM1IDM2LDM1IEMzMS45NzUsMzUgMjkuODI2LDM0LjM5NiAyOS4xNTksMzQgQzI5LjgyNiwzMy42MDQgMzEuOTc1LDMzIDM2LDMzIEwzNiwzMyBaIE0zMyw1NCBMMzQsNTQgQzM0LjA0Myw1NCAzNC4wODYsNTMuOTk3IDM0LjEyOCw1My45OTIgQzM1LjM1Miw1My44MzMgMzYuOTA5LDUyLjg4NyAzOC4yNzIsNTIuMDEzIEwzOC41MzUsNTEuODQ1IEMzOC44MjQsNTEuNjYxIDM5LDUxLjM0MiAzOSw1MSBMMzksNDYuMjM2IEw0NC41NTksMzUuMTIgQzQ0LjgzMywzNC44MDEgNDUsMzQuNDM0IDQ1LDM0IEM0NSwzMS4zOSAzOS4zNjEsMzEgMzYsMzEgQzMyLjYzOSwzMSAyNywzMS4zOSAyNywzNCBDMjcsMzQuMzY2IDI3LjEyLDM0LjY4NCAyNy4zMiwzNC45NjcgTDMyLDQ2LjIgTDMyLDUzIEMzMiw1My41NTIgMzIuNDQ3LDU0IDMzLDU0IEwzMyw1NCBaIE02Miw1MyBDNjMuMTAzLDUzIDY0LDUzLjg5NyA2NCw1NSBDNjQsNTYuMTAzIDYzLjEwMyw1NyA2Miw1NyBDNjAuODk3LDU3IDYwLDU2LjEwMyA2MCw1NSBDNjAsNTMuODk3IDYwLjg5Nyw1MyA2Miw1MyBMNjIsNTMgWiBNNjIsMjMgQzYzLjEwMywyMyA2NCwyMy44OTcgNjQsMjUgQzY0LDI2LjEwMyA2My4xMDMsMjcgNjIsMjcgQzYwLjg5NywyNyA2MCwyNi4xMDMgNjAsMjUgQzYwLDIzLjg5NyA2MC44OTcsMjMgNjIsMjMgTDYyLDIzIFogTTY0LDM4IEM2NS4xMDMsMzggNjYsMzguODk3IDY2LDQwIEM2Niw0MS4xMDMgNjUuMTAzLDQyIDY0LDQyIEM2Mi44OTcsNDIgNjIsNDEuMTAzIDYyLDQwIEM2MiwzOC44OTcgNjIuODk3LDM4IDY0LDM4IEw2NCwzOCBaIE01NCw0MSBMNjAuMTQzLDQxIEM2MC41ODksNDIuNzIgNjIuMTQyLDQ0IDY0LDQ0IEM2Ni4yMDYsNDQgNjgsNDIuMjA2IDY4LDQwIEM2OCwzNy43OTQgNjYuMjA2LDM2IDY0LDM2IEM2Mi4xNDIsMzYgNjAuNTg5LDM3LjI4IDYwLjE0MywzOSBMNTQsMzkgTDU0LDI2IEw1OC4xNDMsMjYgQzU4LjU4OSwyNy43MiA2MC4xNDIsMjkgNjIsMjkgQzY0LjIwNiwyOSA2NiwyNy4yMDYgNjYsMjUgQzY2LDIyLjc5NCA2NC4yMDYsMjEgNjIsMjEgQzYwLjE0MiwyMSA1OC41ODksMjIuMjggNTguMTQzLDI0IEw1MywyNCBDNTIuNDQ3LDI0IDUyLDI0LjQ0OCA1MiwyNSBMNTIsMzkgTDQ1LDM5IEw0NSw0MSBMNTIsNDEgTDUyLDU1IEM1Miw1NS41NTIgNTIuNDQ3LDU2IDUzLDU2IEw1OC4xNDMsNTYgQzU4LjU4OSw1Ny43MiA2MC4xNDIsNTkgNjIsNTkgQzY0LjIwNiw1OSA2Niw1Ny4yMDYgNjYsNTUgQzY2LDUyLjc5NCA2NC4yMDYsNTEgNjIsNTEgQzYwLjE0Miw1MSA1OC41ODksNTIuMjggNTguMTQzLDU0IEw1NCw1NCBMNTQsNDEgWiIgaWQ9IkFXUy1TaW1wbGUtTm90aWZpY2F0aW9uLVNlcnZpY2VfSWNvbl82NF9TcXVpZCIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgPC9nPgo8L3N2Zz4=",
|
||||
"layout": [
|
||||
{
|
||||
"h": 6,
|
||||
"i": "4eb87f89-0213-4773-9b06-6aecc6701898",
|
||||
"moved": false,
|
||||
"static": false,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"h": 6,
|
||||
"i": "7a010b4e-ea7c-4a45-a9eb-93af650c45b4",
|
||||
"moved": false,
|
||||
"static": false,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"h": 6,
|
||||
"i": "2299d4e3-6c40-4bf2-a550-c7bb8a7acd38",
|
||||
"moved": false,
|
||||
"static": false,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"h": 6,
|
||||
"i": "16eec8b7-de1a-4039-b180-24c7a6704b6e",
|
||||
"moved": false,
|
||||
"static": false,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 6
|
||||
}
|
||||
],
|
||||
"panelMap": {},
|
||||
"tags": [],
|
||||
"title": "SNS Overview",
|
||||
"uploadedGrafana": false,
|
||||
"variables": {
|
||||
"51f4fa2b-89c7-47c2-9795-f32cffaab985": {
|
||||
"allSelected": false,
|
||||
"customValue": "",
|
||||
"description": "AWS Account ID",
|
||||
"id": "51f4fa2b-89c7-47c2-9795-f32cffaab985",
|
||||
"key": "51f4fa2b-89c7-47c2-9795-f32cffaab985",
|
||||
"modificationUUID": "b7a6b06b-fa1f-4fb8-b70e-6bd9b350f29e",
|
||||
"multiSelect": false,
|
||||
"name": "Account",
|
||||
"order": 0,
|
||||
"queryValue": "SELECT DISTINCT JSONExtractString(labels, 'cloud.account.id') AS `cloud.account.id`\nFROM signoz_metrics.distributed_time_series_v4_1day\nWHERE metric_name = 'aws_SNS_PublishSize_count' GROUP BY `cloud.account.id`",
|
||||
"showALLOption": false,
|
||||
"sort": "DISABLED",
|
||||
"textboxValue": "",
|
||||
"type": "QUERY"
|
||||
},
|
||||
"9faf0f4b-b245-4b3c-83a3-60cfa76dfeb0": {
|
||||
"allSelected": false,
|
||||
"customValue": "",
|
||||
"description": "Account Region",
|
||||
"id": "9faf0f4b-b245-4b3c-83a3-60cfa76dfeb0",
|
||||
"key": "9faf0f4b-b245-4b3c-83a3-60cfa76dfeb0",
|
||||
"modificationUUID": "8428a5de-bfd1-4a69-9601-63e3041cd556",
|
||||
"multiSelect": false,
|
||||
"name": "Region",
|
||||
"order": 1,
|
||||
"queryValue": "SELECT DISTINCT JSONExtractString(labels, 'cloud.region') AS region\nFROM signoz_metrics.distributed_time_series_v4_1day\nWHERE metric_name = 'aws_SNS_PublishSize_count' AND JSONExtractString(labels, 'cloud.account.id') IN {{.Account}} GROUP BY region",
|
||||
"showALLOption": false,
|
||||
"sort": "ASC",
|
||||
"textboxValue": "",
|
||||
"type": "QUERY"
|
||||
},
|
||||
"bfbdbcbe-a168-4d81-b108-36339e249116": {
|
||||
"allSelected": true,
|
||||
"customValue": "",
|
||||
"description": "SNS Topic Name",
|
||||
"id": "bfbdbcbe-a168-4d81-b108-36339e249116",
|
||||
"modificationUUID": "dfed7272-16dc-4eb6-99bf-7c82fc8e04f0",
|
||||
"multiSelect": true,
|
||||
"name": "Topic",
|
||||
"order": 2,
|
||||
"queryValue": "SELECT DISTINCT JSONExtractString(labels, 'TopicName') AS topic\nFROM signoz_metrics.distributed_time_series_v4_1day\nWHERE metric_name = 'aws_SNS_PublishSize_count' AND JSONExtractString(labels, 'cloud.account.id') IN {{.Account}} AND JSONExtractString(labels, 'cloud.region') IN {{.Region}}\nGROUP BY topic",
|
||||
"showALLOption": true,
|
||||
"sort": "ASC",
|
||||
"textboxValue": "",
|
||||
"type": "QUERY"
|
||||
}
|
||||
},
|
||||
"version": "v4",
|
||||
"widgets": [
|
||||
{
|
||||
"bucketCount": 30,
|
||||
"bucketWidth": 0,
|
||||
"columnUnits": {},
|
||||
"description": "",
|
||||
"fillSpans": false,
|
||||
"id": "4eb87f89-0213-4773-9b06-6aecc6701898",
|
||||
"isLogScale": false,
|
||||
"isStacked": false,
|
||||
"mergeAllActiveQueries": false,
|
||||
"nullZeroValues": "zero",
|
||||
"opacity": "1",
|
||||
"panelTypes": "graph",
|
||||
"query": {
|
||||
"builder": {
|
||||
"queryData": [
|
||||
{
|
||||
"aggregateAttribute": {
|
||||
"dataType": "float64",
|
||||
"id": "aws_SNS_NumberOfMessagesPublished_max--float64--Gauge--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "aws_SNS_NumberOfMessagesPublished_max",
|
||||
"type": "Gauge"
|
||||
},
|
||||
"aggregateOperator": "max",
|
||||
"dataSource": "metrics",
|
||||
"disabled": false,
|
||||
"expression": "A",
|
||||
"filters": {
|
||||
"items": [
|
||||
{
|
||||
"id": "8fd51b53",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "TopicName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "TopicName",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "in",
|
||||
"value": [
|
||||
"$Topic"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "b18187c3",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.region--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.region",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Region"
|
||||
},
|
||||
{
|
||||
"id": "eebe4578",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.account.id--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.account.id",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Account"
|
||||
}
|
||||
],
|
||||
"op": "AND"
|
||||
},
|
||||
"functions": [],
|
||||
"groupBy": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "TopicName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "TopicName",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"having": [],
|
||||
"legend": "{{TopicName}}",
|
||||
"limit": null,
|
||||
"orderBy": [],
|
||||
"queryName": "A",
|
||||
"reduceTo": "avg",
|
||||
"spaceAggregation": "max",
|
||||
"stepInterval": 60,
|
||||
"timeAggregation": "max"
|
||||
}
|
||||
],
|
||||
"queryFormulas": []
|
||||
},
|
||||
"clickhouse_sql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"id": "9c67615a-55f7-42da-835c-86922f2ff8bb",
|
||||
"promql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"queryType": "builder"
|
||||
},
|
||||
"selectedLogFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "body",
|
||||
"type": ""
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "timestamp",
|
||||
"type": ""
|
||||
}
|
||||
],
|
||||
"selectedTracesFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "serviceName--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "serviceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "name--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "name",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "float64",
|
||||
"id": "durationNano--float64--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "durationNano",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "httpMethod--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "httpMethod",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "responseStatusCode--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "responseStatusCode",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"softMax": 0,
|
||||
"softMin": 0,
|
||||
"stackedBarChart": false,
|
||||
"thresholds": [],
|
||||
"timePreferance": "GLOBAL_TIME",
|
||||
"title": "Number of Messages Published",
|
||||
"yAxisUnit": "none"
|
||||
},
|
||||
{
|
||||
"bucketCount": 30,
|
||||
"bucketWidth": 0,
|
||||
"columnUnits": {},
|
||||
"description": "",
|
||||
"fillSpans": false,
|
||||
"id": "7a010b4e-ea7c-4a45-a9eb-93af650c45b4",
|
||||
"isLogScale": false,
|
||||
"isStacked": false,
|
||||
"mergeAllActiveQueries": false,
|
||||
"nullZeroValues": "zero",
|
||||
"opacity": "1",
|
||||
"panelTypes": "graph",
|
||||
"query": {
|
||||
"builder": {
|
||||
"queryData": [
|
||||
{
|
||||
"aggregateAttribute": {
|
||||
"dataType": "float64",
|
||||
"id": "aws_SNS_PublishSize_max--float64--Gauge--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "aws_SNS_PublishSize_max",
|
||||
"type": "Gauge"
|
||||
},
|
||||
"aggregateOperator": "max",
|
||||
"dataSource": "metrics",
|
||||
"disabled": false,
|
||||
"expression": "A",
|
||||
"filters": {
|
||||
"items": [
|
||||
{
|
||||
"id": "1aa0d1a9",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "TopicName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "TopicName",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "in",
|
||||
"value": [
|
||||
"$Topic"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "62255cff",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.region--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.region",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Region"
|
||||
},
|
||||
{
|
||||
"id": "17c7153e",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.account.id--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.account.id",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Account"
|
||||
}
|
||||
],
|
||||
"op": "AND"
|
||||
},
|
||||
"functions": [],
|
||||
"groupBy": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "TopicName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "TopicName",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"having": [],
|
||||
"legend": "{{TopicName}}",
|
||||
"limit": null,
|
||||
"orderBy": [],
|
||||
"queryName": "A",
|
||||
"reduceTo": "avg",
|
||||
"spaceAggregation": "max",
|
||||
"stepInterval": 60,
|
||||
"timeAggregation": "max"
|
||||
}
|
||||
],
|
||||
"queryFormulas": []
|
||||
},
|
||||
"clickhouse_sql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"id": "a635a15b-dfe6-4617-a82e-29d93e27deaf",
|
||||
"promql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"queryType": "builder"
|
||||
},
|
||||
"selectedLogFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "body",
|
||||
"type": ""
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "timestamp",
|
||||
"type": ""
|
||||
}
|
||||
],
|
||||
"selectedTracesFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "serviceName--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "serviceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "name--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "name",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "float64",
|
||||
"id": "durationNano--float64--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "durationNano",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "httpMethod--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "httpMethod",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "responseStatusCode--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "responseStatusCode",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"softMax": 0,
|
||||
"softMin": 0,
|
||||
"stackedBarChart": false,
|
||||
"thresholds": [],
|
||||
"timePreferance": "GLOBAL_TIME",
|
||||
"title": "Published Message Size",
|
||||
"yAxisUnit": "decbytes"
|
||||
},
|
||||
{
|
||||
"bucketCount": 30,
|
||||
"bucketWidth": 0,
|
||||
"columnUnits": {},
|
||||
"description": "",
|
||||
"fillSpans": false,
|
||||
"id": "2299d4e3-6c40-4bf2-a550-c7bb8a7acd38",
|
||||
"isLogScale": false,
|
||||
"isStacked": false,
|
||||
"mergeAllActiveQueries": false,
|
||||
"nullZeroValues": "zero",
|
||||
"opacity": "1",
|
||||
"panelTypes": "graph",
|
||||
"query": {
|
||||
"builder": {
|
||||
"queryData": [
|
||||
{
|
||||
"aggregateAttribute": {
|
||||
"dataType": "float64",
|
||||
"id": "aws_SNS_NumberOfNotificationsDelivered_max--float64--Gauge--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "aws_SNS_NumberOfNotificationsDelivered_max",
|
||||
"type": "Gauge"
|
||||
},
|
||||
"aggregateOperator": "max",
|
||||
"dataSource": "metrics",
|
||||
"disabled": false,
|
||||
"expression": "A",
|
||||
"filters": {
|
||||
"items": [
|
||||
{
|
||||
"id": "c96a4ac0",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "TopicName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "TopicName",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "in",
|
||||
"value": [
|
||||
"$Topic"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "8ca86829",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.region--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.region",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Region"
|
||||
},
|
||||
{
|
||||
"id": "8a444f66",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.account.id--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.account.id",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Account"
|
||||
}
|
||||
],
|
||||
"op": "AND"
|
||||
},
|
||||
"functions": [],
|
||||
"groupBy": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "TopicName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "TopicName",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"having": [],
|
||||
"legend": "{{TopicName}}",
|
||||
"limit": null,
|
||||
"orderBy": [],
|
||||
"queryName": "A",
|
||||
"reduceTo": "avg",
|
||||
"spaceAggregation": "max",
|
||||
"stepInterval": 60,
|
||||
"timeAggregation": "max"
|
||||
}
|
||||
],
|
||||
"queryFormulas": []
|
||||
},
|
||||
"clickhouse_sql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"id": "0d2fc26c-9b21-4dfc-b631-64b7c8d3bd71",
|
||||
"promql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"queryType": "builder"
|
||||
},
|
||||
"selectedLogFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "body",
|
||||
"type": ""
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "timestamp",
|
||||
"type": ""
|
||||
}
|
||||
],
|
||||
"selectedTracesFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "serviceName--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "serviceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "name--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "name",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "float64",
|
||||
"id": "durationNano--float64--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "durationNano",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "httpMethod--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "httpMethod",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "responseStatusCode--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "responseStatusCode",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"softMax": 0,
|
||||
"softMin": 0,
|
||||
"stackedBarChart": false,
|
||||
"thresholds": [],
|
||||
"timePreferance": "GLOBAL_TIME",
|
||||
"title": "Number of Notifications Delivered",
|
||||
"yAxisUnit": "none"
|
||||
},
|
||||
{
|
||||
"bucketCount": 30,
|
||||
"bucketWidth": 0,
|
||||
"columnUnits": {},
|
||||
"description": "",
|
||||
"fillSpans": false,
|
||||
"id": "16eec8b7-de1a-4039-b180-24c7a6704b6e",
|
||||
"isLogScale": false,
|
||||
"isStacked": false,
|
||||
"mergeAllActiveQueries": false,
|
||||
"nullZeroValues": "zero",
|
||||
"opacity": "1",
|
||||
"panelTypes": "graph",
|
||||
"query": {
|
||||
"builder": {
|
||||
"queryData": [
|
||||
{
|
||||
"aggregateAttribute": {
|
||||
"dataType": "float64",
|
||||
"id": "aws_SNS_NumberOfNotificationsFailed_max--float64--Gauge--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "aws_SNS_NumberOfNotificationsFailed_max",
|
||||
"type": "Gauge"
|
||||
},
|
||||
"aggregateOperator": "max",
|
||||
"dataSource": "metrics",
|
||||
"disabled": false,
|
||||
"expression": "A",
|
||||
"filters": {
|
||||
"items": [
|
||||
{
|
||||
"id": "6175f3d5",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "TopicName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "TopicName",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "in",
|
||||
"value": [
|
||||
"$Topic"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "e2084931",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.region--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.region",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Region"
|
||||
},
|
||||
{
|
||||
"id": "0b05209a",
|
||||
"key": {
|
||||
"dataType": "string",
|
||||
"id": "cloud.account.id--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "cloud.account.id",
|
||||
"type": "tag"
|
||||
},
|
||||
"op": "=",
|
||||
"value": "$Account"
|
||||
}
|
||||
],
|
||||
"op": "AND"
|
||||
},
|
||||
"functions": [],
|
||||
"groupBy": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "TopicName--string--tag--false",
|
||||
"isColumn": false,
|
||||
"isJSON": false,
|
||||
"key": "TopicName",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"having": [],
|
||||
"legend": "{{TopicName}}",
|
||||
"limit": null,
|
||||
"orderBy": [],
|
||||
"queryName": "A",
|
||||
"reduceTo": "avg",
|
||||
"spaceAggregation": "max",
|
||||
"stepInterval": 60,
|
||||
"timeAggregation": "max"
|
||||
}
|
||||
],
|
||||
"queryFormulas": []
|
||||
},
|
||||
"clickhouse_sql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"id": "526247af-6ac9-42ff-83e9-cce0e32a9e63",
|
||||
"promql": [
|
||||
{
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"queryType": "builder"
|
||||
},
|
||||
"selectedLogFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "body",
|
||||
"type": ""
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"name": "timestamp",
|
||||
"type": ""
|
||||
}
|
||||
],
|
||||
"selectedTracesFields": [
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "serviceName--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "serviceName",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "name--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "name",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "float64",
|
||||
"id": "durationNano--float64--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "durationNano",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "httpMethod--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "httpMethod",
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"dataType": "string",
|
||||
"id": "responseStatusCode--string--tag--true",
|
||||
"isColumn": true,
|
||||
"isJSON": false,
|
||||
"key": "responseStatusCode",
|
||||
"type": "tag"
|
||||
}
|
||||
],
|
||||
"softMax": 0,
|
||||
"softMin": 0,
|
||||
"stackedBarChart": false,
|
||||
"thresholds": [],
|
||||
"timePreferance": "GLOBAL_TIME",
|
||||
"title": "Number of Notifications Failed",
|
||||
"yAxisUnit": "none"
|
||||
}
|
||||
]
|
||||
}
|
||||
1761
pkg/sqlmigration/086_migrate_ci_dashboards/aws/sqs/overview.json
Normal file
1761
pkg/sqlmigration/086_migrate_ci_dashboards/aws/sqs/overview.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
44
pkg/types/cloudintegrationtypes/integration_dashboard.go
Normal file
44
pkg/types/cloudintegrationtypes/integration_dashboard.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package cloudintegrationtypes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type IntegrationDashboardProviderType struct{ valuer.String }
|
||||
|
||||
var IntegrationDashboardProviderCloudIntegration = IntegrationDashboardProviderType{valuer.NewString("cloud_integration")}
|
||||
|
||||
type StorableIntegrationDashboard struct {
|
||||
bun.BaseModel `bun:"table:integration_dashboard"`
|
||||
|
||||
ID string `bun:"id,pk,type:text"`
|
||||
DashboardID string `bun:"dashboard_id,type:text"`
|
||||
Provider IntegrationDashboardProviderType `bun:"provider,type:text"`
|
||||
Slug string `bun:"slug,type:text"`
|
||||
CreatedAt time.Time `bun:"created_at"`
|
||||
UpdatedAt time.Time `bun:"updated_at"`
|
||||
}
|
||||
|
||||
func NewStorableIntegrationDashboard(dashboardID string, provider IntegrationDashboardProviderType, slug string) *StorableIntegrationDashboard {
|
||||
now := time.Now()
|
||||
return &StorableIntegrationDashboard{
|
||||
ID: valuer.GenerateUUID().StringValue(),
|
||||
DashboardID: dashboardID,
|
||||
Provider: provider,
|
||||
Slug: slug,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
}
|
||||
|
||||
func IntegrationDashboardSlug(provider CloudProviderType, serviceID ServiceID, dashName string) string {
|
||||
return fmt.Sprintf("%s-%s-%s", provider.StringValue(), serviceID.StringValue(), dashName)
|
||||
}
|
||||
|
||||
func IntegrationDashboardSlugPrefix(provider CloudProviderType, serviceID ServiceID) string {
|
||||
return fmt.Sprintf("%s-%s-", provider.StringValue(), serviceID.StringValue())
|
||||
}
|
||||
@@ -2,8 +2,6 @@ package cloudintegrationtypes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
@@ -319,56 +317,18 @@ func (updatableService *UpdatableService) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// UTILITIES
|
||||
|
||||
// GetCloudIntegrationDashboardID returns the dashboard id for a cloud integration, given the cloud provider, service id, and dashboard id.
|
||||
// This is used to generate unique dashboard ids for cloud integration, and also to parse the dashboard id to get the cloud provider and service id when needed.
|
||||
func GetCloudIntegrationDashboardID(cloudProvider CloudProviderType, svcID, dashboardID string) string {
|
||||
return fmt.Sprintf("cloud-integration--%s--%s--%s", cloudProvider.StringValue(), svcID, dashboardID)
|
||||
}
|
||||
|
||||
// ParseCloudIntegrationDashboardID parses a dashboard id generated by GetCloudIntegrationDashboardID
|
||||
// into its constituent parts (cloudProvider, serviceID, dashboardID).
|
||||
func ParseCloudIntegrationDashboardID(id string) (CloudProviderType, string, string, error) {
|
||||
parts := strings.SplitN(id, "--", 4)
|
||||
if len(parts) != 4 || parts[0] != "cloud-integration" {
|
||||
return CloudProviderType{}, "", "", errors.New(errors.TypeNotFound, ErrCodeCloudIntegrationNotFound, "invalid cloud integration dashboard id")
|
||||
// IsServiceSharedWithMetricsEnabled returns true if any of the provided services has metrics enabled.
|
||||
// It is used to determine whether dashboards for a service type should be deprovisioned when
|
||||
// an account is disconnected or a service is updated.
|
||||
func IsServiceSharedWithMetricsEnabled(provider CloudProviderType, services []*StorableCloudIntegrationService) bool {
|
||||
for _, svc := range services {
|
||||
cfg, err := NewServiceConfigFromJSON(provider, svc.Config)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if cfg.IsMetricsEnabled(provider) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
provider, err := NewCloudProvider(parts[1])
|
||||
if err != nil {
|
||||
return CloudProviderType{}, "", "", err
|
||||
}
|
||||
return provider, parts[2], parts[3], nil
|
||||
}
|
||||
|
||||
// GetDashboardsFromAssets returns the list of dashboards for the cloud provider service from definition.
|
||||
func GetDashboardsFromAssets(
|
||||
svcID string,
|
||||
orgID valuer.UUID,
|
||||
cloudProvider CloudProviderType,
|
||||
createdAt time.Time,
|
||||
assets Assets,
|
||||
) []*dashboardtypes.Dashboard {
|
||||
dashboards := make([]*dashboardtypes.Dashboard, 0)
|
||||
|
||||
for _, d := range assets.Dashboards {
|
||||
author := fmt.Sprintf("%s-integration", cloudProvider.StringValue())
|
||||
dashboards = append(dashboards, &dashboardtypes.Dashboard{
|
||||
ID: d.ID,
|
||||
Locked: true,
|
||||
OrgID: orgID,
|
||||
Data: d.Definition,
|
||||
TimeAuditable: types.TimeAuditable{
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
},
|
||||
UserAuditable: types.UserAuditable{
|
||||
CreatedBy: author,
|
||||
UpdatedBy: author,
|
||||
},
|
||||
Source: dashboardtypes.SourceIntegration,
|
||||
})
|
||||
}
|
||||
|
||||
return dashboards
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -39,13 +39,30 @@ type Store interface {
|
||||
// ListServices returns all the cloud integration services for the given cloud integration id
|
||||
ListServices(ctx context.Context, cloudIntegrationID valuer.UUID) ([]*StorableCloudIntegrationService, error)
|
||||
|
||||
// ListSharedServices returns a map of service type to services from other connected accounts
|
||||
// that share that service type with the given cloudIntegrationID.
|
||||
// Only service types present in the given account are included.
|
||||
// The caller is responsible for any further filtering (e.g. metrics-enabled checks).
|
||||
ListSharedServices(ctx context.Context, orgID valuer.UUID, provider CloudProviderType, cloudIntegrationID valuer.UUID) (map[ServiceID][]*StorableCloudIntegrationService, error)
|
||||
|
||||
// CreateService creates a new cloud integration service
|
||||
CreateService(ctx context.Context, service *StorableCloudIntegrationService) error
|
||||
|
||||
// UpdateService updates an existing cloud integration service
|
||||
UpdateService(ctx context.Context, service *StorableCloudIntegrationService) error
|
||||
|
||||
// DeleteServicesByCloudIntegrationID deletes all services for the given cloud integration id
|
||||
DeleteServicesByCloudIntegrationID(ctx context.Context, orgID, cloudIntegrationID valuer.UUID) error
|
||||
|
||||
RunInTx(context.Context, func(ctx context.Context) error) error
|
||||
|
||||
CreateIntegrationDashboard(ctx context.Context, row *StorableIntegrationDashboard) error
|
||||
|
||||
GetIntegrationDashboardBySlug(ctx context.Context, orgID valuer.UUID, provider IntegrationDashboardProviderType, slug string) (*StorableIntegrationDashboard, error)
|
||||
|
||||
ListIntegrationDashboardsBySlugPrefix(ctx context.Context, orgID valuer.UUID, provider IntegrationDashboardProviderType, slugPrefix string) ([]*StorableIntegrationDashboard, error)
|
||||
|
||||
DeleteIntegrationDashboardBySlug(ctx context.Context, orgID valuer.UUID, provider IntegrationDashboardProviderType, slug string) error
|
||||
}
|
||||
|
||||
type ServiceDefinitionStore interface {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user