mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-16 05:06:03 +08:00
Merge branch 'main' into SIG-7395-1
This commit is contained in:
commit
4e78c91567
1
.gitignore
vendored
1
.gitignore
vendored
@ -66,6 +66,7 @@ e2e/.auth
|
|||||||
# go
|
# go
|
||||||
vendor/
|
vendor/
|
||||||
**/main/**
|
**/main/**
|
||||||
|
__debug_bin**
|
||||||
|
|
||||||
# git-town
|
# git-town
|
||||||
.git-branches.toml
|
.git-branches.toml
|
||||||
|
@ -207,3 +207,11 @@ emailing:
|
|||||||
key_file_path:
|
key_file_path:
|
||||||
# The path to the certificate file.
|
# The path to the certificate file.
|
||||||
cert_file_path:
|
cert_file_path:
|
||||||
|
|
||||||
|
##################### Sharder (experimental) #####################
|
||||||
|
sharder:
|
||||||
|
# Specifies the sharder provider to use.
|
||||||
|
provider: noop
|
||||||
|
single:
|
||||||
|
# The org id to which this instance belongs to.
|
||||||
|
org_id: org_id
|
||||||
|
@ -174,7 +174,7 @@ services:
|
|||||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||||
signoz:
|
signoz:
|
||||||
!!merge <<: *db-depend
|
!!merge <<: *db-depend
|
||||||
image: signoz/signoz:v0.85.2
|
image: signoz/signoz:v0.85.3
|
||||||
command:
|
command:
|
||||||
- --config=/root/config/prometheus.yml
|
- --config=/root/config/prometheus.yml
|
||||||
ports:
|
ports:
|
||||||
|
@ -110,7 +110,7 @@ services:
|
|||||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||||
signoz:
|
signoz:
|
||||||
!!merge <<: *db-depend
|
!!merge <<: *db-depend
|
||||||
image: signoz/signoz:v0.85.2
|
image: signoz/signoz:v0.85.3
|
||||||
command:
|
command:
|
||||||
- --config=/root/config/prometheus.yml
|
- --config=/root/config/prometheus.yml
|
||||||
ports:
|
ports:
|
||||||
|
@ -177,7 +177,7 @@ services:
|
|||||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||||
signoz:
|
signoz:
|
||||||
!!merge <<: *db-depend
|
!!merge <<: *db-depend
|
||||||
image: signoz/signoz:${VERSION:-v0.85.2}
|
image: signoz/signoz:${VERSION:-v0.85.3}
|
||||||
container_name: signoz
|
container_name: signoz
|
||||||
command:
|
command:
|
||||||
- --config=/root/config/prometheus.yml
|
- --config=/root/config/prometheus.yml
|
||||||
|
@ -110,7 +110,7 @@ services:
|
|||||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||||
signoz:
|
signoz:
|
||||||
!!merge <<: *db-depend
|
!!merge <<: *db-depend
|
||||||
image: signoz/signoz:${VERSION:-v0.85.2}
|
image: signoz/signoz:${VERSION:-v0.85.3}
|
||||||
container_name: signoz
|
container_name: signoz
|
||||||
command:
|
command:
|
||||||
- --config=/root/config/prometheus.yml
|
- --config=/root/config/prometheus.yml
|
||||||
|
@ -5,10 +5,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/ee/query-service/constants"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/ee/licensing/licensingstore/sqllicensingstore"
|
"github.com/SigNoz/signoz/ee/licensing/licensingstore/sqllicensingstore"
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
"github.com/SigNoz/signoz/pkg/licensing"
|
"github.com/SigNoz/signoz/pkg/licensing"
|
||||||
|
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
"github.com/SigNoz/signoz/pkg/types/featuretypes"
|
"github.com/SigNoz/signoz/pkg/types/featuretypes"
|
||||||
"github.com/SigNoz/signoz/pkg/types/licensetypes"
|
"github.com/SigNoz/signoz/pkg/types/licensetypes"
|
||||||
@ -18,23 +21,31 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type provider struct {
|
type provider struct {
|
||||||
store licensetypes.Store
|
store licensetypes.Store
|
||||||
zeus zeus.Zeus
|
zeus zeus.Zeus
|
||||||
config licensing.Config
|
config licensing.Config
|
||||||
settings factory.ScopedProviderSettings
|
settings factory.ScopedProviderSettings
|
||||||
stopChan chan struct{}
|
orgGetter organization.Getter
|
||||||
|
stopChan chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProviderFactory(store sqlstore.SQLStore, zeus zeus.Zeus) factory.ProviderFactory[licensing.Licensing, licensing.Config] {
|
func NewProviderFactory(store sqlstore.SQLStore, zeus zeus.Zeus, orgGetter organization.Getter) factory.ProviderFactory[licensing.Licensing, licensing.Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("http"), func(ctx context.Context, providerSettings factory.ProviderSettings, config licensing.Config) (licensing.Licensing, error) {
|
return factory.NewProviderFactory(factory.MustNewName("http"), func(ctx context.Context, providerSettings factory.ProviderSettings, config licensing.Config) (licensing.Licensing, error) {
|
||||||
return New(ctx, providerSettings, config, store, zeus)
|
return New(ctx, providerSettings, config, store, zeus, orgGetter)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, ps factory.ProviderSettings, config licensing.Config, sqlstore sqlstore.SQLStore, zeus zeus.Zeus) (licensing.Licensing, error) {
|
func New(ctx context.Context, ps factory.ProviderSettings, config licensing.Config, sqlstore sqlstore.SQLStore, zeus zeus.Zeus, orgGetter organization.Getter) (licensing.Licensing, error) {
|
||||||
settings := factory.NewScopedProviderSettings(ps, "github.com/SigNoz/signoz/ee/licensing/httplicensing")
|
settings := factory.NewScopedProviderSettings(ps, "github.com/SigNoz/signoz/ee/licensing/httplicensing")
|
||||||
licensestore := sqllicensingstore.New(sqlstore)
|
licensestore := sqllicensingstore.New(sqlstore)
|
||||||
return &provider{store: licensestore, zeus: zeus, config: config, settings: settings, stopChan: make(chan struct{})}, nil
|
return &provider{
|
||||||
|
store: licensestore,
|
||||||
|
zeus: zeus,
|
||||||
|
config: config,
|
||||||
|
settings: settings,
|
||||||
|
orgGetter: orgGetter,
|
||||||
|
stopChan: make(chan struct{}),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) Start(ctx context.Context) error {
|
func (provider *provider) Start(ctx context.Context) error {
|
||||||
@ -66,13 +77,13 @@ func (provider *provider) Stop(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) Validate(ctx context.Context) error {
|
func (provider *provider) Validate(ctx context.Context) error {
|
||||||
organizations, err := provider.store.ListOrganizations(ctx)
|
organizations, err := provider.orgGetter.ListByOwnedKeyRange(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, organizationID := range organizations {
|
for _, organization := range organizations {
|
||||||
err := provider.Refresh(ctx, organizationID)
|
err := provider.Refresh(ctx, organization.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -167,6 +178,11 @@ func (provider *provider) Refresh(ctx context.Context, organizationID valuer.UUI
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = provider.InitFeatures(ctx, activeLicense.Features)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +267,13 @@ func (provider *provider) GetFeatureFlags(ctx context.Context) ([]*featuretypes.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if constants.IsDotMetricsEnabled {
|
||||||
|
gettableFeatures = append(gettableFeatures, &featuretypes.GettableFeature{
|
||||||
|
Name: featuretypes.DotMetricsEnabled,
|
||||||
|
Active: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return gettableFeatures, nil
|
return gettableFeatures, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
"github.com/SigNoz/signoz/pkg/types"
|
|
||||||
"github.com/SigNoz/signoz/pkg/types/featuretypes"
|
"github.com/SigNoz/signoz/pkg/types/featuretypes"
|
||||||
"github.com/SigNoz/signoz/pkg/types/licensetypes"
|
"github.com/SigNoz/signoz/pkg/types/licensetypes"
|
||||||
"github.com/SigNoz/signoz/pkg/valuer"
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
@ -82,31 +81,6 @@ func (store *store) Update(ctx context.Context, organizationID valuer.UUID, stor
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *store) ListOrganizations(ctx context.Context) ([]valuer.UUID, error) {
|
|
||||||
orgIDStrs := make([]string, 0)
|
|
||||||
err := store.sqlstore.
|
|
||||||
BunDB().
|
|
||||||
NewSelect().
|
|
||||||
Model(new(types.Organization)).
|
|
||||||
Column("id").
|
|
||||||
Scan(ctx, &orgIDStrs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
orgIDs := make([]valuer.UUID, len(orgIDStrs))
|
|
||||||
for idx, orgIDStr := range orgIDStrs {
|
|
||||||
orgID, err := valuer.NewUUID(orgIDStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
orgIDs[idx] = orgID
|
|
||||||
}
|
|
||||||
|
|
||||||
return orgIDs, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (store *store) CreateFeature(ctx context.Context, storableFeature *featuretypes.StorableFeature) error {
|
func (store *store) CreateFeature(ctx context.Context, storableFeature *featuretypes.StorableFeature) error {
|
||||||
_, err := store.
|
_, err := store.
|
||||||
sqlstore.
|
sqlstore.
|
||||||
|
@ -96,13 +96,7 @@ func (ah *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) {
|
|||||||
// note: add ee override methods first
|
// note: add ee override methods first
|
||||||
|
|
||||||
// routes available only in ee version
|
// routes available only in ee version
|
||||||
|
|
||||||
router.HandleFunc("/api/v1/featureFlags", am.OpenAccess(ah.getFeatureFlags)).Methods(http.MethodGet)
|
router.HandleFunc("/api/v1/featureFlags", am.OpenAccess(ah.getFeatureFlags)).Methods(http.MethodGet)
|
||||||
router.HandleFunc("/api/v1/loginPrecheck", am.OpenAccess(ah.Signoz.Handlers.User.LoginPrecheck)).Methods(http.MethodGet)
|
|
||||||
|
|
||||||
// invite
|
|
||||||
router.HandleFunc("/api/v1/invite/{token}", am.OpenAccess(ah.Signoz.Handlers.User.GetInvite)).Methods(http.MethodGet)
|
|
||||||
router.HandleFunc("/api/v1/invite/accept", am.OpenAccess(ah.Signoz.Handlers.User.AcceptInvite)).Methods(http.MethodPost)
|
|
||||||
|
|
||||||
// paid plans specific routes
|
// paid plans specific routes
|
||||||
router.HandleFunc("/api/v1/complete/saml", am.OpenAccess(ah.receiveSAML)).Methods(http.MethodPost)
|
router.HandleFunc("/api/v1/complete/saml", am.OpenAccess(ah.receiveSAML)).Methods(http.MethodPost)
|
||||||
@ -114,9 +108,6 @@ func (ah *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) {
|
|||||||
router.HandleFunc("/api/v1/billing", am.AdminAccess(ah.getBilling)).Methods(http.MethodGet)
|
router.HandleFunc("/api/v1/billing", am.AdminAccess(ah.getBilling)).Methods(http.MethodGet)
|
||||||
router.HandleFunc("/api/v1/portal", am.AdminAccess(ah.LicensingAPI.Portal)).Methods(http.MethodPost)
|
router.HandleFunc("/api/v1/portal", am.AdminAccess(ah.LicensingAPI.Portal)).Methods(http.MethodPost)
|
||||||
|
|
||||||
router.HandleFunc("/api/v1/dashboards/{uuid}/lock", am.EditAccess(ah.lockDashboard)).Methods(http.MethodPut)
|
|
||||||
router.HandleFunc("/api/v1/dashboards/{uuid}/unlock", am.EditAccess(ah.unlockDashboard)).Methods(http.MethodPut)
|
|
||||||
|
|
||||||
// v3
|
// v3
|
||||||
router.HandleFunc("/api/v3/licenses", am.AdminAccess(ah.LicensingAPI.Activate)).Methods(http.MethodPost)
|
router.HandleFunc("/api/v3/licenses", am.AdminAccess(ah.LicensingAPI.Activate)).Methods(http.MethodPost)
|
||||||
router.HandleFunc("/api/v3/licenses", am.AdminAccess(ah.LicensingAPI.Refresh)).Methods(http.MethodPut)
|
router.HandleFunc("/api/v3/licenses", am.AdminAccess(ah.LicensingAPI.Refresh)).Methods(http.MethodPut)
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
|
||||||
"github.com/SigNoz/signoz/pkg/http/render"
|
|
||||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (ah *APIHandler) lockDashboard(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ah.lockUnlockDashboard(w, r, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ah *APIHandler) unlockDashboard(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ah.lockUnlockDashboard(w, r, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ah *APIHandler) lockUnlockDashboard(w http.ResponseWriter, r *http.Request, lock bool) {
|
|
||||||
// Locking can only be done by the owner of the dashboard
|
|
||||||
// or an admin
|
|
||||||
|
|
||||||
// - Fetch the dashboard
|
|
||||||
// - Check if the user is the owner or an admin
|
|
||||||
// - If yes, lock/unlock the dashboard
|
|
||||||
// - If no, return 403
|
|
||||||
|
|
||||||
// Get the dashboard UUID from the request
|
|
||||||
uuid := mux.Vars(r)["uuid"]
|
|
||||||
if strings.HasPrefix(uuid, "integration") {
|
|
||||||
render.Error(w, errors.Newf(errors.TypeForbidden, errors.CodeForbidden, "dashboards created by integrations cannot be modified"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
claims, err := authtypes.ClaimsFromContext(r.Context())
|
|
||||||
if err != nil {
|
|
||||||
render.Error(w, errors.Newf(errors.TypeUnauthenticated, errors.CodeUnauthenticated, "unauthenticated"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dashboard, err := ah.Signoz.Modules.Dashboard.Get(r.Context(), claims.OrgID, uuid)
|
|
||||||
if err != nil {
|
|
||||||
render.Error(w, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := claims.IsAdmin(); err != nil && (dashboard.CreatedBy != claims.Email) {
|
|
||||||
render.Error(w, errors.Newf(errors.TypeForbidden, errors.CodeForbidden, "You are not authorized to lock/unlock this dashboard"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock/Unlock the dashboard
|
|
||||||
err = ah.Signoz.Modules.Dashboard.LockUnlock(r.Context(), claims.OrgID, uuid, lock)
|
|
||||||
if err != nil {
|
|
||||||
render.Error(w, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ah.Respond(w, "Dashboard updated successfully")
|
|
||||||
}
|
|
@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||||
"github.com/SigNoz/signoz/pkg/cache"
|
"github.com/SigNoz/signoz/pkg/cache"
|
||||||
"github.com/SigNoz/signoz/pkg/http/middleware"
|
"github.com/SigNoz/signoz/pkg/http/middleware"
|
||||||
|
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||||
"github.com/SigNoz/signoz/pkg/prometheus"
|
"github.com/SigNoz/signoz/pkg/prometheus"
|
||||||
"github.com/SigNoz/signoz/pkg/signoz"
|
"github.com/SigNoz/signoz/pkg/signoz"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
@ -113,6 +114,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
|
|||||||
serverOptions.SigNoz.SQLStore,
|
serverOptions.SigNoz.SQLStore,
|
||||||
serverOptions.SigNoz.TelemetryStore,
|
serverOptions.SigNoz.TelemetryStore,
|
||||||
serverOptions.SigNoz.Prometheus,
|
serverOptions.SigNoz.Prometheus,
|
||||||
|
serverOptions.SigNoz.Modules.OrgGetter,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -157,7 +159,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start the usagemanager
|
// start the usagemanager
|
||||||
usageManager, err := usage.New(serverOptions.SigNoz.Licensing, serverOptions.SigNoz.TelemetryStore.ClickhouseDB(), serverOptions.SigNoz.Zeus, serverOptions.SigNoz.Modules.Organization)
|
usageManager, err := usage.New(serverOptions.SigNoz.Licensing, serverOptions.SigNoz.TelemetryStore.ClickhouseDB(), serverOptions.SigNoz.Zeus, serverOptions.SigNoz.Modules.OrgGetter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -225,7 +227,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
|
|||||||
&opAmpModel.AllAgents, agentConfMgr,
|
&opAmpModel.AllAgents, agentConfMgr,
|
||||||
)
|
)
|
||||||
|
|
||||||
orgs, err := apiHandler.Signoz.Modules.Organization.GetAll(context.Background())
|
orgs, err := apiHandler.Signoz.Modules.OrgGetter.ListByOwnedKeyRange(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -240,11 +242,10 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) createPrivateServer(apiHandler *api.APIHandler) (*http.Server, error) {
|
func (s *Server) createPrivateServer(apiHandler *api.APIHandler) (*http.Server, error) {
|
||||||
|
|
||||||
r := baseapp.NewRouter()
|
r := baseapp.NewRouter()
|
||||||
|
|
||||||
r.Use(middleware.NewAuth(s.serverOptions.Jwt, []string{"Authorization", "Sec-WebSocket-Protocol"}).Wrap)
|
r.Use(middleware.NewAuth(s.serverOptions.Jwt, []string{"Authorization", "Sec-WebSocket-Protocol"}, s.serverOptions.SigNoz.Sharder, s.serverOptions.SigNoz.Instrumentation.Logger()).Wrap)
|
||||||
r.Use(middleware.NewAPIKey(s.serverOptions.SigNoz.SQLStore, []string{"SIGNOZ-API-KEY"}, s.serverOptions.SigNoz.Instrumentation.Logger()).Wrap)
|
r.Use(middleware.NewAPIKey(s.serverOptions.SigNoz.SQLStore, []string{"SIGNOZ-API-KEY"}, s.serverOptions.SigNoz.Instrumentation.Logger(), s.serverOptions.SigNoz.Sharder).Wrap)
|
||||||
r.Use(middleware.NewTimeout(s.serverOptions.SigNoz.Instrumentation.Logger(),
|
r.Use(middleware.NewTimeout(s.serverOptions.SigNoz.Instrumentation.Logger(),
|
||||||
s.serverOptions.Config.APIServer.Timeout.ExcludedRoutes,
|
s.serverOptions.Config.APIServer.Timeout.ExcludedRoutes,
|
||||||
s.serverOptions.Config.APIServer.Timeout.Default,
|
s.serverOptions.Config.APIServer.Timeout.Default,
|
||||||
@ -275,8 +276,8 @@ func (s *Server) createPublicServer(apiHandler *api.APIHandler, web web.Web) (*h
|
|||||||
r := baseapp.NewRouter()
|
r := baseapp.NewRouter()
|
||||||
am := middleware.NewAuthZ(s.serverOptions.SigNoz.Instrumentation.Logger())
|
am := middleware.NewAuthZ(s.serverOptions.SigNoz.Instrumentation.Logger())
|
||||||
|
|
||||||
r.Use(middleware.NewAuth(s.serverOptions.Jwt, []string{"Authorization", "Sec-WebSocket-Protocol"}).Wrap)
|
r.Use(middleware.NewAuth(s.serverOptions.Jwt, []string{"Authorization", "Sec-WebSocket-Protocol"}, s.serverOptions.SigNoz.Sharder, s.serverOptions.SigNoz.Instrumentation.Logger()).Wrap)
|
||||||
r.Use(middleware.NewAPIKey(s.serverOptions.SigNoz.SQLStore, []string{"SIGNOZ-API-KEY"}, s.serverOptions.SigNoz.Instrumentation.Logger()).Wrap)
|
r.Use(middleware.NewAPIKey(s.serverOptions.SigNoz.SQLStore, []string{"SIGNOZ-API-KEY"}, s.serverOptions.SigNoz.Instrumentation.Logger(), s.serverOptions.SigNoz.Sharder).Wrap)
|
||||||
r.Use(middleware.NewTimeout(s.serverOptions.SigNoz.Instrumentation.Logger(),
|
r.Use(middleware.NewTimeout(s.serverOptions.SigNoz.Instrumentation.Logger(),
|
||||||
s.serverOptions.Config.APIServer.Timeout.ExcludedRoutes,
|
s.serverOptions.Config.APIServer.Timeout.ExcludedRoutes,
|
||||||
s.serverOptions.Config.APIServer.Timeout.Default,
|
s.serverOptions.Config.APIServer.Timeout.Default,
|
||||||
@ -297,6 +298,7 @@ func (s *Server) createPublicServer(apiHandler *api.APIHandler, web web.Web) (*h
|
|||||||
apiHandler.RegisterMessagingQueuesRoutes(r, am)
|
apiHandler.RegisterMessagingQueuesRoutes(r, am)
|
||||||
apiHandler.RegisterThirdPartyApiRoutes(r, am)
|
apiHandler.RegisterThirdPartyApiRoutes(r, am)
|
||||||
apiHandler.MetricExplorerRoutes(r, am)
|
apiHandler.MetricExplorerRoutes(r, am)
|
||||||
|
apiHandler.RegisterTraceFunnelsRoutes(r, am)
|
||||||
|
|
||||||
c := cors.New(cors.Options{
|
c := cors.New(cors.Options{
|
||||||
AllowedOrigins: []string{"*"},
|
AllowedOrigins: []string{"*"},
|
||||||
@ -450,6 +452,7 @@ func makeRulesManager(
|
|||||||
sqlstore sqlstore.SQLStore,
|
sqlstore sqlstore.SQLStore,
|
||||||
telemetryStore telemetrystore.TelemetryStore,
|
telemetryStore telemetrystore.TelemetryStore,
|
||||||
prometheus prometheus.Prometheus,
|
prometheus prometheus.Prometheus,
|
||||||
|
orgGetter organization.Getter,
|
||||||
) (*baserules.Manager, error) {
|
) (*baserules.Manager, error) {
|
||||||
// create manager opts
|
// create manager opts
|
||||||
managerOpts := &baserules.ManagerOptions{
|
managerOpts := &baserules.ManagerOptions{
|
||||||
@ -465,6 +468,7 @@ func makeRulesManager(
|
|||||||
PrepareTestRuleFunc: rules.TestNotification,
|
PrepareTestRuleFunc: rules.TestNotification,
|
||||||
Alertmanager: alertmanager,
|
Alertmanager: alertmanager,
|
||||||
SQLStore: sqlstore,
|
SQLStore: sqlstore,
|
||||||
|
OrgGetter: orgGetter,
|
||||||
}
|
}
|
||||||
|
|
||||||
// create Manager
|
// create Manager
|
||||||
|
@ -4,6 +4,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultSiteURL = "https://localhost:8080"
|
||||||
|
)
|
||||||
|
|
||||||
var LicenseSignozIo = "https://license.signoz.io/api/v1"
|
var LicenseSignozIo = "https://license.signoz.io/api/v1"
|
||||||
var LicenseAPIKey = GetOrDefaultEnv("SIGNOZ_LICENSE_API_KEY", "")
|
var LicenseAPIKey = GetOrDefaultEnv("SIGNOZ_LICENSE_API_KEY", "")
|
||||||
var SaasSegmentKey = GetOrDefaultEnv("SIGNOZ_SAAS_SEGMENT_KEY", "")
|
var SaasSegmentKey = GetOrDefaultEnv("SIGNOZ_SAAS_SEGMENT_KEY", "")
|
||||||
@ -20,3 +24,22 @@ func GetOrDefaultEnv(key string, fallback string) string {
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constant functions that override env vars
|
||||||
|
|
||||||
|
// GetDefaultSiteURL returns default site url, primarily
|
||||||
|
// used to send saml request and allowing backend to
|
||||||
|
// handle http redirect
|
||||||
|
func GetDefaultSiteURL() string {
|
||||||
|
return GetOrDefaultEnv("SIGNOZ_SITE_URL", DefaultSiteURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
const DotMetricsEnabled = "DOT_METRICS_ENABLED"
|
||||||
|
|
||||||
|
var IsDotMetricsEnabled = false
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if GetOrDefaultEnv(DotMetricsEnabled, "false") == "true" {
|
||||||
|
IsDotMetricsEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/config/fileprovider"
|
"github.com/SigNoz/signoz/pkg/config/fileprovider"
|
||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
pkglicensing "github.com/SigNoz/signoz/pkg/licensing"
|
pkglicensing "github.com/SigNoz/signoz/pkg/licensing"
|
||||||
|
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||||
baseconst "github.com/SigNoz/signoz/pkg/query-service/constants"
|
baseconst "github.com/SigNoz/signoz/pkg/query-service/constants"
|
||||||
"github.com/SigNoz/signoz/pkg/signoz"
|
"github.com/SigNoz/signoz/pkg/signoz"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
@ -133,8 +134,8 @@ func main() {
|
|||||||
zeus.Config(),
|
zeus.Config(),
|
||||||
httpzeus.NewProviderFactory(),
|
httpzeus.NewProviderFactory(),
|
||||||
licensing.Config(24*time.Hour, 3),
|
licensing.Config(24*time.Hour, 3),
|
||||||
func(sqlstore sqlstore.SQLStore, zeus pkgzeus.Zeus) factory.ProviderFactory[pkglicensing.Licensing, pkglicensing.Config] {
|
func(sqlstore sqlstore.SQLStore, zeus pkgzeus.Zeus, orgGetter organization.Getter) factory.ProviderFactory[pkglicensing.Licensing, pkglicensing.Config] {
|
||||||
return httplicensing.NewProviderFactory(sqlstore, zeus)
|
return httplicensing.NewProviderFactory(sqlstore, zeus, orgGetter)
|
||||||
},
|
},
|
||||||
signoz.NewEmailingProviderFactories(),
|
signoz.NewEmailingProviderFactories(),
|
||||||
signoz.NewCacheProviderFactories(),
|
signoz.NewCacheProviderFactories(),
|
||||||
|
@ -41,16 +41,16 @@ type Manager struct {
|
|||||||
|
|
||||||
zeus zeus.Zeus
|
zeus zeus.Zeus
|
||||||
|
|
||||||
organizationModule organization.Module
|
orgGetter organization.Getter
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(licenseService licensing.Licensing, clickhouseConn clickhouse.Conn, zeus zeus.Zeus, organizationModule organization.Module) (*Manager, error) {
|
func New(licenseService licensing.Licensing, clickhouseConn clickhouse.Conn, zeus zeus.Zeus, orgGetter organization.Getter) (*Manager, error) {
|
||||||
m := &Manager{
|
m := &Manager{
|
||||||
clickhouseConn: clickhouseConn,
|
clickhouseConn: clickhouseConn,
|
||||||
licenseService: licenseService,
|
licenseService: licenseService,
|
||||||
scheduler: gocron.NewScheduler(time.UTC).Every(1).Day().At("00:00"), // send usage every at 00:00 UTC
|
scheduler: gocron.NewScheduler(time.UTC).Every(1).Day().At("00:00"), // send usage every at 00:00 UTC
|
||||||
zeus: zeus,
|
zeus: zeus,
|
||||||
organizationModule: organizationModule,
|
orgGetter: orgGetter,
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
@ -74,8 +74,7 @@ func (lm *Manager) Start(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (lm *Manager) UploadUsage(ctx context.Context) {
|
func (lm *Manager) UploadUsage(ctx context.Context) {
|
||||||
|
organizations, err := lm.orgGetter.ListByOwnedKeyRange(ctx)
|
||||||
organizations, err := lm.organizationModule.GetAll(context.Background())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.L().Error("failed to get organizations", zap.Error(err))
|
zap.L().Error("failed to get organizations", zap.Error(err))
|
||||||
return
|
return
|
||||||
|
@ -28,6 +28,7 @@ import { QueryBuilderProvider } from 'providers/QueryBuilder';
|
|||||||
import { Suspense, useCallback, useEffect, useState } from 'react';
|
import { Suspense, useCallback, useEffect, useState } from 'react';
|
||||||
import { Route, Router, Switch } from 'react-router-dom';
|
import { Route, Router, Switch } from 'react-router-dom';
|
||||||
import { CompatRouter } from 'react-router-dom-v5-compat';
|
import { CompatRouter } from 'react-router-dom-v5-compat';
|
||||||
|
import { LicenseStatus } from 'types/api/licensesV3/getActive';
|
||||||
import { Userpilot } from 'userpilot';
|
import { Userpilot } from 'userpilot';
|
||||||
import { extractDomain } from 'utils/app';
|
import { extractDomain } from 'utils/app';
|
||||||
|
|
||||||
@ -171,11 +172,13 @@ function App(): JSX.Element {
|
|||||||
user &&
|
user &&
|
||||||
!!user.email
|
!!user.email
|
||||||
) {
|
) {
|
||||||
|
// either the active API returns error with 404 or 501 and if it returns a terminated license means it's on basic plan
|
||||||
const isOnBasicPlan =
|
const isOnBasicPlan =
|
||||||
activeLicenseFetchError &&
|
(activeLicenseFetchError &&
|
||||||
[StatusCodes.NOT_FOUND, StatusCodes.NOT_IMPLEMENTED].includes(
|
[StatusCodes.NOT_FOUND, StatusCodes.NOT_IMPLEMENTED].includes(
|
||||||
activeLicenseFetchError?.getHttpStatusCode(),
|
activeLicenseFetchError?.getHttpStatusCode(),
|
||||||
);
|
)) ||
|
||||||
|
(activeLicense?.status && activeLicense.status === LicenseStatus.INVALID);
|
||||||
const isIdentifiedUser = getLocalStorageApi(LOCALSTORAGE.IS_IDENTIFIED_USER);
|
const isIdentifiedUser = getLocalStorageApi(LOCALSTORAGE.IS_IDENTIFIED_USER);
|
||||||
|
|
||||||
if (isLoggedInState && user && user.id && user.email && !isIdentifiedUser) {
|
if (isLoggedInState && user && user.id && user.email && !isIdentifiedUser) {
|
||||||
@ -190,6 +193,10 @@ function App(): JSX.Element {
|
|||||||
updatedRoutes = updatedRoutes.filter(
|
updatedRoutes = updatedRoutes.filter(
|
||||||
(route) => route?.path !== ROUTES.BILLING,
|
(route) => route?.path !== ROUTES.BILLING,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (isEnterpriseSelfHostedUser) {
|
||||||
|
updatedRoutes.push(LIST_LICENSES);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// always add support route for cloud users
|
// always add support route for cloud users
|
||||||
updatedRoutes = [...updatedRoutes, SUPPORT_ROUTE];
|
updatedRoutes = [...updatedRoutes, SUPPORT_ROUTE];
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
import axios from 'api';
|
|
||||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
|
||||||
import { AxiosError } from 'axios';
|
|
||||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
|
||||||
import { PayloadProps, Props } from 'types/api/dashboard/create';
|
|
||||||
|
|
||||||
const createDashboard = async (
|
|
||||||
props: Props,
|
|
||||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
|
||||||
const url = props.uploadedGrafana ? '/dashboards/grafana' : '/dashboards';
|
|
||||||
try {
|
|
||||||
const response = await axios.post(url, {
|
|
||||||
...props,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
error: null,
|
|
||||||
message: response.data.status,
|
|
||||||
payload: response.data.data,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default createDashboard;
|
|
@ -1,9 +0,0 @@
|
|||||||
import axios from 'api';
|
|
||||||
import { PayloadProps, Props } from 'types/api/dashboard/delete';
|
|
||||||
|
|
||||||
const deleteDashboard = (props: Props): Promise<PayloadProps> =>
|
|
||||||
axios
|
|
||||||
.delete<PayloadProps>(`/dashboards/${props.uuid}`)
|
|
||||||
.then((response) => response.data);
|
|
||||||
|
|
||||||
export default deleteDashboard;
|
|
@ -1,11 +0,0 @@
|
|||||||
import axios from 'api';
|
|
||||||
import { ApiResponse } from 'types/api';
|
|
||||||
import { Props } from 'types/api/dashboard/get';
|
|
||||||
import { Dashboard } from 'types/api/dashboard/getAll';
|
|
||||||
|
|
||||||
const getDashboard = (props: Props): Promise<Dashboard> =>
|
|
||||||
axios
|
|
||||||
.get<ApiResponse<Dashboard>>(`/dashboards/${props.uuid}`)
|
|
||||||
.then((res) => res.data.data);
|
|
||||||
|
|
||||||
export default getDashboard;
|
|
@ -1,8 +0,0 @@
|
|||||||
import axios from 'api';
|
|
||||||
import { ApiResponse } from 'types/api';
|
|
||||||
import { Dashboard } from 'types/api/dashboard/getAll';
|
|
||||||
|
|
||||||
export const getAllDashboardList = (): Promise<Dashboard[]> =>
|
|
||||||
axios
|
|
||||||
.get<ApiResponse<Dashboard[]>>('/dashboards')
|
|
||||||
.then((res) => res.data.data);
|
|
@ -1,11 +0,0 @@
|
|||||||
import axios from 'api';
|
|
||||||
import { AxiosResponse } from 'axios';
|
|
||||||
|
|
||||||
interface LockDashboardProps {
|
|
||||||
uuid: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lockDashboard = (props: LockDashboardProps): Promise<AxiosResponse> =>
|
|
||||||
axios.put(`/dashboards/${props.uuid}/lock`);
|
|
||||||
|
|
||||||
export default lockDashboard;
|
|
@ -1,11 +0,0 @@
|
|||||||
import axios from 'api';
|
|
||||||
import { AxiosResponse } from 'axios';
|
|
||||||
|
|
||||||
interface UnlockDashboardProps {
|
|
||||||
uuid: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unlockDashboard = (props: UnlockDashboardProps): Promise<AxiosResponse> =>
|
|
||||||
axios.put(`/dashboards/${props.uuid}/unlock`);
|
|
||||||
|
|
||||||
export default unlockDashboard;
|
|
@ -1,20 +0,0 @@
|
|||||||
import axios from 'api';
|
|
||||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
|
||||||
import { PayloadProps, Props } from 'types/api/dashboard/update';
|
|
||||||
|
|
||||||
const updateDashboard = async (
|
|
||||||
props: Props,
|
|
||||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
|
||||||
const response = await axios.put(`/dashboards/${props.uuid}`, {
|
|
||||||
...props.data,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
error: null,
|
|
||||||
message: response.data.status,
|
|
||||||
payload: response.data.data,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default updateDashboard;
|
|
@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
import { UnderscoreToDotMap } from '../utils';
|
||||||
|
|
||||||
export interface K8sClustersListPayload {
|
export interface K8sClustersListPayload {
|
||||||
filters: TagFilter;
|
filters: TagFilter;
|
||||||
groupBy?: BaseAutocompleteData[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
@ -40,23 +42,80 @@ export interface K8sClustersListResponse {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const clustersMetaMap = [
|
||||||
|
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
|
||||||
|
{ dot: 'k8s.cluster.uid', under: 'k8s_cluster_uid' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function mapClustersMeta(
|
||||||
|
raw: Record<string, unknown>,
|
||||||
|
): K8sClustersData['meta'] {
|
||||||
|
const out: Record<string, unknown> = { ...raw };
|
||||||
|
clustersMetaMap.forEach(({ dot, under }) => {
|
||||||
|
if (dot in raw) {
|
||||||
|
const v = raw[dot];
|
||||||
|
out[under] = typeof v === 'string' ? v : raw[under];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out as K8sClustersData['meta'];
|
||||||
|
}
|
||||||
|
|
||||||
export const getK8sClustersList = async (
|
export const getK8sClustersList = async (
|
||||||
props: K8sClustersListPayload,
|
props: K8sClustersListPayload,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
headers?: Record<string, string>,
|
headers?: Record<string, string>,
|
||||||
|
dotMetricsEnabled = false,
|
||||||
): Promise<SuccessResponse<K8sClustersListResponse> | ErrorResponse> => {
|
): Promise<SuccessResponse<K8sClustersListResponse> | ErrorResponse> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('/clusters/list', props, {
|
const requestProps =
|
||||||
|
dotMetricsEnabled && Array.isArray(props.filters?.items)
|
||||||
|
? {
|
||||||
|
...props,
|
||||||
|
filters: {
|
||||||
|
...props.filters,
|
||||||
|
items: props.filters.items.reduce<typeof props.filters.items>(
|
||||||
|
(acc, item) => {
|
||||||
|
if (item.value === undefined) return acc;
|
||||||
|
if (
|
||||||
|
item.key &&
|
||||||
|
typeof item.key === 'object' &&
|
||||||
|
'key' in item.key &&
|
||||||
|
typeof item.key.key === 'string'
|
||||||
|
) {
|
||||||
|
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
|
||||||
|
acc.push({
|
||||||
|
...item,
|
||||||
|
key: { ...item.key, key: mappedKey },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
acc.push(item);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[] as typeof props.filters.items,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: props;
|
||||||
|
|
||||||
|
const response = await axios.post('/clusters/list', requestProps, {
|
||||||
signal,
|
signal,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
const payload: K8sClustersListResponse = response.data;
|
||||||
|
|
||||||
|
// one-liner meta mapping
|
||||||
|
payload.data.records = payload.data.records.map((record) => ({
|
||||||
|
...record,
|
||||||
|
meta: mapClustersMeta(record.meta as Record<string, unknown>),
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: 'Success',
|
message: 'Success',
|
||||||
payload: response.data,
|
payload,
|
||||||
params: props,
|
params: requestProps,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
import { UnderscoreToDotMap } from '../utils';
|
||||||
|
|
||||||
export interface K8sDaemonSetsListPayload {
|
export interface K8sDaemonSetsListPayload {
|
||||||
filters: TagFilter;
|
filters: TagFilter;
|
||||||
groupBy?: BaseAutocompleteData[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
@ -46,23 +48,82 @@ export interface K8sDaemonSetsListResponse {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const daemonSetsMetaMap = [
|
||||||
|
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
|
||||||
|
{ dot: 'k8s.daemonset.name', under: 'k8s_daemonset_name' },
|
||||||
|
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function mapDaemonSetsMeta(
|
||||||
|
raw: Record<string, unknown>,
|
||||||
|
): K8sDaemonSetsData['meta'] {
|
||||||
|
const out: Record<string, unknown> = { ...raw };
|
||||||
|
daemonSetsMetaMap.forEach(({ dot, under }) => {
|
||||||
|
if (dot in raw) {
|
||||||
|
const v = raw[dot];
|
||||||
|
out[under] = typeof v === 'string' ? v : raw[under];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out as K8sDaemonSetsData['meta'];
|
||||||
|
}
|
||||||
|
|
||||||
export const getK8sDaemonSetsList = async (
|
export const getK8sDaemonSetsList = async (
|
||||||
props: K8sDaemonSetsListPayload,
|
props: K8sDaemonSetsListPayload,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
headers?: Record<string, string>,
|
headers?: Record<string, string>,
|
||||||
|
dotMetricsEnabled = false,
|
||||||
): Promise<SuccessResponse<K8sDaemonSetsListResponse> | ErrorResponse> => {
|
): Promise<SuccessResponse<K8sDaemonSetsListResponse> | ErrorResponse> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('/daemonsets/list', props, {
|
// filter prep (unchanged)…
|
||||||
|
const requestProps =
|
||||||
|
dotMetricsEnabled && Array.isArray(props.filters?.items)
|
||||||
|
? {
|
||||||
|
...props,
|
||||||
|
filters: {
|
||||||
|
...props.filters,
|
||||||
|
items: props.filters.items.reduce<typeof props.filters.items>(
|
||||||
|
(acc, item) => {
|
||||||
|
if (item.value === undefined) return acc;
|
||||||
|
if (
|
||||||
|
item.key &&
|
||||||
|
typeof item.key === 'object' &&
|
||||||
|
'key' in item.key &&
|
||||||
|
typeof item.key.key === 'string'
|
||||||
|
) {
|
||||||
|
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
|
||||||
|
acc.push({
|
||||||
|
...item,
|
||||||
|
key: { ...item.key, key: mappedKey },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
acc.push(item);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[] as typeof props.filters.items,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: props;
|
||||||
|
|
||||||
|
const response = await axios.post('/daemonsets/list', requestProps, {
|
||||||
signal,
|
signal,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
const payload: K8sDaemonSetsListResponse = response.data;
|
||||||
|
|
||||||
|
// single-line meta mapping
|
||||||
|
payload.data.records = payload.data.records.map((record) => ({
|
||||||
|
...record,
|
||||||
|
meta: mapDaemonSetsMeta(record.meta as Record<string, unknown>),
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: 'Success',
|
message: 'Success',
|
||||||
payload: response.data,
|
payload,
|
||||||
params: props,
|
params: requestProps,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
import { UnderscoreToDotMap } from '../utils';
|
||||||
|
|
||||||
export interface K8sDeploymentsListPayload {
|
export interface K8sDeploymentsListPayload {
|
||||||
filters: TagFilter;
|
filters: TagFilter;
|
||||||
groupBy?: BaseAutocompleteData[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
@ -46,23 +48,81 @@ export interface K8sDeploymentsListResponse {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deploymentsMetaMap = [
|
||||||
|
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
|
||||||
|
{ dot: 'k8s.deployment.name', under: 'k8s_deployment_name' },
|
||||||
|
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function mapDeploymentsMeta(
|
||||||
|
raw: Record<string, unknown>,
|
||||||
|
): K8sDeploymentsData['meta'] {
|
||||||
|
const out: Record<string, unknown> = { ...raw };
|
||||||
|
deploymentsMetaMap.forEach(({ dot, under }) => {
|
||||||
|
if (dot in raw) {
|
||||||
|
const v = raw[dot];
|
||||||
|
out[under] = typeof v === 'string' ? v : raw[under];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out as K8sDeploymentsData['meta'];
|
||||||
|
}
|
||||||
|
|
||||||
export const getK8sDeploymentsList = async (
|
export const getK8sDeploymentsList = async (
|
||||||
props: K8sDeploymentsListPayload,
|
props: K8sDeploymentsListPayload,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
headers?: Record<string, string>,
|
headers?: Record<string, string>,
|
||||||
|
dotMetricsEnabled = false,
|
||||||
): Promise<SuccessResponse<K8sDeploymentsListResponse> | ErrorResponse> => {
|
): Promise<SuccessResponse<K8sDeploymentsListResponse> | ErrorResponse> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('/deployments/list', props, {
|
const requestProps =
|
||||||
|
dotMetricsEnabled && Array.isArray(props.filters?.items)
|
||||||
|
? {
|
||||||
|
...props,
|
||||||
|
filters: {
|
||||||
|
...props.filters,
|
||||||
|
items: props.filters.items.reduce<typeof props.filters.items>(
|
||||||
|
(acc, item) => {
|
||||||
|
if (item.value === undefined) return acc;
|
||||||
|
if (
|
||||||
|
item.key &&
|
||||||
|
typeof item.key === 'object' &&
|
||||||
|
'key' in item.key &&
|
||||||
|
typeof item.key.key === 'string'
|
||||||
|
) {
|
||||||
|
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
|
||||||
|
acc.push({
|
||||||
|
...item,
|
||||||
|
key: { ...item.key, key: mappedKey },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
acc.push(item);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[] as typeof props.filters.items,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: props;
|
||||||
|
|
||||||
|
const response = await axios.post('/deployments/list', requestProps, {
|
||||||
signal,
|
signal,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
const payload: K8sDeploymentsListResponse = response.data;
|
||||||
|
|
||||||
|
// single-line mapping
|
||||||
|
payload.data.records = payload.data.records.map((record) => ({
|
||||||
|
...record,
|
||||||
|
meta: mapDeploymentsMeta(record.meta as Record<string, unknown>),
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: 'Success',
|
message: 'Success',
|
||||||
payload: response.data,
|
payload,
|
||||||
params: props,
|
params: requestProps,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
import { UnderscoreToDotMap } from '../utils';
|
||||||
|
|
||||||
export interface K8sJobsListPayload {
|
export interface K8sJobsListPayload {
|
||||||
filters: TagFilter;
|
filters: TagFilter;
|
||||||
groupBy?: BaseAutocompleteData[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
@ -48,23 +50,79 @@ export interface K8sJobsListResponse {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const jobsMetaMap = [
|
||||||
|
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
|
||||||
|
{ dot: 'k8s.job.name', under: 'k8s_job_name' },
|
||||||
|
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function mapJobsMeta(raw: Record<string, unknown>): K8sJobsData['meta'] {
|
||||||
|
const out: Record<string, unknown> = { ...raw };
|
||||||
|
jobsMetaMap.forEach(({ dot, under }) => {
|
||||||
|
if (dot in raw) {
|
||||||
|
const v = raw[dot];
|
||||||
|
out[under] = typeof v === 'string' ? v : raw[under];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out as K8sJobsData['meta'];
|
||||||
|
}
|
||||||
|
|
||||||
export const getK8sJobsList = async (
|
export const getK8sJobsList = async (
|
||||||
props: K8sJobsListPayload,
|
props: K8sJobsListPayload,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
headers?: Record<string, string>,
|
headers?: Record<string, string>,
|
||||||
|
dotMetricsEnabled = false,
|
||||||
): Promise<SuccessResponse<K8sJobsListResponse> | ErrorResponse> => {
|
): Promise<SuccessResponse<K8sJobsListResponse> | ErrorResponse> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('/jobs/list', props, {
|
const requestProps =
|
||||||
|
dotMetricsEnabled && Array.isArray(props.filters?.items)
|
||||||
|
? {
|
||||||
|
...props,
|
||||||
|
filters: {
|
||||||
|
...props.filters,
|
||||||
|
items: props.filters.items.reduce<typeof props.filters.items>(
|
||||||
|
(acc, item) => {
|
||||||
|
if (item.value === undefined) return acc;
|
||||||
|
if (
|
||||||
|
item.key &&
|
||||||
|
typeof item.key === 'object' &&
|
||||||
|
'key' in item.key &&
|
||||||
|
typeof item.key.key === 'string'
|
||||||
|
) {
|
||||||
|
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
|
||||||
|
acc.push({
|
||||||
|
...item,
|
||||||
|
key: { ...item.key, key: mappedKey },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
acc.push(item);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[] as typeof props.filters.items,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: props;
|
||||||
|
|
||||||
|
const response = await axios.post('/jobs/list', requestProps, {
|
||||||
signal,
|
signal,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
const payload: K8sJobsListResponse = response.data;
|
||||||
|
|
||||||
|
// one-liner meta mapping
|
||||||
|
payload.data.records = payload.data.records.map((record) => ({
|
||||||
|
...record,
|
||||||
|
meta: mapJobsMeta(record.meta as Record<string, unknown>),
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: 'Success',
|
message: 'Success',
|
||||||
payload: response.data,
|
payload,
|
||||||
params: props,
|
params: requestProps,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
import { UnderscoreToDotMap } from '../utils';
|
||||||
|
|
||||||
export interface K8sNamespacesListPayload {
|
export interface K8sNamespacesListPayload {
|
||||||
filters: TagFilter;
|
filters: TagFilter;
|
||||||
groupBy?: BaseAutocompleteData[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
@ -38,23 +40,79 @@ export interface K8sNamespacesListResponse {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const namespacesMetaMap = [
|
||||||
|
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
|
||||||
|
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function mapNamespacesMeta(
|
||||||
|
raw: Record<string, unknown>,
|
||||||
|
): K8sNamespacesData['meta'] {
|
||||||
|
const out: Record<string, unknown> = { ...raw };
|
||||||
|
namespacesMetaMap.forEach(({ dot, under }) => {
|
||||||
|
if (dot in raw) {
|
||||||
|
const v = raw[dot];
|
||||||
|
out[under] = typeof v === 'string' ? v : raw[under];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out as K8sNamespacesData['meta'];
|
||||||
|
}
|
||||||
|
|
||||||
export const getK8sNamespacesList = async (
|
export const getK8sNamespacesList = async (
|
||||||
props: K8sNamespacesListPayload,
|
props: K8sNamespacesListPayload,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
headers?: Record<string, string>,
|
headers?: Record<string, string>,
|
||||||
|
dotMetricsEnabled = false,
|
||||||
): Promise<SuccessResponse<K8sNamespacesListResponse> | ErrorResponse> => {
|
): Promise<SuccessResponse<K8sNamespacesListResponse> | ErrorResponse> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('/namespaces/list', props, {
|
const requestProps =
|
||||||
|
dotMetricsEnabled && Array.isArray(props.filters?.items)
|
||||||
|
? {
|
||||||
|
...props,
|
||||||
|
filters: {
|
||||||
|
...props.filters,
|
||||||
|
items: props.filters.items.reduce<typeof props.filters.items>(
|
||||||
|
(acc, item) => {
|
||||||
|
if (item.value === undefined) return acc;
|
||||||
|
if (
|
||||||
|
item.key &&
|
||||||
|
typeof item.key === 'object' &&
|
||||||
|
'key' in item.key &&
|
||||||
|
typeof item.key.key === 'string'
|
||||||
|
) {
|
||||||
|
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
|
||||||
|
acc.push({
|
||||||
|
...item,
|
||||||
|
key: { ...item.key, key: mappedKey },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
acc.push(item);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[] as typeof props.filters.items,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: props;
|
||||||
|
|
||||||
|
const response = await axios.post('/namespaces/list', requestProps, {
|
||||||
signal,
|
signal,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
const payload: K8sNamespacesListResponse = response.data;
|
||||||
|
|
||||||
|
payload.data.records = payload.data.records.map((record) => ({
|
||||||
|
...record,
|
||||||
|
meta: mapNamespacesMeta(record.meta as Record<string, unknown>),
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: 'Success',
|
message: 'Success',
|
||||||
payload: response.data,
|
payload,
|
||||||
params: props,
|
params: requestProps,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
import { UnderscoreToDotMap } from '../utils';
|
||||||
|
|
||||||
export interface K8sNodesListPayload {
|
export interface K8sNodesListPayload {
|
||||||
filters: TagFilter;
|
filters: TagFilter;
|
||||||
groupBy?: BaseAutocompleteData[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
@ -41,23 +43,81 @@ export interface K8sNodesListResponse {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const nodesMetaMap = [
|
||||||
|
{ dot: 'k8s.node.name', under: 'k8s_node_name' },
|
||||||
|
{ dot: 'k8s.node.uid', under: 'k8s_node_uid' },
|
||||||
|
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function mapNodesMeta(
|
||||||
|
raw: Record<string, unknown>,
|
||||||
|
): K8sNodesData['meta'] {
|
||||||
|
const out: Record<string, unknown> = { ...raw };
|
||||||
|
nodesMetaMap.forEach(({ dot, under }) => {
|
||||||
|
if (dot in raw) {
|
||||||
|
const v = raw[dot];
|
||||||
|
out[under] = typeof v === 'string' ? v : raw[under];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out as K8sNodesData['meta'];
|
||||||
|
}
|
||||||
|
|
||||||
export const getK8sNodesList = async (
|
export const getK8sNodesList = async (
|
||||||
props: K8sNodesListPayload,
|
props: K8sNodesListPayload,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
headers?: Record<string, string>,
|
headers?: Record<string, string>,
|
||||||
|
dotMetricsEnabled = false,
|
||||||
): Promise<SuccessResponse<K8sNodesListResponse> | ErrorResponse> => {
|
): Promise<SuccessResponse<K8sNodesListResponse> | ErrorResponse> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('/nodes/list', props, {
|
const requestProps =
|
||||||
|
dotMetricsEnabled && Array.isArray(props.filters?.items)
|
||||||
|
? {
|
||||||
|
...props,
|
||||||
|
filters: {
|
||||||
|
...props.filters,
|
||||||
|
items: props.filters.items.reduce<typeof props.filters.items>(
|
||||||
|
(acc, item) => {
|
||||||
|
if (item.value === undefined) return acc;
|
||||||
|
if (
|
||||||
|
item.key &&
|
||||||
|
typeof item.key === 'object' &&
|
||||||
|
'key' in item.key &&
|
||||||
|
typeof item.key.key === 'string'
|
||||||
|
) {
|
||||||
|
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
|
||||||
|
acc.push({
|
||||||
|
...item,
|
||||||
|
key: { ...item.key, key: mappedKey },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
acc.push(item);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[] as typeof props.filters.items,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: props;
|
||||||
|
|
||||||
|
const response = await axios.post('/nodes/list', requestProps, {
|
||||||
signal,
|
signal,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
const payload: K8sNodesListResponse = response.data;
|
||||||
|
|
||||||
|
// one-liner to map dot→underscore
|
||||||
|
payload.data.records = payload.data.records.map((record) => ({
|
||||||
|
...record,
|
||||||
|
meta: mapNodesMeta(record.meta as Record<string, unknown>),
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: 'Success',
|
message: 'Success',
|
||||||
payload: response.data,
|
payload,
|
||||||
params: props,
|
params: requestProps,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
import { UnderscoreToDotMap } from '../utils';
|
||||||
|
|
||||||
export interface K8sPodsListPayload {
|
export interface K8sPodsListPayload {
|
||||||
filters: TagFilter;
|
filters: TagFilter;
|
||||||
groupBy?: BaseAutocompleteData[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
@ -69,23 +71,87 @@ export interface K8sPodsListResponse {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const podsMetaMap = [
|
||||||
|
{ dot: 'k8s.cronjob.name', under: 'k8s_cronjob_name' },
|
||||||
|
{ dot: 'k8s.daemonset.name', under: 'k8s_daemonset_name' },
|
||||||
|
{ dot: 'k8s.deployment.name', under: 'k8s_deployment_name' },
|
||||||
|
{ dot: 'k8s.job.name', under: 'k8s_job_name' },
|
||||||
|
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
|
||||||
|
{ dot: 'k8s.node.name', under: 'k8s_node_name' },
|
||||||
|
{ dot: 'k8s.pod.name', under: 'k8s_pod_name' },
|
||||||
|
{ dot: 'k8s.pod.uid', under: 'k8s_pod_uid' },
|
||||||
|
{ dot: 'k8s.statefulset.name', under: 'k8s_statefulset_name' },
|
||||||
|
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function mapPodsMeta(raw: Record<string, unknown>): K8sPodsData['meta'] {
|
||||||
|
// clone everything
|
||||||
|
const out: Record<string, unknown> = { ...raw };
|
||||||
|
// overlay only the dot→under mappings
|
||||||
|
podsMetaMap.forEach(({ dot, under }) => {
|
||||||
|
if (dot in raw) {
|
||||||
|
const v = raw[dot];
|
||||||
|
out[under] = typeof v === 'string' ? v : raw[under];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out as K8sPodsData['meta'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// getK8sPodsList
|
||||||
export const getK8sPodsList = async (
|
export const getK8sPodsList = async (
|
||||||
props: K8sPodsListPayload,
|
props: K8sPodsListPayload,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
headers?: Record<string, string>,
|
headers?: Record<string, string>,
|
||||||
|
dotMetricsEnabled = false,
|
||||||
): Promise<SuccessResponse<K8sPodsListResponse> | ErrorResponse> => {
|
): Promise<SuccessResponse<K8sPodsListResponse> | ErrorResponse> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('/pods/list', props, {
|
const requestProps =
|
||||||
|
dotMetricsEnabled && Array.isArray(props.filters?.items)
|
||||||
|
? {
|
||||||
|
...props,
|
||||||
|
filters: {
|
||||||
|
...props.filters,
|
||||||
|
items: props.filters.items.reduce<typeof props.filters.items>(
|
||||||
|
(acc, item) => {
|
||||||
|
if (item.value === undefined) return acc;
|
||||||
|
if (
|
||||||
|
item.key &&
|
||||||
|
typeof item.key === 'object' &&
|
||||||
|
'key' in item.key &&
|
||||||
|
typeof item.key.key === 'string'
|
||||||
|
) {
|
||||||
|
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
|
||||||
|
acc.push({
|
||||||
|
...item,
|
||||||
|
key: { ...item.key, key: mappedKey },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
acc.push(item);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[] as typeof props.filters.items,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: props;
|
||||||
|
|
||||||
|
const response = await axios.post('/pods/list', requestProps, {
|
||||||
signal,
|
signal,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
const payload: K8sPodsListResponse = response.data;
|
||||||
|
payload.data.records = payload.data.records.map((record) => ({
|
||||||
|
...record,
|
||||||
|
meta: mapPodsMeta(record.meta as Record<string, unknown>),
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: 'Success',
|
message: 'Success',
|
||||||
payload: response.data,
|
payload,
|
||||||
params: props,
|
params: requestProps,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
import { UnderscoreToDotMap } from '../utils';
|
||||||
|
|
||||||
export interface K8sVolumesListPayload {
|
export interface K8sVolumesListPayload {
|
||||||
filters: TagFilter;
|
filters: TagFilter;
|
||||||
groupBy?: BaseAutocompleteData[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
@ -47,23 +49,92 @@ export interface K8sVolumesListResponse {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const volumesMetaMap: Array<{
|
||||||
|
dot: keyof Record<string, unknown>;
|
||||||
|
under: keyof K8sVolumesData['meta'];
|
||||||
|
}> = [
|
||||||
|
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
|
||||||
|
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
|
||||||
|
{ dot: 'k8s.node.name', under: 'k8s_node_name' },
|
||||||
|
{
|
||||||
|
dot: 'k8s.persistentvolumeclaim.name',
|
||||||
|
under: 'k8s_persistentvolumeclaim_name',
|
||||||
|
},
|
||||||
|
{ dot: 'k8s.pod.name', under: 'k8s_pod_name' },
|
||||||
|
{ dot: 'k8s.pod.uid', under: 'k8s_pod_uid' },
|
||||||
|
{ dot: 'k8s.statefulset.name', under: 'k8s_statefulset_name' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export function mapVolumesMeta(
|
||||||
|
rawMeta: Record<string, unknown>,
|
||||||
|
): K8sVolumesData['meta'] {
|
||||||
|
// start with everything that was already there
|
||||||
|
const out: Record<string, unknown> = { ...rawMeta };
|
||||||
|
|
||||||
|
// for each dot→under rule, if the raw has the dot, overwrite the underscore
|
||||||
|
volumesMetaMap.forEach(({ dot, under }) => {
|
||||||
|
if (dot in rawMeta) {
|
||||||
|
const val = rawMeta[dot];
|
||||||
|
out[under] = typeof val === 'string' ? val : rawMeta[under];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return out as K8sVolumesData['meta'];
|
||||||
|
}
|
||||||
|
|
||||||
export const getK8sVolumesList = async (
|
export const getK8sVolumesList = async (
|
||||||
props: K8sVolumesListPayload,
|
props: K8sVolumesListPayload,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
headers?: Record<string, string>,
|
headers?: Record<string, string>,
|
||||||
|
dotMetricsEnabled = false,
|
||||||
): Promise<SuccessResponse<K8sVolumesListResponse> | ErrorResponse> => {
|
): Promise<SuccessResponse<K8sVolumesListResponse> | ErrorResponse> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('/pvcs/list', props, {
|
// Prepare filters
|
||||||
|
const requestProps =
|
||||||
|
dotMetricsEnabled && Array.isArray(props.filters?.items)
|
||||||
|
? {
|
||||||
|
...props,
|
||||||
|
filters: {
|
||||||
|
...props.filters,
|
||||||
|
items: props.filters.items.reduce<typeof props.filters.items>(
|
||||||
|
(acc, item) => {
|
||||||
|
if (item.value === undefined) return acc;
|
||||||
|
if (
|
||||||
|
item.key &&
|
||||||
|
typeof item.key === 'object' &&
|
||||||
|
'key' in item.key &&
|
||||||
|
typeof item.key.key === 'string'
|
||||||
|
) {
|
||||||
|
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
|
||||||
|
acc.push({ ...item, key: { ...item.key, key: mappedKey } });
|
||||||
|
} else {
|
||||||
|
acc.push(item);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[] as typeof props.filters.items,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: props;
|
||||||
|
|
||||||
|
const response = await axios.post('/pvcs/list', requestProps, {
|
||||||
signal,
|
signal,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
const payload: K8sVolumesListResponse = response.data;
|
||||||
|
|
||||||
|
payload.data.records = payload.data.records.map((record) => ({
|
||||||
|
...record,
|
||||||
|
meta: mapVolumesMeta(record.meta as Record<string, unknown>),
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: 'Success',
|
message: 'Success',
|
||||||
payload: response.data,
|
payload,
|
||||||
params: props,
|
params: requestProps,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
import { UnderscoreToDotMap } from '../utils';
|
||||||
|
|
||||||
export interface K8sStatefulSetsListPayload {
|
export interface K8sStatefulSetsListPayload {
|
||||||
filters: TagFilter;
|
filters: TagFilter;
|
||||||
groupBy?: BaseAutocompleteData[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
@ -45,23 +47,78 @@ export interface K8sStatefulSetsListResponse {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const statefulSetsMetaMap = [
|
||||||
|
{ dot: 'k8s.statefulset.name', under: 'k8s_statefulset_name' },
|
||||||
|
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function mapStatefulSetsMeta(
|
||||||
|
raw: Record<string, unknown>,
|
||||||
|
): K8sStatefulSetsData['meta'] {
|
||||||
|
const out: Record<string, unknown> = { ...raw };
|
||||||
|
statefulSetsMetaMap.forEach(({ dot, under }) => {
|
||||||
|
if (dot in raw) {
|
||||||
|
const v = raw[dot];
|
||||||
|
out[under] = typeof v === 'string' ? v : raw[under];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out as K8sStatefulSetsData['meta'];
|
||||||
|
}
|
||||||
|
|
||||||
export const getK8sStatefulSetsList = async (
|
export const getK8sStatefulSetsList = async (
|
||||||
props: K8sStatefulSetsListPayload,
|
props: K8sStatefulSetsListPayload,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
headers?: Record<string, string>,
|
headers?: Record<string, string>,
|
||||||
|
dotMetricsEnabled = false,
|
||||||
): Promise<SuccessResponse<K8sStatefulSetsListResponse> | ErrorResponse> => {
|
): Promise<SuccessResponse<K8sStatefulSetsListResponse> | ErrorResponse> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('/statefulsets/list', props, {
|
// Prepare filters
|
||||||
|
const requestProps =
|
||||||
|
dotMetricsEnabled && Array.isArray(props.filters?.items)
|
||||||
|
? {
|
||||||
|
...props,
|
||||||
|
filters: {
|
||||||
|
...props.filters,
|
||||||
|
items: props.filters.items.reduce<typeof props.filters.items>(
|
||||||
|
(acc, item) => {
|
||||||
|
if (item.value === undefined) return acc;
|
||||||
|
if (
|
||||||
|
item.key &&
|
||||||
|
typeof item.key === 'object' &&
|
||||||
|
'key' in item.key &&
|
||||||
|
typeof item.key.key === 'string'
|
||||||
|
) {
|
||||||
|
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
|
||||||
|
acc.push({ ...item, key: { ...item.key, key: mappedKey } });
|
||||||
|
} else {
|
||||||
|
acc.push(item);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[] as typeof props.filters.items,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: props;
|
||||||
|
|
||||||
|
const response = await axios.post('/statefulsets/list', requestProps, {
|
||||||
signal,
|
signal,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
const payload: K8sStatefulSetsListResponse = response.data;
|
||||||
|
|
||||||
|
// apply our helper
|
||||||
|
payload.data.records = payload.data.records.map((record) => ({
|
||||||
|
...record,
|
||||||
|
meta: mapStatefulSetsMeta(record.meta as Record<string, unknown>),
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: 'Success',
|
message: 'Success',
|
||||||
payload: response.data,
|
payload,
|
||||||
params: props,
|
params: requestProps,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
@ -17,3 +17,19 @@ export const Logout = (): void => {
|
|||||||
|
|
||||||
history.push(ROUTES.LOGIN);
|
history.push(ROUTES.LOGIN);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const UnderscoreToDotMap: Record<string, string> = {
|
||||||
|
k8s_cluster_name: 'k8s.cluster.name',
|
||||||
|
k8s_cluster_uid: 'k8s.cluster.uid',
|
||||||
|
k8s_namespace_name: 'k8s.namespace.name',
|
||||||
|
k8s_node_name: 'k8s.node.name',
|
||||||
|
k8s_node_uid: 'k8s.node.uid',
|
||||||
|
k8s_pod_name: 'k8s.pod.name',
|
||||||
|
k8s_pod_uid: 'k8s.pod.uid',
|
||||||
|
k8s_deployment_name: 'k8s.deployment.name',
|
||||||
|
k8s_daemonset_name: 'k8s.daemonset.name',
|
||||||
|
k8s_statefulset_name: 'k8s.statefulset.name',
|
||||||
|
k8s_cronjob_name: 'k8s.cronjob.name',
|
||||||
|
k8s_job_name: 'k8s.job.name',
|
||||||
|
k8s_persistentvolumeclaim_name: 'k8s.persistentvolumeclaim.name',
|
||||||
|
};
|
||||||
|
23
frontend/src/api/v1/dashboards/create.ts
Normal file
23
frontend/src/api/v1/dashboards/create.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import axios from 'api';
|
||||||
|
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||||
|
import { PayloadProps, Props } from 'types/api/dashboard/create';
|
||||||
|
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||||
|
|
||||||
|
const create = async (props: Props): Promise<SuccessResponseV2<Dashboard>> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post<PayloadProps>('/dashboards', {
|
||||||
|
...props,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
httpStatusCode: response.status,
|
||||||
|
data: response.data.data,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default create;
|
19
frontend/src/api/v1/dashboards/getAll.ts
Normal file
19
frontend/src/api/v1/dashboards/getAll.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import axios from 'api';
|
||||||
|
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||||
|
import { Dashboard, PayloadProps } from 'types/api/dashboard/getAll';
|
||||||
|
|
||||||
|
const getAll = async (): Promise<SuccessResponseV2<Dashboard[]>> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get<PayloadProps>('/dashboards');
|
||||||
|
return {
|
||||||
|
httpStatusCode: response.status,
|
||||||
|
data: response.data.data,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getAll;
|
21
frontend/src/api/v1/dashboards/id/delete.ts
Normal file
21
frontend/src/api/v1/dashboards/id/delete.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import axios from 'api';
|
||||||
|
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||||
|
import { PayloadProps, Props } from 'types/api/dashboard/delete';
|
||||||
|
|
||||||
|
const deleteDashboard = async (
|
||||||
|
props: Props,
|
||||||
|
): Promise<SuccessResponseV2<null>> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.delete<PayloadProps>(`/dashboards/${props.id}`);
|
||||||
|
return {
|
||||||
|
httpStatusCode: response.status,
|
||||||
|
data: null,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default deleteDashboard;
|
20
frontend/src/api/v1/dashboards/id/get.ts
Normal file
20
frontend/src/api/v1/dashboards/id/get.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import axios from 'api';
|
||||||
|
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||||
|
import { PayloadProps, Props } from 'types/api/dashboard/get';
|
||||||
|
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||||
|
|
||||||
|
const get = async (props: Props): Promise<SuccessResponseV2<Dashboard>> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get<PayloadProps>(`/dashboards/${props.id}`);
|
||||||
|
return {
|
||||||
|
httpStatusCode: response.status,
|
||||||
|
data: response.data.data,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default get;
|
23
frontend/src/api/v1/dashboards/id/lock.ts
Normal file
23
frontend/src/api/v1/dashboards/id/lock.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import axios from 'api';
|
||||||
|
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||||
|
import { PayloadProps, Props } from 'types/api/dashboard/lockUnlock';
|
||||||
|
|
||||||
|
const lock = async (props: Props): Promise<SuccessResponseV2<null>> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.put<PayloadProps>(
|
||||||
|
`/dashboards/${props.id}/lock`,
|
||||||
|
{ lock: props.lock },
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
httpStatusCode: response.status,
|
||||||
|
data: response.data.data,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default lock;
|
23
frontend/src/api/v1/dashboards/id/update.ts
Normal file
23
frontend/src/api/v1/dashboards/id/update.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import axios from 'api';
|
||||||
|
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||||
|
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||||
|
import { PayloadProps, Props } from 'types/api/dashboard/update';
|
||||||
|
|
||||||
|
const update = async (props: Props): Promise<SuccessResponseV2<Dashboard>> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.put<PayloadProps>(`/dashboards/${props.id}`, {
|
||||||
|
...props.data,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
httpStatusCode: response.status,
|
||||||
|
data: response.data.data,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default update;
|
@ -23,6 +23,9 @@ import { useQueries, UseQueryResult } from 'react-query';
|
|||||||
import { SuccessResponse } from 'types/api';
|
import { SuccessResponse } from 'types/api';
|
||||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
|
|
||||||
interface MetricsTabProps {
|
interface MetricsTabProps {
|
||||||
timeRange: {
|
timeRange: {
|
||||||
startTime: number;
|
startTime: number;
|
||||||
@ -45,9 +48,20 @@ function Metrics({
|
|||||||
handleTimeChange,
|
handleTimeChange,
|
||||||
isModalTimeSelection,
|
isModalTimeSelection,
|
||||||
}: MetricsTabProps): JSX.Element {
|
}: MetricsTabProps): JSX.Element {
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const queryPayloads = useMemo(
|
const queryPayloads = useMemo(
|
||||||
() => getHostQueryPayload(hostName, timeRange.startTime, timeRange.endTime),
|
() =>
|
||||||
[hostName, timeRange.startTime, timeRange.endTime],
|
getHostQueryPayload(
|
||||||
|
hostName,
|
||||||
|
timeRange.startTime,
|
||||||
|
timeRange.endTime,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
|
[hostName, timeRange.startTime, timeRange.endTime, dotMetricsEnabled],
|
||||||
);
|
);
|
||||||
|
|
||||||
const queries = useQueries(
|
const queries = useQueries(
|
||||||
|
@ -16,6 +16,7 @@ import JSONView from 'container/LogDetailedView/JsonView';
|
|||||||
import Overview from 'container/LogDetailedView/Overview';
|
import Overview from 'container/LogDetailedView/Overview';
|
||||||
import {
|
import {
|
||||||
aggregateAttributesResourcesToString,
|
aggregateAttributesResourcesToString,
|
||||||
|
escapeHtml,
|
||||||
removeEscapeCharacters,
|
removeEscapeCharacters,
|
||||||
unescapeString,
|
unescapeString,
|
||||||
} from 'container/LogDetailedView/utils';
|
} from 'container/LogDetailedView/utils';
|
||||||
@ -118,7 +119,7 @@ function LogDetail({
|
|||||||
const htmlBody = useMemo(
|
const htmlBody = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
__html: convert.toHtml(
|
__html: convert.toHtml(
|
||||||
dompurify.sanitize(unescapeString(log?.body || ''), {
|
dompurify.sanitize(unescapeString(escapeHtml(log?.body || '')), {
|
||||||
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
|
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
@ -7,7 +7,7 @@ import cx from 'classnames';
|
|||||||
import LogDetail from 'components/LogDetail';
|
import LogDetail from 'components/LogDetail';
|
||||||
import { VIEW_TYPES } from 'components/LogDetail/constants';
|
import { VIEW_TYPES } from 'components/LogDetail/constants';
|
||||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||||
import { unescapeString } from 'container/LogDetailedView/utils';
|
import { escapeHtml, unescapeString } from 'container/LogDetailedView/utils';
|
||||||
import { FontSize } from 'container/OptionsMenu/types';
|
import { FontSize } from 'container/OptionsMenu/types';
|
||||||
import dompurify from 'dompurify';
|
import dompurify from 'dompurify';
|
||||||
import { useActiveLog } from 'hooks/logs/useActiveLog';
|
import { useActiveLog } from 'hooks/logs/useActiveLog';
|
||||||
@ -58,7 +58,7 @@ function LogGeneralField({
|
|||||||
const html = useMemo(
|
const html = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
__html: convert.toHtml(
|
__html: convert.toHtml(
|
||||||
dompurify.sanitize(unescapeString(fieldValue), {
|
dompurify.sanitize(unescapeString(escapeHtml(fieldValue)), {
|
||||||
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
|
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
@ -5,7 +5,7 @@ import { DrawerProps } from 'antd';
|
|||||||
import LogDetail from 'components/LogDetail';
|
import LogDetail from 'components/LogDetail';
|
||||||
import { VIEW_TYPES, VIEWS } from 'components/LogDetail/constants';
|
import { VIEW_TYPES, VIEWS } from 'components/LogDetail/constants';
|
||||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||||
import { unescapeString } from 'container/LogDetailedView/utils';
|
import { escapeHtml, unescapeString } from 'container/LogDetailedView/utils';
|
||||||
import LogsExplorerContext from 'container/LogsExplorerContext';
|
import LogsExplorerContext from 'container/LogsExplorerContext';
|
||||||
import dompurify from 'dompurify';
|
import dompurify from 'dompurify';
|
||||||
import { useActiveLog } from 'hooks/logs/useActiveLog';
|
import { useActiveLog } from 'hooks/logs/useActiveLog';
|
||||||
@ -177,7 +177,7 @@ function RawLogView({
|
|||||||
const html = useMemo(
|
const html = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
__html: convert.toHtml(
|
__html: convert.toHtml(
|
||||||
dompurify.sanitize(unescapeString(text), {
|
dompurify.sanitize(unescapeString(escapeHtml(text)), {
|
||||||
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
|
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
@ -10,4 +10,5 @@ export enum FeatureKeys {
|
|||||||
ONBOARDING_V3 = 'ONBOARDING_V3',
|
ONBOARDING_V3 = 'ONBOARDING_V3',
|
||||||
THIRD_PARTY_API = 'THIRD_PARTY_API',
|
THIRD_PARTY_API = 'THIRD_PARTY_API',
|
||||||
TRACE_FUNNELS = 'TRACE_FUNNELS',
|
TRACE_FUNNELS = 'TRACE_FUNNELS',
|
||||||
|
DOT_METRICS_ENABLED = 'DOT_METRICS_ENABLED',
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,10 @@ import ROUTES from 'constants/routes';
|
|||||||
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
|
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
import { useNotifications } from 'hooks/useNotifications';
|
||||||
import useResourceAttribute from 'hooks/useResourceAttribute';
|
import useResourceAttribute from 'hooks/useResourceAttribute';
|
||||||
import { convertCompositeQueryToTraceSelectedTags } from 'hooks/useResourceAttribute/utils';
|
import {
|
||||||
|
convertCompositeQueryToTraceSelectedTags,
|
||||||
|
getResourceDeploymentKeys,
|
||||||
|
} from 'hooks/useResourceAttribute/utils';
|
||||||
import { TimestampInput } from 'hooks/useTimezoneFormatter/useTimezoneFormatter';
|
import { TimestampInput } from 'hooks/useTimezoneFormatter/useTimezoneFormatter';
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import createQueryParams from 'lib/createQueryParams';
|
import createQueryParams from 'lib/createQueryParams';
|
||||||
@ -38,6 +41,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
|||||||
import { Exception, PayloadProps } from 'types/api/errors/getAll';
|
import { Exception, PayloadProps } from 'types/api/errors/getAll';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../constants/features';
|
||||||
|
import { useAppContext } from '../../providers/App/App';
|
||||||
import { FilterDropdownExtendsProps } from './types';
|
import { FilterDropdownExtendsProps } from './types';
|
||||||
import {
|
import {
|
||||||
extractFilterValues,
|
extractFilterValues,
|
||||||
@ -405,6 +410,11 @@ function AllErrors(): JSX.Element {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const onChangeHandler: TableProps<Exception>['onChange'] = useCallback(
|
const onChangeHandler: TableProps<Exception>['onChange'] = useCallback(
|
||||||
(
|
(
|
||||||
paginations: TablePaginationConfig,
|
paginations: TablePaginationConfig,
|
||||||
@ -438,7 +448,7 @@ function AllErrors(): JSX.Element {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isUndefined(errorCountResponse.data?.payload)) {
|
if (!isUndefined(errorCountResponse.data?.payload)) {
|
||||||
const selectedEnvironments = queries.find(
|
const selectedEnvironments = queries.find(
|
||||||
(val) => val.tagKey === 'resource_deployment_environment',
|
(val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
|
||||||
)?.tagValue;
|
)?.tagValue;
|
||||||
|
|
||||||
logEvent('Exception: List page visited', {
|
logEvent('Exception: List page visited', {
|
||||||
|
@ -10,6 +10,8 @@ import { Provider, useSelector } from 'react-redux';
|
|||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import store from 'store';
|
import store from 'store';
|
||||||
|
|
||||||
|
import * as appContextHooks from '../../../providers/App/App';
|
||||||
|
import { LicenseEvent } from '../../../types/api/licensesV3/getActive';
|
||||||
import AllErrors from '../index';
|
import AllErrors from '../index';
|
||||||
import {
|
import {
|
||||||
INIT_URL_WITH_COMMON_QUERY,
|
INIT_URL_WITH_COMMON_QUERY,
|
||||||
@ -28,6 +30,30 @@ jest.mock('react-redux', () => ({
|
|||||||
useSelector: jest.fn(),
|
useSelector: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.spyOn(appContextHooks, 'useAppContext').mockReturnValue({
|
||||||
|
user: {
|
||||||
|
role: 'admin',
|
||||||
|
},
|
||||||
|
activeLicenseV3: {
|
||||||
|
event_queue: {
|
||||||
|
created_at: '0',
|
||||||
|
event: LicenseEvent.NO_EVENT,
|
||||||
|
scheduled_at: '0',
|
||||||
|
status: '',
|
||||||
|
updated_at: '0',
|
||||||
|
},
|
||||||
|
license: {
|
||||||
|
license_key: 'test-license-key',
|
||||||
|
license_type: 'trial',
|
||||||
|
org_id: 'test-org-id',
|
||||||
|
plan_id: 'test-plan-id',
|
||||||
|
plan_name: 'test-plan-name',
|
||||||
|
plan_type: 'trial',
|
||||||
|
plan_version: 'test-plan-version',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as any);
|
||||||
|
|
||||||
function Exceptions({ initUrl }: { initUrl?: string[] }): JSX.Element {
|
function Exceptions({ initUrl }: { initUrl?: string[] }): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<MemoryRouter initialEntries={initUrl ?? ['/exceptions']}>
|
<MemoryRouter initialEntries={initUrl ?? ['/exceptions']}>
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { Button, Typography } from 'antd';
|
import { Button, Typography } from 'antd';
|
||||||
import createDashboard from 'api/dashboard/create';
|
import createDashboard from 'api/v1/dashboards/create';
|
||||||
import { ENTITY_VERSION_V4 } from 'constants/app';
|
import { ENTITY_VERSION_V4 } from 'constants/app';
|
||||||
import { useGetAllDashboard } from 'hooks/dashboard/useGetAllDashboard';
|
import { useGetAllDashboard } from 'hooks/dashboard/useGetAllDashboard';
|
||||||
import useAxiosError from 'hooks/useAxiosError';
|
import { useErrorModal } from 'providers/ErrorModalProvider';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useMutation } from 'react-query';
|
import { useMutation } from 'react-query';
|
||||||
|
import APIError from 'types/api/error';
|
||||||
|
|
||||||
import { ExportPanelProps } from '.';
|
import { ExportPanelProps } from '.';
|
||||||
import {
|
import {
|
||||||
@ -33,26 +34,28 @@ function ExportPanelContainer({
|
|||||||
refetch,
|
refetch,
|
||||||
} = useGetAllDashboard();
|
} = useGetAllDashboard();
|
||||||
|
|
||||||
const handleError = useAxiosError();
|
const { showErrorModal } = useErrorModal();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
mutate: createNewDashboard,
|
mutate: createNewDashboard,
|
||||||
isLoading: createDashboardLoading,
|
isLoading: createDashboardLoading,
|
||||||
} = useMutation(createDashboard, {
|
} = useMutation(createDashboard, {
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
if (data.payload) {
|
if (data.data) {
|
||||||
onExport(data?.payload, true);
|
onExport(data?.data, true);
|
||||||
}
|
}
|
||||||
refetch();
|
refetch();
|
||||||
},
|
},
|
||||||
onError: handleError,
|
onError: (error) => {
|
||||||
|
showErrorModal(error as APIError);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const options = useMemo(() => getSelectOptions(data || []), [data]);
|
const options = useMemo(() => getSelectOptions(data?.data || []), [data]);
|
||||||
|
|
||||||
const handleExportClick = useCallback((): void => {
|
const handleExportClick = useCallback((): void => {
|
||||||
const currentSelectedDashboard = data?.find(
|
const currentSelectedDashboard = data?.data?.find(
|
||||||
({ uuid }) => uuid === selectedDashboardId,
|
({ id }) => id === selectedDashboardId,
|
||||||
);
|
);
|
||||||
|
|
||||||
onExport(currentSelectedDashboard || null, false);
|
onExport(currentSelectedDashboard || null, false);
|
||||||
@ -66,14 +69,18 @@ function ExportPanelContainer({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleNewDashboard = useCallback(async () => {
|
const handleNewDashboard = useCallback(async () => {
|
||||||
createNewDashboard({
|
try {
|
||||||
title: t('new_dashboard_title', {
|
await createNewDashboard({
|
||||||
ns: 'dashboard',
|
title: t('new_dashboard_title', {
|
||||||
}),
|
ns: 'dashboard',
|
||||||
uploadedGrafana: false,
|
}),
|
||||||
version: ENTITY_VERSION_V4,
|
uploadedGrafana: false,
|
||||||
});
|
version: ENTITY_VERSION_V4,
|
||||||
}, [t, createNewDashboard]);
|
});
|
||||||
|
} catch (error) {
|
||||||
|
showErrorModal(error as APIError);
|
||||||
|
}
|
||||||
|
}, [createNewDashboard, t, showErrorModal]);
|
||||||
|
|
||||||
const isDashboardLoading = isAllDashboardsLoading || createDashboardLoading;
|
const isDashboardLoading = isAllDashboardsLoading || createDashboardLoading;
|
||||||
|
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import { SelectProps } from 'antd';
|
import { SelectProps } from 'antd';
|
||||||
import { PayloadProps as AllDashboardsData } from 'types/api/dashboard/getAll';
|
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||||
|
|
||||||
export const getSelectOptions = (
|
export const getSelectOptions = (data: Dashboard[]): SelectProps['options'] =>
|
||||||
data: AllDashboardsData,
|
data.map(({ id, data }) => ({
|
||||||
): SelectProps['options'] =>
|
|
||||||
data.map(({ uuid, data }) => ({
|
|
||||||
label: data.title,
|
label: data.title,
|
||||||
value: uuid,
|
value: id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const filterOptions: SelectProps['filterOption'] = (
|
export const filterOptions: SelectProps['filterOption'] = (
|
||||||
|
@ -38,7 +38,7 @@ export default function DashboardEmptyState(): JSX.Element {
|
|||||||
setSelectedRowWidgetId(null);
|
setSelectedRowWidgetId(null);
|
||||||
handleToggleDashboardSlider(true);
|
handleToggleDashboardSlider(true);
|
||||||
logEvent('Dashboard Detail: Add new panel clicked', {
|
logEvent('Dashboard Detail: Add new panel clicked', {
|
||||||
dashboardId: selectedDashboard?.uuid,
|
dashboardId: selectedDashboard?.id,
|
||||||
dashboardName: selectedDashboard?.data.title,
|
dashboardName: selectedDashboard?.data.title,
|
||||||
numberOfPanels: selectedDashboard?.data.widgets?.length,
|
numberOfPanels: selectedDashboard?.data.widgets?.length,
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,7 @@ import { fireEvent, render, screen } from '@testing-library/react';
|
|||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
import { AppProvider } from 'providers/App/App';
|
import { AppProvider } from 'providers/App/App';
|
||||||
|
import { ErrorModalProvider } from 'providers/ErrorModalProvider';
|
||||||
import MockQueryClientProvider from 'providers/test/MockQueryClientProvider';
|
import MockQueryClientProvider from 'providers/test/MockQueryClientProvider';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import store from 'store';
|
import store from 'store';
|
||||||
@ -189,24 +190,26 @@ describe('WidgetGraphComponent', () => {
|
|||||||
it('should show correct menu items when hovering over more options while loading', async () => {
|
it('should show correct menu items when hovering over more options while loading', async () => {
|
||||||
const { getByTestId, findByRole, getByText, container } = render(
|
const { getByTestId, findByRole, getByText, container } = render(
|
||||||
<MockQueryClientProvider>
|
<MockQueryClientProvider>
|
||||||
<Provider store={store}>
|
<ErrorModalProvider>
|
||||||
<AppProvider>
|
<Provider store={store}>
|
||||||
<WidgetGraphComponent
|
<AppProvider>
|
||||||
widget={mockProps.widget}
|
<WidgetGraphComponent
|
||||||
queryResponse={mockProps.queryResponse}
|
widget={mockProps.widget}
|
||||||
errorMessage={mockProps.errorMessage}
|
queryResponse={mockProps.queryResponse}
|
||||||
version={mockProps.version}
|
errorMessage={mockProps.errorMessage}
|
||||||
headerMenuList={mockProps.headerMenuList}
|
version={mockProps.version}
|
||||||
isWarning={mockProps.isWarning}
|
headerMenuList={mockProps.headerMenuList}
|
||||||
isFetchingResponse={mockProps.isFetchingResponse}
|
isWarning={mockProps.isWarning}
|
||||||
setRequestData={mockProps.setRequestData}
|
isFetchingResponse={mockProps.isFetchingResponse}
|
||||||
onClickHandler={mockProps.onClickHandler}
|
setRequestData={mockProps.setRequestData}
|
||||||
onDragSelect={mockProps.onDragSelect}
|
onClickHandler={mockProps.onClickHandler}
|
||||||
openTracesButton={mockProps.openTracesButton}
|
onDragSelect={mockProps.onDragSelect}
|
||||||
onOpenTraceBtnClick={mockProps.onOpenTraceBtnClick}
|
openTracesButton={mockProps.openTracesButton}
|
||||||
/>
|
onOpenTraceBtnClick={mockProps.onOpenTraceBtnClick}
|
||||||
</AppProvider>
|
/>
|
||||||
</Provider>
|
</AppProvider>
|
||||||
|
</Provider>
|
||||||
|
</ErrorModalProvider>
|
||||||
</MockQueryClientProvider>,
|
</MockQueryClientProvider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import { Skeleton, Tooltip, Typography } from 'antd';
|
|||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import { useNavigateToExplorer } from 'components/CeleryTask/useNavigateToExplorer';
|
import { useNavigateToExplorer } from 'components/CeleryTask/useNavigateToExplorer';
|
||||||
import { ToggleGraphProps } from 'components/Graph/types';
|
import { ToggleGraphProps } from 'components/Graph/types';
|
||||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
|
||||||
import { QueryParams } from 'constants/query';
|
import { QueryParams } from 'constants/query';
|
||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { placeWidgetAtBottom } from 'container/NewWidget/utils';
|
import { placeWidgetAtBottom } from 'container/NewWidget/utils';
|
||||||
@ -31,7 +30,7 @@ import {
|
|||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { Dashboard } from 'types/api/dashboard/getAll';
|
import { Props } from 'types/api/dashboard/update';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
@ -119,29 +118,23 @@ function WidgetGraphComponent({
|
|||||||
const updatedLayout =
|
const updatedLayout =
|
||||||
selectedDashboard.data.layout?.filter((e) => e.i !== widget.id) || [];
|
selectedDashboard.data.layout?.filter((e) => e.i !== widget.id) || [];
|
||||||
|
|
||||||
const updatedSelectedDashboard: Dashboard = {
|
const updatedSelectedDashboard: Props = {
|
||||||
...selectedDashboard,
|
|
||||||
data: {
|
data: {
|
||||||
...selectedDashboard.data,
|
...selectedDashboard.data,
|
||||||
widgets: updatedWidgets,
|
widgets: updatedWidgets,
|
||||||
layout: updatedLayout,
|
layout: updatedLayout,
|
||||||
},
|
},
|
||||||
uuid: selectedDashboard.uuid,
|
id: selectedDashboard.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
updateDashboardMutation.mutateAsync(updatedSelectedDashboard, {
|
updateDashboardMutation.mutateAsync(updatedSelectedDashboard, {
|
||||||
onSuccess: (updatedDashboard) => {
|
onSuccess: (updatedDashboard) => {
|
||||||
if (setLayouts) setLayouts(updatedDashboard.payload?.data?.layout || []);
|
if (setLayouts) setLayouts(updatedDashboard.data?.data?.layout || []);
|
||||||
if (setSelectedDashboard && updatedDashboard.payload) {
|
if (setSelectedDashboard && updatedDashboard.data) {
|
||||||
setSelectedDashboard(updatedDashboard.payload);
|
setSelectedDashboard(updatedDashboard.data);
|
||||||
}
|
}
|
||||||
setDeleteModal(false);
|
setDeleteModal(false);
|
||||||
},
|
},
|
||||||
onError: () => {
|
|
||||||
notifications.error({
|
|
||||||
message: SOMETHING_WENT_WRONG,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -166,7 +159,8 @@ function WidgetGraphComponent({
|
|||||||
|
|
||||||
updateDashboardMutation.mutateAsync(
|
updateDashboardMutation.mutateAsync(
|
||||||
{
|
{
|
||||||
...selectedDashboard,
|
id: selectedDashboard.id,
|
||||||
|
|
||||||
data: {
|
data: {
|
||||||
...selectedDashboard.data,
|
...selectedDashboard.data,
|
||||||
layout,
|
layout,
|
||||||
@ -183,9 +177,9 @@ function WidgetGraphComponent({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
onSuccess: (updatedDashboard) => {
|
onSuccess: (updatedDashboard) => {
|
||||||
if (setLayouts) setLayouts(updatedDashboard.payload?.data?.layout || []);
|
if (setLayouts) setLayouts(updatedDashboard.data?.data?.layout || []);
|
||||||
if (setSelectedDashboard && updatedDashboard.payload) {
|
if (setSelectedDashboard && updatedDashboard.data) {
|
||||||
setSelectedDashboard(updatedDashboard.payload);
|
setSelectedDashboard(updatedDashboard.data);
|
||||||
}
|
}
|
||||||
notifications.success({
|
notifications.success({
|
||||||
message: 'Panel cloned successfully, redirecting to new copy.',
|
message: 'Panel cloned successfully, redirecting to new copy.',
|
||||||
|
@ -6,7 +6,6 @@ import { Button, Form, Input, Modal, Typography } from 'antd';
|
|||||||
import { useForm } from 'antd/es/form/Form';
|
import { useForm } from 'antd/es/form/Form';
|
||||||
import logEvent from 'api/common/logEvent';
|
import logEvent from 'api/common/logEvent';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
|
||||||
import { QueryParams } from 'constants/query';
|
import { QueryParams } from 'constants/query';
|
||||||
import { PANEL_GROUP_TYPES, PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_GROUP_TYPES, PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { themeColors } from 'constants/theme';
|
import { themeColors } from 'constants/theme';
|
||||||
@ -14,7 +13,6 @@ import { DEFAULT_ROW_NAME } from 'container/NewDashboard/DashboardDescription/ut
|
|||||||
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
|
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
|
||||||
import useComponentPermission from 'hooks/useComponentPermission';
|
import useComponentPermission from 'hooks/useComponentPermission';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
|
||||||
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import { defaultTo, isUndefined } from 'lodash-es';
|
import { defaultTo, isUndefined } from 'lodash-es';
|
||||||
@ -36,7 +34,8 @@ import { ItemCallback, Layout } from 'react-grid-layout';
|
|||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { UpdateTimeInterval } from 'store/actions';
|
import { UpdateTimeInterval } from 'store/actions';
|
||||||
import { Dashboard, Widgets } from 'types/api/dashboard/getAll';
|
import { Widgets } from 'types/api/dashboard/getAll';
|
||||||
|
import { Props } from 'types/api/dashboard/update';
|
||||||
import { ROLES, USER_ROLES } from 'types/roles';
|
import { ROLES, USER_ROLES } from 'types/roles';
|
||||||
import { ComponentTypes } from 'utils/permission';
|
import { ComponentTypes } from 'utils/permission';
|
||||||
|
|
||||||
@ -107,7 +106,6 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
|||||||
|
|
||||||
const updateDashboardMutation = useUpdateDashboard();
|
const updateDashboardMutation = useUpdateDashboard();
|
||||||
|
|
||||||
const { notifications } = useNotifications();
|
|
||||||
const urlQuery = useUrlQuery();
|
const urlQuery = useUrlQuery();
|
||||||
|
|
||||||
let permissions: ComponentTypes[] = ['save_layout', 'add_panel'];
|
let permissions: ComponentTypes[] = ['save_layout', 'add_panel'];
|
||||||
@ -158,20 +156,20 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!logEventCalledRef.current && !isUndefined(data)) {
|
if (!logEventCalledRef.current && !isUndefined(data)) {
|
||||||
logEvent('Dashboard Detail: Opened', {
|
logEvent('Dashboard Detail: Opened', {
|
||||||
dashboardId: data.uuid,
|
dashboardId: selectedDashboard?.id,
|
||||||
dashboardName: data.title,
|
dashboardName: data.title,
|
||||||
numberOfPanels: data.widgets?.length,
|
numberOfPanels: data.widgets?.length,
|
||||||
numberOfVariables: Object.keys(data?.variables || {}).length || 0,
|
numberOfVariables: Object.keys(data?.variables || {}).length || 0,
|
||||||
});
|
});
|
||||||
logEventCalledRef.current = true;
|
logEventCalledRef.current = true;
|
||||||
}
|
}
|
||||||
}, [data]);
|
}, [data, selectedDashboard?.id]);
|
||||||
|
|
||||||
const onSaveHandler = (): void => {
|
const onSaveHandler = (): void => {
|
||||||
if (!selectedDashboard) return;
|
if (!selectedDashboard) return;
|
||||||
|
|
||||||
const updatedDashboard: Dashboard = {
|
const updatedDashboard: Props = {
|
||||||
...selectedDashboard,
|
id: selectedDashboard.id,
|
||||||
data: {
|
data: {
|
||||||
...selectedDashboard.data,
|
...selectedDashboard.data,
|
||||||
panelMap: { ...currentPanelMap },
|
panelMap: { ...currentPanelMap },
|
||||||
@ -186,24 +184,18 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
|||||||
return widget;
|
return widget;
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
uuid: selectedDashboard.uuid,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
updateDashboardMutation.mutate(updatedDashboard, {
|
updateDashboardMutation.mutate(updatedDashboard, {
|
||||||
onSuccess: (updatedDashboard) => {
|
onSuccess: (updatedDashboard) => {
|
||||||
setSelectedRowWidgetId(null);
|
setSelectedRowWidgetId(null);
|
||||||
if (updatedDashboard.payload) {
|
if (updatedDashboard.data) {
|
||||||
if (updatedDashboard.payload.data.layout)
|
if (updatedDashboard.data.data.layout)
|
||||||
setLayouts(sortLayout(updatedDashboard.payload.data.layout));
|
setLayouts(sortLayout(updatedDashboard.data.data.layout));
|
||||||
setSelectedDashboard(updatedDashboard.payload);
|
setSelectedDashboard(updatedDashboard.data);
|
||||||
setPanelMap(updatedDashboard.payload?.data?.panelMap || {});
|
setPanelMap(updatedDashboard.data?.data?.panelMap || {});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: () => {
|
|
||||||
notifications.error({
|
|
||||||
message: SOMETHING_WENT_WRONG,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -286,33 +278,25 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
|||||||
|
|
||||||
updatedWidgets?.push(currentWidget);
|
updatedWidgets?.push(currentWidget);
|
||||||
|
|
||||||
const updatedSelectedDashboard: Dashboard = {
|
const updatedSelectedDashboard: Props = {
|
||||||
...selectedDashboard,
|
id: selectedDashboard.id,
|
||||||
data: {
|
data: {
|
||||||
...selectedDashboard.data,
|
...selectedDashboard.data,
|
||||||
widgets: updatedWidgets,
|
widgets: updatedWidgets,
|
||||||
},
|
},
|
||||||
uuid: selectedDashboard.uuid,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
updateDashboardMutation.mutateAsync(updatedSelectedDashboard, {
|
updateDashboardMutation.mutateAsync(updatedSelectedDashboard, {
|
||||||
onSuccess: (updatedDashboard) => {
|
onSuccess: (updatedDashboard) => {
|
||||||
if (setLayouts) setLayouts(updatedDashboard.payload?.data?.layout || []);
|
if (setLayouts) setLayouts(updatedDashboard.data?.data?.layout || []);
|
||||||
if (setSelectedDashboard && updatedDashboard.payload) {
|
if (setSelectedDashboard && updatedDashboard.data) {
|
||||||
setSelectedDashboard(updatedDashboard.payload);
|
setSelectedDashboard(updatedDashboard.data);
|
||||||
}
|
}
|
||||||
if (setPanelMap)
|
if (setPanelMap) setPanelMap(updatedDashboard.data?.data?.panelMap || {});
|
||||||
setPanelMap(updatedDashboard.payload?.data?.panelMap || {});
|
|
||||||
form.setFieldValue('title', '');
|
form.setFieldValue('title', '');
|
||||||
setIsSettingsModalOpen(false);
|
setIsSettingsModalOpen(false);
|
||||||
setCurrentSelectRowId(null);
|
setCurrentSelectRowId(null);
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
|
||||||
onError: () => {
|
|
||||||
notifications.error({
|
|
||||||
message: SOMETHING_WENT_WRONG,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -447,34 +431,26 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
|||||||
const updatedPanelMap = { ...currentPanelMap };
|
const updatedPanelMap = { ...currentPanelMap };
|
||||||
delete updatedPanelMap[currentSelectRowId];
|
delete updatedPanelMap[currentSelectRowId];
|
||||||
|
|
||||||
const updatedSelectedDashboard: Dashboard = {
|
const updatedSelectedDashboard: Props = {
|
||||||
...selectedDashboard,
|
id: selectedDashboard.id,
|
||||||
data: {
|
data: {
|
||||||
...selectedDashboard.data,
|
...selectedDashboard.data,
|
||||||
widgets: updatedWidgets,
|
widgets: updatedWidgets,
|
||||||
layout: updatedLayout,
|
layout: updatedLayout,
|
||||||
panelMap: updatedPanelMap,
|
panelMap: updatedPanelMap,
|
||||||
},
|
},
|
||||||
uuid: selectedDashboard.uuid,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
updateDashboardMutation.mutateAsync(updatedSelectedDashboard, {
|
updateDashboardMutation.mutateAsync(updatedSelectedDashboard, {
|
||||||
onSuccess: (updatedDashboard) => {
|
onSuccess: (updatedDashboard) => {
|
||||||
if (setLayouts) setLayouts(updatedDashboard.payload?.data?.layout || []);
|
if (setLayouts) setLayouts(updatedDashboard.data?.data?.layout || []);
|
||||||
if (setSelectedDashboard && updatedDashboard.payload) {
|
if (setSelectedDashboard && updatedDashboard.data) {
|
||||||
setSelectedDashboard(updatedDashboard.payload);
|
setSelectedDashboard(updatedDashboard.data);
|
||||||
}
|
}
|
||||||
if (setPanelMap)
|
if (setPanelMap) setPanelMap(updatedDashboard.data?.data?.panelMap || {});
|
||||||
setPanelMap(updatedDashboard.payload?.data?.panelMap || {});
|
|
||||||
setIsDeleteModalOpen(false);
|
setIsDeleteModalOpen(false);
|
||||||
setCurrentSelectRowId(null);
|
setCurrentSelectRowId(null);
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
|
||||||
onError: () => {
|
|
||||||
notifications.error({
|
|
||||||
message: SOMETHING_WENT_WRONG,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const isDashboardEmpty = useMemo(
|
const isDashboardEmpty = useMemo(
|
||||||
|
@ -33,7 +33,7 @@ export default function Dashboards({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!dashboardsList) return;
|
if (!dashboardsList) return;
|
||||||
|
|
||||||
const sortedDashboards = dashboardsList.sort((a, b) => {
|
const sortedDashboards = dashboardsList.data.sort((a, b) => {
|
||||||
const aUpdateAt = new Date(a.updatedAt).getTime();
|
const aUpdateAt = new Date(a.updatedAt).getTime();
|
||||||
const bUpdateAt = new Date(b.updatedAt).getTime();
|
const bUpdateAt = new Date(b.updatedAt).getTime();
|
||||||
return bUpdateAt - aUpdateAt;
|
return bUpdateAt - aUpdateAt;
|
||||||
@ -103,7 +103,7 @@ export default function Dashboards({
|
|||||||
<div className="home-dashboards-list-container home-data-item-container">
|
<div className="home-dashboards-list-container home-data-item-container">
|
||||||
<div className="dashboards-list">
|
<div className="dashboards-list">
|
||||||
{sortedDashboards.slice(0, 5).map((dashboard) => {
|
{sortedDashboards.slice(0, 5).map((dashboard) => {
|
||||||
const getLink = (): string => `${ROUTES.ALL_DASHBOARD}/${dashboard.uuid}`;
|
const getLink = (): string => `${ROUTES.ALL_DASHBOARD}/${dashboard.id}`;
|
||||||
|
|
||||||
const onClickHandler = (event: React.MouseEvent<HTMLElement>): void => {
|
const onClickHandler = (event: React.MouseEvent<HTMLElement>): void => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@ -134,7 +134,7 @@ export default function Dashboards({
|
|||||||
<div className="dashboard-item-name-container home-data-item-name-container">
|
<div className="dashboard-item-name-container home-data-item-name-container">
|
||||||
<img
|
<img
|
||||||
src={
|
src={
|
||||||
dashboard.id % 2 === 0
|
Math.random() % 2 === 0
|
||||||
? '/Icons/eight-ball.svg'
|
? '/Icons/eight-ball.svg'
|
||||||
: '/Icons/circus-tent.svg'
|
: '/Icons/circus-tent.svg'
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import getAllUserPreferences from 'api/preferences/getAllUserPreference';
|
|||||||
import updateUserPreferenceAPI from 'api/preferences/updateUserPreference';
|
import updateUserPreferenceAPI from 'api/preferences/updateUserPreference';
|
||||||
import Header from 'components/Header/Header';
|
import Header from 'components/Header/Header';
|
||||||
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
|
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
|
||||||
|
import { FeatureKeys } from 'constants/features';
|
||||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||||
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||||
@ -161,10 +162,20 @@ export default function Home(): JSX.Element {
|
|||||||
enabled: !!query,
|
enabled: !!query,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: k8sPodsData } = useGetK8sPodsList(query as K8sPodsListPayload, {
|
const { featureFlags } = useAppContext();
|
||||||
queryKey: ['K8sPodsList', query],
|
const dotMetricsEnabled =
|
||||||
enabled: !!query,
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
});
|
?.active || false;
|
||||||
|
|
||||||
|
const { data: k8sPodsData } = useGetK8sPodsList(
|
||||||
|
query as K8sPodsListPayload,
|
||||||
|
{
|
||||||
|
queryKey: ['K8sPodsList', query],
|
||||||
|
enabled: !!query,
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
);
|
||||||
|
|
||||||
const [isLogsIngestionActive, setIsLogsIngestionActive] = useState(false);
|
const [isLogsIngestionActive, setIsLogsIngestionActive] = useState(false);
|
||||||
const [isTracesIngestionActive, setIsTracesIngestionActive] = useState(false);
|
const [isTracesIngestionActive, setIsTracesIngestionActive] = useState(false);
|
||||||
|
@ -30,6 +30,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
|||||||
import { Tags } from 'types/reducer/trace';
|
import { Tags } from 'types/reducer/trace';
|
||||||
import { USER_ROLES } from 'types/roles';
|
import { USER_ROLES } from 'types/roles';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
import { DOCS_LINKS } from '../constants';
|
import { DOCS_LINKS } from '../constants';
|
||||||
import { columns, TIME_PICKER_OPTIONS } from './constants';
|
import { columns, TIME_PICKER_OPTIONS } from './constants';
|
||||||
|
|
||||||
@ -210,6 +211,11 @@ function ServiceMetrics({
|
|||||||
|
|
||||||
const topLevelOperations = useMemo(() => Object.entries(data || {}), [data]);
|
const topLevelOperations = useMemo(() => Object.entries(data || {}), [data]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const queryRangeRequestData = useMemo(
|
const queryRangeRequestData = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getQueryRangeRequestData({
|
getQueryRangeRequestData({
|
||||||
@ -217,12 +223,14 @@ function ServiceMetrics({
|
|||||||
minTime: timeRange.startTime * 1e6,
|
minTime: timeRange.startTime * 1e6,
|
||||||
maxTime: timeRange.endTime * 1e6,
|
maxTime: timeRange.endTime * 1e6,
|
||||||
globalSelectedInterval,
|
globalSelectedInterval,
|
||||||
|
dotMetricsEnabled,
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
globalSelectedInterval,
|
globalSelectedInterval,
|
||||||
timeRange.endTime,
|
timeRange.endTime,
|
||||||
timeRange.startTime,
|
timeRange.startTime,
|
||||||
topLevelOperations,
|
topLevelOperations,
|
||||||
|
dotMetricsEnabled,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -25,9 +25,11 @@ import { AppState } from 'store/reducers';
|
|||||||
import { IBuilderQuery, Query } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery, Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../constants/features';
|
||||||
|
import { useAppContext } from '../../providers/App/App';
|
||||||
import HostsListControls from './HostsListControls';
|
import HostsListControls from './HostsListControls';
|
||||||
import HostsListTable from './HostsListTable';
|
import HostsListTable from './HostsListTable';
|
||||||
import { getHostListsQuery, HostsQuickFiltersConfig } from './utils';
|
import { getHostListsQuery, GetHostsQuickFiltersConfig } from './utils';
|
||||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||||
function HostsList(): JSX.Element {
|
function HostsList(): JSX.Element {
|
||||||
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
|
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
|
||||||
@ -114,6 +116,11 @@ function HostsList(): JSX.Element {
|
|||||||
entityVersion: '',
|
entityVersion: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const handleFiltersChange = useCallback(
|
const handleFiltersChange = useCallback(
|
||||||
(value: IBuilderQuery['filters']): void => {
|
(value: IBuilderQuery['filters']): void => {
|
||||||
const isNewFilterAdded = value.items.length !== filters.items.length;
|
const isNewFilterAdded = value.items.length !== filters.items.length;
|
||||||
@ -182,7 +189,7 @@ function HostsList(): JSX.Element {
|
|||||||
</div>
|
</div>
|
||||||
<QuickFilters
|
<QuickFilters
|
||||||
source={QuickFiltersSource.INFRA_MONITORING}
|
source={QuickFiltersSource.INFRA_MONITORING}
|
||||||
config={HostsQuickFiltersConfig}
|
config={GetHostsQuickFiltersConfig(dotMetricsEnabled)}
|
||||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||||
onFilterChange={handleQuickFiltersChange}
|
onFilterChange={handleQuickFiltersChange}
|
||||||
/>
|
/>
|
||||||
|
@ -198,3 +198,48 @@ export const HostsQuickFiltersConfig: IQuickFiltersConfig[] = [
|
|||||||
defaultOpen: true,
|
defaultOpen: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export function GetHostsQuickFiltersConfig(
|
||||||
|
dotMetricsEnabled: boolean,
|
||||||
|
): IQuickFiltersConfig[] {
|
||||||
|
// These keys don’t change with dotMetricsEnabled
|
||||||
|
const hostNameKey = dotMetricsEnabled ? 'host.name' : 'host_name';
|
||||||
|
const osTypeKey = dotMetricsEnabled ? 'os.type' : 'os_type';
|
||||||
|
// This metric stays the same regardless of notation
|
||||||
|
const metricName = dotMetricsEnabled
|
||||||
|
? 'system.cpu.load_average.15m'
|
||||||
|
: 'system_cpu_load_average_15m';
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: FiltersType.CHECKBOX,
|
||||||
|
title: 'Host Name',
|
||||||
|
attributeKey: {
|
||||||
|
key: hostNameKey,
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
type: 'resource',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
},
|
||||||
|
aggregateOperator: 'noop',
|
||||||
|
aggregateAttribute: metricName,
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
defaultOpen: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FiltersType.CHECKBOX,
|
||||||
|
title: 'OS Type',
|
||||||
|
attributeKey: {
|
||||||
|
key: osTypeKey,
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
type: 'resource',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
},
|
||||||
|
aggregateOperator: 'noop',
|
||||||
|
aggregateAttribute: metricName,
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
defaultOpen: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -28,11 +28,13 @@ import { AppState } from 'store/reducers';
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
import { getOrderByFromParams } from '../commonUtils';
|
import { getOrderByFromParams } from '../commonUtils';
|
||||||
import {
|
import {
|
||||||
|
GetK8sEntityToAggregateAttribute,
|
||||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||||
K8sCategory,
|
K8sCategory,
|
||||||
K8sEntityToAggregateAttributeMapping,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import K8sHeader from '../K8sHeader';
|
import K8sHeader from '../K8sHeader';
|
||||||
import LoadingContainer from '../LoadingContainer';
|
import LoadingContainer from '../LoadingContainer';
|
||||||
@ -135,6 +137,11 @@ function K8sClustersList({
|
|||||||
}
|
}
|
||||||
}, [quickFiltersLastUpdated]);
|
}, [quickFiltersLastUpdated]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const createFiltersForSelectedRowData = (
|
const createFiltersForSelectedRowData = (
|
||||||
selectedRowData: K8sClustersRowData,
|
selectedRowData: K8sClustersRowData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -194,6 +201,8 @@ function K8sClustersList({
|
|||||||
queryKey: ['clusterList', fetchGroupedByRowDataQuery],
|
queryKey: ['clusterList', fetchGroupedByRowDataQuery],
|
||||||
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -202,8 +211,10 @@ function K8sClustersList({
|
|||||||
} = useGetAggregateKeys(
|
} = useGetAggregateKeys(
|
||||||
{
|
{
|
||||||
dataSource: currentQuery.builder.queryData[0].dataSource,
|
dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||||
aggregateAttribute:
|
aggregateAttribute: GetK8sEntityToAggregateAttribute(
|
||||||
K8sEntityToAggregateAttributeMapping[K8sCategory.CLUSTERS],
|
K8sCategory.CLUSTERS,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
aggregateOperator: 'noop',
|
aggregateOperator: 'noop',
|
||||||
searchText: '',
|
searchText: '',
|
||||||
tagType: '',
|
tagType: '',
|
||||||
@ -249,6 +260,8 @@ function K8sClustersList({
|
|||||||
queryKey: ['clusterList', query],
|
queryKey: ['clusterList', query],
|
||||||
enabled: !!query,
|
enabled: !!query,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const clustersData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
const clustersData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
||||||
|
@ -136,6 +136,11 @@ export const getK8sClustersListColumns = (
|
|||||||
return columnsConfig as ColumnType<K8sClustersRowData>[];
|
return columnsConfig as ColumnType<K8sClustersRowData>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dotToUnder: Record<string, keyof K8sClustersData['meta']> = {
|
||||||
|
'k8s.cluster.name': 'k8s_cluster_name',
|
||||||
|
'k8s.cluster.uid': 'k8s_cluster_uid',
|
||||||
|
};
|
||||||
|
|
||||||
const getGroupByEle = (
|
const getGroupByEle = (
|
||||||
cluster: K8sClustersData,
|
cluster: K8sClustersData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -143,7 +148,13 @@ const getGroupByEle = (
|
|||||||
const groupByValues: string[] = [];
|
const groupByValues: string[] = [];
|
||||||
|
|
||||||
groupBy.forEach((group) => {
|
groupBy.forEach((group) => {
|
||||||
groupByValues.push(cluster.meta[group.key as keyof typeof cluster.meta]);
|
const rawKey = group.key as string;
|
||||||
|
|
||||||
|
// Choose mapped key if present, otherwise use rawKey
|
||||||
|
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof cluster.meta;
|
||||||
|
const value = cluster.meta[metaKey];
|
||||||
|
|
||||||
|
groupByValues.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
import { getOrderByFromParams } from '../commonUtils';
|
import { getOrderByFromParams } from '../commonUtils';
|
||||||
import {
|
import {
|
||||||
|
GetK8sEntityToAggregateAttribute,
|
||||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||||
K8sCategory,
|
K8sCategory,
|
||||||
K8sEntityToAggregateAttributeMapping,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import K8sHeader from '../K8sHeader';
|
import K8sHeader from '../K8sHeader';
|
||||||
import LoadingContainer from '../LoadingContainer';
|
import LoadingContainer from '../LoadingContainer';
|
||||||
@ -137,6 +139,11 @@ function K8sDaemonSetsList({
|
|||||||
}
|
}
|
||||||
}, [quickFiltersLastUpdated]);
|
}, [quickFiltersLastUpdated]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const createFiltersForSelectedRowData = (
|
const createFiltersForSelectedRowData = (
|
||||||
selectedRowData: K8sDaemonSetsRowData,
|
selectedRowData: K8sDaemonSetsRowData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -196,6 +203,8 @@ function K8sDaemonSetsList({
|
|||||||
queryKey: ['daemonSetList', fetchGroupedByRowDataQuery],
|
queryKey: ['daemonSetList', fetchGroupedByRowDataQuery],
|
||||||
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -204,8 +213,10 @@ function K8sDaemonSetsList({
|
|||||||
} = useGetAggregateKeys(
|
} = useGetAggregateKeys(
|
||||||
{
|
{
|
||||||
dataSource: currentQuery.builder.queryData[0].dataSource,
|
dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||||
aggregateAttribute:
|
aggregateAttribute: GetK8sEntityToAggregateAttribute(
|
||||||
K8sEntityToAggregateAttributeMapping[K8sCategory.DAEMONSETS],
|
K8sCategory.DAEMONSETS,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
aggregateOperator: 'noop',
|
aggregateOperator: 'noop',
|
||||||
searchText: '',
|
searchText: '',
|
||||||
tagType: '',
|
tagType: '',
|
||||||
@ -246,6 +257,8 @@ function K8sDaemonSetsList({
|
|||||||
queryKey: ['daemonSetList', query],
|
queryKey: ['daemonSetList', query],
|
||||||
enabled: !!query,
|
enabled: !!query,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const daemonSetsData = useMemo(() => data?.payload?.data?.records || [], [
|
const daemonSetsData = useMemo(() => data?.payload?.data?.records || [], [
|
||||||
|
@ -236,6 +236,12 @@ export const getK8sDaemonSetsListColumns = (
|
|||||||
return columnsConfig as ColumnType<K8sDaemonSetsRowData>[];
|
return columnsConfig as ColumnType<K8sDaemonSetsRowData>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dotToUnder: Record<string, keyof K8sDaemonSetsData['meta']> = {
|
||||||
|
'k8s.daemonset.name': 'k8s_daemonset_name',
|
||||||
|
'k8s.namespace.name': 'k8s_namespace_name',
|
||||||
|
'k8s.cluster.name': 'k8s_cluster_name',
|
||||||
|
};
|
||||||
|
|
||||||
const getGroupByEle = (
|
const getGroupByEle = (
|
||||||
daemonSet: K8sDaemonSetsData,
|
daemonSet: K8sDaemonSetsData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -243,7 +249,13 @@ const getGroupByEle = (
|
|||||||
const groupByValues: string[] = [];
|
const groupByValues: string[] = [];
|
||||||
|
|
||||||
groupBy.forEach((group) => {
|
groupBy.forEach((group) => {
|
||||||
groupByValues.push(daemonSet.meta[group.key as keyof typeof daemonSet.meta]);
|
const rawKey = group.key as string;
|
||||||
|
|
||||||
|
// Choose mapped key if present, otherwise use rawKey
|
||||||
|
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof daemonSet.meta;
|
||||||
|
const value = daemonSet.meta[metaKey];
|
||||||
|
|
||||||
|
groupByValues.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
import { getOrderByFromParams } from '../commonUtils';
|
import { getOrderByFromParams } from '../commonUtils';
|
||||||
import {
|
import {
|
||||||
|
GetK8sEntityToAggregateAttribute,
|
||||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||||
K8sCategory,
|
K8sCategory,
|
||||||
K8sEntityToAggregateAttributeMapping,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import K8sHeader from '../K8sHeader';
|
import K8sHeader from '../K8sHeader';
|
||||||
import LoadingContainer from '../LoadingContainer';
|
import LoadingContainer from '../LoadingContainer';
|
||||||
@ -138,6 +140,11 @@ function K8sDeploymentsList({
|
|||||||
}
|
}
|
||||||
}, [quickFiltersLastUpdated]);
|
}, [quickFiltersLastUpdated]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const createFiltersForSelectedRowData = (
|
const createFiltersForSelectedRowData = (
|
||||||
selectedRowData: K8sDeploymentsRowData,
|
selectedRowData: K8sDeploymentsRowData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -197,6 +204,8 @@ function K8sDeploymentsList({
|
|||||||
queryKey: ['deploymentList', fetchGroupedByRowDataQuery],
|
queryKey: ['deploymentList', fetchGroupedByRowDataQuery],
|
||||||
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -205,8 +214,10 @@ function K8sDeploymentsList({
|
|||||||
} = useGetAggregateKeys(
|
} = useGetAggregateKeys(
|
||||||
{
|
{
|
||||||
dataSource: currentQuery.builder.queryData[0].dataSource,
|
dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||||
aggregateAttribute:
|
aggregateAttribute: GetK8sEntityToAggregateAttribute(
|
||||||
K8sEntityToAggregateAttributeMapping[K8sCategory.DEPLOYMENTS],
|
K8sCategory.DEPLOYMENTS,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
aggregateOperator: 'noop',
|
aggregateOperator: 'noop',
|
||||||
searchText: '',
|
searchText: '',
|
||||||
tagType: '',
|
tagType: '',
|
||||||
@ -247,6 +258,8 @@ function K8sDeploymentsList({
|
|||||||
queryKey: ['deploymentList', query],
|
queryKey: ['deploymentList', query],
|
||||||
enabled: !!query,
|
enabled: !!query,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const deploymentsData = useMemo(() => data?.payload?.data?.records || [], [
|
const deploymentsData = useMemo(() => data?.payload?.data?.records || [], [
|
||||||
|
@ -226,6 +226,12 @@ export const getK8sDeploymentsListColumns = (
|
|||||||
return columnsConfig as ColumnType<K8sDeploymentsRowData>[];
|
return columnsConfig as ColumnType<K8sDeploymentsRowData>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dotToUnder: Record<string, keyof K8sDeploymentsData['meta']> = {
|
||||||
|
'k8s.deployment.name': 'k8s_deployment_name',
|
||||||
|
'k8s.namespace.name': 'k8s_namespace_name',
|
||||||
|
'k8s.cluster.name': 'k8s_cluster_name',
|
||||||
|
};
|
||||||
|
|
||||||
const getGroupByEle = (
|
const getGroupByEle = (
|
||||||
deployment: K8sDeploymentsData,
|
deployment: K8sDeploymentsData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -233,9 +239,14 @@ const getGroupByEle = (
|
|||||||
const groupByValues: string[] = [];
|
const groupByValues: string[] = [];
|
||||||
|
|
||||||
groupBy.forEach((group) => {
|
groupBy.forEach((group) => {
|
||||||
groupByValues.push(
|
const rawKey = group.key as string;
|
||||||
deployment.meta[group.key as keyof typeof deployment.meta],
|
|
||||||
);
|
// Choose mapped key if present, otherwise use rawKey
|
||||||
|
const metaKey = (dotToUnder[rawKey] ??
|
||||||
|
rawKey) as keyof typeof deployment.meta;
|
||||||
|
const value = deployment.meta[metaKey];
|
||||||
|
|
||||||
|
groupByValues.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -29,6 +29,9 @@ import { SuccessResponse } from 'types/api';
|
|||||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||||
import { Options } from 'uplot';
|
import { Options } from 'uplot';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../../providers/App/App';
|
||||||
|
|
||||||
interface EntityMetricsProps<T> {
|
interface EntityMetricsProps<T> {
|
||||||
timeRange: {
|
timeRange: {
|
||||||
startTime: number;
|
startTime: number;
|
||||||
@ -49,6 +52,7 @@ interface EntityMetricsProps<T> {
|
|||||||
node: T,
|
node: T,
|
||||||
start: number,
|
start: number,
|
||||||
end: number,
|
end: number,
|
||||||
|
dotMetricsEnabled: boolean,
|
||||||
) => GetQueryResultsProps[];
|
) => GetQueryResultsProps[];
|
||||||
queryKey: string;
|
queryKey: string;
|
||||||
category: K8sCategory;
|
category: K8sCategory;
|
||||||
@ -65,9 +69,25 @@ function EntityMetrics<T>({
|
|||||||
queryKey,
|
queryKey,
|
||||||
category,
|
category,
|
||||||
}: EntityMetricsProps<T>): JSX.Element {
|
}: EntityMetricsProps<T>): JSX.Element {
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
const queryPayloads = useMemo(
|
const queryPayloads = useMemo(
|
||||||
() => getEntityQueryPayload(entity, timeRange.startTime, timeRange.endTime),
|
() =>
|
||||||
[getEntityQueryPayload, entity, timeRange.startTime, timeRange.endTime],
|
getEntityQueryPayload(
|
||||||
|
entity,
|
||||||
|
timeRange.startTime,
|
||||||
|
timeRange.endTime,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
|
[
|
||||||
|
getEntityQueryPayload,
|
||||||
|
entity,
|
||||||
|
timeRange.startTime,
|
||||||
|
timeRange.endTime,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const queries = useQueries(
|
const queries = useQueries(
|
||||||
|
@ -26,19 +26,21 @@ import { useState } from 'react';
|
|||||||
import { useSearchParams } from 'react-router-dom-v5-compat';
|
import { useSearchParams } from 'react-router-dom-v5-compat';
|
||||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../constants/features';
|
||||||
|
import { useAppContext } from '../../providers/App/App';
|
||||||
import K8sClustersList from './Clusters/K8sClustersList';
|
import K8sClustersList from './Clusters/K8sClustersList';
|
||||||
import {
|
import {
|
||||||
ClustersQuickFiltersConfig,
|
GetClustersQuickFiltersConfig,
|
||||||
DaemonSetsQuickFiltersConfig,
|
GetDaemonsetsQuickFiltersConfig,
|
||||||
DeploymentsQuickFiltersConfig,
|
GetDeploymentsQuickFiltersConfig,
|
||||||
|
GetJobsQuickFiltersConfig,
|
||||||
|
GetNamespaceQuickFiltersConfig,
|
||||||
|
GetNodesQuickFiltersConfig,
|
||||||
|
GetPodsQuickFiltersConfig,
|
||||||
|
GetStatefulsetsQuickFiltersConfig,
|
||||||
|
GetVolumesQuickFiltersConfig,
|
||||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||||
JobsQuickFiltersConfig,
|
|
||||||
K8sCategories,
|
K8sCategories,
|
||||||
NamespaceQuickFiltersConfig,
|
|
||||||
NodesQuickFiltersConfig,
|
|
||||||
PodsQuickFiltersConfig,
|
|
||||||
StatefulsetsQuickFiltersConfig,
|
|
||||||
VolumesQuickFiltersConfig,
|
|
||||||
} from './constants';
|
} from './constants';
|
||||||
import K8sDaemonSetsList from './DaemonSets/K8sDaemonSetsList';
|
import K8sDaemonSetsList from './DaemonSets/K8sDaemonSetsList';
|
||||||
import K8sDeploymentsList from './Deployments/K8sDeploymentsList';
|
import K8sDeploymentsList from './Deployments/K8sDeploymentsList';
|
||||||
@ -74,6 +76,11 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
|||||||
entityVersion: '',
|
entityVersion: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const handleFilterChange = (query: Query): void => {
|
const handleFilterChange = (query: Query): void => {
|
||||||
// update the current query with the new filters
|
// update the current query with the new filters
|
||||||
// in infra monitoring k8s, we are using only one query, hence updating the 0th index of queryData
|
// in infra monitoring k8s, we are using only one query, hence updating the 0th index of queryData
|
||||||
@ -109,7 +116,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
|||||||
children: (
|
children: (
|
||||||
<QuickFilters
|
<QuickFilters
|
||||||
source={QuickFiltersSource.INFRA_MONITORING}
|
source={QuickFiltersSource.INFRA_MONITORING}
|
||||||
config={PodsQuickFiltersConfig}
|
config={GetPodsQuickFiltersConfig(dotMetricsEnabled)}
|
||||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||||
onFilterChange={handleFilterChange}
|
onFilterChange={handleFilterChange}
|
||||||
/>
|
/>
|
||||||
@ -129,7 +136,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
|||||||
children: (
|
children: (
|
||||||
<QuickFilters
|
<QuickFilters
|
||||||
source={QuickFiltersSource.INFRA_MONITORING}
|
source={QuickFiltersSource.INFRA_MONITORING}
|
||||||
config={NodesQuickFiltersConfig}
|
config={GetNodesQuickFiltersConfig(dotMetricsEnabled)}
|
||||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||||
onFilterChange={handleFilterChange}
|
onFilterChange={handleFilterChange}
|
||||||
/>
|
/>
|
||||||
@ -152,7 +159,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
|||||||
children: (
|
children: (
|
||||||
<QuickFilters
|
<QuickFilters
|
||||||
source={QuickFiltersSource.INFRA_MONITORING}
|
source={QuickFiltersSource.INFRA_MONITORING}
|
||||||
config={NamespaceQuickFiltersConfig}
|
config={GetNamespaceQuickFiltersConfig(dotMetricsEnabled)}
|
||||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||||
onFilterChange={handleFilterChange}
|
onFilterChange={handleFilterChange}
|
||||||
/>
|
/>
|
||||||
@ -172,7 +179,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
|||||||
children: (
|
children: (
|
||||||
<QuickFilters
|
<QuickFilters
|
||||||
source={QuickFiltersSource.INFRA_MONITORING}
|
source={QuickFiltersSource.INFRA_MONITORING}
|
||||||
config={ClustersQuickFiltersConfig}
|
config={GetClustersQuickFiltersConfig(dotMetricsEnabled)}
|
||||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||||
onFilterChange={handleFilterChange}
|
onFilterChange={handleFilterChange}
|
||||||
/>
|
/>
|
||||||
@ -192,7 +199,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
|||||||
children: (
|
children: (
|
||||||
<QuickFilters
|
<QuickFilters
|
||||||
source={QuickFiltersSource.INFRA_MONITORING}
|
source={QuickFiltersSource.INFRA_MONITORING}
|
||||||
config={DeploymentsQuickFiltersConfig}
|
config={GetDeploymentsQuickFiltersConfig(dotMetricsEnabled)}
|
||||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||||
onFilterChange={handleFilterChange}
|
onFilterChange={handleFilterChange}
|
||||||
/>
|
/>
|
||||||
@ -212,7 +219,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
|||||||
children: (
|
children: (
|
||||||
<QuickFilters
|
<QuickFilters
|
||||||
source={QuickFiltersSource.INFRA_MONITORING}
|
source={QuickFiltersSource.INFRA_MONITORING}
|
||||||
config={JobsQuickFiltersConfig}
|
config={GetJobsQuickFiltersConfig(dotMetricsEnabled)}
|
||||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||||
onFilterChange={handleFilterChange}
|
onFilterChange={handleFilterChange}
|
||||||
/>
|
/>
|
||||||
@ -232,7 +239,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
|||||||
children: (
|
children: (
|
||||||
<QuickFilters
|
<QuickFilters
|
||||||
source={QuickFiltersSource.INFRA_MONITORING}
|
source={QuickFiltersSource.INFRA_MONITORING}
|
||||||
config={DaemonSetsQuickFiltersConfig}
|
config={GetDaemonsetsQuickFiltersConfig(dotMetricsEnabled)}
|
||||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||||
onFilterChange={handleFilterChange}
|
onFilterChange={handleFilterChange}
|
||||||
/>
|
/>
|
||||||
@ -255,7 +262,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
|||||||
children: (
|
children: (
|
||||||
<QuickFilters
|
<QuickFilters
|
||||||
source={QuickFiltersSource.INFRA_MONITORING}
|
source={QuickFiltersSource.INFRA_MONITORING}
|
||||||
config={StatefulsetsQuickFiltersConfig}
|
config={GetStatefulsetsQuickFiltersConfig(dotMetricsEnabled)}
|
||||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||||
onFilterChange={handleFilterChange}
|
onFilterChange={handleFilterChange}
|
||||||
/>
|
/>
|
||||||
@ -275,7 +282,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
|||||||
children: (
|
children: (
|
||||||
<QuickFilters
|
<QuickFilters
|
||||||
source={QuickFiltersSource.INFRA_MONITORING}
|
source={QuickFiltersSource.INFRA_MONITORING}
|
||||||
config={VolumesQuickFiltersConfig}
|
config={GetVolumesQuickFiltersConfig(dotMetricsEnabled)}
|
||||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||||
onFilterChange={handleFilterChange}
|
onFilterChange={handleFilterChange}
|
||||||
/>
|
/>
|
||||||
|
@ -30,395 +30,415 @@ export const getJobMetricsQueryPayload = (
|
|||||||
job: K8sJobsData,
|
job: K8sJobsData,
|
||||||
start: number,
|
start: number,
|
||||||
end: number,
|
end: number,
|
||||||
): GetQueryResultsProps[] => [
|
dotMetricsEnabled: boolean,
|
||||||
{
|
): GetQueryResultsProps[] => {
|
||||||
selectedTime: 'GLOBAL_TIME',
|
const k8sPodCpuUtilizationKey = dotMetricsEnabled
|
||||||
graphType: PANEL_TYPES.TIME_SERIES,
|
? 'k8s.pod.cpu.utilization'
|
||||||
query: {
|
: 'k8s_pod_cpu_utilization';
|
||||||
builder: {
|
const k8sPodMemoryUsageKey = dotMetricsEnabled
|
||||||
queryData: [
|
? 'k8s.pod.memory.usage'
|
||||||
|
: 'k8s_pod_memory_usage';
|
||||||
|
const k8sPodNetworkIoKey = dotMetricsEnabled
|
||||||
|
? 'k8s.pod.network.io'
|
||||||
|
: 'k8s_pod_network_io';
|
||||||
|
const k8sPodNetworkErrorsKey = dotMetricsEnabled
|
||||||
|
? 'k8s.pod.network.errors'
|
||||||
|
: 'k8s_pod_network_errors';
|
||||||
|
const k8sJobNameKey = dotMetricsEnabled ? 'k8s.job.name' : 'k8s_job_name';
|
||||||
|
const k8sNamespaceNameKey = dotMetricsEnabled
|
||||||
|
? 'k8s.namespace.name'
|
||||||
|
: 'k8s_namespace_name';
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
selectedTime: 'GLOBAL_TIME',
|
||||||
|
graphType: PANEL_TYPES.TIME_SERIES,
|
||||||
|
query: {
|
||||||
|
builder: {
|
||||||
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
id: 'k8s_pod_cpu_utilization--float64--Gauge--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sPodCpuUtilizationKey,
|
||||||
|
type: 'Gauge',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'avg',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: '6b59b690',
|
||||||
|
key: {
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'k8s_job_name--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sJobNameKey,
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
op: '=',
|
||||||
|
value: job.jobName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '47b3adae',
|
||||||
|
key: {
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'k8s_namespace_name--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sNamespaceNameKey,
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
op: '=',
|
||||||
|
value: job.meta.k8s_namespace_name,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
op: 'AND',
|
||||||
|
},
|
||||||
|
functions: [],
|
||||||
|
groupBy: [],
|
||||||
|
having: [],
|
||||||
|
legend: 'usage',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'avg',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'avg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
queryFormulas: [],
|
||||||
|
},
|
||||||
|
clickhouse_sql: [
|
||||||
{
|
{
|
||||||
aggregateAttribute: {
|
|
||||||
dataType: DataTypes.Float64,
|
|
||||||
id: 'k8s_pod_cpu_utilization--float64--Gauge--true',
|
|
||||||
isColumn: true,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_pod_cpu_utilization',
|
|
||||||
type: 'Gauge',
|
|
||||||
},
|
|
||||||
aggregateOperator: 'avg',
|
|
||||||
dataSource: DataSource.METRICS,
|
|
||||||
disabled: false,
|
disabled: false,
|
||||||
expression: 'A',
|
legend: '',
|
||||||
filters: {
|
name: 'A',
|
||||||
items: [
|
query: '',
|
||||||
{
|
|
||||||
id: '6b59b690',
|
|
||||||
key: {
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'k8s_job_name--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_job_name',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
op: '=',
|
|
||||||
value: job.jobName,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '47b3adae',
|
|
||||||
key: {
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'k8s_namespace_name--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_namespace_name',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
op: '=',
|
|
||||||
value: job.meta.k8s_namespace_name,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
op: 'AND',
|
|
||||||
},
|
|
||||||
functions: [],
|
|
||||||
groupBy: [],
|
|
||||||
having: [],
|
|
||||||
legend: 'usage',
|
|
||||||
limit: null,
|
|
||||||
orderBy: [],
|
|
||||||
queryName: 'A',
|
|
||||||
reduceTo: 'avg',
|
|
||||||
spaceAggregation: 'sum',
|
|
||||||
stepInterval: 60,
|
|
||||||
timeAggregation: 'avg',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
queryFormulas: [],
|
id: v4(),
|
||||||
},
|
promql: [
|
||||||
clickhouse_sql: [
|
|
||||||
{
|
|
||||||
disabled: false,
|
|
||||||
legend: '',
|
|
||||||
name: 'A',
|
|
||||||
query: '',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
id: v4(),
|
|
||||||
promql: [
|
|
||||||
{
|
|
||||||
disabled: false,
|
|
||||||
legend: '',
|
|
||||||
name: 'A',
|
|
||||||
query: '',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
queryType: EQueryType.QUERY_BUILDER,
|
|
||||||
},
|
|
||||||
variables: {},
|
|
||||||
formatForWeb: false,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
selectedTime: 'GLOBAL_TIME',
|
|
||||||
graphType: PANEL_TYPES.TIME_SERIES,
|
|
||||||
query: {
|
|
||||||
builder: {
|
|
||||||
queryData: [
|
|
||||||
{
|
{
|
||||||
aggregateAttribute: {
|
|
||||||
dataType: DataTypes.Float64,
|
|
||||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
|
||||||
isColumn: true,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_pod_memory_usage',
|
|
||||||
type: 'Gauge',
|
|
||||||
},
|
|
||||||
aggregateOperator: 'avg',
|
|
||||||
dataSource: DataSource.METRICS,
|
|
||||||
disabled: false,
|
disabled: false,
|
||||||
expression: 'A',
|
legend: '',
|
||||||
filters: {
|
name: 'A',
|
||||||
items: [
|
query: '',
|
||||||
{
|
|
||||||
id: '8c217f4d',
|
|
||||||
key: {
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'k8s_job_name--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_job_name',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
op: '=',
|
|
||||||
value: job.jobName,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '47b3adae',
|
|
||||||
key: {
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'k8s_namespace_name--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_namespace_name',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
op: '=',
|
|
||||||
value: job.meta.k8s_namespace_name,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
op: 'AND',
|
|
||||||
},
|
|
||||||
functions: [],
|
|
||||||
groupBy: [],
|
|
||||||
having: [],
|
|
||||||
legend: 'usage',
|
|
||||||
limit: null,
|
|
||||||
orderBy: [],
|
|
||||||
queryName: 'A',
|
|
||||||
reduceTo: 'avg',
|
|
||||||
spaceAggregation: 'sum',
|
|
||||||
stepInterval: 60,
|
|
||||||
timeAggregation: 'avg',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
queryFormulas: [],
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
},
|
},
|
||||||
clickhouse_sql: [
|
variables: {},
|
||||||
{
|
formatForWeb: false,
|
||||||
disabled: false,
|
start,
|
||||||
legend: '',
|
end,
|
||||||
name: 'A',
|
|
||||||
query: '',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
id: v4(),
|
|
||||||
promql: [
|
|
||||||
{
|
|
||||||
disabled: false,
|
|
||||||
legend: '',
|
|
||||||
name: 'A',
|
|
||||||
query: '',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
queryType: EQueryType.QUERY_BUILDER,
|
|
||||||
},
|
},
|
||||||
variables: {},
|
{
|
||||||
formatForWeb: false,
|
selectedTime: 'GLOBAL_TIME',
|
||||||
start,
|
graphType: PANEL_TYPES.TIME_SERIES,
|
||||||
end,
|
query: {
|
||||||
},
|
builder: {
|
||||||
{
|
queryData: [
|
||||||
selectedTime: 'GLOBAL_TIME',
|
{
|
||||||
graphType: PANEL_TYPES.TIME_SERIES,
|
aggregateAttribute: {
|
||||||
query: {
|
dataType: DataTypes.Float64,
|
||||||
builder: {
|
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||||
queryData: [
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sPodMemoryUsageKey,
|
||||||
|
type: 'Gauge',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'avg',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: '8c217f4d',
|
||||||
|
key: {
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'k8s_job_name--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sJobNameKey,
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
op: '=',
|
||||||
|
value: job.jobName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '47b3adae',
|
||||||
|
key: {
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'k8s_namespace_name--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sNamespaceNameKey,
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
op: '=',
|
||||||
|
value: job.meta.k8s_namespace_name,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
op: 'AND',
|
||||||
|
},
|
||||||
|
functions: [],
|
||||||
|
groupBy: [],
|
||||||
|
having: [],
|
||||||
|
legend: 'usage',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'avg',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'avg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
queryFormulas: [],
|
||||||
|
},
|
||||||
|
clickhouse_sql: [
|
||||||
{
|
{
|
||||||
aggregateAttribute: {
|
|
||||||
dataType: DataTypes.Float64,
|
|
||||||
id: 'k8s_pod_network_io--float64--Sum--true',
|
|
||||||
isColumn: true,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_pod_network_io',
|
|
||||||
type: 'Sum',
|
|
||||||
},
|
|
||||||
aggregateOperator: 'rate',
|
|
||||||
dataSource: DataSource.METRICS,
|
|
||||||
disabled: false,
|
disabled: false,
|
||||||
expression: 'A',
|
legend: '',
|
||||||
filters: {
|
name: 'A',
|
||||||
items: [
|
query: '',
|
||||||
{
|
|
||||||
id: '2bbf9d0c',
|
|
||||||
key: {
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'k8s_job_name--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_job_name',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
op: '=',
|
|
||||||
value: job.jobName,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '47b3adae',
|
|
||||||
key: {
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'k8s_namespace_name--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_namespace_name',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
op: '=',
|
|
||||||
value: job.meta.k8s_namespace_name,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
op: 'AND',
|
|
||||||
},
|
|
||||||
functions: [],
|
|
||||||
groupBy: [
|
|
||||||
{
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'direction--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'direction',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'interface--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'interface',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
having: [],
|
|
||||||
legend: '{{direction}} :: {{interface}}',
|
|
||||||
limit: null,
|
|
||||||
orderBy: [],
|
|
||||||
queryName: 'A',
|
|
||||||
reduceTo: 'avg',
|
|
||||||
spaceAggregation: 'sum',
|
|
||||||
stepInterval: 60,
|
|
||||||
timeAggregation: 'rate',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
queryFormulas: [],
|
id: v4(),
|
||||||
},
|
promql: [
|
||||||
clickhouse_sql: [
|
|
||||||
{
|
|
||||||
disabled: false,
|
|
||||||
legend: '',
|
|
||||||
name: 'A',
|
|
||||||
query: '',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
id: v4(),
|
|
||||||
promql: [
|
|
||||||
{
|
|
||||||
disabled: false,
|
|
||||||
legend: '',
|
|
||||||
name: 'A',
|
|
||||||
query: '',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
queryType: EQueryType.QUERY_BUILDER,
|
|
||||||
},
|
|
||||||
variables: {},
|
|
||||||
formatForWeb: false,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
selectedTime: 'GLOBAL_TIME',
|
|
||||||
graphType: PANEL_TYPES.TIME_SERIES,
|
|
||||||
query: {
|
|
||||||
builder: {
|
|
||||||
queryData: [
|
|
||||||
{
|
{
|
||||||
aggregateAttribute: {
|
|
||||||
dataType: DataTypes.Float64,
|
|
||||||
id: 'k8s_pod_network_errors--float64--Sum--true',
|
|
||||||
isColumn: true,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_pod_network_errors',
|
|
||||||
type: 'Sum',
|
|
||||||
},
|
|
||||||
aggregateOperator: 'increase',
|
|
||||||
dataSource: DataSource.METRICS,
|
|
||||||
disabled: false,
|
disabled: false,
|
||||||
expression: 'A',
|
legend: '',
|
||||||
filters: {
|
name: 'A',
|
||||||
items: [
|
query: '',
|
||||||
{
|
|
||||||
id: '448e6cf7',
|
|
||||||
key: {
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'k8s_job_name--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_job_name',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
op: '=',
|
|
||||||
value: job.jobName,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '47b3adae',
|
|
||||||
key: {
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'k8s_namespace_name--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'k8s_namespace_name',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
op: '=',
|
|
||||||
value: job.meta.k8s_namespace_name,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
op: 'AND',
|
|
||||||
},
|
|
||||||
functions: [],
|
|
||||||
groupBy: [
|
|
||||||
{
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'direction--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'direction',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
id: 'interface--string--tag--false',
|
|
||||||
isColumn: false,
|
|
||||||
isJSON: false,
|
|
||||||
key: 'interface',
|
|
||||||
type: 'tag',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
having: [],
|
|
||||||
legend: '{{direction}} :: {{interface}}',
|
|
||||||
limit: null,
|
|
||||||
orderBy: [],
|
|
||||||
queryName: 'A',
|
|
||||||
reduceTo: 'avg',
|
|
||||||
spaceAggregation: 'sum',
|
|
||||||
stepInterval: 60,
|
|
||||||
timeAggregation: 'increase',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
queryFormulas: [],
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
},
|
},
|
||||||
clickhouse_sql: [
|
variables: {},
|
||||||
{
|
formatForWeb: false,
|
||||||
disabled: false,
|
start,
|
||||||
legend: '',
|
end,
|
||||||
name: 'A',
|
|
||||||
query: '',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
id: v4(),
|
|
||||||
promql: [
|
|
||||||
{
|
|
||||||
disabled: false,
|
|
||||||
legend: '',
|
|
||||||
name: 'A',
|
|
||||||
query: '',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
queryType: EQueryType.QUERY_BUILDER,
|
|
||||||
},
|
},
|
||||||
variables: {},
|
{
|
||||||
formatForWeb: false,
|
selectedTime: 'GLOBAL_TIME',
|
||||||
start,
|
graphType: PANEL_TYPES.TIME_SERIES,
|
||||||
end,
|
query: {
|
||||||
},
|
builder: {
|
||||||
];
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
id: 'k8s_pod_network_io--float64--Sum--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sPodNetworkIoKey,
|
||||||
|
type: 'Sum',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'rate',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: '2bbf9d0c',
|
||||||
|
key: {
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'k8s_job_name--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sJobNameKey,
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
op: '=',
|
||||||
|
value: job.jobName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '47b3adae',
|
||||||
|
key: {
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'k8s_namespace_name--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sNamespaceNameKey,
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
op: '=',
|
||||||
|
value: job.meta.k8s_namespace_name,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
op: 'AND',
|
||||||
|
},
|
||||||
|
functions: [],
|
||||||
|
groupBy: [
|
||||||
|
{
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'direction--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: 'direction',
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'interface--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: 'interface',
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
having: [],
|
||||||
|
legend: '{{direction}} :: {{interface}}',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'avg',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'rate',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
queryFormulas: [],
|
||||||
|
},
|
||||||
|
clickhouse_sql: [
|
||||||
|
{
|
||||||
|
disabled: false,
|
||||||
|
legend: '',
|
||||||
|
name: 'A',
|
||||||
|
query: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: v4(),
|
||||||
|
promql: [
|
||||||
|
{
|
||||||
|
disabled: false,
|
||||||
|
legend: '',
|
||||||
|
name: 'A',
|
||||||
|
query: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
|
},
|
||||||
|
variables: {},
|
||||||
|
formatForWeb: false,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selectedTime: 'GLOBAL_TIME',
|
||||||
|
graphType: PANEL_TYPES.TIME_SERIES,
|
||||||
|
query: {
|
||||||
|
builder: {
|
||||||
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
id: 'k8s_pod_network_errors--float64--Sum--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sPodNetworkErrorsKey,
|
||||||
|
type: 'Sum',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'increase',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: '448e6cf7',
|
||||||
|
key: {
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'k8s_job_name--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sJobNameKey,
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
op: '=',
|
||||||
|
value: job.jobName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '47b3adae',
|
||||||
|
key: {
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'k8s_namespace_name--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: k8sNamespaceNameKey,
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
op: '=',
|
||||||
|
value: job.meta.k8s_namespace_name,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
op: 'AND',
|
||||||
|
},
|
||||||
|
functions: [],
|
||||||
|
groupBy: [
|
||||||
|
{
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'direction--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: 'direction',
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
id: 'interface--string--tag--false',
|
||||||
|
isColumn: false,
|
||||||
|
isJSON: false,
|
||||||
|
key: 'interface',
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
having: [],
|
||||||
|
legend: '{{direction}} :: {{interface}}',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'avg',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'increase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
queryFormulas: [],
|
||||||
|
},
|
||||||
|
clickhouse_sql: [
|
||||||
|
{
|
||||||
|
disabled: false,
|
||||||
|
legend: '',
|
||||||
|
name: 'A',
|
||||||
|
query: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: v4(),
|
||||||
|
promql: [
|
||||||
|
{
|
||||||
|
disabled: false,
|
||||||
|
legend: '',
|
||||||
|
name: 'A',
|
||||||
|
query: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
|
},
|
||||||
|
variables: {},
|
||||||
|
formatForWeb: false,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
import { getOrderByFromParams } from '../commonUtils';
|
import { getOrderByFromParams } from '../commonUtils';
|
||||||
import {
|
import {
|
||||||
|
GetK8sEntityToAggregateAttribute,
|
||||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||||
K8sCategory,
|
K8sCategory,
|
||||||
K8sEntityToAggregateAttributeMapping,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import K8sHeader from '../K8sHeader';
|
import K8sHeader from '../K8sHeader';
|
||||||
import LoadingContainer from '../LoadingContainer';
|
import LoadingContainer from '../LoadingContainer';
|
||||||
@ -132,6 +134,11 @@ function K8sJobsList({
|
|||||||
}
|
}
|
||||||
}, [quickFiltersLastUpdated]);
|
}, [quickFiltersLastUpdated]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const createFiltersForSelectedRowData = (
|
const createFiltersForSelectedRowData = (
|
||||||
selectedRowData: K8sJobsRowData,
|
selectedRowData: K8sJobsRowData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -185,10 +192,15 @@ function K8sJobsList({
|
|||||||
isLoading: isLoadingGroupedByRowData,
|
isLoading: isLoadingGroupedByRowData,
|
||||||
isError: isErrorGroupedByRowData,
|
isError: isErrorGroupedByRowData,
|
||||||
refetch: fetchGroupedByRowData,
|
refetch: fetchGroupedByRowData,
|
||||||
} = useGetK8sJobsList(fetchGroupedByRowDataQuery as K8sJobsListPayload, {
|
} = useGetK8sJobsList(
|
||||||
queryKey: ['jobList', fetchGroupedByRowDataQuery],
|
fetchGroupedByRowDataQuery as K8sJobsListPayload,
|
||||||
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
{
|
||||||
});
|
queryKey: ['jobList', fetchGroupedByRowDataQuery],
|
||||||
|
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: groupByFiltersData,
|
data: groupByFiltersData,
|
||||||
@ -196,7 +208,10 @@ function K8sJobsList({
|
|||||||
} = useGetAggregateKeys(
|
} = useGetAggregateKeys(
|
||||||
{
|
{
|
||||||
dataSource: currentQuery.builder.queryData[0].dataSource,
|
dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||||
aggregateAttribute: K8sEntityToAggregateAttributeMapping[K8sCategory.JOBS],
|
aggregateAttribute: GetK8sEntityToAggregateAttribute(
|
||||||
|
K8sCategory.JOBS,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
aggregateOperator: 'noop',
|
aggregateOperator: 'noop',
|
||||||
searchText: '',
|
searchText: '',
|
||||||
tagType: '',
|
tagType: '',
|
||||||
@ -242,6 +257,8 @@ function K8sJobsList({
|
|||||||
queryKey: ['jobList', query],
|
queryKey: ['jobList', query],
|
||||||
enabled: !!query,
|
enabled: !!query,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const jobsData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
const jobsData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
||||||
|
@ -263,6 +263,12 @@ export const getK8sJobsListColumns = (
|
|||||||
return columnsConfig as ColumnType<K8sJobsRowData>[];
|
return columnsConfig as ColumnType<K8sJobsRowData>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dotToUnder: Record<string, keyof K8sJobsData['meta']> = {
|
||||||
|
'k8s.job.name': 'k8s_job_name',
|
||||||
|
'k8s.namespace.name': 'k8s_namespace_name',
|
||||||
|
'k8s.cluster.name': 'k8s_cluster_name',
|
||||||
|
};
|
||||||
|
|
||||||
const getGroupByEle = (
|
const getGroupByEle = (
|
||||||
job: K8sJobsData,
|
job: K8sJobsData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -270,7 +276,13 @@ const getGroupByEle = (
|
|||||||
const groupByValues: string[] = [];
|
const groupByValues: string[] = [];
|
||||||
|
|
||||||
groupBy.forEach((group) => {
|
groupBy.forEach((group) => {
|
||||||
groupByValues.push(job.meta[group.key as keyof typeof job.meta]);
|
const rawKey = group.key as string;
|
||||||
|
|
||||||
|
// Choose mapped key if present, otherwise use rawKey
|
||||||
|
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof job.meta;
|
||||||
|
const value = job.meta[metaKey];
|
||||||
|
|
||||||
|
groupByValues.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -28,11 +28,13 @@ import { AppState } from 'store/reducers';
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
import { getOrderByFromParams } from '../commonUtils';
|
import { getOrderByFromParams } from '../commonUtils';
|
||||||
import {
|
import {
|
||||||
|
GetK8sEntityToAggregateAttribute,
|
||||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||||
K8sCategory,
|
K8sCategory,
|
||||||
K8sEntityToAggregateAttributeMapping,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import K8sHeader from '../K8sHeader';
|
import K8sHeader from '../K8sHeader';
|
||||||
import LoadingContainer from '../LoadingContainer';
|
import LoadingContainer from '../LoadingContainer';
|
||||||
@ -136,6 +138,11 @@ function K8sNamespacesList({
|
|||||||
}
|
}
|
||||||
}, [quickFiltersLastUpdated]);
|
}, [quickFiltersLastUpdated]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const createFiltersForSelectedRowData = (
|
const createFiltersForSelectedRowData = (
|
||||||
selectedRowData: K8sNamespacesRowData,
|
selectedRowData: K8sNamespacesRowData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -195,6 +202,8 @@ function K8sNamespacesList({
|
|||||||
queryKey: ['namespaceList', fetchGroupedByRowDataQuery],
|
queryKey: ['namespaceList', fetchGroupedByRowDataQuery],
|
||||||
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -203,8 +212,10 @@ function K8sNamespacesList({
|
|||||||
} = useGetAggregateKeys(
|
} = useGetAggregateKeys(
|
||||||
{
|
{
|
||||||
dataSource: currentQuery.builder.queryData[0].dataSource,
|
dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||||
aggregateAttribute:
|
aggregateAttribute: GetK8sEntityToAggregateAttribute(
|
||||||
K8sEntityToAggregateAttributeMapping[K8sCategory.NAMESPACES],
|
K8sCategory.NAMESPACES,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
aggregateOperator: 'noop',
|
aggregateOperator: 'noop',
|
||||||
searchText: '',
|
searchText: '',
|
||||||
tagType: '',
|
tagType: '',
|
||||||
@ -245,6 +256,8 @@ function K8sNamespacesList({
|
|||||||
queryKey: ['namespaceList', query],
|
queryKey: ['namespaceList', query],
|
||||||
enabled: !!query,
|
enabled: !!query,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const namespacesData = useMemo(() => data?.payload?.data?.records || [], [
|
const namespacesData = useMemo(() => data?.payload?.data?.records || [], [
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -122,6 +122,11 @@ export const getK8sNamespacesListColumns = (
|
|||||||
return columnsConfig as ColumnType<K8sNamespacesRowData>[];
|
return columnsConfig as ColumnType<K8sNamespacesRowData>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dotToUnder: Record<string, keyof K8sNamespacesData['meta']> = {
|
||||||
|
'k8s.namespace.name': 'k8s_namespace_name',
|
||||||
|
'k8s.cluster.name': 'k8s_cluster_name',
|
||||||
|
};
|
||||||
|
|
||||||
const getGroupByEle = (
|
const getGroupByEle = (
|
||||||
namespace: K8sNamespacesData,
|
namespace: K8sNamespacesData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -129,7 +134,13 @@ const getGroupByEle = (
|
|||||||
const groupByValues: string[] = [];
|
const groupByValues: string[] = [];
|
||||||
|
|
||||||
groupBy.forEach((group) => {
|
groupBy.forEach((group) => {
|
||||||
groupByValues.push(namespace.meta[group.key as keyof typeof namespace.meta]);
|
const rawKey = group.key as string;
|
||||||
|
|
||||||
|
// Choose mapped key if present, otherwise use rawKey
|
||||||
|
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof namespace.meta;
|
||||||
|
const value = namespace.meta[metaKey];
|
||||||
|
|
||||||
|
groupByValues.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -28,11 +28,13 @@ import { AppState } from 'store/reducers';
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
import { getOrderByFromParams } from '../commonUtils';
|
import { getOrderByFromParams } from '../commonUtils';
|
||||||
import {
|
import {
|
||||||
|
GetK8sEntityToAggregateAttribute,
|
||||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||||
K8sCategory,
|
K8sCategory,
|
||||||
K8sEntityToAggregateAttributeMapping,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import K8sHeader from '../K8sHeader';
|
import K8sHeader from '../K8sHeader';
|
||||||
import LoadingContainer from '../LoadingContainer';
|
import LoadingContainer from '../LoadingContainer';
|
||||||
@ -130,6 +132,11 @@ function K8sNodesList({
|
|||||||
}
|
}
|
||||||
}, [quickFiltersLastUpdated]);
|
}, [quickFiltersLastUpdated]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const createFiltersForSelectedRowData = (
|
const createFiltersForSelectedRowData = (
|
||||||
selectedRowData: K8sNodesRowData,
|
selectedRowData: K8sNodesRowData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -183,10 +190,15 @@ function K8sNodesList({
|
|||||||
isLoading: isLoadingGroupedByRowData,
|
isLoading: isLoadingGroupedByRowData,
|
||||||
isError: isErrorGroupedByRowData,
|
isError: isErrorGroupedByRowData,
|
||||||
refetch: fetchGroupedByRowData,
|
refetch: fetchGroupedByRowData,
|
||||||
} = useGetK8sNodesList(fetchGroupedByRowDataQuery as K8sNodesListPayload, {
|
} = useGetK8sNodesList(
|
||||||
queryKey: ['nodeList', fetchGroupedByRowDataQuery],
|
fetchGroupedByRowDataQuery as K8sNodesListPayload,
|
||||||
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
{
|
||||||
});
|
queryKey: ['nodeList', fetchGroupedByRowDataQuery],
|
||||||
|
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: groupByFiltersData,
|
data: groupByFiltersData,
|
||||||
@ -194,7 +206,10 @@ function K8sNodesList({
|
|||||||
} = useGetAggregateKeys(
|
} = useGetAggregateKeys(
|
||||||
{
|
{
|
||||||
dataSource: currentQuery.builder.queryData[0].dataSource,
|
dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||||
aggregateAttribute: K8sEntityToAggregateAttributeMapping[K8sCategory.NODES],
|
aggregateAttribute: GetK8sEntityToAggregateAttribute(
|
||||||
|
K8sCategory.NODES,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
aggregateOperator: 'noop',
|
aggregateOperator: 'noop',
|
||||||
searchText: '',
|
searchText: '',
|
||||||
tagType: '',
|
tagType: '',
|
||||||
@ -240,6 +255,8 @@ function K8sNodesList({
|
|||||||
queryKey: ['nodeList', query],
|
queryKey: ['nodeList', query],
|
||||||
enabled: !!query,
|
enabled: !!query,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const nodesData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
const nodesData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -152,6 +152,12 @@ export const getK8sNodesListColumns = (
|
|||||||
return columnsConfig as ColumnType<K8sNodesRowData>[];
|
return columnsConfig as ColumnType<K8sNodesRowData>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dotToUnder: Record<string, keyof K8sNodesData['meta']> = {
|
||||||
|
'k8s.node.name': 'k8s_node_name',
|
||||||
|
'k8s.cluster.name': 'k8s_cluster_name',
|
||||||
|
'k8s.node.uid': 'k8s_node_uid',
|
||||||
|
};
|
||||||
|
|
||||||
const getGroupByEle = (
|
const getGroupByEle = (
|
||||||
node: K8sNodesData,
|
node: K8sNodesData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -159,7 +165,14 @@ const getGroupByEle = (
|
|||||||
const groupByValues: string[] = [];
|
const groupByValues: string[] = [];
|
||||||
|
|
||||||
groupBy.forEach((group) => {
|
groupBy.forEach((group) => {
|
||||||
groupByValues.push(node.meta[group.key as keyof typeof node.meta]);
|
const rawKey = group.key as string;
|
||||||
|
|
||||||
|
// Choose mapped key if present, otherwise use rawKey
|
||||||
|
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof node.meta;
|
||||||
|
|
||||||
|
const value = node.meta[metaKey];
|
||||||
|
|
||||||
|
groupByValues.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
import { getOrderByFromParams } from '../commonUtils';
|
import { getOrderByFromParams } from '../commonUtils';
|
||||||
import {
|
import {
|
||||||
|
GetK8sEntityToAggregateAttribute,
|
||||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||||
K8sCategory,
|
K8sCategory,
|
||||||
K8sEntityToAggregateAttributeMapping,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import K8sHeader from '../K8sHeader';
|
import K8sHeader from '../K8sHeader';
|
||||||
import LoadingContainer from '../LoadingContainer';
|
import LoadingContainer from '../LoadingContainer';
|
||||||
@ -118,13 +120,21 @@ function K8sPodsList({
|
|||||||
[currentQuery?.builder?.queryData],
|
[currentQuery?.builder?.queryData],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: groupByFiltersData,
|
data: groupByFiltersData,
|
||||||
isLoading: isLoadingGroupByFilters,
|
isLoading: isLoadingGroupByFilters,
|
||||||
} = useGetAggregateKeys(
|
} = useGetAggregateKeys(
|
||||||
{
|
{
|
||||||
dataSource: currentQuery.builder.queryData[0].dataSource,
|
dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||||
aggregateAttribute: K8sEntityToAggregateAttributeMapping[K8sCategory.PODS],
|
aggregateAttribute: GetK8sEntityToAggregateAttribute(
|
||||||
|
K8sCategory.PODS,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
aggregateOperator: 'noop',
|
aggregateOperator: 'noop',
|
||||||
searchText: '',
|
searchText: '',
|
||||||
tagType: '',
|
tagType: '',
|
||||||
@ -201,6 +211,8 @@ function K8sPodsList({
|
|||||||
queryKey: ['hostList', query],
|
queryKey: ['hostList', query],
|
||||||
enabled: !!query,
|
enabled: !!query,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const createFiltersForSelectedRowData = (
|
const createFiltersForSelectedRowData = (
|
||||||
@ -255,10 +267,15 @@ function K8sPodsList({
|
|||||||
isLoading: isLoadingGroupedByRowData,
|
isLoading: isLoadingGroupedByRowData,
|
||||||
isError: isErrorGroupedByRowData,
|
isError: isErrorGroupedByRowData,
|
||||||
refetch: fetchGroupedByRowData,
|
refetch: fetchGroupedByRowData,
|
||||||
} = useGetK8sPodsList(fetchGroupedByRowDataQuery as K8sPodsListPayload, {
|
} = useGetK8sPodsList(
|
||||||
queryKey: ['hostList', fetchGroupedByRowDataQuery],
|
fetchGroupedByRowDataQuery as K8sPodsListPayload,
|
||||||
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
{
|
||||||
});
|
queryKey: ['hostList', fetchGroupedByRowDataQuery],
|
||||||
|
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
);
|
||||||
|
|
||||||
const podsData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
const podsData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
||||||
const totalCount = data?.payload?.data?.total || 0;
|
const totalCount = data?.payload?.data?.total || 0;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
import { getOrderByFromParams } from '../commonUtils';
|
import { getOrderByFromParams } from '../commonUtils';
|
||||||
import {
|
import {
|
||||||
|
GetK8sEntityToAggregateAttribute,
|
||||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||||
K8sCategory,
|
K8sCategory,
|
||||||
K8sEntityToAggregateAttributeMapping,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import K8sHeader from '../K8sHeader';
|
import K8sHeader from '../K8sHeader';
|
||||||
import LoadingContainer from '../LoadingContainer';
|
import LoadingContainer from '../LoadingContainer';
|
||||||
@ -137,6 +139,11 @@ function K8sStatefulSetsList({
|
|||||||
}
|
}
|
||||||
}, [quickFiltersLastUpdated]);
|
}, [quickFiltersLastUpdated]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const createFiltersForSelectedRowData = (
|
const createFiltersForSelectedRowData = (
|
||||||
selectedRowData: K8sStatefulSetsRowData,
|
selectedRowData: K8sStatefulSetsRowData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -196,6 +203,8 @@ function K8sStatefulSetsList({
|
|||||||
queryKey: ['statefulSetList', fetchGroupedByRowDataQuery],
|
queryKey: ['statefulSetList', fetchGroupedByRowDataQuery],
|
||||||
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -204,8 +213,10 @@ function K8sStatefulSetsList({
|
|||||||
} = useGetAggregateKeys(
|
} = useGetAggregateKeys(
|
||||||
{
|
{
|
||||||
dataSource: currentQuery.builder.queryData[0].dataSource,
|
dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||||
aggregateAttribute:
|
aggregateAttribute: GetK8sEntityToAggregateAttribute(
|
||||||
K8sEntityToAggregateAttributeMapping[K8sCategory.STATEFULSETS],
|
K8sCategory.STATEFULSETS,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
aggregateOperator: 'noop',
|
aggregateOperator: 'noop',
|
||||||
searchText: '',
|
searchText: '',
|
||||||
tagType: '',
|
tagType: '',
|
||||||
@ -251,6 +262,8 @@ function K8sStatefulSetsList({
|
|||||||
queryKey: ['statefulSetList', query],
|
queryKey: ['statefulSetList', query],
|
||||||
enabled: !!query,
|
enabled: !!query,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const statefulSetsData = useMemo(() => data?.payload?.data?.records || [], [
|
const statefulSetsData = useMemo(() => data?.payload?.data?.records || [], [
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -236,6 +236,11 @@ export const getK8sStatefulSetsListColumns = (
|
|||||||
return columnsConfig as ColumnType<K8sStatefulSetsRowData>[];
|
return columnsConfig as ColumnType<K8sStatefulSetsRowData>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dotToUnder: Record<string, keyof K8sStatefulSetsData['meta']> = {
|
||||||
|
'k8s.namespace.name': 'k8s_namespace_name',
|
||||||
|
'k8s.statefulset.name': 'k8s_statefulset_name',
|
||||||
|
};
|
||||||
|
|
||||||
const getGroupByEle = (
|
const getGroupByEle = (
|
||||||
statefulSet: K8sStatefulSetsData,
|
statefulSet: K8sStatefulSetsData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -243,9 +248,14 @@ const getGroupByEle = (
|
|||||||
const groupByValues: string[] = [];
|
const groupByValues: string[] = [];
|
||||||
|
|
||||||
groupBy.forEach((group) => {
|
groupBy.forEach((group) => {
|
||||||
groupByValues.push(
|
const rawKey = group.key as string;
|
||||||
statefulSet.meta[group.key as keyof typeof statefulSet.meta],
|
|
||||||
);
|
// Choose mapped key if present, otherwise use rawKey
|
||||||
|
const metaKey = (dotToUnder[rawKey] ??
|
||||||
|
rawKey) as keyof typeof statefulSet.meta;
|
||||||
|
const value = statefulSet.meta[metaKey];
|
||||||
|
|
||||||
|
groupByValues.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
import { getOrderByFromParams } from '../commonUtils';
|
import { getOrderByFromParams } from '../commonUtils';
|
||||||
import {
|
import {
|
||||||
|
GetK8sEntityToAggregateAttribute,
|
||||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||||
K8sCategory,
|
K8sCategory,
|
||||||
K8sEntityToAggregateAttributeMapping,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import K8sHeader from '../K8sHeader';
|
import K8sHeader from '../K8sHeader';
|
||||||
import LoadingContainer from '../LoadingContainer';
|
import LoadingContainer from '../LoadingContainer';
|
||||||
@ -137,6 +139,11 @@ function K8sVolumesList({
|
|||||||
}
|
}
|
||||||
}, [quickFiltersLastUpdated]);
|
}, [quickFiltersLastUpdated]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const createFiltersForSelectedRowData = (
|
const createFiltersForSelectedRowData = (
|
||||||
selectedRowData: K8sVolumesRowData,
|
selectedRowData: K8sVolumesRowData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -190,10 +197,15 @@ function K8sVolumesList({
|
|||||||
isLoading: isLoadingGroupedByRowData,
|
isLoading: isLoadingGroupedByRowData,
|
||||||
isError: isErrorGroupedByRowData,
|
isError: isErrorGroupedByRowData,
|
||||||
refetch: fetchGroupedByRowData,
|
refetch: fetchGroupedByRowData,
|
||||||
} = useGetK8sVolumesList(fetchGroupedByRowDataQuery as K8sVolumesListPayload, {
|
} = useGetK8sVolumesList(
|
||||||
queryKey: ['volumeList', fetchGroupedByRowDataQuery],
|
fetchGroupedByRowDataQuery as K8sVolumesListPayload,
|
||||||
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
{
|
||||||
});
|
queryKey: ['volumeList', fetchGroupedByRowDataQuery],
|
||||||
|
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: groupByFiltersData,
|
data: groupByFiltersData,
|
||||||
@ -201,7 +213,10 @@ function K8sVolumesList({
|
|||||||
} = useGetAggregateKeys(
|
} = useGetAggregateKeys(
|
||||||
{
|
{
|
||||||
dataSource: currentQuery.builder.queryData[0].dataSource,
|
dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||||
aggregateAttribute: K8sEntityToAggregateAttributeMapping[K8sCategory.NODES],
|
aggregateAttribute: GetK8sEntityToAggregateAttribute(
|
||||||
|
K8sCategory.NODES,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
),
|
||||||
aggregateOperator: 'noop',
|
aggregateOperator: 'noop',
|
||||||
searchText: '',
|
searchText: '',
|
||||||
tagType: '',
|
tagType: '',
|
||||||
@ -247,6 +262,8 @@ function K8sVolumesList({
|
|||||||
queryKey: ['volumeList', query],
|
queryKey: ['volumeList', query],
|
||||||
enabled: !!query,
|
enabled: !!query,
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
|
dotMetricsEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
const volumesData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
const volumesData = useMemo(() => data?.payload?.data?.records || [], [data]);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -142,6 +142,16 @@ export const getK8sVolumesListColumns = (
|
|||||||
return columnsConfig as ColumnType<K8sVolumesRowData>[];
|
return columnsConfig as ColumnType<K8sVolumesRowData>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dotToUnder: Record<string, keyof K8sVolumesData['meta']> = {
|
||||||
|
'k8s.namespace.name': 'k8s_namespace_name',
|
||||||
|
'k8s.node.name': 'k8s_node_name',
|
||||||
|
'k8s.pod.name': 'k8s_pod_name',
|
||||||
|
'k8s.pod.uid': 'k8s_pod_uid',
|
||||||
|
'k8s.statefulset.name': 'k8s_statefulset_name',
|
||||||
|
'k8s.cluster.name': 'k8s_cluster_name',
|
||||||
|
'k8s.persistentvolumeclaim.name': 'k8s_persistentvolumeclaim_name',
|
||||||
|
};
|
||||||
|
|
||||||
const getGroupByEle = (
|
const getGroupByEle = (
|
||||||
volume: K8sVolumesData,
|
volume: K8sVolumesData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -149,7 +159,13 @@ const getGroupByEle = (
|
|||||||
const groupByValues: string[] = [];
|
const groupByValues: string[] = [];
|
||||||
|
|
||||||
groupBy.forEach((group) => {
|
groupBy.forEach((group) => {
|
||||||
groupByValues.push(volume.meta[group.key as keyof typeof volume.meta]);
|
const rawKey = group.key as string;
|
||||||
|
|
||||||
|
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof volume.meta;
|
||||||
|
|
||||||
|
const value = volume.meta[metaKey];
|
||||||
|
|
||||||
|
groupByValues.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -299,6 +299,19 @@ export const getK8sPodsListColumns = (
|
|||||||
return updatedColumnsConfig as ColumnType<K8sPodsRowData>[];
|
return updatedColumnsConfig as ColumnType<K8sPodsRowData>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dotToUnder: Record<string, keyof K8sPodsData['meta']> = {
|
||||||
|
'k8s.cronjob.name': 'k8s_cronjob_name',
|
||||||
|
'k8s.daemonset.name': 'k8s_daemonset_name',
|
||||||
|
'k8s.deployment.name': 'k8s_deployment_name',
|
||||||
|
'k8s.job.name': 'k8s_job_name',
|
||||||
|
'k8s.namespace.name': 'k8s_namespace_name',
|
||||||
|
'k8s.node.name': 'k8s_node_name',
|
||||||
|
'k8s.pod.name': 'k8s_pod_name',
|
||||||
|
'k8s.pod.uid': 'k8s_pod_uid',
|
||||||
|
'k8s.statefulset.name': 'k8s_statefulset_name',
|
||||||
|
'k8s.cluster.name': 'k8s_cluster_name',
|
||||||
|
};
|
||||||
|
|
||||||
const getGroupByEle = (
|
const getGroupByEle = (
|
||||||
pod: K8sPodsData,
|
pod: K8sPodsData,
|
||||||
groupBy: IBuilderQuery['groupBy'],
|
groupBy: IBuilderQuery['groupBy'],
|
||||||
@ -306,7 +319,13 @@ const getGroupByEle = (
|
|||||||
const groupByValues: string[] = [];
|
const groupByValues: string[] = [];
|
||||||
|
|
||||||
groupBy.forEach((group) => {
|
groupBy.forEach((group) => {
|
||||||
groupByValues.push(pod.meta[group.key as keyof typeof pod.meta]);
|
const rawKey = group.key as string;
|
||||||
|
|
||||||
|
// Choose mapped key if present, otherwise use rawKey
|
||||||
|
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof pod.meta;
|
||||||
|
const value = pod.meta[metaKey];
|
||||||
|
|
||||||
|
groupByValues.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { TableProps } from 'antd/lib';
|
import { TableProps } from 'antd/lib';
|
||||||
import logEvent from 'api/common/logEvent';
|
import logEvent from 'api/common/logEvent';
|
||||||
import createDashboard from 'api/dashboard/create';
|
import createDashboard from 'api/v1/dashboards/create';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import { ENTITY_VERSION_V4 } from 'constants/app';
|
import { ENTITY_VERSION_V4 } from 'constants/app';
|
||||||
@ -63,6 +63,7 @@ import {
|
|||||||
import { handleContactSupport } from 'pages/Integrations/utils';
|
import { handleContactSupport } from 'pages/Integrations/utils';
|
||||||
import { useAppContext } from 'providers/App/App';
|
import { useAppContext } from 'providers/App/App';
|
||||||
import { useDashboard } from 'providers/Dashboard/Dashboard';
|
import { useDashboard } from 'providers/Dashboard/Dashboard';
|
||||||
|
import { useErrorModal } from 'providers/ErrorModalProvider';
|
||||||
import { useTimezone } from 'providers/Timezone';
|
import { useTimezone } from 'providers/Timezone';
|
||||||
import {
|
import {
|
||||||
ChangeEvent,
|
ChangeEvent,
|
||||||
@ -83,6 +84,7 @@ import {
|
|||||||
WidgetRow,
|
WidgetRow,
|
||||||
Widgets,
|
Widgets,
|
||||||
} from 'types/api/dashboard/getAll';
|
} from 'types/api/dashboard/getAll';
|
||||||
|
import APIError from 'types/api/error';
|
||||||
|
|
||||||
import DashboardTemplatesModal from './DashboardTemplates/DashboardTemplatesModal';
|
import DashboardTemplatesModal from './DashboardTemplates/DashboardTemplatesModal';
|
||||||
import ImportJSON from './ImportJSON';
|
import ImportJSON from './ImportJSON';
|
||||||
@ -226,7 +228,7 @@ function DashboardsList(): JSX.Element {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const filteredDashboards = filterDashboard(
|
const filteredDashboards = filterDashboard(
|
||||||
searchString,
|
searchString,
|
||||||
dashboardListResponse || [],
|
dashboardListResponse?.data || [],
|
||||||
);
|
);
|
||||||
if (sortOrder.columnKey === 'updatedAt') {
|
if (sortOrder.columnKey === 'updatedAt') {
|
||||||
sortDashboardsByUpdatedAt(filteredDashboards || []);
|
sortDashboardsByUpdatedAt(filteredDashboards || []);
|
||||||
@ -256,17 +258,19 @@ function DashboardsList(): JSX.Element {
|
|||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { showErrorModal } = useErrorModal();
|
||||||
|
|
||||||
const data: Data[] =
|
const data: Data[] =
|
||||||
dashboards?.map((e) => ({
|
dashboards?.map((e) => ({
|
||||||
createdAt: e.createdAt,
|
createdAt: e.createdAt,
|
||||||
description: e.data.description || '',
|
description: e.data.description || '',
|
||||||
id: e.uuid,
|
id: e.id,
|
||||||
lastUpdatedTime: e.updatedAt,
|
lastUpdatedTime: e.updatedAt,
|
||||||
name: e.data.title,
|
name: e.data.title,
|
||||||
tags: e.data.tags || [],
|
tags: e.data.tags || [],
|
||||||
key: e.uuid,
|
key: e.id,
|
||||||
createdBy: e.createdBy,
|
createdBy: e.createdBy,
|
||||||
isLocked: !!e.isLocked || false,
|
isLocked: !!e.locked || false,
|
||||||
lastUpdatedBy: e.updatedBy,
|
lastUpdatedBy: e.updatedBy,
|
||||||
image: e.data.image || Base64Icons[0],
|
image: e.data.image || Base64Icons[0],
|
||||||
variables: e.data.variables,
|
variables: e.data.variables,
|
||||||
@ -292,28 +296,20 @@ function DashboardsList(): JSX.Element {
|
|||||||
version: ENTITY_VERSION_V4,
|
version: ENTITY_VERSION_V4,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.statusCode === 200) {
|
safeNavigate(
|
||||||
safeNavigate(
|
generatePath(ROUTES.DASHBOARD, {
|
||||||
generatePath(ROUTES.DASHBOARD, {
|
dashboardId: response.data.id,
|
||||||
dashboardId: response.payload.uuid,
|
}),
|
||||||
}),
|
);
|
||||||
);
|
|
||||||
} else {
|
|
||||||
setNewDashboardState({
|
|
||||||
...newDashboardState,
|
|
||||||
loading: false,
|
|
||||||
error: true,
|
|
||||||
errorMessage: response.error || 'Something went wrong',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
showErrorModal(error as APIError);
|
||||||
setNewDashboardState({
|
setNewDashboardState({
|
||||||
...newDashboardState,
|
...newDashboardState,
|
||||||
error: true,
|
error: true,
|
||||||
errorMessage: (error as AxiosError).toString() || 'Something went Wrong',
|
errorMessage: (error as AxiosError).toString() || 'Something went Wrong',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [newDashboardState, safeNavigate, t]);
|
}, [newDashboardState, safeNavigate, showErrorModal, t]);
|
||||||
|
|
||||||
const onModalHandler = (uploadedGrafana: boolean): void => {
|
const onModalHandler = (uploadedGrafana: boolean): void => {
|
||||||
logEvent('Dashboard List: Import JSON clicked', {});
|
logEvent('Dashboard List: Import JSON clicked', {});
|
||||||
@ -327,7 +323,7 @@ function DashboardsList(): JSX.Element {
|
|||||||
const searchText = (event as React.BaseSyntheticEvent)?.target?.value || '';
|
const searchText = (event as React.BaseSyntheticEvent)?.target?.value || '';
|
||||||
const filteredDashboards = filterDashboard(
|
const filteredDashboards = filterDashboard(
|
||||||
searchText,
|
searchText,
|
||||||
dashboardListResponse || [],
|
dashboardListResponse?.data || [],
|
||||||
);
|
);
|
||||||
setDashboards(filteredDashboards);
|
setDashboards(filteredDashboards);
|
||||||
setIsFilteringDashboards(false);
|
setIsFilteringDashboards(false);
|
||||||
@ -677,7 +673,7 @@ function DashboardsList(): JSX.Element {
|
|||||||
!isUndefined(dashboardListResponse)
|
!isUndefined(dashboardListResponse)
|
||||||
) {
|
) {
|
||||||
logEvent('Dashboard List: Page visited', {
|
logEvent('Dashboard List: Page visited', {
|
||||||
number: dashboardListResponse?.length,
|
number: dashboardListResponse?.data?.length,
|
||||||
});
|
});
|
||||||
logEventCalledRef.current = true;
|
logEventCalledRef.current = true;
|
||||||
}
|
}
|
||||||
|
@ -14,19 +14,21 @@ import {
|
|||||||
UploadProps,
|
UploadProps,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import logEvent from 'api/common/logEvent';
|
import logEvent from 'api/common/logEvent';
|
||||||
import createDashboard from 'api/dashboard/create';
|
import createDashboard from 'api/v1/dashboards/create';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
import { useNotifications } from 'hooks/useNotifications';
|
||||||
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
||||||
import { getUpdatedLayout } from 'lib/dashboard/getUpdatedLayout';
|
import { getUpdatedLayout } from 'lib/dashboard/getUpdatedLayout';
|
||||||
import { ExternalLink, Github, MonitorDot, MoveRight, X } from 'lucide-react';
|
import { ExternalLink, Github, MonitorDot, MoveRight, X } from 'lucide-react';
|
||||||
|
import { useErrorModal } from 'providers/ErrorModalProvider';
|
||||||
// #TODO: Lucide will be removing brand icons like GitHub in the future. In that case, we can use Simple Icons. https://simpleicons.org/
|
// #TODO: Lucide will be removing brand icons like GitHub in the future. In that case, we can use Simple Icons. https://simpleicons.org/
|
||||||
// See more: https://github.com/lucide-icons/lucide/issues/94
|
// See more: https://github.com/lucide-icons/lucide/issues/94
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { generatePath } from 'react-router-dom';
|
import { generatePath } from 'react-router-dom';
|
||||||
import { DashboardData } from 'types/api/dashboard/getAll';
|
import { DashboardData } from 'types/api/dashboard/getAll';
|
||||||
|
import APIError from 'types/api/error';
|
||||||
|
|
||||||
function ImportJSON({
|
function ImportJSON({
|
||||||
isImportJSONModalVisible,
|
isImportJSONModalVisible,
|
||||||
@ -74,6 +76,8 @@ function ImportJSON({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { showErrorModal } = useErrorModal();
|
||||||
|
|
||||||
const onClickLoadJsonHandler = async (): Promise<void> => {
|
const onClickLoadJsonHandler = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
setDashboardCreating(true);
|
setDashboardCreating(true);
|
||||||
@ -81,11 +85,6 @@ function ImportJSON({
|
|||||||
|
|
||||||
const dashboardData = JSON.parse(editorValue) as DashboardData;
|
const dashboardData = JSON.parse(editorValue) as DashboardData;
|
||||||
|
|
||||||
// Remove uuid from the dashboard data, in all cases - empty, duplicate or any valid not duplicate uuid
|
|
||||||
if (dashboardData.uuid !== undefined) {
|
|
||||||
delete dashboardData.uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dashboardData?.layout) {
|
if (dashboardData?.layout) {
|
||||||
dashboardData.layout = getUpdatedLayout(dashboardData.layout);
|
dashboardData.layout = getUpdatedLayout(dashboardData.layout);
|
||||||
} else {
|
} else {
|
||||||
@ -97,28 +96,19 @@ function ImportJSON({
|
|||||||
uploadedGrafana,
|
uploadedGrafana,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.statusCode === 200) {
|
safeNavigate(
|
||||||
safeNavigate(
|
generatePath(ROUTES.DASHBOARD, {
|
||||||
generatePath(ROUTES.DASHBOARD, {
|
dashboardId: response.data.id,
|
||||||
dashboardId: response.payload.uuid,
|
}),
|
||||||
}),
|
);
|
||||||
);
|
logEvent('Dashboard List: New dashboard imported successfully', {
|
||||||
logEvent('Dashboard List: New dashboard imported successfully', {
|
dashboardId: response.data?.id,
|
||||||
dashboardId: response.payload?.uuid,
|
dashboardName: response.data?.data?.title,
|
||||||
dashboardName: response.payload?.data?.title,
|
});
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setIsCreateDashboardError(true);
|
|
||||||
notifications.error({
|
|
||||||
message:
|
|
||||||
response.error ||
|
|
||||||
t('something_went_wrong', {
|
|
||||||
ns: 'common',
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setDashboardCreating(false);
|
setDashboardCreating(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
showErrorModal(error as APIError);
|
||||||
setDashboardCreating(false);
|
setDashboardCreating(false);
|
||||||
setIsCreateDashboardError(true);
|
setIsCreateDashboardError(true);
|
||||||
notifications.error({
|
notifications.error({
|
||||||
|
@ -6,8 +6,7 @@ import { executeSearchQueries } from '../utils';
|
|||||||
|
|
||||||
describe('executeSearchQueries', () => {
|
describe('executeSearchQueries', () => {
|
||||||
const firstDashboard: Dashboard = {
|
const firstDashboard: Dashboard = {
|
||||||
id: 11111,
|
id: uuid(),
|
||||||
uuid: uuid(),
|
|
||||||
createdAt: '',
|
createdAt: '',
|
||||||
updatedAt: '',
|
updatedAt: '',
|
||||||
createdBy: '',
|
createdBy: '',
|
||||||
@ -18,8 +17,7 @@ describe('executeSearchQueries', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const secondDashboard: Dashboard = {
|
const secondDashboard: Dashboard = {
|
||||||
id: 22222,
|
id: uuid(),
|
||||||
uuid: uuid(),
|
|
||||||
createdAt: '',
|
createdAt: '',
|
||||||
updatedAt: '',
|
updatedAt: '',
|
||||||
createdBy: '',
|
createdBy: '',
|
||||||
@ -30,8 +28,7 @@ describe('executeSearchQueries', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const thirdDashboard: Dashboard = {
|
const thirdDashboard: Dashboard = {
|
||||||
id: 333333,
|
id: uuid(),
|
||||||
uuid: uuid(),
|
|
||||||
createdAt: '',
|
createdAt: '',
|
||||||
updatedAt: '',
|
updatedAt: '',
|
||||||
createdBy: '',
|
createdBy: '',
|
||||||
|
@ -59,7 +59,7 @@ export function DeleteButton({
|
|||||||
onClick: (e) => {
|
onClick: (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
deleteDashboardMutation.mutateAsync(undefined, {
|
deleteDashboardMutation.mutate(undefined, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
notifications.success({
|
notifications.success({
|
||||||
message: t('dashboard:delete_dashboard_success', {
|
message: t('dashboard:delete_dashboard_success', {
|
||||||
|
@ -14,7 +14,7 @@ export const generateSearchData = (
|
|||||||
|
|
||||||
dashboards.forEach((dashboard) => {
|
dashboards.forEach((dashboard) => {
|
||||||
dashboardSearchData.push({
|
dashboardSearchData.push({
|
||||||
id: dashboard.uuid,
|
id: dashboard.id,
|
||||||
title: dashboard.data.title,
|
title: dashboard.data.title,
|
||||||
description: dashboard.data.description,
|
description: dashboard.data.description,
|
||||||
tags: dashboard.data.tags || [],
|
tags: dashboard.data.tags || [],
|
||||||
|
@ -15,6 +15,8 @@ import { SuccessResponse } from 'types/api';
|
|||||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||||
import uPlot from 'uplot';
|
import uPlot from 'uplot';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
|
import { useAppContext } from '../../../providers/App/App';
|
||||||
import {
|
import {
|
||||||
getHostQueryPayload,
|
getHostQueryPayload,
|
||||||
getNodeQueryPayload,
|
getNodeQueryPayload,
|
||||||
@ -49,12 +51,23 @@ function NodeMetrics({
|
|||||||
};
|
};
|
||||||
}, [logLineTimestamp]);
|
}, [logLineTimestamp]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const queryPayloads = useMemo(() => {
|
const queryPayloads = useMemo(() => {
|
||||||
if (nodeName) {
|
if (nodeName) {
|
||||||
return getNodeQueryPayload(clusterName, nodeName, start, end);
|
return getNodeQueryPayload(
|
||||||
|
clusterName,
|
||||||
|
nodeName,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
dotMetricsEnabled,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return getHostQueryPayload(hostName, start, end);
|
return getHostQueryPayload(hostName, start, end, dotMetricsEnabled);
|
||||||
}, [nodeName, hostName, clusterName, start, end]);
|
}, [nodeName, hostName, clusterName, start, end, dotMetricsEnabled]);
|
||||||
|
|
||||||
const widgetInfo = nodeName ? nodeWidgetInfo : hostWidgetInfo;
|
const widgetInfo = nodeName ? nodeWidgetInfo : hostWidgetInfo;
|
||||||
const queries = useQueries(
|
const queries = useQueries(
|
||||||
|
@ -8,6 +8,7 @@ import { useResizeObserver } from 'hooks/useDimensions';
|
|||||||
import { GetMetricQueryRange } from 'lib/dashboard/getQueryResults';
|
import { GetMetricQueryRange } from 'lib/dashboard/getQueryResults';
|
||||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
|
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
|
||||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
|
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
|
||||||
|
import { useAppContext } from 'providers/App/App';
|
||||||
import { useTimezone } from 'providers/Timezone';
|
import { useTimezone } from 'providers/Timezone';
|
||||||
import { useMemo, useRef } from 'react';
|
import { useMemo, useRef } from 'react';
|
||||||
import { useQueries, UseQueryResult } from 'react-query';
|
import { useQueries, UseQueryResult } from 'react-query';
|
||||||
@ -15,6 +16,7 @@ import { SuccessResponse } from 'types/api';
|
|||||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||||
import uPlot from 'uplot';
|
import uPlot from 'uplot';
|
||||||
|
|
||||||
|
import { FeatureKeys } from '../../../constants/features';
|
||||||
import { getPodQueryPayload, podWidgetInfo } from './constants';
|
import { getPodQueryPayload, podWidgetInfo } from './constants';
|
||||||
|
|
||||||
function PodMetrics({
|
function PodMetrics({
|
||||||
@ -41,9 +43,15 @@ function PodMetrics({
|
|||||||
verticalLineTimestamp: logTimestamp.unix(),
|
verticalLineTimestamp: logTimestamp.unix(),
|
||||||
};
|
};
|
||||||
}, [logLineTimestamp]);
|
}, [logLineTimestamp]);
|
||||||
|
|
||||||
|
const { featureFlags } = useAppContext();
|
||||||
|
const dotMetricsEnabled =
|
||||||
|
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||||
|
?.active || false;
|
||||||
|
|
||||||
const queryPayloads = useMemo(
|
const queryPayloads = useMemo(
|
||||||
() => getPodQueryPayload(clusterName, podName, start, end),
|
() => getPodQueryPayload(clusterName, podName, start, end, dotMetricsEnabled),
|
||||||
[clusterName, end, podName, start],
|
[clusterName, end, podName, start, dotMetricsEnabled],
|
||||||
);
|
);
|
||||||
const queries = useQueries(
|
const queries = useQueries(
|
||||||
queryPayloads.map((payload) => ({
|
queryPayloads.map((payload) => ({
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -21,8 +21,10 @@ import { FORBID_DOM_PURIFY_TAGS } from 'utils/app';
|
|||||||
|
|
||||||
import { DataType } from '../TableView';
|
import { DataType } from '../TableView';
|
||||||
import {
|
import {
|
||||||
|
escapeHtml,
|
||||||
filterKeyForField,
|
filterKeyForField,
|
||||||
jsonToDataNodes,
|
jsonToDataNodes,
|
||||||
|
parseFieldValue,
|
||||||
recursiveParseJSON,
|
recursiveParseJSON,
|
||||||
removeEscapeCharacters,
|
removeEscapeCharacters,
|
||||||
unescapeString,
|
unescapeString,
|
||||||
@ -85,7 +87,7 @@ export function TableViewActions(
|
|||||||
record.field === 'body'
|
record.field === 'body'
|
||||||
? {
|
? {
|
||||||
__html: convert.toHtml(
|
__html: convert.toHtml(
|
||||||
dompurify.sanitize(unescapeString(record.value), {
|
dompurify.sanitize(unescapeString(escapeHtml(record.value)), {
|
||||||
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
|
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
@ -155,7 +157,11 @@ export function TableViewActions(
|
|||||||
<ArrowDownToDot size={14} style={{ transform: 'rotate(90deg)' }} />
|
<ArrowDownToDot size={14} style={{ transform: 'rotate(90deg)' }} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
onClick={onClickHandler(OPERATORS['='], fieldFilterKey, fieldData.value)}
|
onClick={onClickHandler(
|
||||||
|
OPERATORS['='],
|
||||||
|
fieldFilterKey,
|
||||||
|
parseFieldValue(fieldData.value),
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title="Filter out value">
|
<Tooltip title="Filter out value">
|
||||||
@ -171,7 +177,7 @@ export function TableViewActions(
|
|||||||
onClick={onClickHandler(
|
onClick={onClickHandler(
|
||||||
OPERATORS['!='],
|
OPERATORS['!='],
|
||||||
fieldFilterKey,
|
fieldFilterKey,
|
||||||
fieldData.value,
|
parseFieldValue(fieldData.value),
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
@ -259,6 +259,24 @@ export const getDataTypes = (value: unknown): DataTypes => {
|
|||||||
return determineType(value);
|
return determineType(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// prevent html rendering in the value
|
||||||
|
export const escapeHtml = (unsafe: string): string =>
|
||||||
|
unsafe
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''');
|
||||||
|
|
||||||
|
// parse field value to remove escaping characters
|
||||||
|
export const parseFieldValue = (value: string): string => {
|
||||||
|
try {
|
||||||
|
return JSON.parse(value);
|
||||||
|
} catch (error) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// now we do not want to render colors everywhere like in tooltip and monaco editor hence we remove such codes to make
|
// now we do not want to render colors everywhere like in tooltip and monaco editor hence we remove such codes to make
|
||||||
// the log line readable
|
// the log line readable
|
||||||
export const removeEscapeCharacters = (str: string): string =>
|
export const removeEscapeCharacters = (str: string): string =>
|
||||||
|
@ -28,16 +28,12 @@ import LogsExplorerTable from 'container/LogsExplorerTable';
|
|||||||
import { useOptionsMenu } from 'container/OptionsMenu';
|
import { useOptionsMenu } from 'container/OptionsMenu';
|
||||||
import TimeSeriesView from 'container/TimeSeriesView/TimeSeriesView';
|
import TimeSeriesView from 'container/TimeSeriesView/TimeSeriesView';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
|
|
||||||
import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils';
|
|
||||||
import { useCopyLogLink } from 'hooks/logs/useCopyLogLink';
|
import { useCopyLogLink } from 'hooks/logs/useCopyLogLink';
|
||||||
import { useGetExplorerQueryRange } from 'hooks/queryBuilder/useGetExplorerQueryRange';
|
import { useGetExplorerQueryRange } from 'hooks/queryBuilder/useGetExplorerQueryRange';
|
||||||
import { useGetPanelTypesQueryParam } from 'hooks/queryBuilder/useGetPanelTypesQueryParam';
|
import { useGetPanelTypesQueryParam } from 'hooks/queryBuilder/useGetPanelTypesQueryParam';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import useAxiosError from 'hooks/useAxiosError';
|
|
||||||
import useClickOutside from 'hooks/useClickOutside';
|
import useClickOutside from 'hooks/useClickOutside';
|
||||||
import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange';
|
import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange';
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
|
||||||
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
||||||
import useUrlQueryData from 'hooks/useUrlQueryData';
|
import useUrlQueryData from 'hooks/useUrlQueryData';
|
||||||
import { FlatLogData } from 'lib/logs/flatLogData';
|
import { FlatLogData } from 'lib/logs/flatLogData';
|
||||||
@ -98,7 +94,6 @@ function LogsExplorerViews({
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
chartQueryKeyRef: MutableRefObject<any>;
|
chartQueryKeyRef: MutableRefObject<any>;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const { notifications } = useNotifications();
|
|
||||||
const { safeNavigate } = useSafeNavigate();
|
const { safeNavigate } = useSafeNavigate();
|
||||||
|
|
||||||
// this is to respect the panel type present in the URL rather than defaulting it to list always.
|
// this is to respect the panel type present in the URL rather than defaulting it to list always.
|
||||||
@ -141,8 +136,6 @@ function LogsExplorerViews({
|
|||||||
const [queryId, setQueryId] = useState<string>(v4());
|
const [queryId, setQueryId] = useState<string>(v4());
|
||||||
const [queryStats, setQueryStats] = useState<WsDataEvent>();
|
const [queryStats, setQueryStats] = useState<WsDataEvent>();
|
||||||
|
|
||||||
const handleAxisError = useAxiosError();
|
|
||||||
|
|
||||||
const listQuery = useMemo(() => {
|
const listQuery = useMemo(() => {
|
||||||
if (!stagedQuery || stagedQuery.builder.queryData.length < 1) return null;
|
if (!stagedQuery || stagedQuery.builder.queryData.length < 1) return null;
|
||||||
|
|
||||||
@ -396,11 +389,6 @@ function LogsExplorerViews({
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [data?.payload]);
|
}, [data?.payload]);
|
||||||
|
|
||||||
const {
|
|
||||||
mutate: updateDashboard,
|
|
||||||
isLoading: isUpdateDashboardLoading,
|
|
||||||
} = useUpdateDashboard();
|
|
||||||
|
|
||||||
const getUpdatedQueryForExport = useCallback((): Query => {
|
const getUpdatedQueryForExport = useCallback((): Query => {
|
||||||
const updatedQuery = cloneDeep(currentQuery);
|
const updatedQuery = cloneDeep(currentQuery);
|
||||||
|
|
||||||
@ -424,68 +412,22 @@ function LogsExplorerViews({
|
|||||||
? getUpdatedQueryForExport()
|
? getUpdatedQueryForExport()
|
||||||
: exportDefaultQuery;
|
: exportDefaultQuery;
|
||||||
|
|
||||||
const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery(
|
|
||||||
dashboard,
|
|
||||||
query,
|
|
||||||
widgetId,
|
|
||||||
panelTypeParam,
|
|
||||||
options.selectColumns,
|
|
||||||
);
|
|
||||||
|
|
||||||
logEvent('Logs Explorer: Add to dashboard successful', {
|
logEvent('Logs Explorer: Add to dashboard successful', {
|
||||||
panelType,
|
panelType,
|
||||||
isNewDashboard,
|
isNewDashboard,
|
||||||
dashboardName: dashboard?.data?.title,
|
dashboardName: dashboard?.data?.title,
|
||||||
});
|
});
|
||||||
|
|
||||||
updateDashboard(updatedDashboard, {
|
const dashboardEditView = generateExportToDashboardLink({
|
||||||
onSuccess: (data) => {
|
query,
|
||||||
if (data.error) {
|
panelType: panelTypeParam,
|
||||||
const message =
|
dashboardId: dashboard.id,
|
||||||
data.error === 'feature usage exceeded' ? (
|
widgetId,
|
||||||
<span>
|
|
||||||
Panel limit exceeded for {DataSource.LOGS} in community edition. Please
|
|
||||||
checkout our paid plans{' '}
|
|
||||||
<a
|
|
||||||
href="https://signoz.io/pricing/?utm_source=product&utm_medium=dashboard-limit"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
here
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
data.error
|
|
||||||
);
|
|
||||||
notifications.error({
|
|
||||||
message,
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dashboardEditView = generateExportToDashboardLink({
|
|
||||||
query,
|
|
||||||
panelType: panelTypeParam,
|
|
||||||
dashboardId: data.payload?.uuid || '',
|
|
||||||
widgetId,
|
|
||||||
});
|
|
||||||
|
|
||||||
safeNavigate(dashboardEditView);
|
|
||||||
},
|
|
||||||
onError: handleAxisError,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
safeNavigate(dashboardEditView);
|
||||||
},
|
},
|
||||||
[
|
[getUpdatedQueryForExport, exportDefaultQuery, safeNavigate, panelType],
|
||||||
getUpdatedQueryForExport,
|
|
||||||
exportDefaultQuery,
|
|
||||||
options.selectColumns,
|
|
||||||
safeNavigate,
|
|
||||||
notifications,
|
|
||||||
panelType,
|
|
||||||
updateDashboard,
|
|
||||||
handleAxisError,
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -811,7 +753,6 @@ function LogsExplorerViews({
|
|||||||
<ExplorerOptionWrapper
|
<ExplorerOptionWrapper
|
||||||
disabled={!stagedQuery}
|
disabled={!stagedQuery}
|
||||||
query={exportDefaultQuery}
|
query={exportDefaultQuery}
|
||||||
isLoading={isUpdateDashboardLoading}
|
|
||||||
onExport={handleExport}
|
onExport={handleExport}
|
||||||
sourcepage={DataSource.LOGS}
|
sourcepage={DataSource.LOGS}
|
||||||
/>
|
/>
|
||||||
|
@ -21,6 +21,7 @@ export const databaseCallsRPS = ({
|
|||||||
servicename,
|
servicename,
|
||||||
legend,
|
legend,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
|
dotMetricsEnabled,
|
||||||
}: DatabaseCallsRPSProps): QueryBuilderData => {
|
}: DatabaseCallsRPSProps): QueryBuilderData => {
|
||||||
const autocompleteData: BaseAutocompleteData[] = [
|
const autocompleteData: BaseAutocompleteData[] = [
|
||||||
{
|
{
|
||||||
@ -34,7 +35,7 @@ export const databaseCallsRPS = ({
|
|||||||
{
|
{
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
key: 'db_system',
|
key: dotMetricsEnabled ? WidgetKeys.Db_system : WidgetKeys.Db_system_norm,
|
||||||
type: 'tag',
|
type: 'tag',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -43,7 +44,9 @@ export const databaseCallsRPS = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Resource,
|
type: MetricsType.Resource,
|
||||||
@ -75,6 +78,7 @@ export const databaseCallsRPS = ({
|
|||||||
export const databaseCallsAvgDuration = ({
|
export const databaseCallsAvgDuration = ({
|
||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
|
dotMetricsEnabled,
|
||||||
}: DatabaseCallProps): QueryBuilderData => {
|
}: DatabaseCallProps): QueryBuilderData => {
|
||||||
const autocompleteDataA: BaseAutocompleteData = {
|
const autocompleteDataA: BaseAutocompleteData = {
|
||||||
key: WidgetKeys.SignozDbLatencySum,
|
key: WidgetKeys.SignozDbLatencySum,
|
||||||
@ -93,7 +97,9 @@ export const databaseCallsAvgDuration = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Resource,
|
type: MetricsType.Resource,
|
||||||
|
@ -33,6 +33,7 @@ export const externalCallErrorPercent = ({
|
|||||||
servicename,
|
servicename,
|
||||||
legend,
|
legend,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
|
dotMetricsEnabled,
|
||||||
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
|
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
|
||||||
const autocompleteDataA: BaseAutocompleteData = {
|
const autocompleteDataA: BaseAutocompleteData = {
|
||||||
key: WidgetKeys.SignozExternalCallLatencyCount,
|
key: WidgetKeys.SignozExternalCallLatencyCount,
|
||||||
@ -51,7 +52,9 @@ export const externalCallErrorPercent = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Resource,
|
type: MetricsType.Resource,
|
||||||
@ -62,7 +65,7 @@ export const externalCallErrorPercent = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.StatusCode,
|
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
|
||||||
dataType: DataTypes.Int64,
|
dataType: DataTypes.Int64,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Tag,
|
type: MetricsType.Tag,
|
||||||
@ -76,7 +79,9 @@ export const externalCallErrorPercent = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Resource,
|
type: MetricsType.Resource,
|
||||||
@ -121,6 +126,7 @@ export const externalCallErrorPercent = ({
|
|||||||
export const externalCallDuration = ({
|
export const externalCallDuration = ({
|
||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
|
dotMetricsEnabled,
|
||||||
}: ExternalCallProps): QueryBuilderData => {
|
}: ExternalCallProps): QueryBuilderData => {
|
||||||
const autocompleteDataA: BaseAutocompleteData = {
|
const autocompleteDataA: BaseAutocompleteData = {
|
||||||
dataType: DataTypes.Float64,
|
dataType: DataTypes.Float64,
|
||||||
@ -144,7 +150,9 @@ export const externalCallDuration = ({
|
|||||||
key: {
|
key: {
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
type: MetricsType.Resource,
|
type: MetricsType.Resource,
|
||||||
},
|
},
|
||||||
op: OPERATORS.IN,
|
op: OPERATORS.IN,
|
||||||
@ -184,6 +192,7 @@ export const externalCallRpsByAddress = ({
|
|||||||
servicename,
|
servicename,
|
||||||
legend,
|
legend,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
|
dotMetricsEnabled,
|
||||||
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
|
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
|
||||||
const autocompleteData: BaseAutocompleteData[] = [
|
const autocompleteData: BaseAutocompleteData[] = [
|
||||||
{
|
{
|
||||||
@ -200,7 +209,9 @@ export const externalCallRpsByAddress = ({
|
|||||||
key: {
|
key: {
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
type: MetricsType.Resource,
|
type: MetricsType.Resource,
|
||||||
},
|
},
|
||||||
op: OPERATORS.IN,
|
op: OPERATORS.IN,
|
||||||
@ -231,6 +242,7 @@ export const externalCallDurationByAddress = ({
|
|||||||
servicename,
|
servicename,
|
||||||
legend,
|
legend,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
|
dotMetricsEnabled,
|
||||||
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
|
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
|
||||||
const autocompleteDataA: BaseAutocompleteData = {
|
const autocompleteDataA: BaseAutocompleteData = {
|
||||||
dataType: DataTypes.Float64,
|
dataType: DataTypes.Float64,
|
||||||
@ -253,7 +265,9 @@ export const externalCallDurationByAddress = ({
|
|||||||
key: {
|
key: {
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
type: MetricsType.Resource,
|
type: MetricsType.Resource,
|
||||||
},
|
},
|
||||||
op: OPERATORS.IN,
|
op: OPERATORS.IN,
|
||||||
|
@ -37,10 +37,18 @@ export const latency = ({
|
|||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
isSpanMetricEnable = false,
|
isSpanMetricEnable = false,
|
||||||
topLevelOperationsRoute,
|
topLevelOperationsRoute,
|
||||||
|
dotMetricsEnabled,
|
||||||
}: LatencyProps): QueryBuilderData => {
|
}: LatencyProps): QueryBuilderData => {
|
||||||
|
const signozLatencyBucketMetrics = dotMetricsEnabled
|
||||||
|
? WidgetKeys.Signoz_latency_bucket
|
||||||
|
: WidgetKeys.Signoz_latency_bucket_norm;
|
||||||
|
|
||||||
|
const signozMetricsServiceName = dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm;
|
||||||
const newAutoCompleteData: BaseAutocompleteData = {
|
const newAutoCompleteData: BaseAutocompleteData = {
|
||||||
key: isSpanMetricEnable
|
key: isSpanMetricEnable
|
||||||
? WidgetKeys.Signoz_latency_bucket
|
? signozLatencyBucketMetrics
|
||||||
: WidgetKeys.DurationNano,
|
: WidgetKeys.DurationNano,
|
||||||
dataType: DataTypes.Float64,
|
dataType: DataTypes.Float64,
|
||||||
isColumn: true,
|
isColumn: true,
|
||||||
@ -53,7 +61,7 @@ export const latency = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: isSpanMetricEnable ? WidgetKeys.Service_name : WidgetKeys.ServiceName,
|
key: isSpanMetricEnable ? signozMetricsServiceName : WidgetKeys.ServiceName,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
type: isSpanMetricEnable ? MetricsType.Resource : MetricsType.Tag,
|
type: isSpanMetricEnable ? MetricsType.Resource : MetricsType.Tag,
|
||||||
isColumn: !isSpanMetricEnable,
|
isColumn: !isSpanMetricEnable,
|
||||||
@ -295,23 +303,30 @@ export const apDexMetricsQueryBuilderQueries = ({
|
|||||||
threashold,
|
threashold,
|
||||||
delta,
|
delta,
|
||||||
metricsBuckets,
|
metricsBuckets,
|
||||||
|
dotMetricsEnabled,
|
||||||
}: ApDexMetricsQueryBuilderQueriesProps): QueryBuilderData => {
|
}: ApDexMetricsQueryBuilderQueriesProps): QueryBuilderData => {
|
||||||
const autoCompleteDataA: BaseAutocompleteData = {
|
const autoCompleteDataA: BaseAutocompleteData = {
|
||||||
key: WidgetKeys.SignozLatencyCount,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.SignozLatencyCount
|
||||||
|
: WidgetKeys.SignozLatencyCountNorm,
|
||||||
dataType: DataTypes.Float64,
|
dataType: DataTypes.Float64,
|
||||||
isColumn: true,
|
isColumn: true,
|
||||||
type: '',
|
type: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
const autoCompleteDataB: BaseAutocompleteData = {
|
const autoCompleteDataB: BaseAutocompleteData = {
|
||||||
key: WidgetKeys.Signoz_latency_bucket,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Signoz_latency_bucket
|
||||||
|
: WidgetKeys.Signoz_latency_bucket_norm,
|
||||||
dataType: DataTypes.Float64,
|
dataType: DataTypes.Float64,
|
||||||
isColumn: true,
|
isColumn: true,
|
||||||
type: '',
|
type: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
const autoCompleteDataC: BaseAutocompleteData = {
|
const autoCompleteDataC: BaseAutocompleteData = {
|
||||||
key: WidgetKeys.Signoz_latency_bucket,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Signoz_latency_bucket
|
||||||
|
: WidgetKeys.Signoz_latency_bucket_norm,
|
||||||
dataType: DataTypes.Float64,
|
dataType: DataTypes.Float64,
|
||||||
isColumn: true,
|
isColumn: true,
|
||||||
type: '',
|
type: '',
|
||||||
@ -321,7 +336,9 @@ export const apDexMetricsQueryBuilderQueries = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Tag,
|
type: MetricsType.Tag,
|
||||||
@ -347,7 +364,7 @@ export const apDexMetricsQueryBuilderQueries = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.StatusCode,
|
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Tag,
|
type: MetricsType.Tag,
|
||||||
@ -369,7 +386,9 @@ export const apDexMetricsQueryBuilderQueries = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Tag,
|
type: MetricsType.Tag,
|
||||||
@ -406,7 +425,7 @@ export const apDexMetricsQueryBuilderQueries = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.StatusCode,
|
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Tag,
|
type: MetricsType.Tag,
|
||||||
@ -417,7 +436,9 @@ export const apDexMetricsQueryBuilderQueries = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Tag,
|
type: MetricsType.Tag,
|
||||||
@ -482,10 +503,13 @@ export const operationPerSec = ({
|
|||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
topLevelOperations,
|
topLevelOperations,
|
||||||
|
dotMetricsEnabled,
|
||||||
}: OperationPerSecProps): QueryBuilderData => {
|
}: OperationPerSecProps): QueryBuilderData => {
|
||||||
const autocompleteData: BaseAutocompleteData[] = [
|
const autocompleteData: BaseAutocompleteData[] = [
|
||||||
{
|
{
|
||||||
key: WidgetKeys.SignozLatencyCount,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.SignozLatencyCount
|
||||||
|
: WidgetKeys.SignozLatencyCountNorm,
|
||||||
dataType: DataTypes.Float64,
|
dataType: DataTypes.Float64,
|
||||||
isColumn: true,
|
isColumn: true,
|
||||||
type: '',
|
type: '',
|
||||||
@ -497,7 +521,9 @@ export const operationPerSec = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Resource,
|
type: MetricsType.Resource,
|
||||||
@ -540,6 +566,7 @@ export const errorPercentage = ({
|
|||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
topLevelOperations,
|
topLevelOperations,
|
||||||
|
dotMetricsEnabled,
|
||||||
}: OperationPerSecProps): QueryBuilderData => {
|
}: OperationPerSecProps): QueryBuilderData => {
|
||||||
const autocompleteDataA: BaseAutocompleteData = {
|
const autocompleteDataA: BaseAutocompleteData = {
|
||||||
key: WidgetKeys.SignozCallsTotal,
|
key: WidgetKeys.SignozCallsTotal,
|
||||||
@ -560,7 +587,9 @@ export const errorPercentage = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Resource,
|
type: MetricsType.Resource,
|
||||||
@ -582,7 +611,9 @@ export const errorPercentage = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.StatusCode,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.StatusCodeNorm,
|
||||||
dataType: DataTypes.Int64,
|
dataType: DataTypes.Int64,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Tag,
|
type: MetricsType.Tag,
|
||||||
@ -597,7 +628,9 @@ export const errorPercentage = ({
|
|||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: {
|
key: {
|
||||||
key: WidgetKeys.Service_name,
|
key: dotMetricsEnabled
|
||||||
|
? WidgetKeys.Service_name
|
||||||
|
: WidgetKeys.Service_name_norm,
|
||||||
dataType: DataTypes.String,
|
dataType: DataTypes.String,
|
||||||
isColumn: false,
|
isColumn: false,
|
||||||
type: MetricsType.Resource,
|
type: MetricsType.Resource,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user