mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-12 21:20:30 +01:00
Compare commits
12 Commits
issue_4522
...
test/seede
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
914e87158b | ||
|
|
b98359a785 | ||
|
|
a913e67acf | ||
|
|
c86df3adcb | ||
|
|
1641d5cdbe | ||
|
|
b9a44dbf02 | ||
|
|
1f5134b3ba | ||
|
|
fa91402577 | ||
|
|
b445b22bd6 | ||
|
|
c533ef5ed8 | ||
|
|
3c1fba3a07 | ||
|
|
0766ab31c0 |
1
.github/workflows/build-community.yaml
vendored
1
.github/workflows/build-community.yaml
vendored
@@ -54,6 +54,7 @@ jobs:
|
||||
JS_SRC: frontend
|
||||
JS_OUTPUT_ARTIFACT_CACHE_KEY: community-jsbuild-${{ github.sha }}
|
||||
JS_OUTPUT_ARTIFACT_PATH: frontend/build
|
||||
JS_PKG_MANAGER: pnpm
|
||||
DOCKER_BUILD: false
|
||||
DOCKER_MANIFEST: false
|
||||
go-build:
|
||||
|
||||
1
.github/workflows/build-enterprise.yaml
vendored
1
.github/workflows/build-enterprise.yaml
vendored
@@ -87,6 +87,7 @@ jobs:
|
||||
JS_INPUT_ARTIFACT_PATH: frontend/.env
|
||||
JS_OUTPUT_ARTIFACT_CACHE_KEY: enterprise-jsbuild-${{ github.sha }}
|
||||
JS_OUTPUT_ARTIFACT_PATH: frontend/build
|
||||
JS_PKG_MANAGER: pnpm
|
||||
DOCKER_BUILD: false
|
||||
DOCKER_MANIFEST: false
|
||||
go-build:
|
||||
|
||||
1
.github/workflows/build-staging.yaml
vendored
1
.github/workflows/build-staging.yaml
vendored
@@ -86,6 +86,7 @@ jobs:
|
||||
JS_INPUT_ARTIFACT_PATH: frontend/.env
|
||||
JS_OUTPUT_ARTIFACT_CACHE_KEY: staging-jsbuild-${{ github.sha }}
|
||||
JS_OUTPUT_ARTIFACT_PATH: frontend/build
|
||||
JS_PKG_MANAGER: pnpm
|
||||
DOCKER_BUILD: false
|
||||
DOCKER_MANIFEST: false
|
||||
go-build:
|
||||
|
||||
22
.github/workflows/e2eci.yaml
vendored
22
.github/workflows/e2eci.yaml
vendored
@@ -21,15 +21,19 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
- name: install-pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
with:
|
||||
version: 10
|
||||
- name: install
|
||||
run: |
|
||||
cd tests/e2e && yarn install --frozen-lockfile
|
||||
cd tests/e2e && pnpm install
|
||||
- name: fmt
|
||||
run: |
|
||||
cd tests/e2e && yarn fmt:check
|
||||
cd tests/e2e && pnpm fmt:check
|
||||
- name: lint
|
||||
run: |
|
||||
cd tests/e2e && yarn lint
|
||||
cd tests/e2e && pnpm lint
|
||||
test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -54,15 +58,19 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
- name: install-pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
with:
|
||||
version: 10
|
||||
- name: python-install
|
||||
run: |
|
||||
cd tests && uv sync
|
||||
- name: yarn-install
|
||||
- name: pnpm-install
|
||||
run: |
|
||||
cd tests/e2e && yarn install --frozen-lockfile
|
||||
cd tests/e2e && pnpm install --frozen-lockfile
|
||||
- name: playwright-browsers
|
||||
run: |
|
||||
cd tests/e2e && yarn playwright install --with-deps ${{ matrix.project }}
|
||||
cd tests/e2e && pnpm playwright install --with-deps ${{ matrix.project }}
|
||||
- name: bring-up-stack
|
||||
run: |
|
||||
cd tests && \
|
||||
@@ -73,7 +81,7 @@ jobs:
|
||||
- name: playwright-test
|
||||
run: |
|
||||
cd tests/e2e && \
|
||||
yarn playwright test --project=${{ matrix.project }}
|
||||
pnpm playwright test --project=${{ matrix.project }}
|
||||
- name: teardown-stack
|
||||
if: always()
|
||||
run: |
|
||||
|
||||
4
.github/workflows/goci.yaml
vendored
4
.github/workflows/goci.yaml
vendored
@@ -77,6 +77,10 @@ jobs:
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: "22"
|
||||
- name: setup-pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
with:
|
||||
version: 10
|
||||
- name: docker-community
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
4
.github/workflows/gor-signoz-community.yaml
vendored
4
.github/workflows/gor-signoz-community.yaml
vendored
@@ -25,6 +25,10 @@ jobs:
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: "22"
|
||||
- name: setup-pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
with:
|
||||
version: 10
|
||||
- name: build-frontend
|
||||
run: make js-build
|
||||
- name: upload-frontend-artifact
|
||||
|
||||
4
.github/workflows/gor-signoz.yaml
vendored
4
.github/workflows/gor-signoz.yaml
vendored
@@ -41,6 +41,10 @@ jobs:
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: "22"
|
||||
- name: setup-pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
with:
|
||||
version: 10
|
||||
- name: build-frontend
|
||||
run: make js-build
|
||||
- name: upload-frontend-artifact
|
||||
|
||||
14
.github/workflows/jsci.yaml
vendored
14
.github/workflows/jsci.yaml
vendored
@@ -22,6 +22,7 @@ jobs:
|
||||
with:
|
||||
PRIMUS_REF: main
|
||||
JS_SRC: frontend
|
||||
JS_PKG_MANAGER: pnpm
|
||||
test:
|
||||
if: |
|
||||
github.event_name == 'merge_group' ||
|
||||
@@ -32,6 +33,7 @@ jobs:
|
||||
with:
|
||||
PRIMUS_REF: main
|
||||
JS_SRC: frontend
|
||||
JS_PKG_MANAGER: pnpm
|
||||
fmt:
|
||||
if: |
|
||||
github.event_name == 'merge_group' ||
|
||||
@@ -42,6 +44,7 @@ jobs:
|
||||
with:
|
||||
PRIMUS_REF: main
|
||||
JS_SRC: frontend
|
||||
JS_PKG_MANAGER: pnpm
|
||||
lint:
|
||||
if: |
|
||||
github.event_name == 'merge_group' ||
|
||||
@@ -52,6 +55,7 @@ jobs:
|
||||
with:
|
||||
PRIMUS_REF: main
|
||||
JS_SRC: frontend
|
||||
JS_PKG_MANAGER: pnpm
|
||||
languages:
|
||||
if: |
|
||||
github.event_name == 'merge_group' ||
|
||||
@@ -76,9 +80,13 @@ jobs:
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: "22"
|
||||
- name: install-pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
with:
|
||||
version: 10
|
||||
- name: install-frontend
|
||||
run: cd frontend && yarn install
|
||||
run: cd frontend && pnpm install
|
||||
- name: generate-api-clients
|
||||
run: |
|
||||
cd frontend && yarn generate:api
|
||||
git diff --compact-summary --exit-code || (echo; echo "Unexpected difference in generated api clients. Run yarn generate:api in frontend/ locally and commit."; exit 1)
|
||||
cd frontend && pnpm generate:api
|
||||
git diff --compact-summary --exit-code || (echo; echo "Unexpected difference in generated api clients. Run pnpm generate:api in frontend/ locally and commit."; exit 1)
|
||||
|
||||
10
.gitpod.yml
10
.gitpod.yml
@@ -1,19 +1,21 @@
|
||||
# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
|
||||
# and commit this file to your remote git repository to share the goodness with others.
|
||||
|
||||
|
||||
tasks:
|
||||
- name: Run Docker Images
|
||||
init: |
|
||||
cd ./deploy/docker
|
||||
sudo docker compose up -d
|
||||
|
||||
- name: Install pnpm
|
||||
init: |
|
||||
npm i -g pnpm
|
||||
|
||||
- name: Run Frontend
|
||||
init: |
|
||||
cd ./frontend
|
||||
yarn install
|
||||
command:
|
||||
yarn dev
|
||||
pnpm install
|
||||
command: pnpm dev
|
||||
|
||||
ports:
|
||||
- port: 8080
|
||||
|
||||
2
Makefile
2
Makefile
@@ -154,7 +154,7 @@ $(GO_BUILD_ARCHS_ENTERPRISE_RACE): go-build-enterprise-race-%: $(TARGET_DIR)
|
||||
.PHONY: js-build
|
||||
js-build: ## Builds the js frontend
|
||||
@echo ">> building js frontend"
|
||||
@cd $(JS_BUILD_CONTEXT) && CI=1 yarn install && yarn build
|
||||
@cd $(JS_BUILD_CONTEXT) && CI=1 pnpm install && pnpm build
|
||||
|
||||
##############################################################
|
||||
# docker commands
|
||||
|
||||
@@ -18,16 +18,19 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/cache"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/flagger"
|
||||
"github.com/SigNoz/signoz/pkg/gateway"
|
||||
"github.com/SigNoz/signoz/pkg/gateway/noopgateway"
|
||||
"github.com/SigNoz/signoz/pkg/global"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/licensing/nooplicensing"
|
||||
"github.com/SigNoz/signoz/pkg/meterreporter"
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration/implcloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard/impldashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/retention"
|
||||
"github.com/SigNoz/signoz/pkg/modules/rulestatehistory"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/prometheus"
|
||||
@@ -109,6 +112,9 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
func(_ licensing.Licensing) factory.NamedMap[factory.ProviderFactory[auditor.Auditor, auditor.Config]] {
|
||||
return signoz.NewAuditorProviderFactories()
|
||||
},
|
||||
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) {
|
||||
return signoz.NewMeterReporterProviderFactories(), "noop"
|
||||
},
|
||||
func(ps factory.ProviderSettings, q querier.Querier, a analytics.Analytics) querier.Handler {
|
||||
return querier.NewHandler(ps, q, a)
|
||||
},
|
||||
|
||||
@@ -3,8 +3,9 @@ FROM node:22-bookworm AS build
|
||||
WORKDIR /opt/
|
||||
COPY ./frontend/ ./
|
||||
ENV NODE_OPTIONS=--max-old-space-size=8192
|
||||
RUN CI=1 yarn install
|
||||
RUN CI=1 yarn build
|
||||
RUN CI=1 npm i -g pnpm
|
||||
RUN CI=1 pnpm install
|
||||
RUN CI=1 pnpm build
|
||||
|
||||
FROM golang:1.25-bookworm
|
||||
|
||||
|
||||
55
cmd/enterprise/meter.go
Normal file
55
cmd/enterprise/meter.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/metercollector"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrylogs"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrymetrics"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrytraces"
|
||||
"github.com/SigNoz/signoz/pkg/types/retentiontypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/zeustypes"
|
||||
)
|
||||
|
||||
var meterConfigs = []metercollector.Config{
|
||||
{
|
||||
Provider: metercollector.ProviderStatic,
|
||||
Static: metercollector.StaticConfig{
|
||||
Name: zeustypes.MeterPlatformActive,
|
||||
Unit: zeustypes.MeterUnitCount,
|
||||
Aggregation: zeustypes.MeterAggregationMax,
|
||||
Value: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
Provider: metercollector.ProviderTelemetry,
|
||||
Telemetry: metercollector.TelemetryConfig{
|
||||
Name: zeustypes.MeterLogSize,
|
||||
Unit: zeustypes.MeterUnitBytes,
|
||||
Aggregation: zeustypes.MeterAggregationSum,
|
||||
DBName: telemetrylogs.DBName,
|
||||
TableName: telemetrylogs.LogsV2LocalTableName,
|
||||
DefaultRetentionDays: retentiontypes.DefaultLogsRetentionDays,
|
||||
},
|
||||
},
|
||||
{
|
||||
Provider: metercollector.ProviderTelemetry,
|
||||
Telemetry: metercollector.TelemetryConfig{
|
||||
Name: zeustypes.MeterSpanSize,
|
||||
Unit: zeustypes.MeterUnitBytes,
|
||||
Aggregation: zeustypes.MeterAggregationSum,
|
||||
DBName: telemetrytraces.DBName,
|
||||
TableName: telemetrytraces.SpanIndexV3LocalTableName,
|
||||
DefaultRetentionDays: retentiontypes.DefaultTracesRetentionDays,
|
||||
},
|
||||
},
|
||||
{
|
||||
Provider: metercollector.ProviderTelemetry,
|
||||
Telemetry: metercollector.TelemetryConfig{
|
||||
Name: zeustypes.MeterDatapointCount,
|
||||
Unit: zeustypes.MeterUnitCount,
|
||||
Aggregation: zeustypes.MeterAggregationSum,
|
||||
DBName: telemetrymetrics.DBName,
|
||||
TableName: telemetrymetrics.SamplesV4LocalTableName,
|
||||
DefaultRetentionDays: retentiontypes.DefaultMetricsRetentionDays,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -18,6 +18,9 @@ import (
|
||||
"github.com/SigNoz/signoz/ee/gateway/httpgateway"
|
||||
enterpriselicensing "github.com/SigNoz/signoz/ee/licensing"
|
||||
"github.com/SigNoz/signoz/ee/licensing/httplicensing"
|
||||
"github.com/SigNoz/signoz/ee/metercollector/staticmetercollector"
|
||||
"github.com/SigNoz/signoz/ee/metercollector/telemetrymetercollector"
|
||||
"github.com/SigNoz/signoz/ee/meterreporter/httpmeterreporter"
|
||||
"github.com/SigNoz/signoz/ee/modules/cloudintegration/implcloudintegration"
|
||||
"github.com/SigNoz/signoz/ee/modules/cloudintegration/implcloudintegration/implcloudprovider"
|
||||
"github.com/SigNoz/signoz/ee/modules/dashboard/impldashboard"
|
||||
@@ -36,14 +39,17 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/cache"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
pkgflagger "github.com/SigNoz/signoz/pkg/flagger"
|
||||
"github.com/SigNoz/signoz/pkg/gateway"
|
||||
"github.com/SigNoz/signoz/pkg/global"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/meterreporter"
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration"
|
||||
pkgcloudintegration "github.com/SigNoz/signoz/pkg/modules/cloudintegration/implcloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
pkgimpldashboard "github.com/SigNoz/signoz/pkg/modules/dashboard/impldashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/retention"
|
||||
"github.com/SigNoz/signoz/pkg/modules/rulestatehistory"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/prometheus"
|
||||
@@ -161,6 +167,20 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
}
|
||||
return factories
|
||||
},
|
||||
func(ctx context.Context, providerSettings factory.ProviderSettings, flagger pkgflagger.Flagger, licensing licensing.Licensing, telemetryStore telemetrystore.TelemetryStore, retentionGetter retention.Getter, orgGetter organization.Getter, zeus zeus.Zeus) (factory.NamedMap[factory.ProviderFactory[meterreporter.Reporter, meterreporter.Config]], string) {
|
||||
factories := signoz.NewMeterReporterProviderFactories()
|
||||
|
||||
collectorFactories := factory.MustNewNamedMap(
|
||||
staticmetercollector.NewFactory(),
|
||||
telemetrymetercollector.NewFactory(telemetryStore, retentionGetter),
|
||||
)
|
||||
|
||||
if err := factories.Add(httpmeterreporter.NewFactory(collectorFactories, meterConfigs, flagger, licensing, orgGetter, zeus)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return factories, "http"
|
||||
},
|
||||
func(ps factory.ProviderSettings, q querier.Querier, a analytics.Analytics) querier.Handler {
|
||||
communityHandler := querier.NewHandler(ps, q, a)
|
||||
return eequerier.NewHandler(ps, q, communityHandler)
|
||||
|
||||
@@ -429,3 +429,10 @@ authz:
|
||||
openfga:
|
||||
# maximum tuples allowed per openfga write operation.
|
||||
max_tuples_per_write: 300
|
||||
|
||||
##################### Meter Reporter #####################
|
||||
meterreporter:
|
||||
# The interval between collection ticks. Minimum 5m.
|
||||
interval: 6h
|
||||
# Whether to backfill sealed days from the license creation day.
|
||||
backfill: true
|
||||
|
||||
@@ -3013,6 +3013,32 @@ components:
|
||||
- end
|
||||
- limit
|
||||
type: object
|
||||
InframonitoringtypesPostableVolumes:
|
||||
properties:
|
||||
end:
|
||||
format: int64
|
||||
type: integer
|
||||
filter:
|
||||
$ref: '#/components/schemas/Querybuildertypesv5Filter'
|
||||
groupBy:
|
||||
items:
|
||||
$ref: '#/components/schemas/Querybuildertypesv5GroupByKey'
|
||||
nullable: true
|
||||
type: array
|
||||
limit:
|
||||
type: integer
|
||||
offset:
|
||||
type: integer
|
||||
orderBy:
|
||||
$ref: '#/components/schemas/Querybuildertypesv5OrderBy'
|
||||
start:
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- start
|
||||
- end
|
||||
- limit
|
||||
type: object
|
||||
InframonitoringtypesRequiredMetricsCheck:
|
||||
properties:
|
||||
missingMetrics:
|
||||
@@ -3028,6 +3054,67 @@ components:
|
||||
- list
|
||||
- grouped_list
|
||||
type: string
|
||||
InframonitoringtypesVolumeRecord:
|
||||
properties:
|
||||
meta:
|
||||
additionalProperties:
|
||||
type: string
|
||||
nullable: true
|
||||
type: object
|
||||
persistentVolumeClaimName:
|
||||
type: string
|
||||
volumeAvailable:
|
||||
format: double
|
||||
type: number
|
||||
volumeCapacity:
|
||||
format: double
|
||||
type: number
|
||||
volumeInodes:
|
||||
format: double
|
||||
type: number
|
||||
volumeInodesFree:
|
||||
format: double
|
||||
type: number
|
||||
volumeInodesUsed:
|
||||
format: double
|
||||
type: number
|
||||
volumeUsage:
|
||||
format: double
|
||||
type: number
|
||||
required:
|
||||
- persistentVolumeClaimName
|
||||
- volumeAvailable
|
||||
- volumeCapacity
|
||||
- volumeUsage
|
||||
- volumeInodes
|
||||
- volumeInodesFree
|
||||
- volumeInodesUsed
|
||||
- meta
|
||||
type: object
|
||||
InframonitoringtypesVolumes:
|
||||
properties:
|
||||
endTimeBeforeRetention:
|
||||
type: boolean
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesVolumeRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
total:
|
||||
type: integer
|
||||
type:
|
||||
$ref: '#/components/schemas/InframonitoringtypesResponseType'
|
||||
warning:
|
||||
$ref: '#/components/schemas/Querybuildertypesv5QueryWarnData'
|
||||
required:
|
||||
- type
|
||||
- records
|
||||
- total
|
||||
- requiredMetricsCheck
|
||||
- endTimeBeforeRetention
|
||||
type: object
|
||||
LlmpricingruletypesGettablePricingRules:
|
||||
properties:
|
||||
items:
|
||||
@@ -5185,19 +5272,17 @@ components:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperConfig'
|
||||
enabled:
|
||||
type: boolean
|
||||
field_context:
|
||||
fieldContext:
|
||||
$ref: '#/components/schemas/SpantypesFieldContext'
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- field_context
|
||||
- fieldContext
|
||||
- config
|
||||
type: object
|
||||
SpantypesPostableSpanMapperGroup:
|
||||
properties:
|
||||
category:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperGroupCategory'
|
||||
condition:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperGroupCondition'
|
||||
enabled:
|
||||
@@ -5206,7 +5291,6 @@ components:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- category
|
||||
- condition
|
||||
type: object
|
||||
SpantypesSpanMapper:
|
||||
@@ -5220,7 +5304,7 @@ components:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
field_context:
|
||||
fieldContext:
|
||||
$ref: '#/components/schemas/SpantypesFieldContext'
|
||||
group_id:
|
||||
type: string
|
||||
@@ -5237,7 +5321,7 @@ components:
|
||||
- id
|
||||
- group_id
|
||||
- name
|
||||
- field_context
|
||||
- fieldContext
|
||||
- config
|
||||
- enabled
|
||||
type: object
|
||||
@@ -5253,8 +5337,6 @@ components:
|
||||
type: object
|
||||
SpantypesSpanMapperGroup:
|
||||
properties:
|
||||
category:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperGroupCategory'
|
||||
condition:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperGroupCondition'
|
||||
createdAt:
|
||||
@@ -5279,13 +5361,11 @@ components:
|
||||
- id
|
||||
- orgId
|
||||
- name
|
||||
- category
|
||||
- condition
|
||||
- enabled
|
||||
type: object
|
||||
SpantypesSpanMapperGroupCategory:
|
||||
type: object
|
||||
SpantypesSpanMapperGroupCondition:
|
||||
nullable: true
|
||||
properties:
|
||||
attributes:
|
||||
items:
|
||||
@@ -5329,7 +5409,7 @@ components:
|
||||
enabled:
|
||||
nullable: true
|
||||
type: boolean
|
||||
field_context:
|
||||
fieldContext:
|
||||
$ref: '#/components/schemas/SpantypesFieldContext'
|
||||
type: object
|
||||
SpantypesUpdatableSpanMapperGroup:
|
||||
@@ -10380,12 +10460,6 @@ paths:
|
||||
org.
|
||||
operationId: ListSpanMapperGroups
|
||||
parameters:
|
||||
- explode: true
|
||||
in: query
|
||||
name: category
|
||||
schema:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperGroupCategory'
|
||||
style: deepObject
|
||||
- in: query
|
||||
name: enabled
|
||||
schema:
|
||||
@@ -12182,6 +12256,77 @@ paths:
|
||||
summary: List Pods for Infra Monitoring
|
||||
tags:
|
||||
- inframonitoring
|
||||
/api/v2/infra_monitoring/pvcs:
|
||||
post:
|
||||
deprecated: false
|
||||
description: 'Returns a paginated list of Kubernetes persistent volume claims
|
||||
(PVCs) with key volume metrics: available bytes, capacity bytes, usage (capacity
|
||||
- available), inodes, free inodes, and used inodes. Each row also includes
|
||||
metadata attributes (k8s.persistentvolumeclaim.name, k8s.pod.uid, k8s.pod.name,
|
||||
k8s.namespace.name, k8s.node.name, k8s.statefulset.name, k8s.cluster.name).
|
||||
Supports filtering via a filter expression, custom groupBy to aggregate volumes
|
||||
by any attribute, ordering by any of the six metrics (available, capacity,
|
||||
usage, inodes, inodes_free, inodes_used), and pagination via offset/limit.
|
||||
The response type is ''list'' for the default k8s.persistentvolumeclaim.name
|
||||
grouping or ''grouped_list'' for custom groupBy keys; in both modes every
|
||||
row aggregates volumes in the group. Also reports missing required metrics
|
||||
and whether the requested time range falls before the data retention boundary.
|
||||
Numeric metric fields (volumeAvailable, volumeCapacity, volumeUsage, volumeInodes,
|
||||
volumeInodesFree, volumeInodesUsed) return -1 as a sentinel when no data is
|
||||
available for that field.'
|
||||
operationId: ListVolumes
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPostableVolumes'
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/InframonitoringtypesVolumes'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: OK
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- VIEWER
|
||||
- tokenizer:
|
||||
- VIEWER
|
||||
summary: List Volumes for Infra Monitoring
|
||||
tags:
|
||||
- inframonitoring
|
||||
/api/v2/livez:
|
||||
get:
|
||||
deprecated: false
|
||||
|
||||
@@ -13,13 +13,12 @@ Before diving in, make sure you have these tools installed:
|
||||
- Download from [go.dev/dl](https://go.dev/dl/)
|
||||
- Check [go.mod](../../go.mod#L3) for the minimum version
|
||||
|
||||
|
||||
- **Node** - Powers our frontend
|
||||
- Download from [nodejs.org](https://nodejs.org)
|
||||
- Check [.nvmrc](../../frontend/.nvmrc) for the version
|
||||
|
||||
- **Yarn** - Our frontend package manager
|
||||
- Follow the [installation guide](https://yarnpkg.com/getting-started/install)
|
||||
- **Pnpm** - Our frontend package manager
|
||||
- Follow the [installation guide](https://pnpm.io/installation)
|
||||
|
||||
- **Docker** - For running Clickhouse and Postgres locally
|
||||
- Get it from [docs.docker.com/get-docker](https://docs.docker.com/get-docker/)
|
||||
@@ -95,7 +94,7 @@ This command:
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
yarn install
|
||||
pnpm install
|
||||
```
|
||||
|
||||
3. Create a `.env` file in this directory:
|
||||
@@ -105,10 +104,10 @@ This command:
|
||||
|
||||
4. Start the development server:
|
||||
```bash
|
||||
yarn dev
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
> 💡 **Tip**: `yarn dev` will automatically rebuild when you make changes to the code
|
||||
> 💡 **Tip**: `pnpm dev` will automatically rebuild when you make changes to the code
|
||||
|
||||
Now you're all set to start developing! Happy coding! 🎉
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ import ec2Url from '@/assets/Logos/ec2.svg';
|
||||
|
||||
1. Add the logo SVG to `src/assets/Logos/` and add a top-level import in the config file (e.g., `import myServiceUrl from '@/assets/Logos/my-service.svg'`)
|
||||
2. Add your data source object to the `onboardingConfigWithLinks` array, referencing the imported variable for `imgUrl`
|
||||
3. Test the flow locally with `yarn dev`
|
||||
3. Test the flow locally with `pnpm dev`
|
||||
4. Validation:
|
||||
- Navigate to the [onboarding page](http://localhost:3301/get-started-with-signoz-cloud) on your local machine
|
||||
- Data source appears in the list
|
||||
|
||||
61
ee/metercollector/staticmetercollector/provider.go
Normal file
61
ee/metercollector/staticmetercollector/provider.go
Normal file
@@ -0,0 +1,61 @@
|
||||
// Package staticmetercollector emits a fixed-value meter reading per org per window.
|
||||
package staticmetercollector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/metercollector"
|
||||
"github.com/SigNoz/signoz/pkg/types/licensetypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/zeustypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
var _ metercollector.MeterCollector = (*Provider)(nil)
|
||||
|
||||
type Provider struct {
|
||||
settings factory.ScopedProviderSettings
|
||||
config metercollector.StaticConfig
|
||||
}
|
||||
|
||||
func NewFactory() factory.ProviderFactory[metercollector.MeterCollector, metercollector.Config] {
|
||||
return factory.NewProviderFactory(factory.MustNewName(metercollector.ProviderStatic), func(ctx context.Context, providerSettings factory.ProviderSettings, config metercollector.Config) (metercollector.MeterCollector, error) {
|
||||
return newProvider(providerSettings, config.Static), nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newProvider(providerSettings factory.ProviderSettings, config metercollector.StaticConfig) *Provider {
|
||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/ee/metercollector/staticmetercollector")
|
||||
|
||||
return &Provider{
|
||||
settings: settings,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (provider *Provider) Name() zeustypes.MeterName { return provider.config.Name }
|
||||
func (provider *Provider) Unit() zeustypes.MeterUnit { return provider.config.Unit }
|
||||
func (provider *Provider) Aggregation() zeustypes.MeterAggregation {
|
||||
return provider.config.Aggregation
|
||||
}
|
||||
|
||||
func (provider *Provider) Origin(_ context.Context, _ valuer.UUID, license *licensetypes.License, _ time.Time) (time.Time, error) {
|
||||
if license == nil || license.CreatedAt.IsZero() {
|
||||
return time.Time{}, nil
|
||||
}
|
||||
|
||||
createdAt := license.CreatedAt.UTC()
|
||||
return time.Date(createdAt.Year(), createdAt.Month(), createdAt.Day(), 0, 0, 0, 0, time.UTC), nil
|
||||
}
|
||||
|
||||
func (provider *Provider) Collect(_ context.Context, orgID valuer.UUID, license *licensetypes.License, window zeustypes.MeterWindow) ([]zeustypes.Meter, error) {
|
||||
if license == nil || license.Key == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return []zeustypes.Meter{
|
||||
zeustypes.NewMeter(provider.config.Name, provider.config.Value, provider.config.Unit, provider.config.Aggregation, window, zeustypes.NewDimensions(zeustypes.OrganizationID.String(orgID.StringValue()))),
|
||||
}, nil
|
||||
}
|
||||
247
ee/metercollector/telemetrymetercollector/provider.go
Normal file
247
ee/metercollector/telemetrymetercollector/provider.go
Normal file
@@ -0,0 +1,247 @@
|
||||
// Package telemetrymetercollector collects telemetry meters (logs, traces, metrics)
|
||||
// by retention. One Provider materializes per TelemetryConfig.
|
||||
package telemetrymetercollector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/huandu/go-sqlbuilder"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/metercollector"
|
||||
"github.com/SigNoz/signoz/pkg/modules/retention"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrymeter"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
||||
"github.com/SigNoz/signoz/pkg/types/licensetypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/retentiontypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/zeustypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
var (
|
||||
labelKeyPattern = regexp.MustCompile(`^[A-Za-z0-9_.\-]+$`)
|
||||
labelValuePattern = regexp.MustCompile(`^[A-Za-z0-9_.\-:]+$`)
|
||||
)
|
||||
|
||||
var _ metercollector.MeterCollector = (*Provider)(nil)
|
||||
|
||||
type Provider struct {
|
||||
settings factory.ScopedProviderSettings
|
||||
config metercollector.TelemetryConfig
|
||||
telemetryStore telemetrystore.TelemetryStore
|
||||
retentionGetter retention.Getter
|
||||
}
|
||||
|
||||
func NewFactory(telemetryStore telemetrystore.TelemetryStore, retentionGetter retention.Getter) factory.ProviderFactory[metercollector.MeterCollector, metercollector.Config] {
|
||||
return factory.NewProviderFactory(factory.MustNewName(metercollector.ProviderTelemetry), func(ctx context.Context, providerSettings factory.ProviderSettings, config metercollector.Config) (metercollector.MeterCollector, error) {
|
||||
return newProvider(providerSettings, config.Telemetry, telemetryStore, retentionGetter), nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newProvider(
|
||||
providerSettings factory.ProviderSettings,
|
||||
config metercollector.TelemetryConfig,
|
||||
telemetryStore telemetrystore.TelemetryStore,
|
||||
retentionGetter retention.Getter,
|
||||
) *Provider {
|
||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/ee/metercollector/telemetrymetercollector")
|
||||
|
||||
return &Provider{
|
||||
settings: settings,
|
||||
config: config,
|
||||
telemetryStore: telemetryStore,
|
||||
retentionGetter: retentionGetter,
|
||||
}
|
||||
}
|
||||
|
||||
func (provider *Provider) Name() zeustypes.MeterName { return provider.config.Name }
|
||||
func (provider *Provider) Unit() zeustypes.MeterUnit { return provider.config.Unit }
|
||||
func (provider *Provider) Aggregation() zeustypes.MeterAggregation {
|
||||
return provider.config.Aggregation
|
||||
}
|
||||
|
||||
func (provider *Provider) Origin(ctx context.Context, _ valuer.UUID, _ *licensetypes.License, todayStart time.Time) (time.Time, error) {
|
||||
query, args := buildOriginQuery(provider.config.Name.String())
|
||||
|
||||
var minMs int64
|
||||
if err := provider.telemetryStore.ClickhouseDB().QueryRow(ctx, query, args...).Scan(&minMs); err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
if minMs == 0 {
|
||||
return todayStart, nil
|
||||
}
|
||||
|
||||
minDay := time.UnixMilli(minMs).UTC()
|
||||
return time.Date(minDay.Year(), minDay.Month(), minDay.Day(), 0, 0, 0, 0, time.UTC), nil
|
||||
}
|
||||
|
||||
func (provider *Provider) Collect(
|
||||
ctx context.Context,
|
||||
orgID valuer.UUID,
|
||||
_ *licensetypes.License,
|
||||
window zeustypes.MeterWindow,
|
||||
) ([]zeustypes.Meter, error) {
|
||||
meterName := provider.config.Name.String()
|
||||
|
||||
segments, err := provider.retentionGetter.GetRetentionPolicySegments(
|
||||
ctx,
|
||||
orgID,
|
||||
provider.config.DBName,
|
||||
provider.config.TableName,
|
||||
provider.config.DefaultRetentionDays,
|
||||
window.StartUnixMilli,
|
||||
window.EndUnixMilli,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
valuesByRetentionDays := make(map[int]int64)
|
||||
|
||||
for _, segment := range segments {
|
||||
query, args, err := buildQuery(meterName, segment)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := provider.telemetryStore.ClickhouseDB().Query(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := func() error {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var retentionDays int32
|
||||
var value int64
|
||||
|
||||
if err := rows.Scan(&retentionDays, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
valuesByRetentionDays[int(retentionDays)] += value
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
meters := make([]zeustypes.Meter, 0, len(valuesByRetentionDays))
|
||||
for retentionDays, value := range valuesByRetentionDays {
|
||||
meters = append(meters, zeustypes.NewMeter(provider.config.Name, value, provider.config.Unit, provider.config.Aggregation, window, buildDimensions(orgID, retentionDays)))
|
||||
}
|
||||
|
||||
// Empty windows still emit a sentinel so checkpoints can advance.
|
||||
if len(meters) == 0 && len(segments) > 0 {
|
||||
meters = append(meters, zeustypes.NewMeter(provider.config.Name, 0, provider.config.Unit, provider.config.Aggregation, window, buildDimensions(orgID, segments[len(segments)-1].DefaultDays)))
|
||||
}
|
||||
|
||||
return meters, nil
|
||||
}
|
||||
|
||||
func buildOriginQuery(meterName string) (string, []any) {
|
||||
sb := sqlbuilder.NewSelectBuilder()
|
||||
sb.Select("toInt64(ifNull(min(unix_milli), 0))")
|
||||
sb.From(telemetrymeter.DBName + "." + telemetrymeter.SamplesTableName)
|
||||
sb.Where(sb.Equal("metric_name", meterName))
|
||||
return sb.BuildWithFlavor(sqlbuilder.ClickHouse)
|
||||
}
|
||||
|
||||
func buildQuery(meterName string, segment *retentiontypes.RetentionPolicySegment) (string, []any, error) {
|
||||
retentionExpr, err := buildRetentionMultiIfSQL(segment.Rules, segment.DefaultDays)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
selects := []string{
|
||||
retentionExpr + " AS retention_days",
|
||||
"toInt64(ifNull(sum(value), 0)) AS value",
|
||||
}
|
||||
|
||||
sb := sqlbuilder.NewSelectBuilder()
|
||||
sb.Select(selects...)
|
||||
sb.From(telemetrymeter.DBName + "." + telemetrymeter.SamplesTableName)
|
||||
sb.Where(
|
||||
sb.Equal("metric_name", meterName),
|
||||
sb.GTE("unix_milli", segment.StartMs),
|
||||
sb.LT("unix_milli", segment.EndMs),
|
||||
)
|
||||
sb.GroupBy("retention_days")
|
||||
query, args := sb.BuildWithFlavor(sqlbuilder.ClickHouse)
|
||||
return query, args, nil
|
||||
}
|
||||
|
||||
func buildRetentionMultiIfSQL(rules []retentiontypes.CustomRetentionRule, defaultDays int) (string, error) {
|
||||
if defaultDays <= 0 {
|
||||
return "", errors.Newf(errors.TypeInvalidInput, metercollector.ErrCodeMeterCollectorInvalidCustomRetentionRule, "non-positive default retention %d", defaultDays)
|
||||
}
|
||||
|
||||
if len(rules) == 0 {
|
||||
return "toInt32(" + strconv.Itoa(defaultDays) + ")", nil
|
||||
}
|
||||
|
||||
arms := make([]string, 0, 2*len(rules)+1)
|
||||
for ruleIndex, rule := range rules {
|
||||
if rule.TTLDays <= 0 {
|
||||
return "", errors.Newf(errors.TypeInvalidInput, metercollector.ErrCodeMeterCollectorInvalidCustomRetentionRule, "rule %d has non-positive ttl_days %d", ruleIndex, rule.TTLDays)
|
||||
}
|
||||
conditionExpr, err := buildRuleConditionSQL(ruleIndex, rule)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
arms = append(arms, conditionExpr)
|
||||
arms = append(arms, strconv.Itoa(rule.TTLDays))
|
||||
}
|
||||
arms = append(arms, strconv.Itoa(defaultDays))
|
||||
|
||||
return "toInt32(multiIf(" + strings.Join(arms, ", ") + "))", nil
|
||||
}
|
||||
|
||||
func buildRuleConditionSQL(ruleIndex int, rule retentiontypes.CustomRetentionRule) (string, error) {
|
||||
if len(rule.Filters) == 0 {
|
||||
return "", errors.Newf(errors.TypeInvalidInput, metercollector.ErrCodeMeterCollectorInvalidCustomRetentionRule, "rule %d has no filters", ruleIndex)
|
||||
}
|
||||
|
||||
filterExprs := make([]string, 0, len(rule.Filters))
|
||||
for filterIndex, filter := range rule.Filters {
|
||||
if !labelKeyPattern.MatchString(filter.Key) {
|
||||
return "", errors.Newf(errors.TypeInvalidInput, metercollector.ErrCodeMeterCollectorInvalidCustomRetentionRule, "rule %d filter %d has invalid key %q", ruleIndex, filterIndex, filter.Key)
|
||||
}
|
||||
if len(filter.Values) == 0 {
|
||||
return "", errors.Newf(errors.TypeInvalidInput, metercollector.ErrCodeMeterCollectorInvalidCustomRetentionRule, "rule %d filter %d has no values", ruleIndex, filterIndex)
|
||||
}
|
||||
|
||||
quoted := make([]string, len(filter.Values))
|
||||
for valueIndex, value := range filter.Values {
|
||||
if !labelValuePattern.MatchString(value) {
|
||||
return "", errors.Newf(errors.TypeInvalidInput, metercollector.ErrCodeMeterCollectorInvalidCustomRetentionRule, "rule %d filter %d value %d is invalid %q", ruleIndex, filterIndex, valueIndex, value)
|
||||
}
|
||||
quoted[valueIndex] = "'" + value + "'"
|
||||
}
|
||||
|
||||
filterExprs = append(filterExprs, fmt.Sprintf("JSONExtractString(labels, '%s') IN (%s)", filter.Key, strings.Join(quoted, ", ")))
|
||||
}
|
||||
|
||||
return strings.Join(filterExprs, " AND "), nil
|
||||
}
|
||||
|
||||
func buildDimensions(orgID valuer.UUID, retentionDays int) map[string]string {
|
||||
retentionDurationSeconds := int64(retentionDays) * 24 * 60 * 60 // seconds
|
||||
|
||||
return zeustypes.NewDimensions(
|
||||
zeustypes.OrganizationID.String(orgID.StringValue()),
|
||||
zeustypes.RetentionDuration.String(strconv.FormatInt(retentionDurationSeconds, 10)),
|
||||
)
|
||||
}
|
||||
318
ee/meterreporter/httpmeterreporter/provider.go
Normal file
318
ee/meterreporter/httpmeterreporter/provider.go
Normal file
@@ -0,0 +1,318 @@
|
||||
package httpmeterreporter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/flagger"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/metercollector"
|
||||
"github.com/SigNoz/signoz/pkg/meterreporter"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/featuretypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/licensetypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/zeustypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/SigNoz/signoz/pkg/zeus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
var _ factory.ServiceWithHealthy = (*Provider)(nil)
|
||||
|
||||
type Provider struct {
|
||||
settings factory.ScopedProviderSettings
|
||||
config meterreporter.Config
|
||||
collectorsByName map[zeustypes.MeterName]metercollector.MeterCollector
|
||||
flagger flagger.Flagger
|
||||
licensing licensing.Licensing
|
||||
orgGetter organization.Getter
|
||||
zeus zeus.Zeus
|
||||
healthyC chan struct{}
|
||||
stopC chan struct{}
|
||||
metrics *reporterMetrics
|
||||
}
|
||||
|
||||
func NewFactory(collectorFactories factory.NamedMap[factory.ProviderFactory[metercollector.MeterCollector, metercollector.Config]], collectorConfigs []metercollector.Config, flagger flagger.Flagger, licensing licensing.Licensing, orgGetter organization.Getter, zeus zeus.Zeus) factory.ProviderFactory[meterreporter.Reporter, meterreporter.Config] {
|
||||
return factory.NewProviderFactory(factory.MustNewName("http"), func(ctx context.Context, providerSettings factory.ProviderSettings, config meterreporter.Config) (meterreporter.Reporter, error) {
|
||||
return newProvider(ctx, providerSettings, config, collectorFactories, collectorConfigs, flagger, licensing, orgGetter, zeus)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newProvider(
|
||||
ctx context.Context,
|
||||
providerSettings factory.ProviderSettings,
|
||||
config meterreporter.Config,
|
||||
collectorFactories factory.NamedMap[factory.ProviderFactory[metercollector.MeterCollector, metercollector.Config]],
|
||||
collectorConfigs []metercollector.Config,
|
||||
flagger flagger.Flagger,
|
||||
licensing licensing.Licensing,
|
||||
orgGetter organization.Getter,
|
||||
zeus zeus.Zeus,
|
||||
) (*Provider, error) {
|
||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/ee/meterreporter/httpmeterreporter")
|
||||
|
||||
collectorsByName := map[zeustypes.MeterName]metercollector.MeterCollector{}
|
||||
for _, collectorConfig := range collectorConfigs {
|
||||
collector, err := factory.NewProviderFromNamedMap(ctx, providerSettings, collectorConfig, collectorFactories, collectorConfig.Provider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, exists := collectorsByName[collector.Name()]; exists {
|
||||
return nil, errors.Newf(errors.TypeAlreadyExists, errors.CodeAlreadyExists, "duplicate meter collector %q", collector.Name())
|
||||
}
|
||||
collectorsByName[collector.Name()] = collector
|
||||
}
|
||||
|
||||
metrics, err := newReporterMetrics(settings.Meter())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Provider{
|
||||
settings: settings,
|
||||
config: config,
|
||||
collectorsByName: collectorsByName,
|
||||
flagger: flagger,
|
||||
licensing: licensing,
|
||||
orgGetter: orgGetter,
|
||||
zeus: zeus,
|
||||
healthyC: make(chan struct{}),
|
||||
stopC: make(chan struct{}),
|
||||
metrics: metrics,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (provider *Provider) Start(ctx context.Context) error {
|
||||
close(provider.healthyC)
|
||||
|
||||
provider.collect(ctx)
|
||||
|
||||
ticker := time.NewTicker(provider.config.Interval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-provider.stopC:
|
||||
return nil
|
||||
case <-ticker.C:
|
||||
provider.collect(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (provider *Provider) collect(ctx context.Context) {
|
||||
ctx, span := provider.settings.Tracer().Start(ctx, "meterreporter.Collect", trace.WithAttributes(attribute.String("meterreporter.provider", "http")))
|
||||
defer span.End()
|
||||
|
||||
orgs, err := provider.orgGetter.ListByOwnedKeyRange(ctx)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
provider.settings.Logger().ErrorContext(ctx, "failed to get orgs data", errors.Attr(err))
|
||||
return
|
||||
}
|
||||
|
||||
for _, org := range orgs {
|
||||
evalCtx := featuretypes.NewFlaggerEvaluationContext(org.ID)
|
||||
if !provider.flagger.BooleanOrEmpty(ctx, flagger.FeatureUseMeterReporter, evalCtx) {
|
||||
provider.settings.Logger().DebugContext(ctx, "meter reporter disabled for org, skipping reporting", slog.String("org_id", org.ID.StringValue()))
|
||||
continue
|
||||
}
|
||||
|
||||
license, err := provider.licensing.GetActive(ctx, org.ID)
|
||||
if err != nil {
|
||||
if errors.Ast(err, errors.TypeNotFound) {
|
||||
provider.settings.Logger().DebugContext(ctx, "no active license found for org, skipping reporting", slog.String("org_id", org.ID.StringValue()))
|
||||
continue
|
||||
}
|
||||
|
||||
span.RecordError(err)
|
||||
provider.settings.Logger().ErrorContext(ctx, "failed to fetch active license for org", errors.Attr(err), slog.String("org_id", org.ID.StringValue()))
|
||||
return
|
||||
}
|
||||
|
||||
if err := provider.collectOrg(ctx, org, license); err != nil {
|
||||
span.RecordError(err)
|
||||
provider.settings.Logger().ErrorContext(ctx, "failed to collect meters", errors.Attr(err), slog.String("org_id", org.ID.StringValue()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (provider *Provider) Stop(ctx context.Context) error {
|
||||
close(provider.stopC)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *Provider) Healthy() <-chan struct{} {
|
||||
return provider.healthyC
|
||||
}
|
||||
|
||||
func (provider *Provider) collectOrg(ctx context.Context, org *types.Organization, license *licensetypes.License) error {
|
||||
now := time.Now().UTC()
|
||||
// Use one timestamp so a tick cannot straddle midnight.
|
||||
todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
|
||||
|
||||
if provider.config.Backfill {
|
||||
checkpointsByMeter, err := provider.checkpoints(ctx, license.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nextByCollector := provider.nextDays(license, todayStart, checkpointsByMeter)
|
||||
|
||||
start, end, ok := backfillRange(nextByCollector, todayStart)
|
||||
if ok {
|
||||
for day := start; !day.After(end); day = day.AddDate(0, 0, 1) {
|
||||
eligible := eligibleCollectors(provider.collectorsByName, nextByCollector, day)
|
||||
if len(eligible) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
window, err := zeustypes.NewMeterWindow(day.UnixMilli(), day.AddDate(0, 0, 1).UnixMilli(), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := provider.report(ctx, org.ID, license, window, eligible); err != nil {
|
||||
provider.settings.Logger().WarnContext(ctx, "failed to backfill for day", errors.Attr(err), slog.String("date", day.Format("2006-01-02")))
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Today's partial window: every collector is always eligible (next <= today).
|
||||
if now.UnixMilli() > todayStart.UnixMilli() {
|
||||
todayWindow, err := zeustypes.NewMeterWindow(todayStart.UnixMilli(), now.UnixMilli(), false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return provider.report(ctx, org.ID, license, todayWindow, provider.collectorsByName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *Provider) checkpoints(ctx context.Context, licenseKey string) (map[string]time.Time, error) {
|
||||
list, err := provider.zeus.ListMeterCheckpoints(ctx, licenseKey)
|
||||
if err != nil {
|
||||
provider.metrics.checkpoints.Add(ctx, 1, metric.WithAttributes(errors.TypeAttr(err)))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
provider.metrics.checkpoints.Add(ctx, 1)
|
||||
|
||||
checkpointsByMeter := make(map[string]time.Time, len(list))
|
||||
for _, checkpoint := range list {
|
||||
checkpointsByMeter[checkpoint.Name] = checkpoint.StartDate.UTC()
|
||||
}
|
||||
|
||||
return checkpointsByMeter, nil
|
||||
}
|
||||
|
||||
func (provider *Provider) nextDays(license *licensetypes.License, todayStart time.Time, checkpointsByMeter map[string]time.Time) map[zeustypes.MeterName]time.Time {
|
||||
nextByCollector := make(map[zeustypes.MeterName]time.Time, len(provider.collectorsByName))
|
||||
licenseCreatedAt := license.CreatedAt.UTC()
|
||||
licenseCreatedAtDay := time.Date(licenseCreatedAt.Year(), licenseCreatedAt.Month(), licenseCreatedAt.Day(), 0, 0, 0, 0, time.UTC)
|
||||
|
||||
for _, collector := range provider.collectorsByName {
|
||||
checkpoint, hasCheckpoint := checkpointsByMeter[collector.Name().String()]
|
||||
nextByCollector[collector.Name()] = nextReportableDay(licenseCreatedAtDay, todayStart, checkpoint, hasCheckpoint)
|
||||
}
|
||||
|
||||
return nextByCollector
|
||||
}
|
||||
|
||||
func nextReportableDay(licenseCreatedAtDay time.Time, todayStart time.Time, checkpoint time.Time, hasCheckpoint bool) time.Time {
|
||||
next := licenseCreatedAtDay
|
||||
if next.IsZero() {
|
||||
next = todayStart
|
||||
}
|
||||
|
||||
if hasCheckpoint {
|
||||
checkpointNext := checkpoint.AddDate(0, 0, 1)
|
||||
if checkpointNext.After(next) {
|
||||
next = checkpointNext
|
||||
}
|
||||
}
|
||||
|
||||
return next
|
||||
}
|
||||
|
||||
func (provider *Provider) report(ctx context.Context, orgID valuer.UUID, license *licensetypes.License, window zeustypes.MeterWindow, collectors map[zeustypes.MeterName]metercollector.MeterCollector) error {
|
||||
date := time.UnixMilli(window.StartUnixMilli).UTC().Format("2006-01-02")
|
||||
|
||||
meters := make([]zeustypes.Meter, 0, len(collectors))
|
||||
for _, collector := range collectors {
|
||||
meterAttr := attribute.String("signoz.meter.name", collector.Name().String())
|
||||
collectedReadings, err := collector.Collect(ctx, orgID, license, window)
|
||||
if err != nil {
|
||||
provider.metrics.collections.Add(ctx, 1, metric.WithAttributes(meterAttr, errors.TypeAttr(err)))
|
||||
continue
|
||||
}
|
||||
|
||||
provider.metrics.collections.Add(ctx, 1, metric.WithAttributes(meterAttr))
|
||||
meters = append(meters, collectedReadings...)
|
||||
}
|
||||
|
||||
if len(meters) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
idempotencyKey := fmt.Sprintf("meterreporter:%s", date)
|
||||
|
||||
body, err := json.Marshal(meters)
|
||||
if err != nil {
|
||||
provider.metrics.reports.Add(ctx, 1, metric.WithAttributes(errors.TypeAttr(err)))
|
||||
return err
|
||||
}
|
||||
|
||||
if err := provider.zeus.PutMetersV3(ctx, license.Key, idempotencyKey, body); err != nil {
|
||||
provider.metrics.reports.Add(ctx, 1, metric.WithAttributes(errors.TypeAttr(err)))
|
||||
return err
|
||||
}
|
||||
|
||||
provider.metrics.reports.Add(ctx, 1)
|
||||
provider.metrics.meters.Add(ctx, int64(len(meters)))
|
||||
return nil
|
||||
}
|
||||
|
||||
// backfillRange returns the inclusive sealed-day range ending at yesterday.
|
||||
func backfillRange(nextByCollector map[zeustypes.MeterName]time.Time, todayStart time.Time) (start, end time.Time, ok bool) {
|
||||
yesterday := todayStart.AddDate(0, 0, -1)
|
||||
|
||||
for _, next := range nextByCollector {
|
||||
if !next.Before(todayStart) {
|
||||
continue
|
||||
}
|
||||
if start.IsZero() || next.Before(start) {
|
||||
start = next
|
||||
}
|
||||
}
|
||||
|
||||
if start.IsZero() || start.After(yesterday) {
|
||||
return time.Time{}, time.Time{}, false
|
||||
}
|
||||
|
||||
return start, yesterday, true
|
||||
}
|
||||
|
||||
func eligibleCollectors(collectors map[zeustypes.MeterName]metercollector.MeterCollector, nextByCollector map[zeustypes.MeterName]time.Time, day time.Time) map[zeustypes.MeterName]metercollector.MeterCollector {
|
||||
eligible := make(map[zeustypes.MeterName]metercollector.MeterCollector, len(collectors))
|
||||
for name, collector := range collectors {
|
||||
if !nextByCollector[name].After(day) {
|
||||
eligible[name] = collector
|
||||
}
|
||||
}
|
||||
|
||||
return eligible
|
||||
}
|
||||
48
ee/meterreporter/httpmeterreporter/telemetry.go
Normal file
48
ee/meterreporter/httpmeterreporter/telemetry.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package httpmeterreporter
|
||||
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
)
|
||||
|
||||
type reporterMetrics struct {
|
||||
checkpoints metric.Int64Counter
|
||||
reports metric.Int64Counter
|
||||
collections metric.Int64Counter
|
||||
meters metric.Int64Counter
|
||||
}
|
||||
|
||||
func newReporterMetrics(meter metric.Meter) (*reporterMetrics, error) {
|
||||
var errs error
|
||||
|
||||
checkpoints, err := meter.Int64Counter("signoz.meterreporter.checkpoints", metric.WithDescription("Zeus meter checkpoint fetches."), metric.WithUnit("{checkpoint}"))
|
||||
if err != nil {
|
||||
errs = errors.Join(errs, err)
|
||||
}
|
||||
|
||||
reports, err := meter.Int64Counter("signoz.meterreporter.reports", metric.WithDescription("Meter reports shipped to Zeus."), metric.WithUnit("{report}"))
|
||||
if err != nil {
|
||||
errs = errors.Join(errs, err)
|
||||
}
|
||||
|
||||
collections, err := meter.Int64Counter("signoz.meterreporter.collections", metric.WithDescription("Per-meter collect calls."), metric.WithUnit("{collection}"))
|
||||
if err != nil {
|
||||
errs = errors.Join(errs, err)
|
||||
}
|
||||
|
||||
meters, err := meter.Int64Counter("signoz.meterreporter.meters", metric.WithDescription("Meter readings shipped to Zeus."), metric.WithUnit("{meter}"))
|
||||
if err != nil {
|
||||
errs = errors.Join(errs, err)
|
||||
}
|
||||
|
||||
if errs != nil {
|
||||
return nil, errs
|
||||
}
|
||||
|
||||
return &reporterMetrics{
|
||||
checkpoints: checkpoints,
|
||||
reports: reports,
|
||||
collections: collections,
|
||||
meters: meters,
|
||||
}, nil
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func NewServer(config signoz.Config, signoz *signoz.SigNoz) (*Server, error) {
|
||||
// initiate agent config handler
|
||||
agentConfMgr, err := agentConf.Initiate(&agentConf.ManagerOptions{
|
||||
Store: signoz.SQLStore,
|
||||
AgentFeatures: []agentConf.AgentFeature{logParsingPipelineController},
|
||||
AgentFeatures: []agentConf.AgentFeature{logParsingPipelineController, signoz.Modules.LLMPricingRule},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -150,6 +150,72 @@ func (provider *Provider) PutMetersV2(ctx context.Context, key string, data []by
|
||||
return err
|
||||
}
|
||||
|
||||
func (provider *Provider) PutMetersV3(ctx context.Context, key string, idempotencyKey string, data []byte) error {
|
||||
headers := http.Header{}
|
||||
if idempotencyKey != "" {
|
||||
headers.Set("X-Idempotency-Key", idempotencyKey)
|
||||
}
|
||||
|
||||
_, err := provider.doWithHeaders(
|
||||
ctx,
|
||||
provider.config.URL.JoinPath("/v2/meters"),
|
||||
http.MethodPost,
|
||||
key,
|
||||
data,
|
||||
headers,
|
||||
)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (provider *Provider) ListMeterCheckpoints(ctx context.Context, key string) ([]zeustypes.MeterCheckpoint, error) {
|
||||
response, err := provider.do(
|
||||
ctx,
|
||||
provider.config.URL.JoinPath("/v2/meters/checkpoints"),
|
||||
http.MethodGet,
|
||||
key,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
checkpointValues := gjson.GetBytes(response, "data")
|
||||
if !checkpointValues.Exists() || checkpointValues.Type == gjson.Null {
|
||||
return nil, errors.Newf(errors.TypeInternal, zeus.ErrCodeResponseMalformed, "meter checkpoints are required")
|
||||
}
|
||||
|
||||
if !checkpointValues.IsArray() {
|
||||
return nil, errors.Newf(errors.TypeInternal, zeus.ErrCodeResponseMalformed, "meter checkpoints must be an array")
|
||||
}
|
||||
|
||||
checkpointResults := checkpointValues.Array()
|
||||
checkpoints := make([]zeustypes.MeterCheckpoint, 0, len(checkpointResults))
|
||||
for _, checkpointValue := range checkpointResults {
|
||||
name := checkpointValue.Get("name").String()
|
||||
if name == "" {
|
||||
return nil, errors.Newf(errors.TypeInternal, zeus.ErrCodeResponseMalformed, "meter checkpoint name is required")
|
||||
}
|
||||
|
||||
startDateString := checkpointValue.Get("start_date").String()
|
||||
if startDateString == "" {
|
||||
return nil, errors.Newf(errors.TypeInternal, zeus.ErrCodeResponseMalformed, "meter checkpoint start_date is required for %q", name)
|
||||
}
|
||||
|
||||
startDate, err := time.Parse("2006-01-02", startDateString)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, errors.TypeInternal, zeus.ErrCodeResponseMalformed, "parse meter checkpoint start_date %q for %q", startDateString, name)
|
||||
}
|
||||
|
||||
checkpoints = append(checkpoints, zeustypes.MeterCheckpoint{
|
||||
Name: name,
|
||||
StartDate: startDate,
|
||||
})
|
||||
}
|
||||
|
||||
return checkpoints, nil
|
||||
}
|
||||
|
||||
func (provider *Provider) PutProfile(ctx context.Context, key string, profile *zeustypes.PostableProfile) error {
|
||||
body, err := json.Marshal(profile)
|
||||
if err != nil {
|
||||
@@ -185,12 +251,21 @@ func (provider *Provider) PutHost(ctx context.Context, key string, host *zeustyp
|
||||
}
|
||||
|
||||
func (provider *Provider) do(ctx context.Context, url *url.URL, method string, key string, requestBody []byte) ([]byte, error) {
|
||||
return provider.doWithHeaders(ctx, url, method, key, requestBody, nil)
|
||||
}
|
||||
|
||||
func (provider *Provider) doWithHeaders(ctx context.Context, url *url.URL, method string, key string, requestBody []byte, extraHeaders http.Header) ([]byte, error) {
|
||||
request, err := http.NewRequestWithContext(ctx, method, url.String(), bytes.NewBuffer(requestBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Header.Set("X-Signoz-Cloud-Api-Key", key)
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
for k, vs := range extraHeaders {
|
||||
for _, v := range vs {
|
||||
request.Header.Add(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
response, err := provider.httpClient.Do(request)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
cd frontend && yarn run commitlint --edit $1
|
||||
cd frontend && pnpm run commitlint --edit $1
|
||||
|
||||
branch="$(git rev-parse --abbrev-ref HEAD)"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
cd frontend && yarn lint-staged
|
||||
cd frontend && pnpm lint-staged
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
registry = 'https://registry.npmjs.org/'
|
||||
registry = 'https://registry.npmjs.org/'
|
||||
|
||||
public-hoist-pattern[]=@commitlint*
|
||||
public-hoist-pattern[]=commitlint
|
||||
@@ -411,7 +411,7 @@
|
||||
"jsx-a11y/media-has-caption": "warn",
|
||||
"jsx-a11y/mouse-events-have-key-events": "warn",
|
||||
"jsx-a11y/no-access-key": "error",
|
||||
"jsx-a11y/no-autofocus": "warn",
|
||||
"jsx-a11y/no-autofocus": "off",
|
||||
"jsx-a11y/no-distracting-elements": "error",
|
||||
"jsx-a11y/no-redundant-roles": "warn",
|
||||
"jsx-a11y/role-has-required-aria-props": "warn",
|
||||
|
||||
@@ -28,8 +28,8 @@ Follow the steps below
|
||||
1. ```git clone https://github.com/SigNoz/signoz.git && cd signoz/frontend```
|
||||
1. change baseURL to ```<test environment URL>``` in file ```src/constants/env.ts```
|
||||
|
||||
1. ```yarn install```
|
||||
1. ```yarn dev```
|
||||
1. ```pnpm install```
|
||||
1. ```pnpm dev```
|
||||
|
||||
```Note: Please ping us in #contributing channel in our slack community and we will DM you with <test environment URL>```
|
||||
|
||||
@@ -41,7 +41,7 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `yarn start`
|
||||
### `pnpm start`
|
||||
|
||||
Runs the app in the development mode.\
|
||||
Open [http://localhost:3301](http://localhost:3301) to view it in the browser.
|
||||
@@ -49,12 +49,12 @@ Open [http://localhost:3301](http://localhost:3301) to view it in the browser.
|
||||
The page will reload if you make edits.\
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### `yarn test`
|
||||
### `pnpm test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.\
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `yarn build`
|
||||
### `pnpm build`
|
||||
|
||||
Builds the app for production to the `build` folder.\
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
@@ -64,7 +64,7 @@ Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `yarn eject`
|
||||
### `pnpm eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
@@ -100,6 +100,6 @@ This section has moved here: [https://facebook.github.io/create-react-app/docs/a
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
||||
|
||||
### `yarn build` fails to minify
|
||||
### `pnpm build` fails to minify
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
||||
|
||||
28
frontend/__mocks__/createIconsMock.tsx
Normal file
28
frontend/__mocks__/createIconsMock.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
|
||||
const IconMock = React.forwardRef<SVGSVGElement, React.SVGProps<SVGSVGElement>>(
|
||||
(props, ref) => <svg ref={ref} {...props} />,
|
||||
);
|
||||
IconMock.displayName = 'IconMock';
|
||||
|
||||
// Returns a Proxy that resolves any named export to IconMock by default,
|
||||
// so `import { AnyIcon } from '@signozhq/icons'` always returns a valid component.
|
||||
// Pass `overrides` to swap in test-specific stubs (e.g. icons with data-testid).
|
||||
export function createIconsMock(
|
||||
overrides: Record<string, unknown> = {},
|
||||
): Record<string | symbol, unknown> {
|
||||
return new Proxy(
|
||||
{ __esModule: true, default: IconMock, ...overrides } as Record<
|
||||
string | symbol,
|
||||
unknown
|
||||
>,
|
||||
{
|
||||
get(target, prop: string | symbol): unknown {
|
||||
if (prop in target) {
|
||||
return target[prop as string];
|
||||
}
|
||||
return IconMock;
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
3
frontend/__mocks__/signozhqIconsMock.tsx
Normal file
3
frontend/__mocks__/signozhqIconsMock.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
import { createIconsMock } from './createIconsMock';
|
||||
|
||||
module.exports = createIconsMock();
|
||||
@@ -24,8 +24,8 @@ const config: Config.InitialOptions = {
|
||||
'^.*/useSafeNavigate$': USE_SAFE_NAVIGATE_MOCK_PATH,
|
||||
'^constants/env$': '<rootDir>/__mocks__/env.ts',
|
||||
'^src/constants/env$': '<rootDir>/__mocks__/env.ts',
|
||||
'^@signozhq/icons$':
|
||||
'<rootDir>/node_modules/@signozhq/icons/dist/index.esm.js',
|
||||
'^@signozhq/icons$': '<rootDir>/__mocks__/signozhqIconsMock.tsx',
|
||||
'^test-mocks/(.*)$': '<rootDir>/__mocks__/$1',
|
||||
'^react-syntax-highlighter/dist/esm/(.*)$':
|
||||
'<rootDir>/node_modules/react-syntax-highlighter/dist/cjs/$1',
|
||||
'^@signozhq/(?!ui(?:/|$))([^/]+)$':
|
||||
@@ -46,7 +46,11 @@ const config: Config.InitialOptions = {
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
// @chenglou/pretext is ESM-only; @signozhq/ui pulls it in via text-ellipsis.
|
||||
'node_modules/(?!(lodash-es|react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend|axios|@chenglou/pretext|@signozhq/design-tokens|@signozhq/table|@signozhq/calendar|@signozhq/input|@signozhq/popover|@signozhq/*|date-fns|d3-interpolate|d3-color|api|@codemirror|@lezer|@marijn|@grafana|nuqs)/)',
|
||||
// Pattern 1: allow .pnpm virtual store through (handled by pattern 2), plus root-level ESM packages.
|
||||
'node_modules/(?!(\\.pnpm|lodash-es|react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend|axios|@chenglou/pretext|@signozhq/design-tokens|@signozhq|date-fns|d3-interpolate|d3-color|api|@codemirror|@lezer|@marijn|@grafana|nuqs|uuid)/)',
|
||||
// Pattern 2: pnpm virtual store — ignore everything except ESM-only packages.
|
||||
// pnpm encodes scoped packages as @scope+name@version, so match on scope prefix.
|
||||
'node_modules/\\.pnpm/(?!(lodash-es|react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend|axios|@chenglou|@signozhq|date-fns|d3-interpolate|d3-color|api|@codemirror|@lezer|@marijn|@grafana|nuqs|uuid)[^/]*/node_modules)',
|
||||
],
|
||||
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
|
||||
testPathIgnorePatterns: ['/node_modules/', '/public/'],
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* Adds custom matchers from the react testing library to all tests
|
||||
*/
|
||||
import '@testing-library/jest-dom';
|
||||
import '@testing-library/jest-dom/extend-expect';
|
||||
import 'jest-styled-components';
|
||||
|
||||
import { server } from './src/mocks-server/server';
|
||||
|
||||
@@ -80,7 +80,7 @@ export default defineConfig({
|
||||
header: (info: { title: string; version: string }): string[] => [
|
||||
`! Do not edit manually`,
|
||||
`* The file has been auto-generated using Orval for SigNoz`,
|
||||
`* regenerate with 'yarn generate:api'`,
|
||||
`* regenerate with 'pnpm generate:api'`,
|
||||
...(info.title ? [info.title] : []),
|
||||
...(info.version ? [`OpenAPI spec version: ${info.version}`] : []),
|
||||
],
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"jest": "jest",
|
||||
"jest:coverage": "jest --coverage",
|
||||
"jest:watch": "jest --watch",
|
||||
"postinstall": "yarn i18n:generate-hash && (is-ci || yarn husky:configure) && node scripts/update-registry.cjs",
|
||||
"postinstall": "pnpm i18n:generate-hash && (is-ci || pnpm husky:configure) && node scripts/update-registry.cjs",
|
||||
"husky:configure": "cd .. && husky install frontend/.husky && cd frontend && chmod ug+x .husky/*",
|
||||
"commitlint": "commitlint --edit $1",
|
||||
"test": "jest",
|
||||
@@ -32,9 +32,10 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "6.0.0",
|
||||
"@ant-design/icons": "4.8.0",
|
||||
"@codemirror/autocomplete": "6.18.6",
|
||||
"@codemirror/lang-javascript": "6.2.3",
|
||||
"@codemirror/state": "6.5.2",
|
||||
"@codemirror/view": "6.36.6",
|
||||
"@dnd-kit/core": "6.1.0",
|
||||
"@dnd-kit/modifiers": "7.0.0",
|
||||
"@dnd-kit/sortable": "8.0.0",
|
||||
@@ -48,7 +49,7 @@
|
||||
"@sentry/react": "8.41.0",
|
||||
"@sentry/vite-plugin": "2.22.6",
|
||||
"@signozhq/design-tokens": "2.1.4",
|
||||
"@signozhq/icons": "0.1.0",
|
||||
"@signozhq/icons": "0.4.0",
|
||||
"@signozhq/resizable": "0.0.2",
|
||||
"@signozhq/ui": "0.0.18",
|
||||
"@tanstack/react-table": "8.21.3",
|
||||
@@ -97,7 +98,6 @@
|
||||
"jest": "30.2.0",
|
||||
"js-base64": "^3.7.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lucide-react": "0.498.0",
|
||||
"mini-css-extract-plugin": "2.4.5",
|
||||
"motion": "12.4.13",
|
||||
"nuqs": "2.8.8",
|
||||
@@ -105,6 +105,7 @@
|
||||
"overlayscrollbars-react": "^0.5.6",
|
||||
"papaparse": "5.4.1",
|
||||
"posthog-js": "1.298.0",
|
||||
"rc-select": "14.10.0",
|
||||
"rc-tween-one": "3.0.6",
|
||||
"react": "18.2.0",
|
||||
"react-addons-update": "15.6.3",
|
||||
@@ -168,8 +169,8 @@
|
||||
"@babel/preset-env": "^7.22.14",
|
||||
"@babel/preset-react": "^7.12.13",
|
||||
"@babel/preset-typescript": "^7.21.4",
|
||||
"@commitlint/cli": "^20.4.2",
|
||||
"@commitlint/config-conventional": "^20.4.2",
|
||||
"@commitlint/cli": "20.4.4",
|
||||
"@commitlint/config-conventional": "20.4.4",
|
||||
"@faker-js/faker": "9.3.0",
|
||||
"@jest/globals": "30.2.0",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
@@ -179,8 +180,11 @@
|
||||
"@types/crypto-js": "4.2.2",
|
||||
"@types/dompurify": "^2.4.0",
|
||||
"@types/event-source-polyfill": "^1.0.0",
|
||||
"@types/d3-hierarchy": "1.1.11",
|
||||
"@types/fontfaceobserver": "2.1.0",
|
||||
"@types/history": "4.7.11",
|
||||
"@types/jest": "30.0.0",
|
||||
"@jest/types": "30.2.0",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"@types/mini-css-extract-plugin": "^2.5.1",
|
||||
"@types/node": "^16.10.3",
|
||||
@@ -198,11 +202,13 @@
|
||||
"@types/react-syntax-highlighter": "15.5.13",
|
||||
"@types/redux-mock-store": "1.0.4",
|
||||
"@types/styled-components": "^5.1.4",
|
||||
"@types/testing-library__jest-dom": "^5.14.5",
|
||||
"@types/uuid": "^8.3.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260421.2",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260430.1",
|
||||
"autoprefixer": "10.4.19",
|
||||
"babel-plugin-styled-components": "^1.12.0",
|
||||
"eslint-plugin-sonarjs": "4.0.2",
|
||||
"glob": "^13.0.6",
|
||||
"husky": "^7.0.4",
|
||||
"imagemin": "^8.0.1",
|
||||
"imagemin-svgo": "^10.0.1",
|
||||
@@ -213,7 +219,7 @@
|
||||
"lint-staged": "^12.5.0",
|
||||
"msw": "1.3.2",
|
||||
"npm-run-all": "latest",
|
||||
"orval": "7.18.0",
|
||||
"orval": "7.21.0",
|
||||
"oxfmt": "0.47.0",
|
||||
"oxlint": "1.62.0",
|
||||
"oxlint-tsgolint": "0.22.1",
|
||||
@@ -230,7 +236,7 @@
|
||||
"stylelint-scss": "7.0.0",
|
||||
"svgo": "4.0.0",
|
||||
"ts-api-utils": "2.4.0",
|
||||
"ts-jest": "29.4.6",
|
||||
"ts-jest": "29.4.9",
|
||||
"ts-node": "^10.2.1",
|
||||
"typescript-plugin-css-modules": "5.2.0",
|
||||
"use-sync-external-store": "1.6.0",
|
||||
|
||||
22419
frontend/pnpm-lock.yaml
generated
Normal file
22419
frontend/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,7 @@ echo "\n✅ Tag files renamed to index.ts"
|
||||
|
||||
# Format generated files
|
||||
echo "\n\n---\nRunning prettier...\n"
|
||||
if ! yarn prettify src/api/generated; then
|
||||
if ! pnpm prettify src/api/generated; then
|
||||
echo "Formatting failed!"
|
||||
exit 1
|
||||
fi
|
||||
@@ -25,7 +25,7 @@ echo "\n✅ Formatting successful"
|
||||
|
||||
# Fix linting issues
|
||||
echo "\n\n---\nRunning lint...\n"
|
||||
if ! yarn lint:generated; then
|
||||
if ! pnpm lint:generated; then
|
||||
echo "Lint check failed! Please fix linting errors before proceeding."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation } from 'react-query';
|
||||
@@ -17,11 +17,13 @@ import type {
|
||||
InframonitoringtypesPostableNamespacesDTO,
|
||||
InframonitoringtypesPostableNodesDTO,
|
||||
InframonitoringtypesPostablePodsDTO,
|
||||
InframonitoringtypesPostableVolumesDTO,
|
||||
ListClusters200,
|
||||
ListHosts200,
|
||||
ListNamespaces200,
|
||||
ListNodes200,
|
||||
ListPods200,
|
||||
ListVolumes200,
|
||||
RenderErrorResponseDTO,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
@@ -448,3 +450,87 @@ export const useListPods = <
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Returns a paginated list of Kubernetes persistent volume claims (PVCs) with key volume metrics: available bytes, capacity bytes, usage (capacity - available), inodes, free inodes, and used inodes. Each row also includes metadata attributes (k8s.persistentvolumeclaim.name, k8s.pod.uid, k8s.pod.name, k8s.namespace.name, k8s.node.name, k8s.statefulset.name, k8s.cluster.name). Supports filtering via a filter expression, custom groupBy to aggregate volumes by any attribute, ordering by any of the six metrics (available, capacity, usage, inodes, inodes_free, inodes_used), and pagination via offset/limit. The response type is 'list' for the default k8s.persistentvolumeclaim.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates volumes in the group. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (volumeAvailable, volumeCapacity, volumeUsage, volumeInodes, volumeInodesFree, volumeInodesUsed) return -1 as a sentinel when no data is available for that field.
|
||||
* @summary List Volumes for Infra Monitoring
|
||||
*/
|
||||
export const listVolumes = (
|
||||
inframonitoringtypesPostableVolumesDTO: BodyType<InframonitoringtypesPostableVolumesDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListVolumes200>({
|
||||
url: `/api/v2/infra_monitoring/pvcs`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: inframonitoringtypesPostableVolumesDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListVolumesMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listVolumes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableVolumesDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listVolumes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableVolumesDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['listVolumes'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof listVolumes>>,
|
||||
{ data: BodyType<InframonitoringtypesPostableVolumesDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return listVolumes(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type ListVolumesMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listVolumes>>
|
||||
>;
|
||||
export type ListVolumesMutationBody =
|
||||
BodyType<InframonitoringtypesPostableVolumesDTO>;
|
||||
export type ListVolumesMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List Volumes for Infra Monitoring
|
||||
*/
|
||||
export const useListVolumes = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listVolumes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableVolumesDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof listVolumes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableVolumesDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getListVolumesMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
export interface AlertmanagertypesChannelDTO {
|
||||
@@ -5085,6 +5085,34 @@ export interface InframonitoringtypesPostablePodsDTO {
|
||||
start: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesPostableVolumesDTO {
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
end: number;
|
||||
filter?: Querybuildertypesv5FilterDTO;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
groupBy?: Querybuildertypesv5GroupByKeyDTO[] | null;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
limit: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
offset?: number;
|
||||
orderBy?: Querybuildertypesv5OrderByDTO;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
start: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesRequiredMetricsCheckDTO {
|
||||
/**
|
||||
* @type array
|
||||
@@ -5097,6 +5125,74 @@ export enum InframonitoringtypesResponseTypeDTO {
|
||||
list = 'list',
|
||||
grouped_list = 'grouped_list',
|
||||
}
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type InframonitoringtypesVolumeRecordDTOMeta = {
|
||||
[key: string]: string;
|
||||
} | null;
|
||||
|
||||
export interface InframonitoringtypesVolumeRecordDTO {
|
||||
/**
|
||||
* @type object
|
||||
* @nullable true
|
||||
*/
|
||||
meta: InframonitoringtypesVolumeRecordDTOMeta;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
persistentVolumeClaimName: string;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeAvailable: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeCapacity: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeInodes: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeInodesFree: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeInodesUsed: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeUsage: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesVolumesDTO {
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
records: InframonitoringtypesVolumeRecordDTO[] | null;
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
total: number;
|
||||
type: InframonitoringtypesResponseTypeDTO;
|
||||
warning?: Querybuildertypesv5QueryWarnDataDTO;
|
||||
}
|
||||
|
||||
export interface LlmpricingruletypesGettablePricingRulesDTO {
|
||||
/**
|
||||
* @type array
|
||||
@@ -7479,7 +7575,7 @@ export interface SpantypesPostableSpanMapperDTO {
|
||||
* @type boolean
|
||||
*/
|
||||
enabled?: boolean;
|
||||
field_context: SpantypesFieldContextDTO;
|
||||
fieldContext: SpantypesFieldContextDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7487,7 +7583,6 @@ export interface SpantypesPostableSpanMapperDTO {
|
||||
}
|
||||
|
||||
export interface SpantypesPostableSpanMapperGroupDTO {
|
||||
category: SpantypesSpanMapperGroupCategoryDTO;
|
||||
condition: SpantypesSpanMapperGroupConditionDTO;
|
||||
/**
|
||||
* @type boolean
|
||||
@@ -7514,7 +7609,7 @@ export interface SpantypesSpanMapperDTO {
|
||||
* @type boolean
|
||||
*/
|
||||
enabled: boolean;
|
||||
field_context: SpantypesFieldContextDTO;
|
||||
fieldContext: SpantypesFieldContextDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7547,7 +7642,6 @@ export interface SpantypesSpanMapperConfigDTO {
|
||||
}
|
||||
|
||||
export interface SpantypesSpanMapperGroupDTO {
|
||||
category: SpantypesSpanMapperGroupCategoryDTO;
|
||||
condition: SpantypesSpanMapperGroupConditionDTO;
|
||||
/**
|
||||
* @type string
|
||||
@@ -7585,11 +7679,10 @@ export interface SpantypesSpanMapperGroupDTO {
|
||||
updatedBy?: string;
|
||||
}
|
||||
|
||||
export interface SpantypesSpanMapperGroupCategoryDTO {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface SpantypesSpanMapperGroupConditionDTO {
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type SpantypesSpanMapperGroupConditionDTO = {
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
@@ -7600,7 +7693,7 @@ export interface SpantypesSpanMapperGroupConditionDTO {
|
||||
* @nullable true
|
||||
*/
|
||||
resource: string[] | null;
|
||||
}
|
||||
} | null;
|
||||
|
||||
export enum SpantypesSpanMapperOperationDTO {
|
||||
move = 'move',
|
||||
@@ -7626,7 +7719,7 @@ export interface SpantypesUpdatableSpanMapperDTO {
|
||||
* @nullable true
|
||||
*/
|
||||
enabled?: boolean | null;
|
||||
field_context?: SpantypesFieldContextDTO;
|
||||
fieldContext?: SpantypesFieldContextDTO;
|
||||
}
|
||||
|
||||
export interface SpantypesUpdatableSpanMapperGroupDTO {
|
||||
@@ -9174,10 +9267,6 @@ export type GetMyServiceAccount200 = {
|
||||
};
|
||||
|
||||
export type ListSpanMapperGroupsParams = {
|
||||
/**
|
||||
* @description undefined
|
||||
*/
|
||||
category?: SpantypesSpanMapperGroupCategoryDTO;
|
||||
/**
|
||||
* @type boolean
|
||||
* @nullable true
|
||||
@@ -9452,6 +9541,14 @@ export type ListPods200 = {
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type ListVolumes200 = {
|
||||
data: InframonitoringtypesVolumesDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type Livez200 = {
|
||||
data: FactoryResponseDTO;
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* * regenerate with 'pnpm generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ErrorContent from 'components/ErrorModal/components/ErrorContent';
|
||||
import { CircleAlert } from 'lucide-react';
|
||||
import { CircleAlert } from '@signozhq/icons';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
import './AuthError.styles.scss';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { ArrowUpRight } from 'lucide-react';
|
||||
import { ArrowUpRight } from '@signozhq/icons';
|
||||
|
||||
import './AuthFooter.styles.scss';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useCallback } from 'react';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { LifeBuoy } from 'lucide-react';
|
||||
import { LifeBuoy } from '@signozhq/icons';
|
||||
|
||||
import signozBrandLogoUrl from '@/assets/Logos/signoz-brand-logo.svg';
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useMutation } from 'react-query';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import { Loader, Search } from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Loader } from '@signozhq/icons';
|
||||
import {
|
||||
Button,
|
||||
Flex,
|
||||
Input,
|
||||
InputRef,
|
||||
Progress,
|
||||
@@ -108,9 +108,11 @@ const getColumnSearchProps = (
|
||||
type="primary"
|
||||
size="small"
|
||||
onClick={(): void => handleSearch(selectedKeys as string[], confirm)}
|
||||
icon={<SearchOutlined />}
|
||||
>
|
||||
Search
|
||||
<Flex align="center" gap={4}>
|
||||
<Search size="md" />
|
||||
Search
|
||||
</Flex>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={(): void => clearFilters && handleReset(clearFilters, confirm)}
|
||||
@@ -132,8 +134,9 @@ const getColumnSearchProps = (
|
||||
</div>
|
||||
),
|
||||
filterIcon: (filtered: boolean): JSX.Element => (
|
||||
<SearchOutlined
|
||||
<Search
|
||||
style={{ color: filtered ? Color.BG_ROBIN_500 : undefined }}
|
||||
size="md"
|
||||
/>
|
||||
),
|
||||
onFilter: (value, record): boolean =>
|
||||
|
||||
@@ -6,7 +6,7 @@ import logEvent from 'api/common/logEvent';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import dayjs from 'dayjs';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { X } from 'lucide-react';
|
||||
import { X } from '@signozhq/icons';
|
||||
import { Widgets } from 'types/api/dashboard/getAll';
|
||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { CardContainer } from 'container/GridCardLayout/styles';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { ChevronDown, ChevronUp } from 'lucide-react';
|
||||
import { ChevronDown, ChevronUp } from '@signozhq/icons';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import cx from 'classnames';
|
||||
import { ArrowDown, ArrowUp } from 'lucide-react';
|
||||
import { ArrowDown, ArrowUp } from '@signozhq/icons';
|
||||
|
||||
import './ChangePercentagePill.styles.scss';
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useMutation } from 'react-query';
|
||||
import { CheckOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import { Button, Modal } from 'antd';
|
||||
import { Check, ChevronsDown, ScrollText, X } from '@signozhq/icons';
|
||||
import { Button, Flex, Modal } from 'antd';
|
||||
import updateUserPreference from 'api/v1/user/preferences/name/update';
|
||||
import cx from 'classnames';
|
||||
import { USER_PREFERENCES } from 'constants/userPreferences';
|
||||
import dayjs from 'dayjs';
|
||||
import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
|
||||
import { ChevronsDown, ScrollText } from 'lucide-react';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { ChangelogSchema } from 'types/api/changelog/getChangelogByVersion';
|
||||
import { UserPreference } from 'types/api/preferences/preference';
|
||||
@@ -116,15 +115,17 @@ function ChangelogModal({ changelog, onClose }: Props): JSX.Element {
|
||||
>
|
||||
{!isCloudUser && (
|
||||
<div className="changelog-modal-footer-ctas">
|
||||
<Button type="default" icon={<CloseOutlined />} onClick={onClose}>
|
||||
Skip for now
|
||||
<Button type="default" onClick={onClose}>
|
||||
<Flex align="center" gap="4px">
|
||||
<X size="md" />
|
||||
Skip for now
|
||||
</Flex>
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<CheckOutlined />}
|
||||
onClick={onClickUpdateWorkspace}
|
||||
>
|
||||
Update my workspace
|
||||
<Button type="primary" onClick={onClickUpdateWorkspace}>
|
||||
<Flex align="center" gap="4px">
|
||||
<Check size="md" />
|
||||
Update my workspace
|
||||
</Flex>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import updateCreditCardApi from 'api/v1/checkout/create';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { CreditCard, MessageSquareText, X } from 'lucide-react';
|
||||
import { CreditCard, MessageSquareText, X } from '@signozhq/icons';
|
||||
import { SuccessResponseV2 } from 'types/api';
|
||||
import { CheckoutSuccessPayloadProps } from 'types/api/billing/checkout';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
@@ -37,7 +37,7 @@ import { validationMapper } from 'hooks/queryBuilder/useIsValidTag';
|
||||
import { operatorTypeMapper } from 'hooks/queryBuilder/useOperatorType';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { isArray, isEmpty, isEqual, isObject } from 'lodash-es';
|
||||
import { ChevronDown, ChevronUp } from 'lucide-react';
|
||||
import { ChevronDown, ChevronUp } from '@signozhq/icons';
|
||||
import type { BaseSelectRef } from 'rc-select';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
CloudintegrationtypesCollectedLogAttributeDTO,
|
||||
CloudintegrationtypesCollectedMetricDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import { BarChart2, ScrollText } from 'lucide-react';
|
||||
import { BarChart, ScrollText } from '@signozhq/icons';
|
||||
|
||||
import './CloudServiceDataCollected.styles.scss';
|
||||
|
||||
@@ -82,7 +82,7 @@ function CloudServiceDataCollected({
|
||||
{metricsData && metricsData.length > 0 && (
|
||||
<div className="cloud-service-data-collected-table">
|
||||
<div className="cloud-service-data-collected-table-heading">
|
||||
<BarChart2 size={14} />
|
||||
<BarChart size={14} />
|
||||
Metrics
|
||||
</div>
|
||||
<Table
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Calendar } from '@signozhq/ui/calendar';
|
||||
import { Button } from 'antd';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import dayjs from 'dayjs';
|
||||
import { CalendarIcon, Check, X } from 'lucide-react';
|
||||
import { Calendar as CalendarIcon, Check, X } from '@signozhq/icons';
|
||||
import { useTimezone } from 'providers/Timezone';
|
||||
|
||||
import { DateRange } from './CustomTimePickerPopoverContent';
|
||||
|
||||
@@ -23,7 +23,7 @@ import { useZoomOut } from 'hooks/useZoomOut';
|
||||
import { isValidShortHandDateTimeFormat } from 'lib/getMinMax';
|
||||
import { isZoomOutDisabled } from 'lib/zoomOutUtils';
|
||||
import { defaultTo, isFunction, noop } from 'lodash-es';
|
||||
import { ChevronDown, ChevronUp, ZoomOut } from 'lucide-react';
|
||||
import { ChevronDown, ChevronUp, ZoomOut } from '@signozhq/icons';
|
||||
import { useTimezone } from 'providers/Timezone';
|
||||
import { getTimeDifference, validateEpochRange } from 'utils/epochUtils';
|
||||
import { popupContainer } from 'utils/selectPopupContainer';
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
Option,
|
||||
} from 'container/TopNav/DateTimeSelectionV2/types';
|
||||
import dayjs from 'dayjs';
|
||||
import { Clock, PenLine, TriangleAlertIcon } from 'lucide-react';
|
||||
import { Clock, PenLine, TriangleAlert } from '@signozhq/icons';
|
||||
import { useTimezone } from 'providers/Timezone';
|
||||
import { getCustomTimeRanges } from 'utils/customTimeRangeUtils';
|
||||
import { TimeRangeValidationResult } from 'utils/timeUtils';
|
||||
@@ -300,7 +300,7 @@ function CustomTimePickerPopoverContent({
|
||||
inputErrorDetails && (
|
||||
<div className="input-error-message-container">
|
||||
<div className="input-error-message-title">
|
||||
<TriangleAlertIcon color={Color.BG_CHERRY_400} size={16} />
|
||||
<TriangleAlert color={Color.BG_CHERRY_400} size={16} />
|
||||
<span className="input-error-message-text">
|
||||
{inputErrorDetails.message}
|
||||
</span>
|
||||
|
||||
@@ -11,7 +11,7 @@ import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
import { TimezonePickerShortcuts } from 'constants/shortcuts/TimezonePickerShortcuts';
|
||||
import { useKeyboardHotkeys } from 'hooks/hotkeys/useKeyboardHotkeys';
|
||||
import { Check, Search } from 'lucide-react';
|
||||
import { Check, Search } from '@signozhq/icons';
|
||||
import { useTimezone } from 'providers/Timezone';
|
||||
|
||||
import { Timezone, TIMEZONE_DATA } from './timezoneUtils';
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Button, Popover, Radio, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { useExportRawData } from 'hooks/useDownloadOptionsMenu/useDownloadOptionsMenu';
|
||||
import { Download, DownloadIcon, Loader2 } from 'lucide-react';
|
||||
import { Download, LoaderCircle } from '@signozhq/icons';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import {
|
||||
@@ -140,9 +140,9 @@ export default function DownloadOptionsMenu({
|
||||
className="periscope-btn ghost"
|
||||
icon={
|
||||
isDownloading ? (
|
||||
<Loader2 size={14} className="animate-spin" />
|
||||
<LoaderCircle size={14} className="animate-spin" />
|
||||
) : (
|
||||
<DownloadIcon size={14} />
|
||||
<Download size={14} />
|
||||
)
|
||||
}
|
||||
data-testid={`periscope-btn-download-${dataSource}`}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { EllipsisOutlined } from '@ant-design/icons';
|
||||
import { Ellipsis } from '@signozhq/icons';
|
||||
import { Button, Dropdown, MenuProps } from 'antd';
|
||||
|
||||
import './DropDown.styles.scss';
|
||||
@@ -38,7 +38,7 @@ function DropDown({
|
||||
setDdOpen(true);
|
||||
}}
|
||||
>
|
||||
<EllipsisOutlined className="dropdown-icon" />
|
||||
<Ellipsis className="dropdown-icon" size={16} />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Modal, Tag } from 'antd';
|
||||
import { CircleAlert, X } from 'lucide-react';
|
||||
import { CircleAlert, X } from '@signozhq/icons';
|
||||
import KeyValueLabel from 'periscope/components/KeyValueLabel';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from 'antd';
|
||||
import ErrorIcon from 'assets/Error';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
import { BookOpenText, ChevronsDown } from 'lucide-react';
|
||||
import { BookOpenText, ChevronsDown } from '@signozhq/icons';
|
||||
import KeyValueLabel from 'periscope/components/KeyValueLabel';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
import {
|
||||
DeleteOutlined,
|
||||
MoreOutlined,
|
||||
SaveOutlined,
|
||||
ShareAltOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
@@ -44,6 +38,7 @@ import {
|
||||
} from './styles';
|
||||
import { ExplorerCardProps } from './types';
|
||||
import { deleteViewHandler } from './utils';
|
||||
import { Ellipsis, Save, Share2, Trash2 } from '@signozhq/icons';
|
||||
|
||||
function ExplorerCard({
|
||||
sourcepage,
|
||||
@@ -159,13 +154,13 @@ function ExplorerCard({
|
||||
key: 'delete',
|
||||
label: <Typography.Text strong>Delete</Typography.Text>,
|
||||
onClick: onDeleteHandler,
|
||||
icon: <DeleteOutlined />,
|
||||
icon: <Trash2 size="md" />,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const saveButtonType = isQueryUpdated ? 'default' : 'primary';
|
||||
const saveButtonIcon = isQueryUpdated ? null : <SaveOutlined />;
|
||||
const saveButtonIcon = isQueryUpdated ? null : <Save size="md" />;
|
||||
|
||||
const showSaveView = false;
|
||||
|
||||
@@ -215,11 +210,7 @@ function ExplorerCard({
|
||||
</Space>
|
||||
)}
|
||||
{isQueryUpdated && (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<SaveOutlined />}
|
||||
onClick={onUpdateQueryHandler}
|
||||
>
|
||||
<Button type="primary" icon={<Save />} onClick={onUpdateQueryHandler}>
|
||||
Save changes
|
||||
</Button>
|
||||
)}
|
||||
@@ -248,10 +239,10 @@ function ExplorerCard({
|
||||
: SaveButtonText.SAVE_VIEW}
|
||||
</Button>
|
||||
</Popover>
|
||||
<ShareAltOutlined onClick={onCopyUrlHandler} />
|
||||
<Share2 onClick={onCopyUrlHandler} size="md" />
|
||||
{viewKey && (
|
||||
<Dropdown trigger={['click']} menu={moreOptionMenu}>
|
||||
<MoreOutlined />
|
||||
<Ellipsis size="md" />
|
||||
</Dropdown>
|
||||
)}
|
||||
</Space>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { MouseEvent, useCallback } from 'react';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import { Trash2 } from '@signozhq/icons';
|
||||
import { Col, Row, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
@@ -32,7 +32,7 @@ function MenuItemGenerator({
|
||||
|
||||
const { mutateAsync: deleteViewAsync } = useDeleteView(uuid);
|
||||
|
||||
const onDeleteHandler = (event: MouseEvent<HTMLElement>): void => {
|
||||
const onDeleteHandler = (event: MouseEvent<SVGSVGElement>): void => {
|
||||
event.stopPropagation();
|
||||
deleteViewHandler({
|
||||
deleteViewAsync,
|
||||
@@ -87,7 +87,12 @@ function MenuItemGenerator({
|
||||
</Col>
|
||||
<Col span={2}>
|
||||
<Typography.Link>
|
||||
<DeleteOutlined onClick={onDeleteHandler} />
|
||||
<Trash2
|
||||
role="img"
|
||||
aria-label="Delete view"
|
||||
onClick={onDeleteHandler}
|
||||
size="md"
|
||||
/>
|
||||
</Typography.Link>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -55,7 +55,7 @@ describe('MenuItemGenerator', () => {
|
||||
);
|
||||
|
||||
const spanElement = screen.getByRole('img', {
|
||||
name: 'delete',
|
||||
name: /delete view/i,
|
||||
});
|
||||
|
||||
expect(spanElement).toBeInTheDocument();
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useLocation } from 'react-router-dom';
|
||||
import { Button, Popover } from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
|
||||
import { Globe, Inbox, SquarePen } from 'lucide-react';
|
||||
import { Globe, Inbox, SquarePen } from '@signozhq/icons';
|
||||
|
||||
import AnnouncementsModal from './AnnouncementsModal';
|
||||
import FeedbackModal from './FeedbackModal';
|
||||
@@ -105,6 +105,7 @@ function HeaderRightSection({
|
||||
onOpenChange={handleOpenAnnouncementsModalChange}
|
||||
>
|
||||
<Button
|
||||
aria-label="Announcements"
|
||||
icon={<Inbox size={14} />}
|
||||
className="periscope-btn ghost announcements-btn"
|
||||
onClick={(): void => {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { QueryParams } from 'constants/query';
|
||||
import ROUTES from 'constants/routes';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
import GetMinMax from 'lib/getMinMax';
|
||||
import { Check, Info, Link2 } from 'lucide-react';
|
||||
import { Check, Info, Link2 } from '@signozhq/icons';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
import { getAbsoluteUrl } from 'utils/basePath';
|
||||
|
||||
@@ -80,15 +80,10 @@ describe('HeaderRightSection', () => {
|
||||
expect(buttons).toHaveLength(3);
|
||||
expect(screen.getByRole('button', { name: /share/i })).toBeInTheDocument();
|
||||
|
||||
// Check for feedback button by class
|
||||
const feedbackButton = document.querySelector(
|
||||
'.share-feedback-btn[class*="share-feedback-btn"]',
|
||||
);
|
||||
expect(feedbackButton).toBeInTheDocument();
|
||||
|
||||
// Check for announcements button by finding the inbox icon
|
||||
const inboxIcon = document.querySelector('.lucide-inbox');
|
||||
expect(inboxIcon).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /feedback/i })).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole('button', { name: /announcements/i }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render only enabled features', () => {
|
||||
@@ -106,22 +101,17 @@ describe('HeaderRightSection', () => {
|
||||
screen.queryByRole('button', { name: /share/i }),
|
||||
).not.toBeInTheDocument();
|
||||
|
||||
// Check that inbox icon is not present
|
||||
const inboxIcon = document.querySelector('.lucide-inbox');
|
||||
expect(inboxIcon).not.toBeInTheDocument();
|
||||
|
||||
// Check that feedback button is present
|
||||
const squarePenIcon = document.querySelector('.lucide-square-pen');
|
||||
expect(squarePenIcon).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByRole('button', { name: /announcements/i }),
|
||||
).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /feedback/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should open feedback modal and log event when feedback button is clicked', async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<HeaderRightSection {...defaultProps} />);
|
||||
|
||||
const feedbackButton = document
|
||||
.querySelector('.lucide-square-pen')
|
||||
?.closest('button');
|
||||
const feedbackButton = screen.getByRole('button', { name: /feedback/i });
|
||||
expect(feedbackButton).toBeInTheDocument();
|
||||
|
||||
await user.click(feedbackButton!);
|
||||
@@ -149,9 +139,9 @@ describe('HeaderRightSection', () => {
|
||||
const user = userEvent.setup();
|
||||
render(<HeaderRightSection {...defaultProps} />);
|
||||
|
||||
const announcementsButton = document
|
||||
.querySelector('.lucide-inbox')
|
||||
?.closest('button');
|
||||
const announcementsButton = screen.getByRole('button', {
|
||||
name: /announcements/i,
|
||||
});
|
||||
expect(announcementsButton).toBeInTheDocument();
|
||||
|
||||
await user.click(announcementsButton!);
|
||||
@@ -166,9 +156,7 @@ describe('HeaderRightSection', () => {
|
||||
render(<HeaderRightSection {...defaultProps} />);
|
||||
|
||||
// Open feedback modal
|
||||
const feedbackButton = document
|
||||
.querySelector('.lucide-square-pen')
|
||||
?.closest('button');
|
||||
const feedbackButton = screen.getByRole('button', { name: /feedback/i });
|
||||
expect(feedbackButton).toBeInTheDocument();
|
||||
|
||||
await user.click(feedbackButton!);
|
||||
@@ -190,9 +178,7 @@ describe('HeaderRightSection', () => {
|
||||
expect(screen.getByTestId('share-modal')).toBeInTheDocument();
|
||||
|
||||
// Open feedback modal - should close share modal
|
||||
const feedbackButton = document
|
||||
.querySelector('.lucide-square-pen')
|
||||
?.closest('button');
|
||||
const feedbackButton = screen.getByRole('button', { name: /feedback/i });
|
||||
expect(feedbackButton).toBeInTheDocument();
|
||||
|
||||
await user.click(feedbackButton!);
|
||||
@@ -210,7 +196,7 @@ describe('HeaderRightSection', () => {
|
||||
|
||||
render(<HeaderRightSection {...defaultProps} />);
|
||||
|
||||
const feedbackButton = document.querySelector('.lucide-square-pen');
|
||||
const feedbackButton = screen.queryByRole('button', { name: /feedback/i });
|
||||
expect(feedbackButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -224,7 +210,7 @@ describe('HeaderRightSection', () => {
|
||||
|
||||
render(<HeaderRightSection {...defaultProps} />);
|
||||
|
||||
const feedbackButton = document.querySelector('.lucide-square-pen');
|
||||
const feedbackButton = screen.queryByRole('button', { name: /feedback/i });
|
||||
expect(feedbackButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -238,7 +224,7 @@ describe('HeaderRightSection', () => {
|
||||
|
||||
render(<HeaderRightSection {...defaultProps} />);
|
||||
|
||||
const feedbackButton = document.querySelector('.lucide-square-pen');
|
||||
const feedbackButton = screen.queryByRole('button', { name: /feedback/i });
|
||||
expect(feedbackButton).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -252,7 +238,7 @@ describe('HeaderRightSection', () => {
|
||||
|
||||
render(<HeaderRightSection {...defaultProps} />);
|
||||
|
||||
const feedbackButton = document.querySelector('.lucide-square-pen');
|
||||
const feedbackButton = screen.queryByRole('button', { name: /feedback/i });
|
||||
expect(feedbackButton).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -272,11 +258,13 @@ describe('HeaderRightSection', () => {
|
||||
|
||||
// Verify which buttons are present
|
||||
expect(screen.getByRole('button', { name: /share/i })).toBeInTheDocument();
|
||||
const inboxIcon = document.querySelector('.lucide-inbox');
|
||||
expect(inboxIcon).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole('button', { name: /announcements/i }),
|
||||
).toBeInTheDocument();
|
||||
|
||||
// Verify feedback button is not present
|
||||
const feedbackIcon = document.querySelector('.lucide-square-pen');
|
||||
expect(feedbackIcon).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByRole('button', { name: /feedback/i }),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Button } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { CheckCircle2, HandPlatter } from 'lucide-react';
|
||||
import { CircleCheckBig, HandPlatter } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
|
||||
import './WaitListFragment.styles.scss';
|
||||
@@ -62,7 +62,7 @@ export default function WaitlistFragment({
|
||||
loading={isSubmitting}
|
||||
icon={
|
||||
isSuccess ? (
|
||||
<CheckCircle2 size={16} color={Color.BG_FOREST_500} />
|
||||
<CircleCheckBig size={16} color={Color.BG_FOREST_500} />
|
||||
) : (
|
||||
<HandPlatter size={16} />
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useState } from 'react';
|
||||
import { Button, Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import { X } from 'lucide-react';
|
||||
import { X } from '@signozhq/icons';
|
||||
|
||||
import './InputWithLabel.styles.scss';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { FeatureKeys } from 'constants/features';
|
||||
import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { defaultTo } from 'lodash-es';
|
||||
import { CreditCard, HelpCircle, X } from 'lucide-react';
|
||||
import { CircleHelp, CreditCard, X } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { SuccessResponseV2 } from 'types/api';
|
||||
import { CheckoutSuccessPayloadProps } from 'types/api/billing/checkout';
|
||||
@@ -170,7 +170,7 @@ function LaunchChatSupport({
|
||||
<Button
|
||||
className={cx('periscope-btn', 'facing-issue-button', className)}
|
||||
onClick={handleFacingIssuesClick}
|
||||
icon={<HelpCircle size={14} />}
|
||||
icon={<CircleHelp size={14} />}
|
||||
>
|
||||
{buttonText || 'Facing issues?'}
|
||||
</Button>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from 'antd';
|
||||
import { ArrowUpRight } from 'lucide-react';
|
||||
import { ArrowUpRight } from '@signozhq/icons';
|
||||
import { openInNewTab } from 'utils/navigation';
|
||||
|
||||
import './LearnMore.styles.scss';
|
||||
|
||||
@@ -36,17 +36,17 @@ import { cloneDeep } from 'lodash-es';
|
||||
import {
|
||||
ArrowDown,
|
||||
ArrowUp,
|
||||
BarChart2,
|
||||
Braces,
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
Compass,
|
||||
Copy,
|
||||
Filter,
|
||||
Histogram,
|
||||
Table,
|
||||
TextSelect,
|
||||
X,
|
||||
} from 'lucide-react';
|
||||
} from '@signozhq/icons';
|
||||
import { JsonView } from 'periscope/components/JsonView';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { AppState } from 'store/reducers';
|
||||
@@ -228,7 +228,7 @@ function LogDetailInner({
|
||||
}
|
||||
|
||||
return log?.body || '';
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return log?.body || '';
|
||||
}
|
||||
}, [isBodyJsonQueryEnabled, log?.body]);
|
||||
@@ -499,7 +499,7 @@ function LogDetailInner({
|
||||
value={VIEW_TYPES.INFRAMETRICS}
|
||||
>
|
||||
<div className="view-title">
|
||||
<BarChart2 size={14} />
|
||||
<Histogram size="md" />
|
||||
Metrics
|
||||
</div>
|
||||
</Radio.Button>
|
||||
@@ -517,7 +517,7 @@ function LogDetailInner({
|
||||
variant="link"
|
||||
color="secondary"
|
||||
size="sm"
|
||||
prefix={<Filter size={12} />}
|
||||
prefix={<Filter size="lg" />}
|
||||
onClick={handleFilterVisible}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { memo, MouseEventHandler } from 'react';
|
||||
import { LinkOutlined } from '@ant-design/icons';
|
||||
import { Link, TextSelect } from '@signozhq/icons';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { TextSelect } from 'lucide-react';
|
||||
|
||||
import './LogLinesActionButtons.styles.scss';
|
||||
|
||||
@@ -29,7 +28,7 @@ function LogLinesActionButtons({
|
||||
<Tooltip title="Copy Link">
|
||||
<Button
|
||||
size="small"
|
||||
icon={<LinkOutlined size={14} />}
|
||||
icon={<Link size={14} />}
|
||||
onClick={onLogCopy}
|
||||
className="copy-log-btn"
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { blue } from '@ant-design/colors';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Col, Row, Space } from 'antd';
|
||||
import { FontSize } from 'container/OptionsMenu/types';
|
||||
import { Info } from 'lucide-react';
|
||||
import { Info } from '@signozhq/icons';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
getActiveLogBackground,
|
||||
|
||||
@@ -12,9 +12,9 @@ import {
|
||||
ChevronRight,
|
||||
Minus,
|
||||
Plus,
|
||||
Sliders,
|
||||
SlidersVertical,
|
||||
X,
|
||||
} from 'lucide-react';
|
||||
} from '@signozhq/icons';
|
||||
|
||||
import './LogsFormatOptionsMenu.styles.scss';
|
||||
|
||||
@@ -473,7 +473,7 @@ function LogsFormatOptionsMenu({
|
||||
<Tooltip title="Options">
|
||||
<Button
|
||||
className="periscope-btn ghost"
|
||||
icon={<Sliders size={14} />}
|
||||
icon={<SlidersVertical size="md" />}
|
||||
data-testid="periscope-btn-format-options"
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import { CheckOutlined, CopyOutlined } from '@ant-design/icons';
|
||||
import { Check, Copy } from '@signozhq/icons';
|
||||
import cx from 'classnames';
|
||||
|
||||
import './CodeCopyBtn.scss';
|
||||
@@ -33,7 +33,7 @@ function CodeCopyBtn({
|
||||
return (
|
||||
<div className={cx('code-copy-btn', isSnippetCopied ? 'copied' : '')}>
|
||||
<button type="button" onClick={handleClick}>
|
||||
{!isSnippetCopied ? <CopyOutlined /> : <CheckOutlined />}
|
||||
{!isSnippetCopied ? <Copy size="md" /> : <Check size="md" />}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user