mirror of
https://github.com/SigNoz/signoz.git
synced 2026-06-15 21:20:28 +01:00
Compare commits
79 Commits
fix/checkb
...
chore/bump
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f71cbf296b | ||
|
|
080aae9567 | ||
|
|
45a9183c82 | ||
|
|
76e7e88641 | ||
|
|
1b7954faaf | ||
|
|
6f79d6b18d | ||
|
|
e57a9556e3 | ||
|
|
bf35748db5 | ||
|
|
2781f73057 | ||
|
|
7eb0095133 | ||
|
|
df26eb1c1d | ||
|
|
36334309bb | ||
|
|
cfcd58b341 | ||
|
|
45fedefbab | ||
|
|
01ae688b58 | ||
|
|
f4e1465c13 | ||
|
|
b22eef6a65 | ||
|
|
4d3d1ef423 | ||
|
|
c775d7e398 | ||
|
|
27603e09d0 | ||
|
|
7b2882abde | ||
|
|
30f1c2d92d | ||
|
|
446dd4589f | ||
|
|
c0c9039428 | ||
|
|
a014e9c0cb | ||
|
|
b898269ddc | ||
|
|
8fdad21a2e | ||
|
|
2e0d25479a | ||
|
|
73c2c15200 | ||
|
|
34203c781f | ||
|
|
1ba9b90855 | ||
|
|
927951b67a | ||
|
|
05ad8d113d | ||
|
|
faad1e659a | ||
|
|
e10a9515ef | ||
|
|
9ad37ad6e6 | ||
|
|
83b2cabbcd | ||
|
|
922800ff98 | ||
|
|
2d3772ef10 | ||
|
|
40e5cb4467 | ||
|
|
b072095a9d | ||
|
|
303908542a | ||
|
|
f52ce461d0 | ||
|
|
2e8aa0f42d | ||
|
|
c688170a13 | ||
|
|
7844fc1fe1 | ||
|
|
e02da843f2 | ||
|
|
0948a983c3 | ||
|
|
4f7ebd1ff1 | ||
|
|
15fbe4f788 | ||
|
|
7da7fda283 | ||
|
|
9093b4c442 | ||
|
|
97191eb7a2 | ||
|
|
9222845ce8 | ||
|
|
b3b245ebc5 | ||
|
|
9c9016d49e | ||
|
|
81eadac3a8 | ||
|
|
eec1c45e3f | ||
|
|
ce26458b9f | ||
|
|
7932917f5f | ||
|
|
4cf8125372 | ||
|
|
959e32b6f3 | ||
|
|
d3304af0ed | ||
|
|
df7ef3cdb5 | ||
|
|
f4ede36d3e | ||
|
|
fa7d941266 | ||
|
|
fdb22e6669 | ||
|
|
95adbc31cc | ||
|
|
c5288fc1ea | ||
|
|
86e71151d7 | ||
|
|
4fce33e2b3 | ||
|
|
a0ae4dfd05 | ||
|
|
a0b14e0835 | ||
|
|
987844dbc8 | ||
|
|
e0ad7e487a | ||
|
|
af72a4118b | ||
|
|
dc6a1d0a4e | ||
|
|
2e60ab0f81 | ||
|
|
29ed44a8ce |
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@@ -188,3 +188,7 @@ go.mod @therealpandey
|
||||
/frontend/src/container/ListAlertRules/ @SigNoz/pulse-frontend
|
||||
/frontend/src/container/TriggeredAlerts/ @SigNoz/pulse-frontend
|
||||
/frontend/src/container/AnomalyAlertEvaluationView/ @SigNoz/pulse-frontend
|
||||
|
||||
## OpenAPI Schema - Generated
|
||||
/frontend/src/api/generated/services/ @therealpandey @vikrantgupta25 @srikanthccv
|
||||
/docs/api/openapi.yml @therealpandey @vikrantgupta25 @srikanthccv
|
||||
|
||||
2
.github/workflows/build-enterprise.yaml
vendored
2
.github/workflows/build-enterprise.yaml
vendored
@@ -69,6 +69,8 @@ jobs:
|
||||
echo 'VITE_APPCUES_APP_ID="${{ secrets.APPCUES_APP_ID }}"' >> frontend/.env
|
||||
echo 'VITE_PYLON_IDENTITY_SECRET="${{ secrets.PYLON_IDENTITY_SECRET }}"' >> frontend/.env
|
||||
echo 'VITE_DOCS_BASE_URL="https://signoz.io"' >> frontend/.env
|
||||
echo 'VITE_ENVIRONMENT="production"' >> frontend/.env
|
||||
echo 'VITE_VERSION="${{ steps.build-info.outputs.version }}"' >> frontend/.env
|
||||
- name: cache-dotenv
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
|
||||
6
.github/workflows/build-staging.yaml
vendored
6
.github/workflows/build-staging.yaml
vendored
@@ -64,12 +64,18 @@ jobs:
|
||||
run: |
|
||||
mkdir -p frontend
|
||||
echo 'CI=1' > frontend/.env
|
||||
echo 'VITE_SENTRY_AUTH_TOKEN="${{ secrets.SENTRY_AUTH_TOKEN }}"' >> frontend/.env
|
||||
echo 'VITE_SENTRY_ORG="${{ secrets.SENTRY_ORG }}"' >> frontend/.env
|
||||
echo 'VITE_SENTRY_PROJECT_ID="${{ secrets.SENTRY_PROJECT_ID }}"' >> frontend/.env
|
||||
echo 'VITE_SENTRY_DSN="${{ secrets.SENTRY_DSN }}"' >> frontend/.env
|
||||
echo 'VITE_TUNNEL_URL="${{ secrets.NP_TUNNEL_URL }}"' >> frontend/.env
|
||||
echo 'VITE_TUNNEL_DOMAIN="${{ secrets.NP_TUNNEL_DOMAIN }}"' >> frontend/.env
|
||||
echo 'VITE_PYLON_APP_ID="${{ secrets.NP_PYLON_APP_ID }}"' >> frontend/.env
|
||||
echo 'VITE_APPCUES_APP_ID="${{ secrets.NP_APPCUES_APP_ID }}"' >> frontend/.env
|
||||
echo 'VITE_PYLON_IDENTITY_SECRET="${{ secrets.NP_PYLON_IDENTITY_SECRET }}"' >> frontend/.env
|
||||
echo 'VITE_DOCS_BASE_URL="https://staging.signoz.io"' >> frontend/.env
|
||||
echo 'VITE_ENVIRONMENT="staging"' >> frontend/.env
|
||||
echo 'VITE_VERSION="${{ steps.build-info.outputs.version }}"' >> frontend/.env
|
||||
- name: cache-dotenv
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
|
||||
2
.github/workflows/gor-signoz.yaml
vendored
2
.github/workflows/gor-signoz.yaml
vendored
@@ -35,6 +35,8 @@ jobs:
|
||||
echo 'VITE_APPCUES_APP_ID="${{ secrets.APPCUES_APP_ID }}"' >> .env
|
||||
echo 'VITE_PYLON_IDENTITY_SECRET="${{ secrets.PYLON_IDENTITY_SECRET }}"' >> .env
|
||||
echo 'VITE_DOCS_BASE_URL="https://signoz.io"' >> .env
|
||||
echo 'VITE_ENVIRONMENT="production"' >> .env
|
||||
echo 'VITE_VERSION="${{ github.ref_name }}"' >> .env
|
||||
- name: node-setup
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
|
||||
5
.github/workflows/integrationci.yaml
vendored
5
.github/workflows/integrationci.yaml
vendored
@@ -39,10 +39,12 @@ jobs:
|
||||
matrix:
|
||||
suite:
|
||||
- alerts
|
||||
- basepath
|
||||
- callbackauthn
|
||||
- cloudintegrations
|
||||
- dashboard
|
||||
- ingestionkeys
|
||||
- inframonitoring
|
||||
- logspipelines
|
||||
- passwordauthn
|
||||
- preference
|
||||
@@ -52,6 +54,7 @@ jobs:
|
||||
- rootuser
|
||||
- serviceaccount
|
||||
- querier_json_body
|
||||
- querier_skip_resource_fingerprint
|
||||
- ttl
|
||||
sqlstore-provider:
|
||||
- postgres
|
||||
@@ -82,7 +85,7 @@ jobs:
|
||||
run: |
|
||||
cd tests && uv sync
|
||||
- name: webdriver
|
||||
if: matrix.suite == 'callbackauthn'
|
||||
if: matrix.suite == 'callbackauthn' || matrix.suite == 'basepath'
|
||||
run: |
|
||||
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
|
||||
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee -a /etc/apt/sources.list.d/google-chrome.list
|
||||
|
||||
@@ -91,7 +91,7 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
sqlstoreProviderFactories(),
|
||||
signoz.NewTelemetryStoreProviderFactories(),
|
||||
func(ctx context.Context, providerSettings factory.ProviderSettings, store authtypes.AuthNStore, licensing licensing.Licensing) (map[authtypes.AuthNProvider]authn.AuthN, error) {
|
||||
return signoz.NewAuthNs(ctx, providerSettings, store, licensing)
|
||||
return signoz.NewAuthNs(ctx, providerSettings, store, licensing, config.Global)
|
||||
},
|
||||
func(ctx context.Context, sqlstore sqlstore.SQLStore, config authz.Config, _ licensing.Licensing, _ []authz.OnBeforeRoleDelete) (factory.ProviderFactory[authz.AuthZ, authz.Config], error) {
|
||||
openfgaDataStore, err := openfgaserver.NewSQLStore(sqlstore, config)
|
||||
|
||||
@@ -107,17 +107,17 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
sqlstoreProviderFactories(),
|
||||
signoz.NewTelemetryStoreProviderFactories(),
|
||||
func(ctx context.Context, providerSettings factory.ProviderSettings, store authtypes.AuthNStore, licensing licensing.Licensing) (map[authtypes.AuthNProvider]authn.AuthN, error) {
|
||||
samlCallbackAuthN, err := samlcallbackauthn.New(ctx, store, licensing)
|
||||
samlCallbackAuthN, err := samlcallbackauthn.New(ctx, store, licensing, config.Global)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oidcCallbackAuthN, err := oidccallbackauthn.New(store, licensing, providerSettings)
|
||||
oidcCallbackAuthN, err := oidccallbackauthn.New(store, licensing, providerSettings, config.Global)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authNs, err := signoz.NewAuthNs(ctx, providerSettings, store, licensing)
|
||||
authNs, err := signoz.NewAuthNs(ctx, providerSettings, store, licensing, config.Global)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -432,7 +432,7 @@ cloudintegration:
|
||||
version: v0.0.8
|
||||
|
||||
##################### Trace Detail #####################
|
||||
tracedetail:
|
||||
traces:
|
||||
waterfall:
|
||||
# Number of spans returned per request when the trace is too large to show all at once.
|
||||
span_page_size: 500
|
||||
@@ -440,6 +440,17 @@ tracedetail:
|
||||
max_depth_to_auto_expand: 5
|
||||
# Threshold below which all spans are returned without windowing.
|
||||
max_limit_to_select_all_spans: 10000
|
||||
flamegraph:
|
||||
# Maximum number of BFS depth levels included in a windowed response.
|
||||
max_selected_levels: 50
|
||||
# Maximum spans per level before sampling is applied.
|
||||
max_spans_per_level: 100
|
||||
# Number of highest-latency spans always included when sampling a level.
|
||||
sampling_top_latency_count: 5
|
||||
# Number of timestamp buckets used for uniform sampling within a level.
|
||||
sampling_bucket_count: 50
|
||||
# Threshold below which all spans are returned without windowing or sampling.
|
||||
select_all_spans_limit: 100000
|
||||
|
||||
##################### Authz #################################
|
||||
authz:
|
||||
|
||||
@@ -190,7 +190,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:v0.126.1
|
||||
image: signoz/signoz:v0.128.0
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
# - "6060:6060" # pprof port
|
||||
@@ -213,7 +213,7 @@ services:
|
||||
retries: 3
|
||||
otel-collector:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:v0.144.4
|
||||
image: signoz/signoz-otel-collector:v0.144.5
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
command:
|
||||
@@ -241,7 +241,7 @@ services:
|
||||
replicas: 3
|
||||
signoz-telemetrystore-migrator:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:v0.144.4
|
||||
image: signoz/signoz-otel-collector:v0.144.5
|
||||
environment:
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN=tcp://clickhouse:9000
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_CLUSTER=cluster
|
||||
|
||||
@@ -117,7 +117,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:v0.126.1
|
||||
image: signoz/signoz:v0.128.0
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
volumes:
|
||||
@@ -139,7 +139,7 @@ services:
|
||||
retries: 3
|
||||
otel-collector:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:v0.144.4
|
||||
image: signoz/signoz-otel-collector:v0.144.5
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
command:
|
||||
@@ -167,7 +167,7 @@ services:
|
||||
replicas: 3
|
||||
signoz-telemetrystore-migrator:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:v0.144.4
|
||||
image: signoz/signoz-otel-collector:v0.144.5
|
||||
environment:
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN=tcp://clickhouse:9000
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_CLUSTER=cluster
|
||||
|
||||
@@ -181,7 +181,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:${VERSION:-v0.126.1}
|
||||
image: signoz/signoz:${VERSION:-v0.128.0}
|
||||
container_name: signoz
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
@@ -204,7 +204,7 @@ services:
|
||||
retries: 3
|
||||
otel-collector:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.4}
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.5}
|
||||
container_name: signoz-otel-collector
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
@@ -229,7 +229,7 @@ services:
|
||||
- "4318:4318" # OTLP HTTP receiver
|
||||
signoz-telemetrystore-migrator:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.4}
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.5}
|
||||
container_name: signoz-telemetrystore-migrator
|
||||
environment:
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN=tcp://clickhouse:9000
|
||||
|
||||
@@ -109,7 +109,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:${VERSION:-v0.126.1}
|
||||
image: signoz/signoz:${VERSION:-v0.128.0}
|
||||
container_name: signoz
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
@@ -132,7 +132,7 @@ services:
|
||||
retries: 3
|
||||
otel-collector:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.4}
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.5}
|
||||
container_name: signoz-otel-collector
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
@@ -157,7 +157,7 @@ services:
|
||||
- "4318:4318" # OTLP HTTP receiver
|
||||
signoz-telemetrystore-migrator:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.4}
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.5}
|
||||
container_name: signoz-telemetrystore-migrator
|
||||
environment:
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN=tcp://clickhouse:9000
|
||||
|
||||
1459
docs/api/openapi.yml
1459
docs/api/openapi.yml
File diff suppressed because it is too large
Load Diff
@@ -333,6 +333,50 @@ func (Step) JSONSchema() (jsonschema.Schema, error) {
|
||||
}
|
||||
```
|
||||
|
||||
### `oneOf` with a discriminator
|
||||
|
||||
For a sum type whose variants are keyed by a property (e.g. `kind`), expose the variants via `JSONSchemaOneOf()` and add a discriminator. Without it, code generators intersect the variants (`A & B & C`) instead of producing a clean discriminated union (`A | B | C`).
|
||||
|
||||
The parent keeps its `JSONSchemaOneOf()` (the `oneOf` itself) and *additionally* tags it via `PrepareJSONSchema` with the `x-signoz-discriminator` extension; `signoz.attachDiscriminators` then promotes that marker to a real OpenAPI 3 `discriminator` (and strips the duplicate parent properties) after reflection.
|
||||
|
||||
```go
|
||||
// On the parent: expose the oneOf variants...
|
||||
func (Plugin) JSONSchemaOneOf() []any {
|
||||
return []any{FooVariant{}}
|
||||
}
|
||||
|
||||
// ...and tag that same oneOf with the discriminator marker.
|
||||
func (Plugin) PrepareJSONSchema(s *jsonschema.Schema) error {
|
||||
if s.ExtraProperties == nil {
|
||||
s.ExtraProperties = map[string]any{}
|
||||
}
|
||||
s.ExtraProperties["x-signoz-discriminator"] = map[string]any{
|
||||
"propertyName": "kind",
|
||||
"mapping": map[string]string{
|
||||
"signoz/Foo": "#/components/schemas/FooVariant",
|
||||
},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
Each variant must declare the discriminator property (`kind`) and mark it `required`.
|
||||
|
||||
This produces the following in the generated OpenAPI spec:
|
||||
|
||||
```yaml
|
||||
Plugin:
|
||||
discriminator:
|
||||
propertyName: kind
|
||||
mapping:
|
||||
signoz/Foo: '#/components/schemas/FooVariant'
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/FooVariant'
|
||||
type: object
|
||||
```
|
||||
|
||||
Note the discriminator property lives in the variants, not on the parent — the parent is only the union.
|
||||
|
||||
|
||||
## What should I remember?
|
||||
|
||||
|
||||
@@ -5,10 +5,12 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/authn"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/global"
|
||||
"github.com/SigNoz/signoz/pkg/http/client"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
@@ -26,13 +28,14 @@ var defaultScopes []string = []string{"email", "profile", oidc.ScopeOpenID}
|
||||
var _ authn.CallbackAuthN = (*AuthN)(nil)
|
||||
|
||||
type AuthN struct {
|
||||
settings factory.ScopedProviderSettings
|
||||
store authtypes.AuthNStore
|
||||
licensing licensing.Licensing
|
||||
httpClient *client.Client
|
||||
settings factory.ScopedProviderSettings
|
||||
store authtypes.AuthNStore
|
||||
licensing licensing.Licensing
|
||||
httpClient *client.Client
|
||||
globalConfig global.Config
|
||||
}
|
||||
|
||||
func New(store authtypes.AuthNStore, licensing licensing.Licensing, providerSettings factory.ProviderSettings) (*AuthN, error) {
|
||||
func New(store authtypes.AuthNStore, licensing licensing.Licensing, providerSettings factory.ProviderSettings, globalConfig global.Config) (*AuthN, error) {
|
||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/ee/authn/callbackauthn/oidccallbackauthn")
|
||||
|
||||
httpClient, err := client.New(providerSettings.Logger, providerSettings.TracerProvider, providerSettings.MeterProvider)
|
||||
@@ -41,10 +44,11 @@ func New(store authtypes.AuthNStore, licensing licensing.Licensing, providerSett
|
||||
}
|
||||
|
||||
return &AuthN{
|
||||
settings: settings,
|
||||
store: store,
|
||||
licensing: licensing,
|
||||
httpClient: httpClient,
|
||||
settings: settings,
|
||||
store: store,
|
||||
licensing: licensing,
|
||||
httpClient: httpClient,
|
||||
globalConfig: globalConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -197,7 +201,7 @@ func (a *AuthN) oidcProviderAndoauth2Config(ctx context.Context, siteURL *url.UR
|
||||
RedirectURL: (&url.URL{
|
||||
Scheme: siteURL.Scheme,
|
||||
Host: siteURL.Host,
|
||||
Path: redirectPath,
|
||||
Path: path.Join(a.globalConfig.ExternalPath(), redirectPath),
|
||||
}).String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -6,10 +6,12 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/authn"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/global"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
@@ -24,14 +26,16 @@ const (
|
||||
var _ authn.CallbackAuthN = (*AuthN)(nil)
|
||||
|
||||
type AuthN struct {
|
||||
store authtypes.AuthNStore
|
||||
licensing licensing.Licensing
|
||||
store authtypes.AuthNStore
|
||||
licensing licensing.Licensing
|
||||
globalConfig global.Config
|
||||
}
|
||||
|
||||
func New(ctx context.Context, store authtypes.AuthNStore, licensing licensing.Licensing) (*AuthN, error) {
|
||||
func New(ctx context.Context, store authtypes.AuthNStore, licensing licensing.Licensing, globalConfig global.Config) (*AuthN, error) {
|
||||
return &AuthN{
|
||||
store: store,
|
||||
licensing: licensing,
|
||||
store: store,
|
||||
licensing: licensing,
|
||||
globalConfig: globalConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -132,7 +136,7 @@ func (a *AuthN) serviceProvider(siteURL *url.URL, authDomain *authtypes.AuthDoma
|
||||
return nil, err
|
||||
}
|
||||
|
||||
acsURL := &url.URL{Scheme: siteURL.Scheme, Host: siteURL.Host, Path: redirectPath}
|
||||
acsURL := &url.URL{Scheme: siteURL.Scheme, Host: siteURL.Host, Path: path.Join(a.globalConfig.ExternalPath(), redirectPath)}
|
||||
|
||||
// Note:
|
||||
// The ServiceProviderIssuer is the client id in case of keycloak. Since we set it to the host here, we need to set the client id == host in keycloak.
|
||||
|
||||
@@ -355,26 +355,32 @@ func (module *module) GetService(ctx context.Context, orgID valuer.UUID, service
|
||||
|
||||
var integrationService *cloudintegrationtypes.CloudIntegrationService
|
||||
|
||||
if !cloudIntegrationID.IsZero() {
|
||||
storedService, err := module.store.GetServiceByServiceID(ctx, cloudIntegrationID, serviceID)
|
||||
if err != nil && !errors.Ast(err, errors.TypeNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
if storedService != nil {
|
||||
serviceConfig, err := cloudintegrationtypes.NewServiceConfigFromJSON(provider, storedService.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
integrationService = cloudintegrationtypes.NewCloudIntegrationServiceFromStorable(storedService, serviceConfig)
|
||||
}
|
||||
|
||||
if err := module.enrichDashboardIDs(ctx, orgID, provider, serviceID, serviceDefinition); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cloudIntegrationID.IsZero() {
|
||||
return cloudintegrationtypes.NewService(provider, serviceDefinition, nil, nil), nil
|
||||
}
|
||||
|
||||
return cloudintegrationtypes.NewService(*serviceDefinition, integrationService), nil
|
||||
storedService, err := module.store.GetServiceByServiceID(ctx, cloudIntegrationID, serviceID)
|
||||
if err != nil && !errors.Ast(err, errors.TypeNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
if storedService == nil {
|
||||
return cloudintegrationtypes.NewService(provider, serviceDefinition, nil, nil), nil
|
||||
}
|
||||
|
||||
serviceConfig, err := cloudintegrationtypes.NewServiceConfigFromJSON(provider, storedService.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
integrationService = cloudintegrationtypes.NewCloudIntegrationServiceFromStorable(storedService, serviceConfig)
|
||||
|
||||
slugPrefix := cloudintegrationtypes.CloudIntegrationDashboardSlugPrefix(provider, serviceID)
|
||||
integrationDashboards, err := module.store.ListIntegrationDashboardsBySlugPrefix(ctx, orgID, cloudintegrationtypes.IntegrationDashboardProviderCloudIntegration, slugPrefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cloudintegrationtypes.NewService(provider, serviceDefinition, integrationService, integrationDashboards), nil
|
||||
}
|
||||
|
||||
func (module *module) CreateService(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, service *cloudintegrationtypes.CloudIntegrationService, provider cloudintegrationtypes.CloudProviderType) error {
|
||||
@@ -583,20 +589,3 @@ func (module *module) deprovisionDashboards(ctx context.Context, orgID valuer.UU
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// enrichDashboardIDs replaces the raw dashboard name in each Dashboard.ID with the provisioned UUID.
|
||||
// TODO: remove this hack and send idiomatic response to client.
|
||||
func (module *module) enrichDashboardIDs(ctx context.Context, orgID valuer.UUID, provider cloudintegrationtypes.CloudProviderType, serviceID cloudintegrationtypes.ServiceID, serviceDefinition *cloudintegrationtypes.ServiceDefinition) error {
|
||||
for i, d := range serviceDefinition.Assets.Dashboards {
|
||||
slug := cloudintegrationtypes.CloudIntegrationDashboardSlug(provider, serviceID, d.ID)
|
||||
row, err := module.store.GetIntegrationDashboardBySlug(ctx, orgID, cloudintegrationtypes.IntegrationDashboardProviderCloudIntegration, slug)
|
||||
if err != nil {
|
||||
if errors.Ast(err, errors.TypeNotFound) {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
serviceDefinition.Assets.Dashboards[i].ID = row.DashboardID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -221,6 +221,47 @@ func (module *module) GetV2(ctx context.Context, orgID valuer.UUID, id valuer.UU
|
||||
return module.pkgDashboardModule.GetV2(ctx, orgID, id)
|
||||
}
|
||||
|
||||
func (module *module) UpdateV2(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, updatable dashboardtypes.UpdatableDashboardV2) (*dashboardtypes.DashboardV2, error) {
|
||||
return module.pkgDashboardModule.UpdateV2(ctx, orgID, id, updatedBy, updatable)
|
||||
}
|
||||
|
||||
func (module *module) PatchV2(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, patch dashboardtypes.PatchableDashboardV2) (*dashboardtypes.DashboardV2, error) {
|
||||
return module.pkgDashboardModule.PatchV2(ctx, orgID, id, updatedBy, patch)
|
||||
}
|
||||
|
||||
func (module *module) DeleteV2(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error {
|
||||
return module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
if err := module.store.DeletePublic(ctx, id.String()); err != nil && !errors.Ast(err, errors.TypeNotFound) {
|
||||
return err
|
||||
}
|
||||
return module.pkgDashboardModule.DeleteV2(ctx, orgID, id)
|
||||
})
|
||||
}
|
||||
|
||||
func (module *module) LockUnlockV2(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, isAdmin bool, lock bool) error {
|
||||
return module.pkgDashboardModule.LockUnlockV2(ctx, orgID, id, updatedBy, isAdmin, lock)
|
||||
}
|
||||
|
||||
func (module *module) ListV2(ctx context.Context, orgID valuer.UUID, params *dashboardtypes.ListDashboardsV2Params) (*dashboardtypes.ListableDashboardV2, error) {
|
||||
return module.pkgDashboardModule.ListV2(ctx, orgID, params)
|
||||
}
|
||||
|
||||
func (module *module) ListForUserV2(ctx context.Context, orgID valuer.UUID, userID valuer.UUID, params *dashboardtypes.ListDashboardsV2Params) (*dashboardtypes.ListableDashboardForUserV2, error) {
|
||||
return module.pkgDashboardModule.ListForUserV2(ctx, orgID, userID, params)
|
||||
}
|
||||
|
||||
func (module *module) PinV2(ctx context.Context, orgID valuer.UUID, userID valuer.UUID, id valuer.UUID) error {
|
||||
return module.pkgDashboardModule.PinV2(ctx, orgID, userID, id)
|
||||
}
|
||||
|
||||
func (module *module) UnpinV2(ctx context.Context, orgID valuer.UUID, userID valuer.UUID, id valuer.UUID) error {
|
||||
return module.pkgDashboardModule.UnpinV2(ctx, orgID, userID, id)
|
||||
}
|
||||
|
||||
func (module *module) DeletePreferencesForUser(ctx context.Context, orgID valuer.UUID, userID valuer.UUID) error {
|
||||
return module.pkgDashboardModule.DeletePreferencesForUser(ctx, orgID, userID)
|
||||
}
|
||||
|
||||
func (module *module) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*dashboardtypes.Dashboard, error) {
|
||||
return module.pkgDashboardModule.Get(ctx, orgID, id)
|
||||
}
|
||||
|
||||
@@ -185,6 +185,7 @@ func (s *Server) createPublicServer(apiHandler *api.APIHandler, web web.Web) (*h
|
||||
s.config.APIServer.Timeout.Default,
|
||||
s.config.APIServer.Timeout.Max,
|
||||
).Wrap)
|
||||
r.Use(middleware.NewResource(s.signoz.Instrumentation.Logger()).Wrap)
|
||||
r.Use(middleware.NewAudit(s.signoz.Instrumentation.Logger(), s.config.APIServer.Logging.ExcludedRoutes, s.signoz.Auditor).Wrap)
|
||||
r.Use(middleware.NewComment().Wrap)
|
||||
|
||||
|
||||
@@ -16,10 +16,11 @@ func newFormatter(dialect schema.Dialect) sqlstore.SQLFormatter {
|
||||
}
|
||||
|
||||
func (f *formatter) JSONExtractString(column, path string) []byte {
|
||||
var sql []byte
|
||||
sql = f.bunf.AppendIdent(sql, column)
|
||||
sql = append(sql, f.convertJSONPathToPostgres(path)...)
|
||||
return sql
|
||||
ops := f.convertJSONPathToPostgres(path)
|
||||
if len(ops) == 0 {
|
||||
return f.bunf.AppendIdent(nil, column)
|
||||
}
|
||||
return append(f.TextToJsonColumn(column), ops...)
|
||||
}
|
||||
|
||||
func (f *formatter) JSONType(column, path string) []byte {
|
||||
|
||||
@@ -18,19 +18,19 @@ func TestJSONExtractString(t *testing.T) {
|
||||
name: "simple path",
|
||||
column: "data",
|
||||
path: "$.field",
|
||||
expected: `"data"->>'field'`,
|
||||
expected: `"data"::jsonb->>'field'`,
|
||||
},
|
||||
{
|
||||
name: "nested path",
|
||||
column: "metadata",
|
||||
path: "$.user.name",
|
||||
expected: `"metadata"->'user'->>'name'`,
|
||||
expected: `"metadata"::jsonb->'user'->>'name'`,
|
||||
},
|
||||
{
|
||||
name: "deeply nested path",
|
||||
column: "json_col",
|
||||
path: "$.level1.level2.level3",
|
||||
expected: `"json_col"->'level1'->'level2'->>'level3'`,
|
||||
expected: `"json_col"::jsonb->'level1'->'level2'->>'level3'`,
|
||||
},
|
||||
{
|
||||
name: "root path",
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// Mock for useSafeNavigate hook to avoid React Router version conflicts in tests
|
||||
interface SafeNavigateOptions {
|
||||
replace?: boolean;
|
||||
state?: unknown;
|
||||
newTab?: boolean;
|
||||
}
|
||||
|
||||
interface SafeNavigateTo {
|
||||
pathname?: string;
|
||||
search?: string;
|
||||
hash?: string;
|
||||
}
|
||||
|
||||
type SafeNavigateToType = string | SafeNavigateTo;
|
||||
|
||||
interface UseSafeNavigateReturn {
|
||||
safeNavigate: jest.MockedFunction<
|
||||
(to: SafeNavigateToType, options?: SafeNavigateOptions) => void
|
||||
>;
|
||||
}
|
||||
|
||||
export const useSafeNavigate = (): UseSafeNavigateReturn => ({
|
||||
safeNavigate: jest.fn(
|
||||
(_to: SafeNavigateToType, _options?: SafeNavigateOptions) => {},
|
||||
) as jest.MockedFunction<
|
||||
(to: SafeNavigateToType, options?: SafeNavigateOptions) => void
|
||||
>,
|
||||
});
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { Config } from '@jest/types';
|
||||
|
||||
const USE_SAFE_NAVIGATE_MOCK_PATH = '<rootDir>/__mocks__/useSafeNavigate.ts';
|
||||
const USE_SAFE_NAVIGATE_MOCK_PATH =
|
||||
'<rootDir>/src/__tests__/safeNavigateMock.ts';
|
||||
const LOG_EVENT_MOCK_PATH = '<rootDir>/src/__tests__/logEventMock.ts';
|
||||
|
||||
const config: Config.InitialOptions = {
|
||||
silent: true,
|
||||
@@ -22,6 +24,8 @@ const config: Config.InitialOptions = {
|
||||
'^hooks/useSafeNavigate$': USE_SAFE_NAVIGATE_MOCK_PATH,
|
||||
'^src/hooks/useSafeNavigate$': USE_SAFE_NAVIGATE_MOCK_PATH,
|
||||
'^.*/useSafeNavigate$': USE_SAFE_NAVIGATE_MOCK_PATH,
|
||||
'^api/common/logEvent$': LOG_EVENT_MOCK_PATH,
|
||||
'^src/api/common/logEvent$': LOG_EVENT_MOCK_PATH,
|
||||
'^constants/env$': '<rootDir>/__mocks__/env.ts',
|
||||
'^src/constants/env$': '<rootDir>/__mocks__/env.ts',
|
||||
'^@signozhq/icons$': '<rootDir>/__mocks__/signozhqIconsMock.tsx',
|
||||
|
||||
@@ -41,6 +41,15 @@ if (typeof window.IntersectionObserver === 'undefined') {
|
||||
(window as any).IntersectionObserver = IntersectionObserverMock;
|
||||
}
|
||||
|
||||
if (typeof window.ResizeObserver === 'undefined') {
|
||||
class ResizeObserverMock {
|
||||
observe(): void {}
|
||||
unobserve(): void {}
|
||||
disconnect(): void {}
|
||||
}
|
||||
(window as any).ResizeObserver = ResizeObserverMock;
|
||||
}
|
||||
|
||||
// Patch getComputedStyle to handle CSS parsing errors from @signozhq/* packages.
|
||||
// These packages inject CSS at import time via style-inject / vite-plugin-css-injected-by-js.
|
||||
// jsdom's nwsapi cannot parse some of the injected selectors (e.g. Tailwind's :animate-in),
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
"@dnd-kit/utilities": "3.2.2",
|
||||
"@grafana/data": "^11.6.14",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@sentry/react": "8.41.0",
|
||||
"@sentry/vite-plugin": "2.22.6",
|
||||
"@sentry/react": "10.57.0",
|
||||
"@sentry/vite-plugin": "5.3.0",
|
||||
"@signozhq/design-tokens": "2.1.4",
|
||||
"@signozhq/icons": "0.4.0",
|
||||
"@signozhq/resizable": "0.0.2",
|
||||
|
||||
283
frontend/pnpm-lock.yaml
generated
283
frontend/pnpm-lock.yaml
generated
@@ -62,11 +62,11 @@ importers:
|
||||
specifier: ^4.7.0
|
||||
version: 4.7.0(monaco-editor@0.55.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
'@sentry/react':
|
||||
specifier: 8.41.0
|
||||
version: 8.41.0(react@18.2.0)
|
||||
specifier: 10.57.0
|
||||
version: 10.57.0(react@18.2.0)
|
||||
'@sentry/vite-plugin':
|
||||
specifier: 2.22.6
|
||||
version: 2.22.6
|
||||
specifier: 5.3.0
|
||||
version: 5.3.0
|
||||
'@signozhq/design-tokens':
|
||||
specifier: 2.1.4
|
||||
version: 2.1.4
|
||||
@@ -3161,97 +3161,108 @@ packages:
|
||||
'@sec-ant/readable-stream@0.4.1':
|
||||
resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
|
||||
|
||||
'@sentry-internal/browser-utils@8.41.0':
|
||||
resolution: {integrity: sha512-nU7Bn3jEUmf1QXRUT3j2ewUBlFJpe9vnAnjqpeVPDWTsVI52BwVNcJHuE37PrGs66OZ1ZkGMfKnQk43oCAa+oQ==}
|
||||
engines: {node: '>=14.18'}
|
||||
'@sentry-internal/browser-utils@10.57.0':
|
||||
resolution: {integrity: sha512-tXObp954rMTSYKlbftjVXHtNl4t/6ssks3jkqyzmKb+PDPWzabGQO7sWwqVuTjT8Kx/8A3FmriS1bGmqxiJy3A==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/feedback@8.41.0':
|
||||
resolution: {integrity: sha512-bw+BrSNw8abOnu/IpD8YSbYubXkkT8jyNS7TM4e4UPZMuXcbtia7/r5d7kAiUfKv/sV5PNMlZLOk+EYJeLTANg==}
|
||||
engines: {node: '>=14.18'}
|
||||
'@sentry-internal/feedback@10.57.0':
|
||||
resolution: {integrity: sha512-ZcF4QhkqGX3iiQSXB2N0N3Awp+j5iqnDRu6PA/qyLFrWqH5ZiiAAgu59OLD9E6XAdg6iFtLYw19MAMZVK8qNOQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/replay-canvas@8.41.0':
|
||||
resolution: {integrity: sha512-lpgOBHWr1ZNxidD72A2pfoUMjIpwonOPYoQZWAHr86Oa3eIVQOyfklZlHW+gKPFl2/IEl9Lbtcke0JiDp3dkIQ==}
|
||||
engines: {node: '>=14.18'}
|
||||
'@sentry-internal/replay-canvas@10.57.0':
|
||||
resolution: {integrity: sha512-zsfa4JcfV0AEc9YhNxNabd5lSZL2Av84saAyexGAqcHs+67m9Gd0cGStOzMb/nCl7UAtmdP0aI+G7a3rcxxN/A==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/replay@8.41.0':
|
||||
resolution: {integrity: sha512-ByXEY7JI95y4Qr9fS3d28l9uuVU5Qa0HgL+xDmYElNx7CXz3Q9hFN6ibgUeC3h8BO5pDULxWNgAppl7FRY8N5w==}
|
||||
engines: {node: '>=14.18'}
|
||||
'@sentry-internal/replay@10.57.0':
|
||||
resolution: {integrity: sha512-Wmnx/6ABynVH1iwuoNUqJNyjIUqsqoGML7qsyivBRKb5Wo2YQtPOQlQYfxfZSvWzGpcoSVdInkRjDssUQxQEQg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/babel-plugin-component-annotate@2.22.6':
|
||||
resolution: {integrity: sha512-V2g1Y1I5eSe7dtUVMBvAJr8BaLRr4CLrgNgtPaZyMT4Rnps82SrZ5zqmEkLXPumlXhLUWR6qzoMNN2u+RXVXfQ==}
|
||||
engines: {node: '>= 14'}
|
||||
'@sentry/babel-plugin-component-annotate@5.3.0':
|
||||
resolution: {integrity: sha512-p4q8gn8wcFqZGP/s2MnJCAAd8fTikaU6A0mM97RDHQgStcrYiaS0Sc5zUNfb1V+UOLPuvdEdL6MwyxfzjYJQTA==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
'@sentry/browser@8.41.0':
|
||||
resolution: {integrity: sha512-FfAU55eYwW2lG4M3dEw2472RvHrD5YWSfHCZvuRf/4skX38kFvKghZQ+epL+CVHTzvIRHOrbj8qQK6YLTGl9ew==}
|
||||
engines: {node: '>=14.18'}
|
||||
'@sentry/browser@10.57.0':
|
||||
resolution: {integrity: sha512-s36AQy/CKXTfyY9Z+qUhzNomntZXgfs0rbaK7q9ffnFkqcPwzE8qQtVs58y3Suut56u+AhwSztgQtERcuZ5VIA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/bundler-plugin-core@2.22.6':
|
||||
resolution: {integrity: sha512-1esQdgSUCww9XAntO4pr7uAM5cfGhLsgTK9MEwAKNfvpMYJi9NUTYa3A7AZmdA8V6107Lo4OD7peIPrDRbaDCg==}
|
||||
engines: {node: '>= 14'}
|
||||
'@sentry/bundler-plugin-core@5.3.0':
|
||||
resolution: {integrity: sha512-L5T60sWdAI3qWwdg3Ptwek/0TY59PERrxyqp4XMUkroayQvGd9r5dIW9Q1kSeXX9iJ442nXbFZKAOyCKV4Z13Q==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
'@sentry/cli-darwin@2.39.1':
|
||||
resolution: {integrity: sha512-kiNGNSAkg46LNGatfNH5tfsmI/kCAaPA62KQuFZloZiemTNzhy9/6NJP8HZ/GxGs8GDMxic6wNrV9CkVEgFLJQ==}
|
||||
'@sentry/cli-darwin@2.58.6':
|
||||
resolution: {integrity: sha512-udAVvcyfNa0R+95GvPz/+43/N3TC0TYKdkQ7D7jhPSzbcMc7l2fxRNN5yB3UpCA5fWFnW4toeaqwDBhb/Wh3LA==}
|
||||
engines: {node: '>=10'}
|
||||
os: [darwin]
|
||||
|
||||
'@sentry/cli-linux-arm64@2.39.1':
|
||||
resolution: {integrity: sha512-5VbVJDatolDrWOgaffsEM7znjs0cR8bHt9Bq0mStM3tBolgAeSDHE89NgHggfZR+DJ2VWOy4vgCwkObrUD6NQw==}
|
||||
'@sentry/cli-linux-arm64@2.58.6':
|
||||
resolution: {integrity: sha512-q8mEcNNmeXMy5i+jWT30TVpH7LcP4HD21CD5XRSPAd/a912HF6EpK0ybf/1USO14WOhoXbAGi9txwaWabSe33g==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [linux, freebsd]
|
||||
os: [linux, freebsd, android]
|
||||
|
||||
'@sentry/cli-linux-arm@2.39.1':
|
||||
resolution: {integrity: sha512-DkENbxyRxUrfLnJLXTA4s5UL/GoctU5Cm4ER1eB7XN7p9WsamFJd/yf2KpltkjEyiTuplv0yAbdjl1KX3vKmEQ==}
|
||||
'@sentry/cli-linux-arm@2.58.6':
|
||||
resolution: {integrity: sha512-pD0LAt5PcUzAinBwvDqc66x9+2CabHEv486yP0gRjWO7SakbaxmfVq/EXd8VLq/Tzi39LAu422UYK1lpW3MILw==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm]
|
||||
os: [linux, freebsd]
|
||||
os: [linux, freebsd, android]
|
||||
|
||||
'@sentry/cli-linux-i686@2.39.1':
|
||||
resolution: {integrity: sha512-pXWVoKXCRrY7N8vc9H7mETiV9ZCz+zSnX65JQCzZxgYrayQPJTc+NPRnZTdYdk5RlAupXaFicBI2GwOCRqVRkg==}
|
||||
'@sentry/cli-linux-i686@2.58.6':
|
||||
resolution: {integrity: sha512-q8vNJi1eOV/4vxAFWBsEwLHoSYapaZHIf4j76KJGJXFKTkEbsjCOOsKbwUIBTQQhRgV4DFWh3ryfsPS/que4Kg==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x86, ia32]
|
||||
os: [linux, freebsd]
|
||||
os: [linux, freebsd, android]
|
||||
|
||||
'@sentry/cli-linux-x64@2.39.1':
|
||||
resolution: {integrity: sha512-IwayNZy+it7FWG4M9LayyUmG1a/8kT9+/IEm67sT5+7dkMIMcpmHDqL8rWcPojOXuTKaOBBjkVdNMBTXy0mXlA==}
|
||||
'@sentry/cli-linux-x64@2.58.6':
|
||||
resolution: {integrity: sha512-DZu956Mhi3ZRjTBe1WdbGV46ldVbA8d2rgp/fh51GsI25zjBHah4wZnPTSzpc+YqxU6pJpg579B/r3jrIK530Q==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [linux, freebsd]
|
||||
os: [linux, freebsd, android]
|
||||
|
||||
'@sentry/cli-win32-i686@2.39.1':
|
||||
resolution: {integrity: sha512-NglnNoqHSmE+Dz/wHeIVRnV2bLMx7tIn3IQ8vXGO5HWA2f8zYJGktbkLq1Lg23PaQmeZLPGlja3gBQfZYSG10Q==}
|
||||
'@sentry/cli-win32-arm64@2.58.6':
|
||||
resolution: {integrity: sha512-nj0Ff/kmAB73EPDhR8B4O9r+NUHK5GkPCkGWC+kXVemqAJWL5jcJ5KdxG0l/S0z6RoEoltID8/43/B+TaMlT7A==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@sentry/cli-win32-i686@2.58.6':
|
||||
resolution: {integrity: sha512-WNZiDzPbgsEMQWq4avsQ391v/xWKJDIWWWo9GYl+N/w5qcYKkoDW7wQG7T9FasI6ENn68phChTOAPXXxbfAdOg==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x86, ia32]
|
||||
os: [win32]
|
||||
|
||||
'@sentry/cli-win32-x64@2.39.1':
|
||||
resolution: {integrity: sha512-xv0R2CMf/X1Fte3cMWie1NXuHmUyQPDBfCyIt6k6RPFPxAYUgcqgMPznYwVMwWEA1W43PaOkSn3d8ZylsDaETw==}
|
||||
'@sentry/cli-win32-x64@2.58.6':
|
||||
resolution: {integrity: sha512-R35WJ17oF4D2eqI1DR2sQQqr0fjRTt5xoP16WrTu91XM2lndRMFsnjh+/GttbxapLCBNlrjzia99MJ0PZHZpgA==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@sentry/cli@2.39.1':
|
||||
resolution: {integrity: sha512-JIb3e9vh0+OmQ0KxmexMXg9oZsR/G7HMwxt5BUIKAXZ9m17Xll4ETXTRnRUBT3sf7EpNGAmlQk1xEmVN9pYZYQ==}
|
||||
'@sentry/cli@2.58.6':
|
||||
resolution: {integrity: sha512-baBcNPLLfUi9WuL+Tpri9BFaAdvugZIKelC5X0tt0Zdy+K0K+PCVSrnNmwMWU/HyaF/SEv6b6UHnXIdqanBlcg==}
|
||||
engines: {node: '>= 10'}
|
||||
hasBin: true
|
||||
|
||||
'@sentry/core@8.41.0':
|
||||
resolution: {integrity: sha512-3v7u3t4LozCA5SpZY4yqUN2U3jSrkXNoLgz6L2SUUiydyCuSwXZIFEwpLJfgQyidpNDifeQbBI5E1O910XkPsA==}
|
||||
engines: {node: '>=14.18'}
|
||||
'@sentry/core@10.57.0':
|
||||
resolution: {integrity: sha512-kntItTA2kiT0YpL7encXaF6mkdZMB+y48lwj8w1wkfBpfJAC7sifdgrzLQZqmsqVNE3crg9VfufaAGA+78uFMg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/react@8.41.0':
|
||||
resolution: {integrity: sha512-/7LEWDNdICYO5s4ie8ztgpmD/GRJ1+1nHlSKvcwjf83COzT1eGvVeuYTiXFAPmXA29sY+lV1RajziwgySadjIQ==}
|
||||
engines: {node: '>=14.18'}
|
||||
'@sentry/react@10.57.0':
|
||||
resolution: {integrity: sha512-6QThwQ4XWQ2rwKZEVQ9P9WKl7JlowC7S5LpAvmMdrwlfJBpLDFOsM7tycnIvbXTXf0ZOOuLFPa4L4YYbdyNGmA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
react: ^16.14.0 || 17.x || 18.x || 19.x
|
||||
|
||||
'@sentry/types@8.41.0':
|
||||
resolution: {integrity: sha512-eqdnGr9k9H++b9CjVUoTNUVahPVWeNnMy0YGkqS5+cjWWC+x43p56202oidGFmWo6702ub/xwUNH6M5PC4kq6A==}
|
||||
engines: {node: '>=14.18'}
|
||||
'@sentry/rollup-plugin@5.3.0':
|
||||
resolution: {integrity: sha512-hgPGPYdQJ/G1cGYOxAb7d4z3V+/k/E5/P/5TFPEEBLuIbFFk+JG0CISUDJdzXJjO382Lb99PBJuXGbueBmO79w==}
|
||||
engines: {node: '>= 18'}
|
||||
peerDependencies:
|
||||
rollup: '>=3.2.0'
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
|
||||
'@sentry/vite-plugin@2.22.6':
|
||||
resolution: {integrity: sha512-zIieP1VLWQb3wUjFJlwOAoaaJygJhXeUoGd0e/Ha2RLb2eW2S+4gjf6y6NqyY71tZ74LYVZKg/4prB6FAZSMXQ==}
|
||||
engines: {node: '>= 14'}
|
||||
'@sentry/vite-plugin@5.3.0':
|
||||
resolution: {integrity: sha512-qcoSzo4n2MulVQ70UUPLq6dTleb2a2HwL2wuwvAgWhPChrYTuk6A6mDg6aQb9fairPAwFPiU9PzOANpoDJcz1A==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
'@shikijs/engine-oniguruma@3.23.0':
|
||||
resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==}
|
||||
@@ -5290,11 +5301,6 @@ packages:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||
|
||||
glob@9.3.5:
|
||||
resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||
|
||||
global-directory@5.0.0:
|
||||
resolution: {integrity: sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==}
|
||||
engines: {node: '>=20'}
|
||||
@@ -6603,10 +6609,6 @@ packages:
|
||||
resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
minimatch@8.0.7:
|
||||
resolution: {integrity: sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
minimatch@9.0.9:
|
||||
resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
@@ -6614,10 +6616,6 @@ packages:
|
||||
minimist@1.2.8:
|
||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
||||
|
||||
minipass@4.2.8:
|
||||
resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
minipass@7.1.3:
|
||||
resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
@@ -8619,9 +8617,6 @@ packages:
|
||||
unload@2.2.0:
|
||||
resolution: {integrity: sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==}
|
||||
|
||||
unplugin@1.0.1:
|
||||
resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==}
|
||||
|
||||
unrs-resolver@1.11.1:
|
||||
resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
|
||||
|
||||
@@ -8815,13 +8810,6 @@ packages:
|
||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
webpack-sources@3.2.3:
|
||||
resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
webpack-virtual-modules@0.5.0:
|
||||
resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==}
|
||||
|
||||
whatwg-encoding@2.0.0:
|
||||
resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -11892,75 +11880,72 @@ snapshots:
|
||||
|
||||
'@sec-ant/readable-stream@0.4.1': {}
|
||||
|
||||
'@sentry-internal/browser-utils@8.41.0':
|
||||
'@sentry-internal/browser-utils@10.57.0':
|
||||
dependencies:
|
||||
'@sentry/core': 8.41.0
|
||||
'@sentry/types': 8.41.0
|
||||
'@sentry/core': 10.57.0
|
||||
|
||||
'@sentry-internal/feedback@8.41.0':
|
||||
'@sentry-internal/feedback@10.57.0':
|
||||
dependencies:
|
||||
'@sentry/core': 8.41.0
|
||||
'@sentry/types': 8.41.0
|
||||
'@sentry/core': 10.57.0
|
||||
|
||||
'@sentry-internal/replay-canvas@8.41.0':
|
||||
'@sentry-internal/replay-canvas@10.57.0':
|
||||
dependencies:
|
||||
'@sentry-internal/replay': 8.41.0
|
||||
'@sentry/core': 8.41.0
|
||||
'@sentry/types': 8.41.0
|
||||
'@sentry-internal/replay': 10.57.0
|
||||
'@sentry/core': 10.57.0
|
||||
|
||||
'@sentry-internal/replay@8.41.0':
|
||||
'@sentry-internal/replay@10.57.0':
|
||||
dependencies:
|
||||
'@sentry-internal/browser-utils': 8.41.0
|
||||
'@sentry/core': 8.41.0
|
||||
'@sentry/types': 8.41.0
|
||||
'@sentry-internal/browser-utils': 10.57.0
|
||||
'@sentry/core': 10.57.0
|
||||
|
||||
'@sentry/babel-plugin-component-annotate@2.22.6': {}
|
||||
'@sentry/babel-plugin-component-annotate@5.3.0': {}
|
||||
|
||||
'@sentry/browser@8.41.0':
|
||||
'@sentry/browser@10.57.0':
|
||||
dependencies:
|
||||
'@sentry-internal/browser-utils': 8.41.0
|
||||
'@sentry-internal/feedback': 8.41.0
|
||||
'@sentry-internal/replay': 8.41.0
|
||||
'@sentry-internal/replay-canvas': 8.41.0
|
||||
'@sentry/core': 8.41.0
|
||||
'@sentry/types': 8.41.0
|
||||
'@sentry-internal/browser-utils': 10.57.0
|
||||
'@sentry-internal/feedback': 10.57.0
|
||||
'@sentry-internal/replay': 10.57.0
|
||||
'@sentry-internal/replay-canvas': 10.57.0
|
||||
'@sentry/core': 10.57.0
|
||||
|
||||
'@sentry/bundler-plugin-core@2.22.6':
|
||||
'@sentry/bundler-plugin-core@5.3.0':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@sentry/babel-plugin-component-annotate': 2.22.6
|
||||
'@sentry/cli': 2.39.1
|
||||
'@sentry/babel-plugin-component-annotate': 5.3.0
|
||||
'@sentry/cli': 2.58.6
|
||||
dotenv: 16.6.1
|
||||
find-up: 5.0.0
|
||||
glob: 9.3.5
|
||||
glob: 13.0.6
|
||||
magic-string: 0.30.8
|
||||
unplugin: 1.0.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
|
||||
'@sentry/cli-darwin@2.39.1':
|
||||
'@sentry/cli-darwin@2.58.6':
|
||||
optional: true
|
||||
|
||||
'@sentry/cli-linux-arm64@2.39.1':
|
||||
'@sentry/cli-linux-arm64@2.58.6':
|
||||
optional: true
|
||||
|
||||
'@sentry/cli-linux-arm@2.39.1':
|
||||
'@sentry/cli-linux-arm@2.58.6':
|
||||
optional: true
|
||||
|
||||
'@sentry/cli-linux-i686@2.39.1':
|
||||
'@sentry/cli-linux-i686@2.58.6':
|
||||
optional: true
|
||||
|
||||
'@sentry/cli-linux-x64@2.39.1':
|
||||
'@sentry/cli-linux-x64@2.58.6':
|
||||
optional: true
|
||||
|
||||
'@sentry/cli-win32-i686@2.39.1':
|
||||
'@sentry/cli-win32-arm64@2.58.6':
|
||||
optional: true
|
||||
|
||||
'@sentry/cli-win32-x64@2.39.1':
|
||||
'@sentry/cli-win32-i686@2.58.6':
|
||||
optional: true
|
||||
|
||||
'@sentry/cli@2.39.1':
|
||||
'@sentry/cli-win32-x64@2.58.6':
|
||||
optional: true
|
||||
|
||||
'@sentry/cli@2.58.6':
|
||||
dependencies:
|
||||
https-proxy-agent: 5.0.1
|
||||
node-fetch: 2.7.0
|
||||
@@ -11968,39 +11953,43 @@ snapshots:
|
||||
proxy-from-env: 1.1.0
|
||||
which: 2.0.2
|
||||
optionalDependencies:
|
||||
'@sentry/cli-darwin': 2.39.1
|
||||
'@sentry/cli-linux-arm': 2.39.1
|
||||
'@sentry/cli-linux-arm64': 2.39.1
|
||||
'@sentry/cli-linux-i686': 2.39.1
|
||||
'@sentry/cli-linux-x64': 2.39.1
|
||||
'@sentry/cli-win32-i686': 2.39.1
|
||||
'@sentry/cli-win32-x64': 2.39.1
|
||||
'@sentry/cli-darwin': 2.58.6
|
||||
'@sentry/cli-linux-arm': 2.58.6
|
||||
'@sentry/cli-linux-arm64': 2.58.6
|
||||
'@sentry/cli-linux-i686': 2.58.6
|
||||
'@sentry/cli-linux-x64': 2.58.6
|
||||
'@sentry/cli-win32-arm64': 2.58.6
|
||||
'@sentry/cli-win32-i686': 2.58.6
|
||||
'@sentry/cli-win32-x64': 2.58.6
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
|
||||
'@sentry/core@8.41.0':
|
||||
dependencies:
|
||||
'@sentry/types': 8.41.0
|
||||
'@sentry/core@10.57.0': {}
|
||||
|
||||
'@sentry/react@8.41.0(react@18.2.0)':
|
||||
'@sentry/react@10.57.0(react@18.2.0)':
|
||||
dependencies:
|
||||
'@sentry/browser': 8.41.0
|
||||
'@sentry/core': 8.41.0
|
||||
'@sentry/types': 8.41.0
|
||||
hoist-non-react-statics: 3.3.2
|
||||
'@sentry/browser': 10.57.0
|
||||
'@sentry/core': 10.57.0
|
||||
react: 18.2.0
|
||||
|
||||
'@sentry/types@8.41.0': {}
|
||||
|
||||
'@sentry/vite-plugin@2.22.6':
|
||||
'@sentry/rollup-plugin@5.3.0':
|
||||
dependencies:
|
||||
'@sentry/bundler-plugin-core': 2.22.6
|
||||
unplugin: 1.0.1
|
||||
'@sentry/bundler-plugin-core': 5.3.0
|
||||
magic-string: 0.30.8
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
|
||||
'@sentry/vite-plugin@5.3.0':
|
||||
dependencies:
|
||||
'@sentry/bundler-plugin-core': 5.3.0
|
||||
'@sentry/rollup-plugin': 5.3.0
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- rollup
|
||||
- supports-color
|
||||
|
||||
'@shikijs/engine-oniguruma@3.23.0':
|
||||
dependencies:
|
||||
'@shikijs/types': 3.23.0
|
||||
@@ -14307,13 +14296,6 @@ snapshots:
|
||||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
|
||||
glob@9.3.5:
|
||||
dependencies:
|
||||
fs.realpath: 1.0.0
|
||||
minimatch: 8.0.7
|
||||
minipass: 4.2.8
|
||||
path-scurry: 1.11.1
|
||||
|
||||
global-directory@5.0.0:
|
||||
dependencies:
|
||||
ini: 6.0.0
|
||||
@@ -16071,18 +16053,12 @@ snapshots:
|
||||
dependencies:
|
||||
brace-expansion: 2.0.2
|
||||
|
||||
minimatch@8.0.7:
|
||||
dependencies:
|
||||
brace-expansion: 2.0.2
|
||||
|
||||
minimatch@9.0.9:
|
||||
dependencies:
|
||||
brace-expansion: 2.0.2
|
||||
|
||||
minimist@1.2.8: {}
|
||||
|
||||
minipass@4.2.8: {}
|
||||
|
||||
minipass@7.1.3: {}
|
||||
|
||||
moment-timezone@0.5.47:
|
||||
@@ -18347,13 +18323,6 @@ snapshots:
|
||||
'@babel/runtime': 7.28.2
|
||||
detect-node: 2.1.0
|
||||
|
||||
unplugin@1.0.1:
|
||||
dependencies:
|
||||
acorn: 8.16.0
|
||||
chokidar: 3.6.0
|
||||
webpack-sources: 3.2.3
|
||||
webpack-virtual-modules: 0.5.0
|
||||
|
||||
unrs-resolver@1.11.1:
|
||||
dependencies:
|
||||
napi-postinstall: 0.3.4
|
||||
@@ -18573,10 +18542,6 @@ snapshots:
|
||||
|
||||
webidl-conversions@7.0.0: {}
|
||||
|
||||
webpack-sources@3.2.3: {}
|
||||
|
||||
webpack-virtual-modules@0.5.0: {}
|
||||
|
||||
whatwg-encoding@2.0.0:
|
||||
dependencies:
|
||||
iconv-lite: 0.6.3
|
||||
|
||||
@@ -351,19 +351,18 @@ function App(): JSX.Element {
|
||||
Sentry.init({
|
||||
dsn: process.env.SENTRY_DSN,
|
||||
tunnel: process.env.TUNNEL_URL,
|
||||
environment: 'production',
|
||||
environment: process.env.ENVIRONMENT,
|
||||
release: process.env.VERSION,
|
||||
integrations: [
|
||||
// Kept for the `transaction` tag used in routing, even though
|
||||
// tracing is disabled. Ref: https://github.com/SigNoz/platform-pod/issues/2393#issuecomment-4603658055
|
||||
Sentry.browserTracingIntegration(),
|
||||
Sentry.replayIntegration({
|
||||
maskAllText: false,
|
||||
blockAllMedia: false,
|
||||
}),
|
||||
],
|
||||
// Performance Monitoring
|
||||
tracesSampleRate: 1.0, // Capture 100% of the transactions
|
||||
// Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
|
||||
tracePropagationTargets: [],
|
||||
// Session Replay
|
||||
tracesSampleRate: 0, // Ref: https://github.com/SigNoz/platform-pod/issues/2393#issuecomment-4603658055
|
||||
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
|
||||
replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
|
||||
beforeSend(event) {
|
||||
|
||||
11
frontend/src/__tests__/logEventMock.ts
Normal file
11
frontend/src/__tests__/logEventMock.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Shared mock for `api/common/logEvent`.
|
||||
// Wired into jest.config.ts moduleNameMapper, so any import of
|
||||
// `api/common/logEvent` in test code resolves to this file.
|
||||
// Tests can import `logEventMock` to assert analytics calls — Jest's
|
||||
// `clearMocks: true` resets call history between tests.
|
||||
|
||||
export const logEventMock: jest.MockedFunction<
|
||||
(eventName: string, attributes?: Record<string, unknown>) => void
|
||||
> = jest.fn();
|
||||
|
||||
export default logEventMock;
|
||||
29
frontend/src/__tests__/safeNavigateMock.ts
Normal file
29
frontend/src/__tests__/safeNavigateMock.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
// Shared mock for `hooks/useSafeNavigate`.
|
||||
// Wired into jest.config.ts moduleNameMapper, so any import of
|
||||
// `hooks/useSafeNavigate` in test code resolves to this file.
|
||||
// Tests can import `safeNavigateMock` to assert navigation calls — Jest's
|
||||
// `clearMocks: true` resets call history between tests.
|
||||
|
||||
interface SafeNavigateOptions {
|
||||
replace?: boolean;
|
||||
state?: unknown;
|
||||
newTab?: boolean;
|
||||
}
|
||||
|
||||
interface SafeNavigateTo {
|
||||
pathname?: string;
|
||||
search?: string;
|
||||
hash?: string;
|
||||
}
|
||||
|
||||
type SafeNavigateToType = string | SafeNavigateTo;
|
||||
|
||||
export const safeNavigateMock: jest.MockedFunction<
|
||||
(to: SafeNavigateToType, options?: SafeNavigateOptions) => void
|
||||
> = jest.fn();
|
||||
|
||||
export const useSafeNavigate = (): {
|
||||
safeNavigate: typeof safeNavigateMock;
|
||||
} => ({
|
||||
safeNavigate: safeNavigateMock,
|
||||
});
|
||||
@@ -5,6 +5,13 @@ import convertObjectIntoParams from 'lib/query/convertObjectIntoParams';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/alerts/getTriggered';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useGetAlerts` hook (or `getAlerts` fetcher) from
|
||||
* `api/generated/services/alerts` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const getTriggered = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
|
||||
@@ -3,13 +3,36 @@ import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
|
||||
export interface DayBreakdownEntry {
|
||||
timestamp: number;
|
||||
total: number;
|
||||
quantity: number;
|
||||
count: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export interface TierEntry {
|
||||
quantity: number;
|
||||
unitPrice: number;
|
||||
tierCost: number;
|
||||
}
|
||||
|
||||
export interface BreakdownEntry {
|
||||
type: string;
|
||||
unit: string;
|
||||
dayWiseBreakdown: {
|
||||
breakdown: DayBreakdownEntry[];
|
||||
};
|
||||
tiers?: TierEntry[];
|
||||
}
|
||||
|
||||
export interface UsageResponsePayloadProps {
|
||||
billingPeriodStart: Date;
|
||||
billingPeriodEnd: Date;
|
||||
billingPeriodStart: number;
|
||||
billingPeriodEnd: number;
|
||||
details: {
|
||||
total: number;
|
||||
baseFee: number;
|
||||
breakdown: [];
|
||||
breakdown: BreakdownEntry[];
|
||||
billTotal: number;
|
||||
};
|
||||
discount: number;
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createEmail';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createMsTeams';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createOpsgenie';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createPager';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createSlack';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createWebhook';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/delete';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useDeleteChannelByID` hook (or `deleteChannelByID` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const deleteChannel = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editEmail';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const editEmail = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editMsTeams';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const editMsTeams = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editOpsgenie';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const editOpsgenie = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps> | ErrorResponse> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editPager';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const editPager = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editSlack';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const editSlack = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editWebhook';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const editWebhook = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -5,6 +5,13 @@ import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/get';
|
||||
import { Channels } from 'types/api/channels/getAll';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useGetChannelByID` hook (or `getChannelByID` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const get = async (props: Props): Promise<SuccessResponseV2<Channels>> => {
|
||||
try {
|
||||
const response = await axios.get<PayloadProps>(`/channels/${props.id}`);
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { Channels, PayloadProps } from 'types/api/channels/getAll';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useListChannels` hook (or `listChannels` fetcher) from
|
||||
* `api/generated/services/channels` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const getAll = async (): Promise<SuccessResponseV2<Channels[]>> => {
|
||||
try {
|
||||
const response = await axios.get<PayloadProps>('/channels');
|
||||
|
||||
@@ -5,6 +5,13 @@ import { DEFAULT_TIME_RANGE } from 'container/TopNav/DateTimeSelectionV2/constan
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { CreatePublicDashboardProps } from 'types/api/dashboard/public/create';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreatePublicDashboard` hook (or `createPublicDashboard` fetcher) from
|
||||
* `api/generated/services/dashboard` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const createPublicDashboard = async (
|
||||
props: CreatePublicDashboardProps,
|
||||
): Promise<SuccessResponseV2<CreatePublicDashboardProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { GetPublicDashboardDataProps, PayloadProps,PublicDashboardDataProps } from 'types/api/dashboard/public/get';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useGetPublicDashboardData` hook (or `getPublicDashboardData` fetcher) from
|
||||
* `api/generated/services/dashboard` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const getPublicDashboardData = async (props: GetPublicDashboardDataProps): Promise<SuccessResponseV2<PublicDashboardDataProps>> => {
|
||||
try {
|
||||
const response = await axios.get<PayloadProps>(`/public/dashboards/${props.id}`);
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { GetPublicDashboardMetaProps, PayloadProps,PublicDashboardMetaProps } from 'types/api/dashboard/public/getMeta';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useGetPublicDashboard` hook (or `getPublicDashboard` fetcher) from
|
||||
* `api/generated/services/dashboard` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const getPublicDashboardMeta = async (props: GetPublicDashboardMetaProps): Promise<SuccessResponseV2<PublicDashboardMetaProps>> => {
|
||||
try {
|
||||
const response = await axios.get<PayloadProps>(`/dashboards/${props.id}/public`);
|
||||
|
||||
@@ -6,6 +6,13 @@ import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { GetPublicDashboardWidgetDataProps } from 'types/api/dashboard/public/getWidgetData';
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useGetPublicDashboardWidgetQueryRange` hook (or `getPublicDashboardWidgetQueryRange` fetcher) from
|
||||
* `api/generated/services/dashboard` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const getPublicDashboardWidgetData = async (props: GetPublicDashboardWidgetDataProps): Promise<SuccessResponseV2<MetricRangePayloadV5>> => {
|
||||
try {
|
||||
const response = await axios.get(`/public/dashboards/${props.id}/widgets/${props.index}/query_range`, {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps,RevokePublicDashboardAccessProps } from 'types/api/dashboard/public/delete';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useDeletePublicDashboard` hook (or `deletePublicDashboard` fetcher) from
|
||||
* `api/generated/services/dashboard` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const revokePublicDashboardAccess = async (
|
||||
props: RevokePublicDashboardAccessProps,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -5,6 +5,13 @@ import { DEFAULT_TIME_RANGE } from 'container/TopNav/DateTimeSelectionV2/constan
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { UpdatePublicDashboardProps } from 'types/api/dashboard/public/update';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useUpdatePublicDashboard` hook (or `updatePublicDashboard` fetcher) from
|
||||
* `api/generated/services/dashboard` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const updatePublicDashboard = async (
|
||||
props: UpdatePublicDashboardProps,
|
||||
): Promise<SuccessResponseV2<UpdatePublicDashboardProps>> => {
|
||||
|
||||
@@ -9,6 +9,13 @@ interface ISubstituteVars {
|
||||
compositeQuery: ICompositeMetricQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useReplaceVariables` hook (or `replaceVariables` fetcher) from
|
||||
* `api/generated/services/querier` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
export const getSubstituteVars = async (
|
||||
props?: Partial<QueryRangePayloadV5>,
|
||||
signal?: AbortSignal,
|
||||
|
||||
@@ -8,6 +8,12 @@ import { FieldKeyResponse } from 'types/api/dynamicVariables/getFieldKeys';
|
||||
* Get field keys for a given signal type
|
||||
* @param signal Type of signal (traces, logs, metrics)
|
||||
* @param name Optional search text
|
||||
*
|
||||
* @deprecated Use the generated `useGetFieldsKeys` hook (or `getFieldsKeys` fetcher) from
|
||||
* `api/generated/services/fields` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
export const getFieldKeys = async (
|
||||
signal?: 'traces' | 'logs' | 'metrics',
|
||||
|
||||
@@ -11,6 +11,12 @@ import { FieldValueResponse } from 'types/api/dynamicVariables/getFieldValues';
|
||||
* @param name Name of the attribute for which values are being fetched
|
||||
* @param value Optional search text
|
||||
* @param existingQuery Optional existing query - across all present dynamic variables
|
||||
*
|
||||
* @deprecated Use the generated `useGetFieldsValues` hook (or `getFieldsValues` fetcher) from
|
||||
* `api/generated/services/fields` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
export const getFieldValues = async (
|
||||
signal?: 'traces' | 'logs' | 'metrics',
|
||||
|
||||
@@ -19,7 +19,7 @@ import type {
|
||||
|
||||
import type {
|
||||
AlertmanagertypesPostableChannelDTO,
|
||||
ConfigReceiverDTO,
|
||||
AlertmanagertypesReceiverDTO,
|
||||
CreateChannel201,
|
||||
DeleteChannelByIDPathParameters,
|
||||
GetChannelByID200,
|
||||
@@ -385,14 +385,14 @@ export const invalidateGetChannelByID = async (
|
||||
*/
|
||||
export const updateChannelByID = (
|
||||
{ id }: UpdateChannelByIDPathParameters,
|
||||
configReceiverDTO?: BodyType<ConfigReceiverDTO>,
|
||||
alertmanagertypesReceiverDTO?: BodyType<AlertmanagertypesReceiverDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/channels/${id}`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: configReceiverDTO,
|
||||
data: alertmanagertypesReceiverDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -406,7 +406,7 @@ export const getUpdateChannelByIDMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data?: BodyType<ConfigReceiverDTO>;
|
||||
data?: BodyType<AlertmanagertypesReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -415,7 +415,7 @@ export const getUpdateChannelByIDMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data?: BodyType<ConfigReceiverDTO>;
|
||||
data?: BodyType<AlertmanagertypesReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
@@ -432,7 +432,7 @@ export const getUpdateChannelByIDMutationOptions = <
|
||||
Awaited<ReturnType<typeof updateChannelByID>>,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data?: BodyType<ConfigReceiverDTO>;
|
||||
data?: BodyType<AlertmanagertypesReceiverDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
@@ -447,7 +447,7 @@ export type UpdateChannelByIDMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateChannelByID>>
|
||||
>;
|
||||
export type UpdateChannelByIDMutationBody =
|
||||
| BodyType<ConfigReceiverDTO>
|
||||
| BodyType<AlertmanagertypesReceiverDTO>
|
||||
| undefined;
|
||||
export type UpdateChannelByIDMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
@@ -463,7 +463,7 @@ export const useUpdateChannelByID = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data?: BodyType<ConfigReceiverDTO>;
|
||||
data?: BodyType<AlertmanagertypesReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -472,7 +472,7 @@ export const useUpdateChannelByID = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateChannelByIDPathParameters;
|
||||
data?: BodyType<ConfigReceiverDTO>;
|
||||
data?: BodyType<AlertmanagertypesReceiverDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
@@ -483,14 +483,14 @@ export const useUpdateChannelByID = <
|
||||
* @summary Test notification channel
|
||||
*/
|
||||
export const testChannel = (
|
||||
configReceiverDTO?: BodyType<ConfigReceiverDTO>,
|
||||
alertmanagertypesReceiverDTO?: BodyType<AlertmanagertypesReceiverDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/channels/test`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: configReceiverDTO,
|
||||
data: alertmanagertypesReceiverDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -502,13 +502,13 @@ export const getTestChannelMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['testChannel'];
|
||||
@@ -522,7 +522,7 @@ export const getTestChannelMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
{ data?: BodyType<ConfigReceiverDTO> }
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -535,7 +535,9 @@ export const getTestChannelMutationOptions = <
|
||||
export type TestChannelMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof testChannel>>
|
||||
>;
|
||||
export type TestChannelMutationBody = BodyType<ConfigReceiverDTO> | undefined;
|
||||
export type TestChannelMutationBody =
|
||||
| BodyType<AlertmanagertypesReceiverDTO>
|
||||
| undefined;
|
||||
export type TestChannelMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -548,13 +550,13 @@ export const useTestChannel = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof testChannel>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getTestChannelMutationOptions(options));
|
||||
@@ -565,14 +567,14 @@ export const useTestChannel = <
|
||||
* @summary Test notification channel (deprecated)
|
||||
*/
|
||||
export const testChannelDeprecated = (
|
||||
configReceiverDTO?: BodyType<ConfigReceiverDTO>,
|
||||
alertmanagertypesReceiverDTO?: BodyType<AlertmanagertypesReceiverDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/testChannel`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: configReceiverDTO,
|
||||
data: alertmanagertypesReceiverDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -584,13 +586,13 @@ export const getTestChannelDeprecatedMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['testChannelDeprecated'];
|
||||
@@ -604,7 +606,7 @@ export const getTestChannelDeprecatedMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
{ data?: BodyType<ConfigReceiverDTO> }
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -618,7 +620,7 @@ export type TestChannelDeprecatedMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>
|
||||
>;
|
||||
export type TestChannelDeprecatedMutationBody =
|
||||
| BodyType<ConfigReceiverDTO>
|
||||
| BodyType<AlertmanagertypesReceiverDTO>
|
||||
| undefined;
|
||||
export type TestChannelDeprecatedMutationError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
@@ -634,13 +636,13 @@ export const useTestChannelDeprecated = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof testChannelDeprecated>>,
|
||||
TError,
|
||||
{ data?: BodyType<ConfigReceiverDTO> },
|
||||
{ data?: BodyType<AlertmanagertypesReceiverDTO> },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getTestChannelDeprecatedMutationOptions(options));
|
||||
|
||||
@@ -31,11 +31,15 @@ import type {
|
||||
DisconnectAccountPathParameters,
|
||||
GetAccount200,
|
||||
GetAccountPathParameters,
|
||||
GetAccountService200,
|
||||
GetAccountServicePathParameters,
|
||||
GetConnectionCredentials200,
|
||||
GetConnectionCredentialsPathParameters,
|
||||
GetService200,
|
||||
GetServiceParams,
|
||||
GetServicePathParameters,
|
||||
ListAccountServicesMetadata200,
|
||||
ListAccountServicesMetadataPathParameters,
|
||||
ListAccounts200,
|
||||
ListAccountsPathParameters,
|
||||
ListServicesMetadata200,
|
||||
@@ -631,6 +635,227 @@ export const useUpdateAccount = <
|
||||
> => {
|
||||
return useMutation(getUpdateAccountMutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* This endpoint lists the services metadata for the specified account and cloud provider
|
||||
* @summary List account services metadata
|
||||
*/
|
||||
export const listAccountServicesMetadata = (
|
||||
{ cloudProvider, id }: ListAccountServicesMetadataPathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListAccountServicesMetadata200>({
|
||||
url: `/api/v1/cloud_integrations/${cloudProvider}/accounts/${id}/services`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListAccountServicesMetadataQueryKey = ({
|
||||
cloudProvider,
|
||||
id,
|
||||
}: ListAccountServicesMetadataPathParameters) => {
|
||||
return [
|
||||
`/api/v1/cloud_integrations/${cloudProvider}/accounts/${id}/services`,
|
||||
] as const;
|
||||
};
|
||||
|
||||
export const getListAccountServicesMetadataQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listAccountServicesMetadata>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ cloudProvider, id }: ListAccountServicesMetadataPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listAccountServicesMetadata>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ??
|
||||
getListAccountServicesMetadataQueryKey({ cloudProvider, id });
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof listAccountServicesMetadata>>
|
||||
> = ({ signal }) => listAccountServicesMetadata({ cloudProvider, id }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!(cloudProvider && id),
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listAccountServicesMetadata>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type ListAccountServicesMetadataQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listAccountServicesMetadata>>
|
||||
>;
|
||||
export type ListAccountServicesMetadataQueryError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List account services metadata
|
||||
*/
|
||||
|
||||
export function useListAccountServicesMetadata<
|
||||
TData = Awaited<ReturnType<typeof listAccountServicesMetadata>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ cloudProvider, id }: ListAccountServicesMetadataPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listAccountServicesMetadata>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getListAccountServicesMetadataQueryOptions(
|
||||
{ cloudProvider, id },
|
||||
options,
|
||||
);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List account services metadata
|
||||
*/
|
||||
export const invalidateListAccountServicesMetadata = async (
|
||||
queryClient: QueryClient,
|
||||
{ cloudProvider, id }: ListAccountServicesMetadataPathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getListAccountServicesMetadataQueryKey({ cloudProvider, id }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint gets a service and its configuration for the specified cloud integration account
|
||||
* @summary Get service for account
|
||||
*/
|
||||
export const getAccountService = (
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<GetAccountService200>({
|
||||
url: `/api/v1/cloud_integrations/${cloudProvider}/accounts/${id}/services/${serviceId}`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetAccountServiceQueryKey = ({
|
||||
cloudProvider,
|
||||
id,
|
||||
serviceId,
|
||||
}: GetAccountServicePathParameters) => {
|
||||
return [
|
||||
`/api/v1/cloud_integrations/${cloudProvider}/accounts/${id}/services/${serviceId}`,
|
||||
] as const;
|
||||
};
|
||||
|
||||
export const getGetAccountServiceQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ??
|
||||
getGetAccountServiceQueryKey({ cloudProvider, id, serviceId });
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof getAccountService>>
|
||||
> = ({ signal }) =>
|
||||
getAccountService({ cloudProvider, id, serviceId }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!(cloudProvider && id && serviceId),
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetAccountServiceQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getAccountService>>
|
||||
>;
|
||||
export type GetAccountServiceQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Get service for account
|
||||
*/
|
||||
|
||||
export function useGetAccountService<
|
||||
TData = Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetAccountServiceQueryOptions(
|
||||
{ cloudProvider, id, serviceId },
|
||||
options,
|
||||
);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get service for account
|
||||
*/
|
||||
export const invalidateGetAccountService = async (
|
||||
queryClient: QueryClient,
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetAccountServiceQueryKey({ cloudProvider, id, serviceId }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint updates a service for the specified cloud provider
|
||||
* @summary Update service
|
||||
|
||||
@@ -21,9 +21,12 @@ import type {
|
||||
CreateDashboardV2201,
|
||||
CreatePublicDashboard201,
|
||||
CreatePublicDashboardPathParameters,
|
||||
DashboardtypesPatchableDashboardV2DTO,
|
||||
DashboardtypesPostableDashboardV2DTO,
|
||||
DashboardtypesPostablePublicDashboardDTO,
|
||||
DashboardtypesUpdatableDashboardV2DTO,
|
||||
DashboardtypesUpdatablePublicDashboardDTO,
|
||||
DeleteDashboardV2PathParameters,
|
||||
DeletePublicDashboardPathParameters,
|
||||
GetDashboardV2200,
|
||||
GetDashboardV2PathParameters,
|
||||
@@ -33,7 +36,19 @@ import type {
|
||||
GetPublicDashboardPathParameters,
|
||||
GetPublicDashboardWidgetQueryRange200,
|
||||
GetPublicDashboardWidgetQueryRangePathParameters,
|
||||
ListDashboardsForUserV2200,
|
||||
ListDashboardsForUserV2Params,
|
||||
ListDashboardsV2200,
|
||||
ListDashboardsV2Params,
|
||||
LockDashboardV2PathParameters,
|
||||
PatchDashboardV2200,
|
||||
PatchDashboardV2PathParameters,
|
||||
PinDashboardV2PathParameters,
|
||||
RenderErrorResponseDTO,
|
||||
UnlockDashboardV2PathParameters,
|
||||
UnpinDashboardV2PathParameters,
|
||||
UpdateDashboardV2200,
|
||||
UpdateDashboardV2PathParameters,
|
||||
UpdatePublicDashboardPathParameters,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
@@ -633,6 +648,103 @@ export const invalidateGetPublicDashboardWidgetQueryRange = async (
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a page of v2-shape dashboards for the org. This is the pure, user-independent list — it carries no pin state. Use ListDashboardsForUserV2 for the personalized, pin-aware list. Supports a filter DSL (`query`), sort (`updated_at`/`created_at`/`name`), order (`asc`/`desc`), and offset-based pagination (`limit`/`offset`).
|
||||
* @summary List dashboards (v2)
|
||||
*/
|
||||
export const listDashboardsV2 = (
|
||||
params?: ListDashboardsV2Params,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListDashboardsV2200>({
|
||||
url: `/api/v2/dashboards`,
|
||||
method: 'GET',
|
||||
params,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListDashboardsV2QueryKey = (
|
||||
params?: ListDashboardsV2Params,
|
||||
) => {
|
||||
return [`/api/v2/dashboards`, ...(params ? [params] : [])] as const;
|
||||
};
|
||||
|
||||
export const getListDashboardsV2QueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listDashboardsV2>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
params?: ListDashboardsV2Params,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listDashboardsV2>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getListDashboardsV2QueryKey(params);
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof listDashboardsV2>>> = ({
|
||||
signal,
|
||||
}) => listDashboardsV2(params, signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listDashboardsV2>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type ListDashboardsV2QueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listDashboardsV2>>
|
||||
>;
|
||||
export type ListDashboardsV2QueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List dashboards (v2)
|
||||
*/
|
||||
|
||||
export function useListDashboardsV2<
|
||||
TData = Awaited<ReturnType<typeof listDashboardsV2>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
params?: ListDashboardsV2Params,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listDashboardsV2>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getListDashboardsV2QueryOptions(params, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List dashboards (v2)
|
||||
*/
|
||||
export const invalidateListDashboardsV2 = async (
|
||||
queryClient: QueryClient,
|
||||
params?: ListDashboardsV2Params,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getListDashboardsV2QueryKey(params) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint creates a dashboard in the v2 format that follows Perses spec.
|
||||
* @summary Create dashboard (v2)
|
||||
@@ -716,6 +828,85 @@ export const useCreateDashboardV2 = <
|
||||
> => {
|
||||
return useMutation(getCreateDashboardV2MutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* This endpoint deletes a v2-shape dashboard along with its tag relations. Locked dashboards are rejected.
|
||||
* @summary Delete dashboard (v2)
|
||||
*/
|
||||
export const deleteDashboardV2 = (
|
||||
{ id }: DeleteDashboardV2PathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v2/dashboards/${id}`,
|
||||
method: 'DELETE',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getDeleteDashboardV2MutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: DeleteDashboardV2PathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: DeleteDashboardV2PathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['deleteDashboardV2'];
|
||||
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 deleteDashboardV2>>,
|
||||
{ pathParams: DeleteDashboardV2PathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return deleteDashboardV2(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type DeleteDashboardV2MutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof deleteDashboardV2>>
|
||||
>;
|
||||
|
||||
export type DeleteDashboardV2MutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Delete dashboard (v2)
|
||||
*/
|
||||
export const useDeleteDashboardV2 = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: DeleteDashboardV2PathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof deleteDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: DeleteDashboardV2PathParameters },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getDeleteDashboardV2MutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* This endpoint returns a v2-shape dashboard.
|
||||
* @summary Get dashboard (v2)
|
||||
@@ -816,3 +1007,617 @@ export const invalidateGetDashboardV2 = async (
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint applies an RFC 6902 JSON Patch to a v2-shape dashboard. The patch is applied against the postable view of the dashboard (metadata, data, tags), so individual panels, queries, variables, layouts, or tags can be updated without re-sending the rest of the dashboard. Apply is lenient: `remove` on a missing path is a no-op (idempotent) and `add` creates any missing parent objects, rather than failing as strict RFC 6902 would. The resulting dashboard is still validated. Locked dashboards are rejected.
|
||||
* @summary Patch dashboard (v2)
|
||||
*/
|
||||
export const patchDashboardV2 = (
|
||||
{ id }: PatchDashboardV2PathParameters,
|
||||
dashboardtypesPatchableDashboardV2DTONull?: BodyType<DashboardtypesPatchableDashboardV2DTO | null> | null,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<PatchDashboardV2200>({
|
||||
url: `/api/v2/dashboards/${id}`,
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: dashboardtypesPatchableDashboardV2DTONull,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getPatchDashboardV2MutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof patchDashboardV2>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: PatchDashboardV2PathParameters;
|
||||
data?: BodyType<DashboardtypesPatchableDashboardV2DTO | null>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof patchDashboardV2>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: PatchDashboardV2PathParameters;
|
||||
data?: BodyType<DashboardtypesPatchableDashboardV2DTO | null>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['patchDashboardV2'];
|
||||
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 patchDashboardV2>>,
|
||||
{
|
||||
pathParams: PatchDashboardV2PathParameters;
|
||||
data?: BodyType<DashboardtypesPatchableDashboardV2DTO | null>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return patchDashboardV2(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type PatchDashboardV2MutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof patchDashboardV2>>
|
||||
>;
|
||||
export type PatchDashboardV2MutationBody =
|
||||
| BodyType<DashboardtypesPatchableDashboardV2DTO | null>
|
||||
| undefined;
|
||||
export type PatchDashboardV2MutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Patch dashboard (v2)
|
||||
*/
|
||||
export const usePatchDashboardV2 = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof patchDashboardV2>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: PatchDashboardV2PathParameters;
|
||||
data?: BodyType<DashboardtypesPatchableDashboardV2DTO | null>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof patchDashboardV2>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: PatchDashboardV2PathParameters;
|
||||
data?: BodyType<DashboardtypesPatchableDashboardV2DTO | null>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getPatchDashboardV2MutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* This endpoint updates a v2-shape dashboard's metadata, data, and tag set. Locked dashboards are rejected.
|
||||
* @summary Update dashboard (v2)
|
||||
*/
|
||||
export const updateDashboardV2 = (
|
||||
{ id }: UpdateDashboardV2PathParameters,
|
||||
dashboardtypesUpdatableDashboardV2DTO?: BodyType<DashboardtypesUpdatableDashboardV2DTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<UpdateDashboardV2200>({
|
||||
url: `/api/v2/dashboards/${id}`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: dashboardtypesUpdatableDashboardV2DTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getUpdateDashboardV2MutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateDashboardV2>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateDashboardV2PathParameters;
|
||||
data?: BodyType<DashboardtypesUpdatableDashboardV2DTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateDashboardV2>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateDashboardV2PathParameters;
|
||||
data?: BodyType<DashboardtypesUpdatableDashboardV2DTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['updateDashboardV2'];
|
||||
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 updateDashboardV2>>,
|
||||
{
|
||||
pathParams: UpdateDashboardV2PathParameters;
|
||||
data?: BodyType<DashboardtypesUpdatableDashboardV2DTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return updateDashboardV2(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UpdateDashboardV2MutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateDashboardV2>>
|
||||
>;
|
||||
export type UpdateDashboardV2MutationBody =
|
||||
| BodyType<DashboardtypesUpdatableDashboardV2DTO>
|
||||
| undefined;
|
||||
export type UpdateDashboardV2MutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Update dashboard (v2)
|
||||
*/
|
||||
export const useUpdateDashboardV2 = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateDashboardV2>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateDashboardV2PathParameters;
|
||||
data?: BodyType<DashboardtypesUpdatableDashboardV2DTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof updateDashboardV2>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateDashboardV2PathParameters;
|
||||
data?: BodyType<DashboardtypesUpdatableDashboardV2DTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getUpdateDashboardV2MutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* This endpoint unlocks a v2-shape dashboard. Only the dashboard's creator or an org admin may lock or unlock.
|
||||
* @summary Unlock dashboard (v2)
|
||||
*/
|
||||
export const unlockDashboardV2 = (
|
||||
{ id }: UnlockDashboardV2PathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v2/dashboards/${id}/lock`,
|
||||
method: 'DELETE',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getUnlockDashboardV2MutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof unlockDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: UnlockDashboardV2PathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof unlockDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: UnlockDashboardV2PathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['unlockDashboardV2'];
|
||||
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 unlockDashboardV2>>,
|
||||
{ pathParams: UnlockDashboardV2PathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return unlockDashboardV2(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UnlockDashboardV2MutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof unlockDashboardV2>>
|
||||
>;
|
||||
|
||||
export type UnlockDashboardV2MutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Unlock dashboard (v2)
|
||||
*/
|
||||
export const useUnlockDashboardV2 = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof unlockDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: UnlockDashboardV2PathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof unlockDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: UnlockDashboardV2PathParameters },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getUnlockDashboardV2MutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* This endpoint locks a v2-shape dashboard. Only the dashboard's creator or an org admin may lock or unlock.
|
||||
* @summary Lock dashboard (v2)
|
||||
*/
|
||||
export const lockDashboardV2 = (
|
||||
{ id }: LockDashboardV2PathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v2/dashboards/${id}/lock`,
|
||||
method: 'PUT',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getLockDashboardV2MutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof lockDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: LockDashboardV2PathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof lockDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: LockDashboardV2PathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['lockDashboardV2'];
|
||||
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 lockDashboardV2>>,
|
||||
{ pathParams: LockDashboardV2PathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return lockDashboardV2(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type LockDashboardV2MutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof lockDashboardV2>>
|
||||
>;
|
||||
|
||||
export type LockDashboardV2MutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Lock dashboard (v2)
|
||||
*/
|
||||
export const useLockDashboardV2 = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof lockDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: LockDashboardV2PathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof lockDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: LockDashboardV2PathParameters },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getLockDashboardV2MutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* Same as ListDashboardsV2 but personalized for the calling user: each dashboard carries the caller's `pinned` state, and pinned dashboards float to the top of the requested ordering. Supports the same filter DSL, sort, order, and pagination.
|
||||
* @summary List dashboards for the current user (v2)
|
||||
*/
|
||||
export const listDashboardsForUserV2 = (
|
||||
params?: ListDashboardsForUserV2Params,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListDashboardsForUserV2200>({
|
||||
url: `/api/v2/users/me/dashboards`,
|
||||
method: 'GET',
|
||||
params,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListDashboardsForUserV2QueryKey = (
|
||||
params?: ListDashboardsForUserV2Params,
|
||||
) => {
|
||||
return [`/api/v2/users/me/dashboards`, ...(params ? [params] : [])] as const;
|
||||
};
|
||||
|
||||
export const getListDashboardsForUserV2QueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listDashboardsForUserV2>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
params?: ListDashboardsForUserV2Params,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listDashboardsForUserV2>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getListDashboardsForUserV2QueryKey(params);
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof listDashboardsForUserV2>>
|
||||
> = ({ signal }) => listDashboardsForUserV2(params, signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listDashboardsForUserV2>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type ListDashboardsForUserV2QueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listDashboardsForUserV2>>
|
||||
>;
|
||||
export type ListDashboardsForUserV2QueryError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List dashboards for the current user (v2)
|
||||
*/
|
||||
|
||||
export function useListDashboardsForUserV2<
|
||||
TData = Awaited<ReturnType<typeof listDashboardsForUserV2>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
params?: ListDashboardsForUserV2Params,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listDashboardsForUserV2>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getListDashboardsForUserV2QueryOptions(params, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List dashboards for the current user (v2)
|
||||
*/
|
||||
export const invalidateListDashboardsForUserV2 = async (
|
||||
queryClient: QueryClient,
|
||||
params?: ListDashboardsForUserV2Params,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getListDashboardsForUserV2QueryKey(params) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the pin for the calling user. Idempotent — unpinning a dashboard that wasn't pinned still returns 204.
|
||||
* @summary Unpin a dashboard for the current user (v2)
|
||||
*/
|
||||
export const unpinDashboardV2 = (
|
||||
{ id }: UnpinDashboardV2PathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v2/users/me/dashboards/${id}/pins`,
|
||||
method: 'DELETE',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getUnpinDashboardV2MutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof unpinDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: UnpinDashboardV2PathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof unpinDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: UnpinDashboardV2PathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['unpinDashboardV2'];
|
||||
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 unpinDashboardV2>>,
|
||||
{ pathParams: UnpinDashboardV2PathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return unpinDashboardV2(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UnpinDashboardV2MutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof unpinDashboardV2>>
|
||||
>;
|
||||
|
||||
export type UnpinDashboardV2MutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Unpin a dashboard for the current user (v2)
|
||||
*/
|
||||
export const useUnpinDashboardV2 = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof unpinDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: UnpinDashboardV2PathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof unpinDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: UnpinDashboardV2PathParameters },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getUnpinDashboardV2MutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* Pins the dashboard for the calling user. A user can pin at most 10 dashboards; pinning when at the limit returns 409. Re-pinning an already-pinned dashboard is a no-op success.
|
||||
* @summary Pin a dashboard for the current user (v2)
|
||||
*/
|
||||
export const pinDashboardV2 = (
|
||||
{ id }: PinDashboardV2PathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v2/users/me/dashboards/${id}/pins`,
|
||||
method: 'PUT',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getPinDashboardV2MutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof pinDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: PinDashboardV2PathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof pinDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: PinDashboardV2PathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['pinDashboardV2'];
|
||||
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 pinDashboardV2>>,
|
||||
{ pathParams: PinDashboardV2PathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return pinDashboardV2(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type PinDashboardV2MutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof pinDashboardV2>>
|
||||
>;
|
||||
|
||||
export type PinDashboardV2MutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Pin a dashboard for the current user (v2)
|
||||
*/
|
||||
export const usePinDashboardV2 = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof pinDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: PinDashboardV2PathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof pinDashboardV2>>,
|
||||
TError,
|
||||
{ pathParams: PinDashboardV2PathParameters },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getPinDashboardV2MutationOptions(options));
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,13 +12,14 @@ import type {
|
||||
} from 'react-query';
|
||||
|
||||
import type {
|
||||
GetFlamegraph200,
|
||||
GetFlamegraphPathParameters,
|
||||
GetTraceAggregations200,
|
||||
GetTraceAggregationsPathParameters,
|
||||
GetWaterfall200,
|
||||
GetWaterfallPathParameters,
|
||||
GetWaterfallV4200,
|
||||
GetWaterfallV4PathParameters,
|
||||
RenderErrorResponseDTO,
|
||||
SpantypesPostableFlamegraphDTO,
|
||||
SpantypesPostableTraceAggregationsDTO,
|
||||
SpantypesPostableWaterfallDTO,
|
||||
} from '../sigNoz.schemas';
|
||||
@@ -127,46 +128,46 @@ export const useGetTraceAggregations = <
|
||||
return useMutation(getGetTraceAggregationsMutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* Returns the waterfall view of spans for a given trace ID with tree structure, metadata, and windowed pagination
|
||||
* @summary Get waterfall view for a trace
|
||||
* Returns the flamegraph view of spans for a given trace ID.
|
||||
* @summary Get flamegraph view for a trace
|
||||
*/
|
||||
export const getWaterfall = (
|
||||
{ traceID }: GetWaterfallPathParameters,
|
||||
spantypesPostableWaterfallDTO?: BodyType<SpantypesPostableWaterfallDTO>,
|
||||
export const getFlamegraph = (
|
||||
{ traceID }: GetFlamegraphPathParameters,
|
||||
spantypesPostableFlamegraphDTO?: BodyType<SpantypesPostableFlamegraphDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<GetWaterfall200>({
|
||||
url: `/api/v3/traces/${traceID}/waterfall`,
|
||||
return GeneratedAPIInstance<GetFlamegraph200>({
|
||||
url: `/api/v3/traces/${traceID}/flamegraph`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: spantypesPostableWaterfallDTO,
|
||||
data: spantypesPostableFlamegraphDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetWaterfallMutationOptions = <
|
||||
export const getGetFlamegraphMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof getWaterfall>>,
|
||||
Awaited<ReturnType<typeof getFlamegraph>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: GetWaterfallPathParameters;
|
||||
data?: BodyType<SpantypesPostableWaterfallDTO>;
|
||||
pathParams: GetFlamegraphPathParameters;
|
||||
data?: BodyType<SpantypesPostableFlamegraphDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof getWaterfall>>,
|
||||
Awaited<ReturnType<typeof getFlamegraph>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: GetWaterfallPathParameters;
|
||||
data?: BodyType<SpantypesPostableWaterfallDTO>;
|
||||
pathParams: GetFlamegraphPathParameters;
|
||||
data?: BodyType<SpantypesPostableFlamegraphDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['getWaterfall'];
|
||||
const mutationKey = ['getFlamegraph'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
@@ -176,54 +177,54 @@ export const getGetWaterfallMutationOptions = <
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof getWaterfall>>,
|
||||
Awaited<ReturnType<typeof getFlamegraph>>,
|
||||
{
|
||||
pathParams: GetWaterfallPathParameters;
|
||||
data?: BodyType<SpantypesPostableWaterfallDTO>;
|
||||
pathParams: GetFlamegraphPathParameters;
|
||||
data?: BodyType<SpantypesPostableFlamegraphDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return getWaterfall(pathParams, data);
|
||||
return getFlamegraph(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type GetWaterfallMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getWaterfall>>
|
||||
export type GetFlamegraphMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getFlamegraph>>
|
||||
>;
|
||||
export type GetWaterfallMutationBody =
|
||||
| BodyType<SpantypesPostableWaterfallDTO>
|
||||
export type GetFlamegraphMutationBody =
|
||||
| BodyType<SpantypesPostableFlamegraphDTO>
|
||||
| undefined;
|
||||
export type GetWaterfallMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
export type GetFlamegraphMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Get waterfall view for a trace
|
||||
* @summary Get flamegraph view for a trace
|
||||
*/
|
||||
export const useGetWaterfall = <
|
||||
export const useGetFlamegraph = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof getWaterfall>>,
|
||||
Awaited<ReturnType<typeof getFlamegraph>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: GetWaterfallPathParameters;
|
||||
data?: BodyType<SpantypesPostableWaterfallDTO>;
|
||||
pathParams: GetFlamegraphPathParameters;
|
||||
data?: BodyType<SpantypesPostableFlamegraphDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof getWaterfall>>,
|
||||
Awaited<ReturnType<typeof getFlamegraph>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: GetWaterfallPathParameters;
|
||||
data?: BodyType<SpantypesPostableWaterfallDTO>;
|
||||
pathParams: GetFlamegraphPathParameters;
|
||||
data?: BodyType<SpantypesPostableFlamegraphDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getGetWaterfallMutationOptions(options));
|
||||
return useMutation(getGetFlamegraphMutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* Returns the waterfall view of spans including all spans if total spans are under a limit, a max count otherwise. Aggregations are dropped compared to v3
|
||||
|
||||
@@ -5,6 +5,13 @@ import {
|
||||
QueryKeySuggestionsResponseProps,
|
||||
} from 'types/api/querySuggestions/types';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useGetFieldsKeys` hook (or `getFieldsKeys` fetcher) from
|
||||
* `api/generated/services/fields` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
export const getKeySuggestions = (
|
||||
props: QueryKeyRequestProps,
|
||||
): Promise<AxiosResponse<QueryKeySuggestionsResponseProps>> => {
|
||||
|
||||
@@ -5,6 +5,13 @@ import {
|
||||
QueryKeyValueSuggestionsResponseProps,
|
||||
} from 'types/api/querySuggestions/types';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useGetFieldsValues` hook (or `getFieldsValues` fetcher) from
|
||||
* `api/generated/services/fields` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
export const getValueSuggestions = (
|
||||
props: QueryKeyValueRequestProps,
|
||||
): Promise<AxiosResponse<QueryKeyValueSuggestionsResponseProps>> => {
|
||||
|
||||
@@ -15,6 +15,13 @@ export interface CreateRoutingPolicyResponse {
|
||||
message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreateRoutePolicy` hook (or `createRoutePolicy` fetcher) from
|
||||
* `api/generated/services/routepolicies` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const createRoutingPolicy = async (
|
||||
props: CreateRoutingPolicyBody,
|
||||
): Promise<
|
||||
|
||||
@@ -8,6 +8,13 @@ export interface DeleteRoutingPolicyResponse {
|
||||
message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useDeleteRoutePolicyByID` hook (or `deleteRoutePolicyByID` fetcher) from
|
||||
* `api/generated/services/routepolicies` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const deleteRoutingPolicy = async (
|
||||
routingPolicyId: string,
|
||||
): Promise<
|
||||
|
||||
@@ -20,6 +20,13 @@ export interface GetRoutingPoliciesResponse {
|
||||
data?: ApiRoutingPolicy[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useGetAllRoutePolicies` hook (or `getAllRoutePolicies` fetcher) from
|
||||
* `api/generated/services/routepolicies` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
export const getRoutingPolicies = async (
|
||||
signal?: AbortSignal,
|
||||
headers?: Record<string, string>,
|
||||
|
||||
@@ -15,6 +15,13 @@ export interface UpdateRoutingPolicyResponse {
|
||||
message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useUpdateRoutePolicy` hook (or `updateRoutePolicy` fetcher) from
|
||||
* `api/generated/services/routepolicies` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const updateRoutingPolicy = async (
|
||||
id: string,
|
||||
props: UpdateRoutingPolicyBody,
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { ApiV3Instance as axios } from 'api';
|
||||
import { omit } from 'lodash-es';
|
||||
import { getWaterfallV4 } from 'api/generated/services/tracedetail';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import {
|
||||
GetTraceV3PayloadProps,
|
||||
GetTraceV3SuccessResponse,
|
||||
GetTraceV4PayloadProps,
|
||||
GetTraceV4SuccessResponse,
|
||||
SpanV3,
|
||||
} from 'types/api/trace/getTraceV3';
|
||||
|
||||
const getTraceV3 = async (
|
||||
props: GetTraceV3PayloadProps,
|
||||
): Promise<SuccessResponse<GetTraceV3SuccessResponse> | ErrorResponse> => {
|
||||
const getTraceV4 = async (
|
||||
props: GetTraceV4PayloadProps,
|
||||
): Promise<SuccessResponse<GetTraceV4SuccessResponse> | ErrorResponse> => {
|
||||
let uncollapsedSpans = [...props.uncollapsedSpans];
|
||||
if (!props.isSelectedSpanIDUnCollapsed) {
|
||||
uncollapsedSpans = uncollapsedSpans.filter(
|
||||
@@ -19,31 +18,36 @@ const getTraceV3 = async (
|
||||
props.selectedSpanId &&
|
||||
!uncollapsedSpans.includes(props.selectedSpanId)
|
||||
) {
|
||||
// V3 backend only uses uncollapsedSpans list (unlike V2 which also interprets
|
||||
// Backend only uses the uncollapsedSpans list (unlike V2 which also interprets
|
||||
// isSelectedSpanIDUnCollapsed server-side), so explicitly add the selected span
|
||||
uncollapsedSpans.push(props.selectedSpanId);
|
||||
}
|
||||
const postData: GetTraceV3PayloadProps = {
|
||||
...props,
|
||||
uncollapsedSpans,
|
||||
limit: 10000,
|
||||
};
|
||||
const response = await axios.post<GetTraceV3SuccessResponse>(
|
||||
`/traces/${props.traceId}/waterfall`,
|
||||
omit(postData, 'traceId'),
|
||||
const response = await getWaterfallV4(
|
||||
{ traceID: props.traceId },
|
||||
{
|
||||
selectedSpanId: props.selectedSpanId,
|
||||
uncollapsedSpans,
|
||||
},
|
||||
);
|
||||
|
||||
// V3 API wraps response in { status, data }
|
||||
const rawPayload = (response.data as any).data || response.data;
|
||||
// Generated client unwraps the axios response; .data is the waterfall payload.
|
||||
// Wire spans carry time_unix; SpanV3's timestamp + 'service.name' are derived below.
|
||||
type WireSpan = Omit<SpanV3, 'timestamp' | 'service.name'> & {
|
||||
time_unix: number;
|
||||
};
|
||||
const rawPayload = response.data as unknown as Omit<
|
||||
GetTraceV4SuccessResponse,
|
||||
'spans'
|
||||
> & { spans: WireSpan[] | null };
|
||||
|
||||
// Derive 'service.name' from resource for convenience — only derived field
|
||||
const spans: SpanV3[] = (rawPayload.spans || []).map((span: any) => ({
|
||||
const spans: SpanV3[] = (rawPayload.spans || []).map((span) => ({
|
||||
...span,
|
||||
'service.name': span.resource?.['service.name'] || '',
|
||||
timestamp: span.time_unix,
|
||||
}));
|
||||
|
||||
// V3 API returns startTimestampMillis/endTimestampMillis as relative durations (ms from epoch offset),
|
||||
// API returns startTimestampMillis/endTimestampMillis as relative durations (ms from epoch offset),
|
||||
// not absolute unix millis like V2. The span timestamps are absolute unix millis.
|
||||
// Convert by using the first span's timestamp as the base if there's a mismatch.
|
||||
let { startTimestampMillis, endTimestampMillis } = rawPayload;
|
||||
@@ -70,4 +74,4 @@ const getTraceV3 = async (
|
||||
};
|
||||
};
|
||||
|
||||
export default getTraceV3;
|
||||
export default getTraceV4;
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/user/resetPassword';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useResetPassword` hook (or `resetPassword` fetcher) from
|
||||
* `api/generated/services/users` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const resetPassword = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { UsersProps } from 'types/api/user/inviteUsers';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreateBulkInvite` hook (or `createBulkInvite` fetcher) from
|
||||
* `api/generated/services/users` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const inviteUsers = async (
|
||||
users: UsersProps,
|
||||
): Promise<SuccessResponseV2<null>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/user/setInvite';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreateInvite` hook (or `createInvite` fetcher) from
|
||||
* `api/generated/services/users` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const sendInvite = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
|
||||
@@ -5,6 +5,13 @@ import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps } from 'types/api/preferences/list';
|
||||
import { OrgPreference } from 'types/api/preferences/preference';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useListOrgPreferences` hook (or `listOrgPreferences` fetcher) from
|
||||
* `api/generated/services/preferences` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const listPreference = async (): Promise<
|
||||
SuccessResponseV2<OrgPreference[]>
|
||||
> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { Props } from 'types/api/preferences/update';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useUpdateOrgPreference` hook (or `updateOrgPreference` fetcher) from
|
||||
* `api/generated/services/preferences` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const update = async (props: Props): Promise<SuccessResponseV2<null>> => {
|
||||
try {
|
||||
const response = await axios.put(`/org/preferences/${props.name}`, {
|
||||
|
||||
@@ -5,6 +5,13 @@ import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps } from 'types/api/preferences/list';
|
||||
import { UserPreference } from 'types/api/preferences/preference';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useListUserPreferences` hook (or `listUserPreferences` fetcher) from
|
||||
* `api/generated/services/preferences` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const list = async (): Promise<SuccessResponseV2<UserPreference[]>> => {
|
||||
try {
|
||||
const response = await axios.get<PayloadProps>(`/user/preferences`);
|
||||
|
||||
@@ -5,6 +5,13 @@ import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/preferences/get';
|
||||
import { UserPreference } from 'types/api/preferences/preference';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useGetUserPreference` hook (or `getUserPreference` fetcher) from
|
||||
* `api/generated/services/preferences` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const get = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<UserPreference>> => {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { Props } from 'types/api/preferences/update';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useUpdateUserPreference` hook (or `updateUserPreference` fetcher) from
|
||||
* `api/generated/services/preferences` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const update = async (props: Props): Promise<SuccessResponseV2<null>> => {
|
||||
try {
|
||||
const response = await axios.put(`/user/preferences/${props.name}`, {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, RawSuccessResponse, SuccessResponseV2 } from 'types/api';
|
||||
import { Props, SessionsContext } from 'types/api/v2/sessions/context/get';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useGetSessionContext` hook (or `getSessionContext` fetcher) from
|
||||
* `api/generated/services/sessions` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const get = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponseV2<SessionsContext>> => {
|
||||
|
||||
@@ -3,6 +3,13 @@ import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, RawSuccessResponse, SuccessResponseV2 } from 'types/api';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useDeleteSession` hook (or `deleteSession` fetcher) from
|
||||
* `api/generated/services/sessions` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const deleteSession = async (): Promise<SuccessResponseV2<null>> => {
|
||||
try {
|
||||
const response = await axios.delete<RawSuccessResponse<null>>('/sessions');
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, RawSuccessResponse, SuccessResponseV2 } from 'types/api';
|
||||
import { Props, Token } from 'types/api/v2/sessions/email_password/post';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useCreateSessionByEmailPassword` hook (or `createSessionByEmailPassword` fetcher) from
|
||||
* `api/generated/services/sessions` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const post = async (props: Props): Promise<SuccessResponseV2<Token>> => {
|
||||
try {
|
||||
const response = await axios.post<RawSuccessResponse<Token>>(
|
||||
|
||||
@@ -4,6 +4,13 @@ import { AxiosError } from 'axios';
|
||||
import { ErrorV2Resp, RawSuccessResponse, SuccessResponseV2 } from 'types/api';
|
||||
import { Props, Token } from 'types/api/v2/sessions/rotate/post';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useRotateSession` hook (or `rotateSession` fetcher) from
|
||||
* `api/generated/services/sessions` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
const post = async (props: Props): Promise<SuccessResponseV2<Token>> => {
|
||||
try {
|
||||
const response = await axios.post<RawSuccessResponse<Token>>(
|
||||
|
||||
@@ -349,7 +349,7 @@ function convertV5DataByType(
|
||||
*/
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
export function convertV5ResponseToLegacy(
|
||||
v5Response: SuccessResponse<MetricRangePayloadV5>,
|
||||
v5Response: SuccessResponse<MetricRangePayloadV5, QueryRangeRequestV5>,
|
||||
legendMap: Record<string, string>,
|
||||
formatForWeb?: boolean,
|
||||
): SuccessResponse<MetricRangePayloadV3> & { warning?: Warning } {
|
||||
@@ -357,7 +357,7 @@ export function convertV5ResponseToLegacy(
|
||||
const v5Data = payload?.data;
|
||||
|
||||
const aggregationPerQuery =
|
||||
(params as QueryRangeRequestV5)?.compositeQuery?.queries
|
||||
params?.compositeQuery?.queries
|
||||
?.filter((query) => query.type === 'builder_query')
|
||||
.reduce(
|
||||
(acc, query) => {
|
||||
|
||||
@@ -8,6 +8,13 @@ import {
|
||||
QueryRangePayloadV5,
|
||||
} from 'types/api/v5/queryRange';
|
||||
|
||||
/**
|
||||
* @deprecated Use the generated `useQueryRangeV5` hook (or `queryRangeV5` fetcher) from
|
||||
* `api/generated/services/querier` instead. This hand-written client targets the
|
||||
* same endpoint and will be removed once call sites migrate.
|
||||
*
|
||||
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
|
||||
*/
|
||||
export const getQueryRangeV5 = async (
|
||||
props: QueryRangePayloadV5,
|
||||
version: string,
|
||||
|
||||
@@ -359,8 +359,7 @@ function CustomTimePickerPopoverContent({
|
||||
<Clock
|
||||
color={Color.BG_ROBIN_400}
|
||||
className="timezone-container__clock-icon"
|
||||
height={12}
|
||||
width={12}
|
||||
size={14}
|
||||
/>
|
||||
|
||||
<span className="timezone__name">{timezone.name}</span>
|
||||
|
||||
@@ -144,10 +144,7 @@ function AddedFields({
|
||||
field={field}
|
||||
onRemove={handleRemove}
|
||||
allowDrag={allowDrag}
|
||||
isRequired={
|
||||
requiredFields.includes(field.name) ||
|
||||
requiredFields.includes(field.key as string)
|
||||
}
|
||||
isRequired={requiredFields.includes(field.key as string)}
|
||||
/>
|
||||
))}
|
||||
</SortableContext>
|
||||
|
||||
@@ -25,7 +25,7 @@ describe('AddedFields — requiredFields', () => {
|
||||
expect(screen.getAllByRole('button', { name: /remove/i })).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('hides the Remove button for fields whose name is in requiredFields', () => {
|
||||
it('hides the Remove button for fields whose composite key is in requiredFields', () => {
|
||||
const fields = [makeField('a'), makeField('b'), makeField('c')];
|
||||
|
||||
render(
|
||||
@@ -33,7 +33,7 @@ describe('AddedFields — requiredFields', () => {
|
||||
inputValue=""
|
||||
fields={fields}
|
||||
onFieldsChange={jest.fn()}
|
||||
requiredFields={['a', 'c']}
|
||||
requiredFields={['log.a', 'log.c']}
|
||||
/>,
|
||||
);
|
||||
|
||||
@@ -50,7 +50,7 @@ describe('AddedFields — requiredFields', () => {
|
||||
inputValue=""
|
||||
fields={fields}
|
||||
onFieldsChange={jest.fn()}
|
||||
requiredFields={['a']}
|
||||
requiredFields={['log.a']}
|
||||
/>,
|
||||
);
|
||||
|
||||
@@ -58,9 +58,9 @@ describe('AddedFields — requiredFields', () => {
|
||||
expect(screen.getByText('b')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('locks all variants of a required name regardless of fieldContext', () => {
|
||||
// Two `body` fields with different contexts — both should lock when
|
||||
// `body` is in requiredFields.
|
||||
it('locks ONLY the canonical variant — a same-name field from another context stays removable', () => {
|
||||
// Two `body` fields with different contexts. requiredFields holds the
|
||||
// canonical composite key only, so the attribute variant is deletable.
|
||||
const fields = [makeField('body', 'log'), makeField('body', 'attribute')];
|
||||
|
||||
render(
|
||||
@@ -68,41 +68,6 @@ describe('AddedFields — requiredFields', () => {
|
||||
inputValue=""
|
||||
fields={fields}
|
||||
onFieldsChange={jest.fn()}
|
||||
requiredFields={['body']}
|
||||
/>,
|
||||
);
|
||||
|
||||
// Both 'body' variants locked → zero Remove buttons.
|
||||
expect(screen.queryAllByRole('button', { name: /remove/i })).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('treats requiredFields as exact-name match (substring does not lock)', () => {
|
||||
const fields = [makeField('body'), makeField('body_extra')];
|
||||
|
||||
render(
|
||||
<AddedFields
|
||||
inputValue=""
|
||||
fields={fields}
|
||||
onFieldsChange={jest.fn()}
|
||||
requiredFields={['body']}
|
||||
/>,
|
||||
);
|
||||
|
||||
// 'body' locked, 'body_extra' removable.
|
||||
expect(screen.getAllByRole('button', { name: /remove/i })).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('also accepts composite IDs in requiredFields (locks a specific variant)', () => {
|
||||
// Two `body` fields with different contexts.
|
||||
const fields = [makeField('body', 'log'), makeField('body', 'attribute')];
|
||||
|
||||
render(
|
||||
<AddedFields
|
||||
inputValue=""
|
||||
fields={fields}
|
||||
onFieldsChange={jest.fn()}
|
||||
// Composite ID — locks ONLY the log variant, attribute variant stays
|
||||
// removable.
|
||||
requiredFields={['log.body']}
|
||||
/>,
|
||||
);
|
||||
@@ -110,4 +75,37 @@ describe('AddedFields — requiredFields', () => {
|
||||
// One Remove button: the attribute variant. log variant is locked.
|
||||
expect(screen.getAllByRole('button', { name: /remove/i })).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('does not lock anything when a bare name is passed (composite key required)', () => {
|
||||
// Bare `body` no longer matches — matching is composite-key only now.
|
||||
const fields = [makeField('body', 'log'), makeField('body', 'attribute')];
|
||||
|
||||
render(
|
||||
<AddedFields
|
||||
inputValue=""
|
||||
fields={fields}
|
||||
onFieldsChange={jest.fn()}
|
||||
requiredFields={['body']}
|
||||
/>,
|
||||
);
|
||||
|
||||
// Neither variant locked → both removable.
|
||||
expect(screen.getAllByRole('button', { name: /remove/i })).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('treats requiredFields as exact composite-key match (substring does not lock)', () => {
|
||||
const fields = [makeField('body'), makeField('body_extra')];
|
||||
|
||||
render(
|
||||
<AddedFields
|
||||
inputValue=""
|
||||
fields={fields}
|
||||
onFieldsChange={jest.fn()}
|
||||
requiredFields={['log.body']}
|
||||
/>,
|
||||
);
|
||||
|
||||
// 'log.body' locked, 'log.body_extra' removable.
|
||||
expect(screen.getAllByRole('button', { name: /remove/i })).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,17 +3,12 @@ import { useLocation } from 'react-router-dom';
|
||||
import { toast } from '@signozhq/ui/sonner';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { logEventMock } from '__tests__/logEventMock';
|
||||
import { handleContactSupport } from 'container/Integrations/utils';
|
||||
import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
|
||||
|
||||
import FeedbackModal from '../FeedbackModal';
|
||||
|
||||
jest.mock('api/common/logEvent', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useLocation: jest.fn(),
|
||||
@@ -35,7 +30,6 @@ jest.mock('container/Integrations/utils', () => ({
|
||||
handleContactSupport: jest.fn(),
|
||||
}));
|
||||
|
||||
const mockLogEvent = logEvent as jest.MockedFunction<typeof logEvent>;
|
||||
const mockUseLocation = useLocation as jest.Mock;
|
||||
const mockUseGetTenantLicense = useGetTenantLicense as jest.Mock;
|
||||
const mockHandleContactSupport = handleContactSupport as jest.Mock;
|
||||
@@ -50,6 +44,7 @@ const mockLocation = {
|
||||
describe('FeedbackModal', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
logEventMock.mockReturnValue(Promise.resolve() as never);
|
||||
mockUseLocation.mockReturnValue(mockLocation);
|
||||
mockUseGetTenantLicense.mockReturnValue({
|
||||
isCloudUser: false,
|
||||
@@ -116,7 +111,7 @@ describe('FeedbackModal', () => {
|
||||
await user.type(textarea, testFeedback);
|
||||
await user.click(submitButton);
|
||||
|
||||
expect(mockLogEvent).toHaveBeenCalledWith('Feedback: Submitted', {
|
||||
expect(logEventMock).toHaveBeenCalledWith('Feedback: Submitted', {
|
||||
data: testFeedback,
|
||||
type: 'feedback',
|
||||
page: mockLocation.pathname,
|
||||
@@ -149,7 +144,7 @@ describe('FeedbackModal', () => {
|
||||
await user.type(textarea, testFeedback);
|
||||
await user.click(submitButton);
|
||||
|
||||
expect(mockLogEvent).toHaveBeenCalledWith('Feedback: Submitted', {
|
||||
expect(logEventMock).toHaveBeenCalledWith('Feedback: Submitted', {
|
||||
data: testFeedback,
|
||||
type: 'reportBug',
|
||||
page: mockLocation.pathname,
|
||||
@@ -182,7 +177,7 @@ describe('FeedbackModal', () => {
|
||||
await user.type(textarea, testFeedback);
|
||||
await user.click(submitButton);
|
||||
|
||||
expect(mockLogEvent).toHaveBeenCalledWith('Feedback: Submitted', {
|
||||
expect(logEventMock).toHaveBeenCalledWith('Feedback: Submitted', {
|
||||
data: testFeedback,
|
||||
type: 'featureRequest',
|
||||
page: mockLocation.pathname,
|
||||
|
||||
@@ -2,16 +2,11 @@
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { logEventMock } from '__tests__/logEventMock';
|
||||
import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
|
||||
|
||||
import HeaderRightSection from '../HeaderRightSection';
|
||||
|
||||
jest.mock('api/common/logEvent', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useLocation: jest.fn(),
|
||||
@@ -50,7 +45,6 @@ jest.mock('hooks/useIsAIAssistantEnabled', () => ({
|
||||
useIsAIAssistantEnabled: (): boolean => false,
|
||||
}));
|
||||
|
||||
const mockLogEvent = logEvent as jest.Mock;
|
||||
const mockUseLocation = useLocation as jest.Mock;
|
||||
const mockUseGetTenantLicense = useGetTenantLicense as jest.Mock;
|
||||
|
||||
@@ -120,7 +114,7 @@ describe('HeaderRightSection', () => {
|
||||
|
||||
await user.click(feedbackButton!);
|
||||
|
||||
expect(mockLogEvent).toHaveBeenCalledWith('Feedback: Clicked', {
|
||||
expect(logEventMock).toHaveBeenCalledWith('Feedback: Clicked', {
|
||||
page: mockLocation.pathname,
|
||||
});
|
||||
expect(screen.getByTestId('feedback-modal')).toBeInTheDocument();
|
||||
@@ -133,7 +127,7 @@ describe('HeaderRightSection', () => {
|
||||
const shareButton = screen.getByRole('button', { name: /share/i });
|
||||
await user.click(shareButton);
|
||||
|
||||
expect(mockLogEvent).toHaveBeenCalledWith('Share: Clicked', {
|
||||
expect(logEventMock).toHaveBeenCalledWith('Share: Clicked', {
|
||||
page: mockLocation.pathname,
|
||||
});
|
||||
expect(screen.getByTestId('share-modal')).toBeInTheDocument();
|
||||
@@ -150,7 +144,7 @@ describe('HeaderRightSection', () => {
|
||||
|
||||
await user.click(announcementsButton!);
|
||||
|
||||
expect(mockLogEvent).toHaveBeenCalledWith('Announcements: Clicked', {
|
||||
expect(logEventMock).toHaveBeenCalledWith('Announcements: Clicked', {
|
||||
page: mockLocation.pathname,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,18 +5,13 @@ import { matchPath, useLocation } from 'react-router-dom';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { logEventMock } from '__tests__/logEventMock';
|
||||
import ROUTES from 'constants/routes';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
import GetMinMax from 'lib/getMinMax';
|
||||
|
||||
import ShareURLModal from '../ShareURLModal';
|
||||
|
||||
jest.mock('api/common/logEvent', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useLocation: jest.fn(),
|
||||
@@ -53,7 +48,6 @@ Object.defineProperty(window, 'location', {
|
||||
writable: true,
|
||||
});
|
||||
|
||||
const mockLogEvent = logEvent as jest.Mock;
|
||||
const mockUseLocation = useLocation as jest.Mock;
|
||||
const mockUseUrlQuery = useUrlQuery as jest.Mock;
|
||||
const mockUseSelector = useSelector as jest.Mock;
|
||||
@@ -125,7 +119,7 @@ describe('ShareURLModal', () => {
|
||||
await user.click(copyButton);
|
||||
|
||||
expect(mockHandleCopyToClipboard).toHaveBeenCalled();
|
||||
expect(mockLogEvent).toHaveBeenCalledWith('Share: Copy link clicked', {
|
||||
expect(logEventMock).toHaveBeenCalledWith('Share: Copy link clicked', {
|
||||
page: TEST_PATH,
|
||||
URL: expect.any(String),
|
||||
});
|
||||
|
||||
@@ -10,9 +10,9 @@ jest.mock('providers/Timezone', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const field = (name: string): IField => ({
|
||||
const field = (name: string, type = ''): IField => ({
|
||||
name,
|
||||
type: '',
|
||||
type,
|
||||
dataType: 'string',
|
||||
});
|
||||
|
||||
@@ -38,18 +38,16 @@ describe('useLogsTableColumns — selectColumns-order respected', () => {
|
||||
useLogsTableColumns({
|
||||
fields: [
|
||||
field('service.name'),
|
||||
field('body'),
|
||||
field('body', 'log'),
|
||||
field('request.id'),
|
||||
field('timestamp'),
|
||||
field('timestamp', 'log'),
|
||||
],
|
||||
fontSize: FontSize.SMALL,
|
||||
}),
|
||||
);
|
||||
|
||||
// body/timestamp are NOT pinned to fixed positions — they appear where the
|
||||
// caller placed them in `fields`. body/timestamp use composite IDs
|
||||
// ('log.body', 'log.timestamp') since their fieldContext is fixed; user
|
||||
// fields here have empty `type` so their composite collapses to bare name.
|
||||
// body/timestamp appear where the caller placed them, keyed by their
|
||||
// composite IDs ('log.*'); contextless user fields collapse to bare name.
|
||||
expect(result.current.map((c) => c.id)).toStrictEqual([
|
||||
'state-indicator',
|
||||
'service.name',
|
||||
@@ -59,6 +57,43 @@ describe('useLogsTableColumns — selectColumns-order respected', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('renders a same-name field from another context as a DISTINCT column (no collision)', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useLogsTableColumns({
|
||||
fields: [field('body', 'log'), field('body', 'attribute')],
|
||||
fontSize: FontSize.SMALL,
|
||||
}),
|
||||
);
|
||||
|
||||
const byId = new Map(result.current.map((c) => [c.id, c]));
|
||||
// Attribute variant is its own column, not a duplicate 'log.body'.
|
||||
expect(result.current.map((c) => c.id)).toStrictEqual([
|
||||
'state-indicator',
|
||||
'log.body',
|
||||
'attribute.body',
|
||||
]);
|
||||
expect(byId.get('log.body')?.enableRemove).toBe(false);
|
||||
expect(byId.get('attribute.body')?.enableRemove).toBe(true);
|
||||
});
|
||||
|
||||
it('applies the same distinct-column treatment to timestamp variants', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useLogsTableColumns({
|
||||
fields: [field('timestamp', 'log'), field('timestamp', 'attribute')],
|
||||
fontSize: FontSize.SMALL,
|
||||
}),
|
||||
);
|
||||
|
||||
const byId = new Map(result.current.map((c) => [c.id, c]));
|
||||
expect(result.current.map((c) => c.id)).toStrictEqual([
|
||||
'state-indicator',
|
||||
'log.timestamp',
|
||||
'attribute.timestamp',
|
||||
]);
|
||||
expect(byId.get('log.timestamp')?.enableRemove).toBe(false);
|
||||
expect(byId.get('attribute.timestamp')?.enableRemove).toBe(true);
|
||||
});
|
||||
|
||||
it('skips the synthetic "id" field name', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useLogsTableColumns({
|
||||
@@ -77,7 +112,11 @@ describe('useLogsTableColumns — selectColumns-order respected', () => {
|
||||
it('uses the special body/timestamp coldefs (canBeHidden=false), not the generic user field def', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useLogsTableColumns({
|
||||
fields: [field('body'), field('timestamp'), field('user_field')],
|
||||
fields: [
|
||||
field('body', 'log'),
|
||||
field('timestamp', 'log'),
|
||||
field('user_field'),
|
||||
],
|
||||
fontSize: FontSize.SMALL,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -96,15 +96,18 @@ export function useLogsTableColumns({
|
||||
),
|
||||
});
|
||||
|
||||
// Match body/timestamp by composite key, not bare name — else a variant
|
||||
// like `attribute.body` collapses onto `log.body`, duplicating the column.
|
||||
const fieldCols = fields
|
||||
.map((f): TableColumnDef<ILog> | null => {
|
||||
if (f.name === 'id') {
|
||||
return null;
|
||||
}
|
||||
if (f.name === 'timestamp') {
|
||||
const compositeKey = buildCompositeKey(f.name, f.type);
|
||||
if (compositeKey === timestampCol.id) {
|
||||
return timestampCol;
|
||||
}
|
||||
if (f.name === 'body') {
|
||||
if (compositeKey === bodyCol.id) {
|
||||
return bodyCol;
|
||||
}
|
||||
return makeUserFieldCol(f);
|
||||
|
||||
@@ -109,6 +109,16 @@ $custom-border-color: #2c3044;
|
||||
color: color-mix(in srgb, var(--l2-foreground) 45%, transparent);
|
||||
}
|
||||
|
||||
.ant-select-clear {
|
||||
background-color: var(--l2-background);
|
||||
color: var(--l2-foreground);
|
||||
font-size: 12px;
|
||||
|
||||
&:hover {
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
// Customize tags in multiselect (dark mode by default)
|
||||
.ant-select-selection-item {
|
||||
background-color: var(--l1-border);
|
||||
@@ -392,7 +402,9 @@ $custom-border-color: #2c3044;
|
||||
// Custom dropdown styles for multi-select
|
||||
.custom-multiselect-dropdown {
|
||||
padding: 8px 0 0 0;
|
||||
max-height: 350px;
|
||||
// Tall enough to hold the react-virtuoso list (<=300px) + header/footer
|
||||
// so only the list scrolls (avoids a second scrollbar on this container).
|
||||
max-height: 410px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scrollbar-width: thin;
|
||||
@@ -483,8 +495,12 @@ $custom-border-color: #2c3044;
|
||||
.option-checkbox {
|
||||
width: 100%;
|
||||
|
||||
> span:not(.ant-checkbox) {
|
||||
width: 100%;
|
||||
// @signozhq/ui Checkbox renders children inside a <label> that is
|
||||
// content-sized by default. Make it fill the row (min-width: 0 lets it
|
||||
// shrink) so the option text below can truncate instead of overflowing.
|
||||
> label {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.all-option-text {
|
||||
@@ -501,7 +517,12 @@ $custom-border-color: #2c3044;
|
||||
width: 100%;
|
||||
|
||||
.option-label-text {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
margin-bottom: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.option-badge {
|
||||
@@ -514,26 +535,30 @@ $custom-border-color: #2c3044;
|
||||
}
|
||||
}
|
||||
|
||||
.only-btn {
|
||||
display: none;
|
||||
}
|
||||
// Size the buttons to the row's resting content height (20px) and fully
|
||||
// override antd's default 32px Button box, so revealing them on hover
|
||||
// never changes the row height.
|
||||
.only-btn,
|
||||
.toggle-btn {
|
||||
display: none;
|
||||
}
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 18px;
|
||||
min-height: 0;
|
||||
padding: 0 6px;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
|
||||
.only-btn:hover {
|
||||
background-color: unset;
|
||||
}
|
||||
.toggle-btn:hover {
|
||||
background-color: unset;
|
||||
&:hover {
|
||||
background-color: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.option-content:hover {
|
||||
.only-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 21px;
|
||||
}
|
||||
.toggle-btn {
|
||||
display: none;
|
||||
@@ -548,9 +573,6 @@ $custom-border-color: #2c3044;
|
||||
.option-checkbox:hover {
|
||||
.toggle-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 21px;
|
||||
}
|
||||
.option-badge {
|
||||
display: none;
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
// TODO: Improve the styling of the query aggregation container and its components. - @YounixM , @H4ad
|
||||
|
||||
$dropdown-base-height: 250px;
|
||||
$recents-header-height: 30px;
|
||||
$recent-row-height: 36px;
|
||||
// how many recents are rendered, this caps how tall the dropdown can grow to fit them.
|
||||
$max-recents-shown: 5;
|
||||
|
||||
.code-mirror-where-clause {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@@ -117,7 +123,23 @@
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
font-family: 'Space Mono', monospace !important;
|
||||
min-height: 200px !important;
|
||||
max-height: $dropdown-base-height !important;
|
||||
overflow-y: auto !important;
|
||||
|
||||
// Recents render at the top of the dropdown ahead of regular suggestions.
|
||||
// At the base max-height, having recents in view would crowd out the
|
||||
// suggestion list below. This loop grows the dropdown by one row's worth
|
||||
// of height for every recent present (up to $max-recents-shown), plus the
|
||||
// section header. `:has(> li:nth-of-type(N) .cm-completionIcon-recent)`
|
||||
// matches when the Nth child of <ul> is a recent — i.e. there are at
|
||||
// least N recents visible.
|
||||
@for $i from 1 through $max-recents-shown {
|
||||
&:has(> li:nth-of-type(#{$i}) .cm-completionIcon-recent) {
|
||||
max-height: $dropdown-base-height +
|
||||
$recents-header-height +
|
||||
($i * $recent-row-height) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0.3rem;
|
||||
@@ -133,6 +155,19 @@
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
completion-section {
|
||||
display: block;
|
||||
padding: 10px 12px 6px;
|
||||
font-size: 10px !important;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--l3-foreground, var(--l2-foreground));
|
||||
opacity: 0.7;
|
||||
border-bottom: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
li {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
@@ -159,11 +194,78 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.cm-completionDetail {
|
||||
margin-left: auto;
|
||||
font-style: normal;
|
||||
font-size: var(--periscope-font-size-small, 11px);
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
&[aria-selected='true'] {
|
||||
background: var(--l3-background) !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
}
|
||||
|
||||
li:has(.cm-completionIcon-recent) {
|
||||
&:hover .cm-recent-delete,
|
||||
&[aria-selected='true'] .cm-recent-delete {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
li .cm-completionLabel {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.cm-recent-delete {
|
||||
margin-left: 8px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
color: var(--l2-foreground);
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
transition:
|
||||
opacity 0.12s ease,
|
||||
background-color 0.12s ease;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
background: color-mix(in srgb, var(--l2-foreground) 18%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '↓↑ to navigate · ↵ to apply · esc to dismiss';
|
||||
display: block;
|
||||
padding: 8px 12px;
|
||||
border-top: 1px solid var(--l1-border);
|
||||
font-family: 'Space Mono', monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.02em;
|
||||
color: var(--l2-foreground);
|
||||
opacity: 0.6;
|
||||
background: color-mix(in srgb, var(--l1-background) 50%, transparent);
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,15 @@ import {
|
||||
import { validateQuery } from 'utils/queryValidationUtils';
|
||||
import { unquote } from 'utils/stringUtils';
|
||||
|
||||
import { queryExamples } from './constants';
|
||||
import { combineInitialAndUserExpression } from './utils';
|
||||
import { getRecentQueries } from 'lib/recentQueries/getRecentQueries';
|
||||
import type { SignalType } from 'types/api/v5/queryRange';
|
||||
|
||||
import { queryExamples, SUGGESTIONS_SECTION } from './constants';
|
||||
import {
|
||||
combineInitialAndUserExpression,
|
||||
getRecentOptions,
|
||||
renderRecentDeleteButton,
|
||||
} from './utils';
|
||||
|
||||
import './QuerySearch.styles.scss';
|
||||
|
||||
@@ -1250,6 +1257,41 @@ function QuerySearch({
|
||||
};
|
||||
}
|
||||
|
||||
const signal = dataSource as SignalType;
|
||||
|
||||
function combinedSuggestions(
|
||||
context: CompletionContext,
|
||||
): CompletionResult | null {
|
||||
const fullDoc = context.state.doc.toString();
|
||||
const recentOptions = getRecentOptions(
|
||||
getRecentQueries(signal, signalSource ?? ''),
|
||||
fullDoc,
|
||||
);
|
||||
const result = autoSuggestions(context);
|
||||
|
||||
const suggestionOptions = (result?.options || []).map((opt) => ({
|
||||
...opt,
|
||||
section: SUGGESTIONS_SECTION,
|
||||
}));
|
||||
|
||||
if (recentOptions.length === 0 && suggestionOptions.length === 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
return {
|
||||
from: 0,
|
||||
to: fullDoc.length,
|
||||
options: recentOptions,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...result,
|
||||
options: [...recentOptions, ...suggestionOptions],
|
||||
};
|
||||
}
|
||||
|
||||
// Effect to handle focus state and trigger suggestions
|
||||
useEffect(() => {
|
||||
const clearTimeout = toggleSuggestions(10);
|
||||
@@ -1398,11 +1440,12 @@ function QuerySearch({
|
||||
})}
|
||||
extensions={[
|
||||
autocompletion({
|
||||
override: [autoSuggestions],
|
||||
override: [combinedSuggestions],
|
||||
defaultKeymap: true,
|
||||
closeOnBlur: true,
|
||||
activateOnTyping: true,
|
||||
maxRenderedOptions: 50,
|
||||
addToOptions: [{ render: renderRecentDeleteButton, position: 100 }],
|
||||
}),
|
||||
javascript({ jsx: false, typescript: false }),
|
||||
EditorView.lineWrapping,
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
export const RECENTS_SECTION = { name: 'Recent searches', rank: 1 } as const;
|
||||
export const SUGGESTIONS_SECTION = { name: 'Suggestions', rank: 2 } as const;
|
||||
|
||||
// Custom CodeMirror Completion.type for recent-query entries. Used to discriminate
|
||||
// recents from regular autocomplete completions in renderers and event handlers.
|
||||
export const RECENT_COMPLETION_TYPE = 'recent';
|
||||
|
||||
// Max number of recents rendered in the autocomplete dropdown.
|
||||
// Do change $max-recents-shown: in QuerySearch.styles.scss if you change this.
|
||||
export const RECENTS_DISPLAY_CAP = 5;
|
||||
|
||||
export const queryExamples = [
|
||||
{
|
||||
label: 'Basic Query',
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
import { closeCompletion, startCompletion } from '@codemirror/autocomplete';
|
||||
import type { Completion } from '@codemirror/autocomplete';
|
||||
import type { EditorView } from '@uiw/react-codemirror';
|
||||
import dayjs from 'dayjs';
|
||||
import { normalizeFilterExpression } from 'lib/recentQueries/normalize';
|
||||
import * as recentQueriesStore from 'lib/recentQueries/recentQueriesStore';
|
||||
import type { RecentQueryEntry } from 'lib/recentQueries/types';
|
||||
import type { SignalType } from 'types/api/v5/queryRange';
|
||||
import 'utils/timeUtils';
|
||||
|
||||
import {
|
||||
RECENT_COMPLETION_TYPE,
|
||||
RECENTS_DISPLAY_CAP,
|
||||
RECENTS_SECTION,
|
||||
} from './constants';
|
||||
|
||||
export function combineInitialAndUserExpression(
|
||||
initial: string,
|
||||
user: string,
|
||||
@@ -38,3 +54,106 @@ export function getUserExpressionFromCombined(
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// Filters and projects a list of recent-query entries into CodeMirror completions.
|
||||
// Entries are supplied by the caller (typically via the useRecents hook) so this
|
||||
// function stays pure and React doesn't have to re-subscribe inside CodeMirror's
|
||||
// autocomplete callback.
|
||||
export function getRecentOptions(
|
||||
entries: RecentQueryEntry[],
|
||||
fullDoc: string,
|
||||
): Completion[] {
|
||||
const normalizedDoc = normalizeFilterExpression(fullDoc);
|
||||
|
||||
const matches = entries
|
||||
.filter((e) => {
|
||||
const normalizedRecent = normalizeFilterExpression(e.filter.expression);
|
||||
if (normalizedRecent === normalizedDoc) {
|
||||
return false;
|
||||
}
|
||||
if (normalizedDoc === '') {
|
||||
return true;
|
||||
}
|
||||
return normalizedRecent.includes(normalizedDoc);
|
||||
})
|
||||
.slice(0, RECENTS_DISPLAY_CAP);
|
||||
|
||||
return matches.map((entry, index) => ({
|
||||
label: entry.filter.expression,
|
||||
type: RECENT_COMPLETION_TYPE,
|
||||
// CodeMirror sorts within a section by boost desc, then label asc. The store
|
||||
// returns entries newest-first, so we mirror that by giving the newest entry
|
||||
// the highest boost — otherwise CM falls back to alphabetical order and the
|
||||
// "most recently used" expectation breaks. Stays within the recents section
|
||||
// because section.rank keeps recents above suggestions regardless of boost.
|
||||
boost: matches.length - index,
|
||||
section: RECENTS_SECTION,
|
||||
detail: dayjs(entry.lastUsedAt).fromNow(),
|
||||
recentId: entry.id,
|
||||
recentSignal: entry.signal,
|
||||
recentSource: entry.source,
|
||||
apply: (view: EditorView): void => {
|
||||
view.dispatch({
|
||||
changes: {
|
||||
from: 0,
|
||||
to: view.state.doc.length,
|
||||
insert: entry.filter.expression,
|
||||
},
|
||||
selection: { anchor: entry.filter.expression.length },
|
||||
});
|
||||
closeCompletion(view);
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
export function renderRecentDeleteButton(
|
||||
completion: Completion,
|
||||
_state: unknown,
|
||||
view: EditorView | null,
|
||||
): Node | null {
|
||||
if (completion.type !== RECENT_COMPLETION_TYPE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const c = completion as Completion & {
|
||||
recentId?: string;
|
||||
recentSignal?: SignalType;
|
||||
recentSource?: string;
|
||||
};
|
||||
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.className = 'cm-recent-delete';
|
||||
btn.setAttribute('aria-label', 'Remove from recent searches');
|
||||
btn.title = 'Remove from recent searches';
|
||||
btn.textContent = '×';
|
||||
queueMicrotask(() => {
|
||||
if (btn.parentElement) {
|
||||
btn.parentElement.title = completion.label;
|
||||
}
|
||||
});
|
||||
|
||||
const stop = (e: Event): void => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
// CodeMirror's autocomplete closes the popup on pointerdown / mousedown outside
|
||||
// the editor. The delete button lives inside the popup, so we must stop those
|
||||
// events early — otherwise clicking × would dismiss the dropdown before the
|
||||
// click handler fires and the entry wouldn't actually get removed.
|
||||
btn.addEventListener('pointerdown', stop);
|
||||
btn.addEventListener('mousedown', stop);
|
||||
btn.addEventListener('click', (e) => {
|
||||
stop(e);
|
||||
if (!c.recentId || !c.recentSignal) {
|
||||
return;
|
||||
}
|
||||
recentQueriesStore.remove(c.recentId, c.recentSignal, c.recentSource ?? '');
|
||||
if (view) {
|
||||
view.focus();
|
||||
startCompletion(view);
|
||||
}
|
||||
});
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
@@ -721,6 +721,53 @@ export const removeKeysFromExpression = (
|
||||
return result?.text ?? '';
|
||||
};
|
||||
|
||||
const escapeRegExp = (value: string): string =>
|
||||
value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
|
||||
export const createVariablePlaceholderRegExp = (
|
||||
variableName: string,
|
||||
): RegExp => {
|
||||
const escapedName = escapeRegExp(variableName);
|
||||
// (?![\w.]) prevents $env from matching inside $environment or $env.attr
|
||||
return new RegExp(
|
||||
`(\\$${escapedName}(?![\\w.])|\\{\\{\\s*\\.?${escapedName}\\s*\\}\\}|\\[\\[\\s*${escapedName}\\s*\\]\\])`,
|
||||
'g',
|
||||
);
|
||||
};
|
||||
|
||||
const matchesVariablePlaceholder = (
|
||||
text: string,
|
||||
variableName: string,
|
||||
): boolean => createVariablePlaceholderRegExp(variableName).test(text);
|
||||
|
||||
export const removeVariableFromExpression = (
|
||||
expression: string | undefined,
|
||||
variableName: string,
|
||||
): string => {
|
||||
if (!expression) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const queryPairs = extractQueryPairs(expression);
|
||||
|
||||
const keysToRemove = queryPairs
|
||||
.filter((pair) => {
|
||||
const singleValue = pair.value?.toString() ?? '';
|
||||
const listValues = (pair.valueList ?? []).join(' ');
|
||||
return (
|
||||
matchesVariablePlaceholder(singleValue, variableName) ||
|
||||
matchesVariablePlaceholder(listValues, variableName)
|
||||
);
|
||||
})
|
||||
.map((pair) => pair.key);
|
||||
|
||||
if (keysToRemove.length === 0) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
return removeKeysFromExpression(expression, keysToRemove, `$${variableName}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert old having format to new having format
|
||||
* @param having - Array of old having objects with columnName, op, and value
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import refreshPaymentStatus from 'api/v3/licenses/put';
|
||||
import cx from 'classnames';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { TooltipSimple } from '@signozhq/ui/tooltip';
|
||||
import { RefreshCcw } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
|
||||
function RefreshPaymentStatus({
|
||||
btnShape,
|
||||
type,
|
||||
className,
|
||||
}: {
|
||||
btnShape?: 'default' | 'round' | 'circle';
|
||||
type?: 'button' | 'text' | 'tooltip';
|
||||
className?: string;
|
||||
}): JSX.Element {
|
||||
const { t } = useTranslation(['failedPayment']);
|
||||
const { activeLicenseRefetch } = useAppContext();
|
||||
@@ -31,26 +31,33 @@ function RefreshPaymentStatus({
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
const button = (
|
||||
<Button
|
||||
variant="link"
|
||||
color={type === 'text' ? 'none' : 'secondary'}
|
||||
size="md"
|
||||
className={className}
|
||||
onClick={handleRefreshPaymentStatus}
|
||||
prefix={<RefreshCcw size={14} />}
|
||||
loading={isLoading}
|
||||
>
|
||||
{type !== 'tooltip' ? t('refreshPaymentStatus') : ''}
|
||||
</Button>
|
||||
);
|
||||
|
||||
return (
|
||||
<span className="refresh-payment-status-btn-wrapper">
|
||||
<Tooltip title={type === 'tooltip' ? t('refreshPaymentStatus') : ''}>
|
||||
<Button
|
||||
type={type === 'text' ? 'text' : 'default'}
|
||||
shape={btnShape}
|
||||
className={cx('periscope-btn', { text: type === 'text' })}
|
||||
onClick={handleRefreshPaymentStatus}
|
||||
icon={<RefreshCcw size={14} />}
|
||||
loading={isLoading}
|
||||
>
|
||||
{type !== 'tooltip' ? t('refreshPaymentStatus') : ''}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{type === 'tooltip' ? (
|
||||
<TooltipSimple title={t('refreshPaymentStatus')}>{button}</TooltipSimple>
|
||||
) : (
|
||||
button
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
RefreshPaymentStatus.defaultProps = {
|
||||
btnShape: 'default',
|
||||
type: 'button',
|
||||
className: undefined,
|
||||
};
|
||||
|
||||
export default RefreshPaymentStatus;
|
||||
|
||||
@@ -139,7 +139,6 @@ jest.mock('react-query', (): unknown => {
|
||||
});
|
||||
|
||||
// mock other side-effecty modules
|
||||
jest.mock('api/common/logEvent', () => jest.fn());
|
||||
jest.mock('api/browser/localstorage/set', () => jest.fn());
|
||||
jest.mock('utils/error', () => ({ showErrorNotification: jest.fn() }));
|
||||
|
||||
|
||||
@@ -33,8 +33,10 @@ export const REACT_QUERY_KEY = {
|
||||
UPDATE_ALERT_RULE: 'UPDATE_ALERT_RULE',
|
||||
GET_ACTIVE_LICENSE_V3: 'GET_ACTIVE_LICENSE_V3',
|
||||
GET_TRACE_V2_WATERFALL: 'GET_TRACE_V2_WATERFALL',
|
||||
GET_TRACE_V3_WATERFALL: 'GET_TRACE_V3_WATERFALL',
|
||||
GET_TRACE_V4_WATERFALL: 'GET_TRACE_V4_WATERFALL',
|
||||
GET_TRACE_AGGREGATIONS: 'GET_TRACE_AGGREGATIONS',
|
||||
GET_TRACE_V2_FLAMEGRAPH: 'GET_TRACE_V2_FLAMEGRAPH',
|
||||
GET_TRACE_V3_FLAMEGRAPH: 'GET_TRACE_V3_FLAMEGRAPH',
|
||||
GET_POD_LIST: 'GET_POD_LIST',
|
||||
GET_NODE_LIST: 'GET_NODE_LIST',
|
||||
GET_DEPLOYMENT_LIST: 'GET_DEPLOYMENT_LIST',
|
||||
|
||||
@@ -70,6 +70,7 @@ export const AIAssistantOpenSource = {
|
||||
Icon: 'icon',
|
||||
Shortcut: 'shortcut',
|
||||
Cmdk: 'cmdk',
|
||||
TraceDetails: 'trace_details',
|
||||
} as const;
|
||||
export type AIAssistantOpenSource =
|
||||
(typeof AIAssistantOpenSource)[keyof typeof AIAssistantOpenSource];
|
||||
|
||||
@@ -40,13 +40,31 @@ type SpeechRecognitionConstructor = new () => ISpeechRecognition;
|
||||
|
||||
// ── Vendor-prefix shim for Safari / older browsers ────────────────────────────
|
||||
|
||||
const SpeechRecognitionAPI: SpeechRecognitionConstructor | null =
|
||||
typeof window !== 'undefined'
|
||||
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
((window as any).SpeechRecognition ??
|
||||
// Some hardened/enterprise browsers install a getter
|
||||
// on window.SpeechRecognition that THROWS on access ("Web Speech API is disabled
|
||||
// due to your security policy") instead of leaving the property undefined.
|
||||
// Because this resolves at module-evaluation time, an uncaught throw here aborts
|
||||
// the entire bundle and the app renders a blank page. Read defensively so a
|
||||
// throwing getter degrades to "unsupported" rather than crashing the app.
|
||||
function resolveSpeechRecognitionAPI(): SpeechRecognitionConstructor | null {
|
||||
if (typeof window === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).SpeechRecognition ??
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).webkitSpeechRecognition ??
|
||||
null)
|
||||
: null;
|
||||
null
|
||||
);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const SpeechRecognitionAPI: SpeechRecognitionConstructor | null =
|
||||
resolveSpeechRecognitionAPI();
|
||||
|
||||
export type SpeechRecognitionError =
|
||||
| 'not-supported'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user