mirror of
https://github.com/SigNoz/signoz.git
synced 2026-02-21 08:03:36 +00:00
Compare commits
53 Commits
fix/remove
...
merge-json
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51bd760d9a | ||
|
|
2a492cc783 | ||
|
|
24afdad36c | ||
|
|
5d20019207 | ||
|
|
1963d5811d | ||
|
|
15cfccad74 | ||
|
|
a0399560e3 | ||
|
|
265e337d5c | ||
|
|
bb8c874755 | ||
|
|
13cbe03d64 | ||
|
|
93621c29b7 | ||
|
|
2c691b5a75 | ||
|
|
cd7e1bb114 | ||
|
|
a1d2ec8b8a | ||
|
|
8bbafb52d5 | ||
|
|
075cfab463 | ||
|
|
86bccaac0c | ||
|
|
de1aac63c0 | ||
|
|
14fe8745b5 | ||
|
|
4013c7ee03 | ||
|
|
0d34360e0b | ||
|
|
d204c89dec | ||
|
|
8dd33c1ab7 | ||
|
|
8e5c3d5ae1 | ||
|
|
d45bb52f33 | ||
|
|
e71818292d | ||
|
|
37557f7f24 | ||
|
|
27ff102660 | ||
|
|
cb2aa4cffd | ||
|
|
58d1d84ec7 | ||
|
|
d8e116a7bc | ||
|
|
6a48bdc37e | ||
|
|
ffb62432f8 | ||
|
|
57c51f070c | ||
|
|
36becfc7a2 | ||
|
|
8e71de09f3 | ||
|
|
56de92de73 | ||
|
|
62b10f8e77 | ||
|
|
20b53d7856 | ||
|
|
8f2c506304 | ||
|
|
7b5b9027dd | ||
|
|
b77f97fcb7 | ||
|
|
62942a4162 | ||
|
|
349bbbbf1d | ||
|
|
1966a7a5f6 | ||
|
|
a4eed9ff13 | ||
|
|
24d1ee33b5 | ||
|
|
3402203021 | ||
|
|
e8e4897cc8 | ||
|
|
96fb88aaee | ||
|
|
5a00e6c2cd | ||
|
|
e2500cff7d | ||
|
|
4864c3bc37 |
@@ -92,19 +92,6 @@ components:
|
||||
tokenType:
|
||||
type: string
|
||||
type: object
|
||||
AuthtypesGettableTransaction:
|
||||
properties:
|
||||
authorized:
|
||||
type: boolean
|
||||
object:
|
||||
$ref: '#/components/schemas/AuthtypesObject'
|
||||
relation:
|
||||
type: string
|
||||
required:
|
||||
- relation
|
||||
- object
|
||||
- authorized
|
||||
type: object
|
||||
AuthtypesGoogleConfig:
|
||||
properties:
|
||||
allowedGroups:
|
||||
@@ -130,8 +117,6 @@ components:
|
||||
serviceAccountJson:
|
||||
type: string
|
||||
type: object
|
||||
AuthtypesName:
|
||||
type: object
|
||||
AuthtypesOIDCConfig:
|
||||
properties:
|
||||
claimMapping:
|
||||
@@ -149,16 +134,6 @@ components:
|
||||
issuerAlias:
|
||||
type: string
|
||||
type: object
|
||||
AuthtypesObject:
|
||||
properties:
|
||||
resource:
|
||||
$ref: '#/components/schemas/AuthtypesResource'
|
||||
selector:
|
||||
$ref: '#/components/schemas/AuthtypesSelector'
|
||||
required:
|
||||
- resource
|
||||
- selector
|
||||
type: object
|
||||
AuthtypesOrgSessionContext:
|
||||
properties:
|
||||
authNSupport:
|
||||
@@ -196,16 +171,6 @@ components:
|
||||
refreshToken:
|
||||
type: string
|
||||
type: object
|
||||
AuthtypesResource:
|
||||
properties:
|
||||
name:
|
||||
$ref: '#/components/schemas/AuthtypesName'
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- type
|
||||
type: object
|
||||
AuthtypesRoleMapping:
|
||||
properties:
|
||||
defaultRole:
|
||||
@@ -231,8 +196,6 @@ components:
|
||||
samlIdp:
|
||||
type: string
|
||||
type: object
|
||||
AuthtypesSelector:
|
||||
type: object
|
||||
AuthtypesSessionContext:
|
||||
properties:
|
||||
exists:
|
||||
@@ -243,18 +206,6 @@ components:
|
||||
nullable: true
|
||||
type: array
|
||||
type: object
|
||||
AuthtypesTransaction:
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
object:
|
||||
$ref: '#/components/schemas/AuthtypesObject'
|
||||
relation:
|
||||
type: string
|
||||
required:
|
||||
- relation
|
||||
- object
|
||||
type: object
|
||||
AuthtypesUpdateableAuthDomain:
|
||||
properties:
|
||||
config:
|
||||
@@ -1662,56 +1613,6 @@ components:
|
||||
status:
|
||||
type: string
|
||||
type: object
|
||||
RoletypesGettableResources:
|
||||
properties:
|
||||
relations:
|
||||
additionalProperties:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
nullable: true
|
||||
type: object
|
||||
resources:
|
||||
items:
|
||||
$ref: '#/components/schemas/AuthtypesResource'
|
||||
nullable: true
|
||||
type: array
|
||||
required:
|
||||
- resources
|
||||
- relations
|
||||
type: object
|
||||
RoletypesPatchableObjects:
|
||||
properties:
|
||||
additions:
|
||||
items:
|
||||
$ref: '#/components/schemas/AuthtypesObject'
|
||||
nullable: true
|
||||
type: array
|
||||
deletions:
|
||||
items:
|
||||
$ref: '#/components/schemas/AuthtypesObject'
|
||||
nullable: true
|
||||
type: array
|
||||
required:
|
||||
- additions
|
||||
- deletions
|
||||
type: object
|
||||
RoletypesPatchableRole:
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
required:
|
||||
- description
|
||||
type: object
|
||||
RoletypesPostableRole:
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
RoletypesRole:
|
||||
properties:
|
||||
createdAt:
|
||||
@@ -1730,11 +1631,6 @@ components:
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- description
|
||||
- type
|
||||
- orgId
|
||||
type: object
|
||||
TelemetrytypesFieldContext:
|
||||
enum:
|
||||
@@ -2126,41 +2022,6 @@ info:
|
||||
version: ""
|
||||
openapi: 3.0.3
|
||||
paths:
|
||||
/api/v1/authz/check:
|
||||
post:
|
||||
deprecated: false
|
||||
description: Checks if the authenticated user has permissions for given transactions
|
||||
operationId: AuthzCheck
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/components/schemas/AuthtypesTransaction'
|
||||
type: array
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/components/schemas/AuthtypesGettableTransaction'
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
type: object
|
||||
description: OK
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
summary: Check permissions
|
||||
tags:
|
||||
- authz
|
||||
/api/v1/changePassword/{id}:
|
||||
post:
|
||||
deprecated: false
|
||||
@@ -3990,11 +3851,6 @@ paths:
|
||||
deprecated: false
|
||||
description: This endpoint creates a role
|
||||
operationId: CreateRole
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RoletypesPostableRole'
|
||||
responses:
|
||||
"201":
|
||||
content:
|
||||
@@ -4007,12 +3863,6 @@ paths:
|
||||
type: string
|
||||
type: object
|
||||
description: Created
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
@@ -4025,30 +3875,12 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"409":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Conflict
|
||||
"451":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unavailable For Legal Reasons
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
"501":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Implemented
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
@@ -4087,30 +3919,12 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"451":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unavailable For Legal Reasons
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
"501":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Implemented
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
@@ -4177,11 +3991,6 @@ paths:
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RoletypesPatchableRole'
|
||||
responses:
|
||||
"204":
|
||||
content:
|
||||
@@ -4201,30 +4010,12 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"451":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unavailable For Legal Reasons
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
"501":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Implemented
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
@@ -4233,202 +4024,6 @@ paths:
|
||||
summary: Patch role
|
||||
tags:
|
||||
- role
|
||||
/api/v1/roles/{id}/relation/{relation}/objects:
|
||||
get:
|
||||
deprecated: false
|
||||
description: Gets all objects connected to the specified role via a given relation
|
||||
type
|
||||
operationId: GetObjects
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: relation
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/components/schemas/AuthtypesObject'
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
type: object
|
||||
description: OK
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"451":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unavailable For Legal Reasons
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
"501":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Implemented
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Get objects for a role by relation
|
||||
tags:
|
||||
- role
|
||||
patch:
|
||||
deprecated: false
|
||||
description: Patches the objects connected to the specified role via a given
|
||||
relation type
|
||||
operationId: PatchObjects
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: relation
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RoletypesPatchableObjects'
|
||||
responses:
|
||||
"204":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
description: No Content
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"451":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unavailable For Legal Reasons
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
"501":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Implemented
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Patch objects for a role by relation
|
||||
tags:
|
||||
- role
|
||||
/api/v1/roles/resources:
|
||||
get:
|
||||
deprecated: false
|
||||
description: Gets all the available resources for role assignment
|
||||
operationId: GetResources
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/RoletypesGettableResources'
|
||||
status:
|
||||
type: string
|
||||
type: object
|
||||
description: OK
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Get resources
|
||||
tags:
|
||||
- role
|
||||
/api/v1/user:
|
||||
get:
|
||||
deprecated: false
|
||||
|
||||
@@ -62,6 +62,10 @@ func (provider *provider) Stop(ctx context.Context) error {
|
||||
return provider.openfgaServer.Stop(ctx)
|
||||
}
|
||||
|
||||
func (provider *provider) Check(ctx context.Context, tuple *openfgav1.TupleKey) error {
|
||||
return provider.openfgaServer.Check(ctx, tuple)
|
||||
}
|
||||
|
||||
func (provider *provider) CheckWithTupleCreation(ctx context.Context, claims authtypes.Claims, orgID valuer.UUID, relation authtypes.Relation, typeable authtypes.Typeable, selectors []authtypes.Selector, roleSelectors []authtypes.Selector) error {
|
||||
return provider.openfgaServer.CheckWithTupleCreation(ctx, claims, orgID, relation, typeable, selectors, roleSelectors)
|
||||
}
|
||||
@@ -70,8 +74,8 @@ func (provider *provider) CheckWithTupleCreationWithoutClaims(ctx context.Contex
|
||||
return provider.openfgaServer.CheckWithTupleCreationWithoutClaims(ctx, orgID, relation, typeable, selectors, roleSelectors)
|
||||
}
|
||||
|
||||
func (provider *provider) BatchCheck(ctx context.Context, tupleReq map[string]*openfgav1.TupleKey) (map[string]*authtypes.TupleKeyAuthorization, error) {
|
||||
return provider.openfgaServer.BatchCheck(ctx, tupleReq)
|
||||
func (provider *provider) BatchCheck(ctx context.Context, tuples []*openfgav1.TupleKey) error {
|
||||
return provider.openfgaServer.BatchCheck(ctx, tuples)
|
||||
}
|
||||
|
||||
func (provider *provider) ListObjects(ctx context.Context, subject string, relation authtypes.Relation, typeable authtypes.Typeable) ([]*authtypes.Object, error) {
|
||||
@@ -183,11 +187,6 @@ func (provider *provider) GetResources(_ context.Context) []*authtypes.Resource
|
||||
}
|
||||
|
||||
func (provider *provider) GetObjects(ctx context.Context, orgID valuer.UUID, id valuer.UUID, relation authtypes.Relation) ([]*authtypes.Object, error) {
|
||||
_, err := provider.licensing.GetActive(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
storableRole, err := provider.store.Get(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -199,7 +198,7 @@ func (provider *provider) GetObjects(ctx context.Context, orgID valuer.UUID, id
|
||||
resourceObjects, err := provider.
|
||||
ListObjects(
|
||||
ctx,
|
||||
authtypes.MustNewSubject(authtypes.TypeableRole, storableRole.Name, orgID, &authtypes.RelationAssignee),
|
||||
authtypes.MustNewSubject(authtypes.TypeableRole, storableRole.ID.String(), orgID, &authtypes.RelationAssignee),
|
||||
relation,
|
||||
authtypes.MustNewTypeableFromType(resource.Type, resource.Name),
|
||||
)
|
||||
|
||||
@@ -2,10 +2,8 @@ package openfgaserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/authz"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
openfgav1 "github.com/openfga/api/proto/openfga/v1"
|
||||
@@ -30,34 +28,27 @@ func (server *Server) Stop(ctx context.Context) error {
|
||||
return server.pkgAuthzService.Stop(ctx)
|
||||
}
|
||||
|
||||
func (server *Server) Check(ctx context.Context, tuple *openfgav1.TupleKey) error {
|
||||
return server.pkgAuthzService.Check(ctx, tuple)
|
||||
}
|
||||
|
||||
func (server *Server) CheckWithTupleCreation(ctx context.Context, claims authtypes.Claims, orgID valuer.UUID, relation authtypes.Relation, typeable authtypes.Typeable, selectors []authtypes.Selector, _ []authtypes.Selector) error {
|
||||
subject, err := authtypes.NewSubject(authtypes.TypeableUser, claims.UserID, orgID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tupleSlice, err := typeable.Tuples(subject, relation, selectors, orgID)
|
||||
tuples, err := typeable.Tuples(subject, relation, selectors, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tuples := make(map[string]*openfgav1.TupleKey, len(tupleSlice))
|
||||
for idx, tuple := range tupleSlice {
|
||||
tuples[strconv.Itoa(idx)] = tuple
|
||||
}
|
||||
|
||||
response, err := server.BatchCheck(ctx, tuples)
|
||||
err = server.BatchCheck(ctx, tuples)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, resp := range response {
|
||||
if resp.Authorized {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Newf(errors.TypeForbidden, authtypes.ErrCodeAuthZForbidden, "subjects are not authorized for requested access")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) CheckWithTupleCreationWithoutClaims(ctx context.Context, orgID valuer.UUID, relation authtypes.Relation, typeable authtypes.Typeable, selectors []authtypes.Selector, _ []authtypes.Selector) error {
|
||||
@@ -66,32 +57,21 @@ func (server *Server) CheckWithTupleCreationWithoutClaims(ctx context.Context, o
|
||||
return err
|
||||
}
|
||||
|
||||
tupleSlice, err := typeable.Tuples(subject, relation, selectors, orgID)
|
||||
tuples, err := typeable.Tuples(subject, relation, selectors, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tuples := make(map[string]*openfgav1.TupleKey, len(tupleSlice))
|
||||
for idx, tuple := range tupleSlice {
|
||||
tuples[strconv.Itoa(idx)] = tuple
|
||||
}
|
||||
|
||||
response, err := server.BatchCheck(ctx, tuples)
|
||||
err = server.BatchCheck(ctx, tuples)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, resp := range response {
|
||||
if resp.Authorized {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Newf(errors.TypeForbidden, authtypes.ErrCodeAuthZForbidden, "subjects are not authorized for requested access")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) BatchCheck(ctx context.Context, tupleReq map[string]*openfgav1.TupleKey) (map[string]*authtypes.TupleKeyAuthorization, error) {
|
||||
return server.pkgAuthzService.BatchCheck(ctx, tupleReq)
|
||||
func (server *Server) BatchCheck(ctx context.Context, tuples []*openfgav1.TupleKey) error {
|
||||
return server.pkgAuthzService.BatchCheck(ctx, tuples)
|
||||
}
|
||||
|
||||
func (server *Server) ListObjects(ctx context.Context, subject string, relation authtypes.Relation, typeable authtypes.Typeable) ([]*authtypes.Object, error) {
|
||||
|
||||
@@ -220,7 +220,6 @@ func (module *module) MustGetManagedRoleTransactions() map[string][]*authtypes.T
|
||||
return map[string][]*authtypes.Transaction{
|
||||
roletypes.SigNozAnonymousRoleName: {
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Relation: authtypes.RelationRead,
|
||||
Object: *authtypes.MustNewObject(
|
||||
authtypes.Resource{
|
||||
|
||||
@@ -2,9 +2,11 @@ package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/ee/licensing/httplicensing"
|
||||
"github.com/SigNoz/signoz/ee/query-service/integrations/gateway"
|
||||
"github.com/SigNoz/signoz/ee/query-service/usage"
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
"github.com/SigNoz/signoz/pkg/global"
|
||||
@@ -29,6 +31,7 @@ type APIHandlerOptions struct {
|
||||
IntegrationsController *integrations.Controller
|
||||
CloudIntegrationsController *cloudintegrations.Controller
|
||||
LogsParsingPipelineController *logparsingpipeline.LogParsingPipelineController
|
||||
Gateway *httputil.ReverseProxy
|
||||
GatewayUrl string
|
||||
// Querier Influx Interval
|
||||
FluxInterval time.Duration
|
||||
@@ -74,6 +77,10 @@ func (ah *APIHandler) UM() *usage.Manager {
|
||||
return ah.opts.UsageManager
|
||||
}
|
||||
|
||||
func (ah *APIHandler) Gateway() *httputil.ReverseProxy {
|
||||
return ah.opts.Gateway
|
||||
}
|
||||
|
||||
// RegisterRoutes registers routes for this handler on the given router
|
||||
func (ah *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) {
|
||||
// note: add ee override methods first
|
||||
@@ -96,6 +103,9 @@ func (ah *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) {
|
||||
// v4
|
||||
router.HandleFunc("/api/v4/query_range", am.ViewAccess(ah.queryRangeV4)).Methods(http.MethodPost)
|
||||
|
||||
// Gateway
|
||||
router.PathPrefix(gateway.RoutePrefix).HandlerFunc(am.EditAccess(ah.ServeGatewayHTTP))
|
||||
|
||||
ah.APIHandler.RegisterRoutes(router, am)
|
||||
|
||||
}
|
||||
|
||||
58
ee/query-service/app/api/gateway.go
Normal file
58
ee/query-service/app/api/gateway.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/SigNoz/signoz/ee/query-service/integrations/gateway"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/http/render"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
func (ah *APIHandler) ServeGatewayHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "orgId is invalid"))
|
||||
return
|
||||
}
|
||||
|
||||
validPath := false
|
||||
for _, allowedPrefix := range gateway.AllowedPrefix {
|
||||
if strings.HasPrefix(req.URL.Path, gateway.RoutePrefix+allowedPrefix) {
|
||||
validPath = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !validPath {
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
license, err := ah.Signoz.Licensing.GetActive(ctx, orgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
//Create headers
|
||||
var licenseKey string
|
||||
if license != nil {
|
||||
licenseKey = license.Key
|
||||
}
|
||||
|
||||
req.Header.Set("X-Signoz-Cloud-Api-Key", licenseKey)
|
||||
req.Header.Set("X-Consumer-Username", "lid:00000000-0000-0000-0000-000000000000")
|
||||
req.Header.Set("X-Consumer-Groups", "ns:default")
|
||||
|
||||
ah.Gateway().ServeHTTP(rw, req)
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/gorilla/handlers"
|
||||
|
||||
"github.com/SigNoz/signoz/ee/query-service/app/api"
|
||||
"github.com/SigNoz/signoz/ee/query-service/integrations/gateway"
|
||||
"github.com/SigNoz/signoz/ee/query-service/rules"
|
||||
"github.com/SigNoz/signoz/ee/query-service/usage"
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
@@ -71,6 +72,11 @@ type Server struct {
|
||||
|
||||
// NewServer creates and initializes Server
|
||||
func NewServer(config signoz.Config, signoz *signoz.SigNoz) (*Server, error) {
|
||||
gatewayProxy, err := gateway.NewProxy(config.Gateway.URL.String(), gateway.RoutePrefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cacheForTraceDetail, err := memorycache.New(context.TODO(), signoz.Instrumentation.ToProviderSettings(), cache.Config{
|
||||
Provider: "memory",
|
||||
Memory: cache.Memory{
|
||||
@@ -164,6 +170,7 @@ func NewServer(config signoz.Config, signoz *signoz.SigNoz) (*Server, error) {
|
||||
CloudIntegrationsController: cloudIntegrationsController,
|
||||
LogsParsingPipelineController: logParsingPipelineController,
|
||||
FluxInterval: config.Querier.FluxInterval,
|
||||
Gateway: gatewayProxy,
|
||||
GatewayUrl: config.Gateway.URL.String(),
|
||||
GlobalConfig: config.Global,
|
||||
}
|
||||
|
||||
9
ee/query-service/integrations/gateway/noop.go
Normal file
9
ee/query-service/integrations/gateway/noop.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"net/http/httputil"
|
||||
)
|
||||
|
||||
func NewNoopProxy() (*httputil.ReverseProxy, error) {
|
||||
return &httputil.ReverseProxy{}, nil
|
||||
}
|
||||
66
ee/query-service/integrations/gateway/proxy.go
Normal file
66
ee/query-service/integrations/gateway/proxy.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
RoutePrefix string = "/api/gateway"
|
||||
AllowedPrefix []string = []string{"/v1/workspaces/me", "/v2/profiles/me", "/v2/deployments/me"}
|
||||
)
|
||||
|
||||
type proxy struct {
|
||||
url *url.URL
|
||||
stripPath string
|
||||
}
|
||||
|
||||
func NewProxy(u string, stripPath string) (*httputil.ReverseProxy, error) {
|
||||
url, err := url.Parse(u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
proxy := &proxy{url: url, stripPath: stripPath}
|
||||
|
||||
return &httputil.ReverseProxy{
|
||||
Rewrite: proxy.rewrite,
|
||||
ModifyResponse: proxy.modifyResponse,
|
||||
ErrorHandler: proxy.errorHandler,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *proxy) rewrite(pr *httputil.ProxyRequest) {
|
||||
pr.SetURL(p.url)
|
||||
pr.SetXForwarded()
|
||||
pr.Out.URL.Path = cleanPath(strings.ReplaceAll(pr.Out.URL.Path, p.stripPath, ""))
|
||||
}
|
||||
|
||||
func (p *proxy) modifyResponse(res *http.Response) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *proxy) errorHandler(rw http.ResponseWriter, req *http.Request, err error) {
|
||||
rw.WriteHeader(http.StatusBadGateway)
|
||||
}
|
||||
|
||||
func cleanPath(p string) string {
|
||||
if p == "" {
|
||||
return "/"
|
||||
}
|
||||
if p[0] != '/' {
|
||||
p = "/" + p
|
||||
}
|
||||
np := path.Clean(p)
|
||||
if p[len(p)-1] == '/' && np != "/" {
|
||||
if len(p) == len(np)+1 && strings.HasPrefix(p, np) {
|
||||
np = p
|
||||
} else {
|
||||
np += "/"
|
||||
}
|
||||
}
|
||||
return np
|
||||
}
|
||||
61
ee/query-service/integrations/gateway/proxy_test.go
Normal file
61
ee/query-service/integrations/gateway/proxy_test.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestProxyRewrite(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
url *url.URL
|
||||
stripPath string
|
||||
in *url.URL
|
||||
expected *url.URL
|
||||
}{
|
||||
{
|
||||
name: "SamePathAdded",
|
||||
url: &url.URL{Scheme: "http", Host: "backend", Path: "/path1"},
|
||||
stripPath: "/strip",
|
||||
in: &url.URL{Scheme: "http", Host: "localhost", Path: "/strip/path1"},
|
||||
expected: &url.URL{Scheme: "http", Host: "backend", Path: "/path1/path1"},
|
||||
},
|
||||
{
|
||||
name: "NoStripPathInput",
|
||||
url: &url.URL{Scheme: "http", Host: "backend"},
|
||||
stripPath: "",
|
||||
in: &url.URL{Scheme: "http", Host: "localhost", Path: "/strip/path1"},
|
||||
expected: &url.URL{Scheme: "http", Host: "backend", Path: "/strip/path1"},
|
||||
},
|
||||
{
|
||||
name: "NoStripPathPresentInReq",
|
||||
url: &url.URL{Scheme: "http", Host: "backend"},
|
||||
stripPath: "/not-found",
|
||||
in: &url.URL{Scheme: "http", Host: "localhost", Path: "/strip/path1"},
|
||||
expected: &url.URL{Scheme: "http", Host: "backend", Path: "/strip/path1"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
proxy, err := NewProxy(tc.url.String(), tc.stripPath)
|
||||
require.NoError(t, err)
|
||||
inReq, err := http.NewRequest(http.MethodGet, tc.in.String(), nil)
|
||||
require.NoError(t, err)
|
||||
proxyReq := &httputil.ProxyRequest{
|
||||
In: inReq,
|
||||
Out: inReq.Clone(context.Background()),
|
||||
}
|
||||
proxy.Rewrite(proxyReq)
|
||||
|
||||
assert.Equal(t, tc.expected.Host, proxyReq.Out.URL.Host)
|
||||
assert.Equal(t, tc.expected.Scheme, proxyReq.Out.URL.Scheme)
|
||||
assert.Equal(t, tc.expected.Path, proxyReq.Out.URL.Path)
|
||||
assert.Equal(t, tc.expected.Query(), proxyReq.Out.URL.Query())
|
||||
}
|
||||
}
|
||||
29
frontend/src/api/IngestionKeys/createIngestionKey.ts
Normal file
29
frontend/src/api/IngestionKeys/createIngestionKey.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { GatewayApiV1Instance } from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import {
|
||||
CreateIngestionKeyProps,
|
||||
IngestionKeyProps,
|
||||
} from 'types/api/ingestionKeys/types';
|
||||
|
||||
const createIngestionKey = async (
|
||||
props: CreateIngestionKeyProps,
|
||||
): Promise<SuccessResponse<IngestionKeyProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await GatewayApiV1Instance.post('/workspaces/me/keys', {
|
||||
...props,
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
|
||||
export default createIngestionKey;
|
||||
26
frontend/src/api/IngestionKeys/deleteIngestionKey.ts
Normal file
26
frontend/src/api/IngestionKeys/deleteIngestionKey.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { GatewayApiV1Instance } from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { AllIngestionKeyProps } from 'types/api/ingestionKeys/types';
|
||||
|
||||
const deleteIngestionKey = async (
|
||||
id: string,
|
||||
): Promise<SuccessResponse<AllIngestionKeyProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await GatewayApiV1Instance.delete(
|
||||
`/workspaces/me/keys/${id}`,
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
|
||||
export default deleteIngestionKey;
|
||||
21
frontend/src/api/IngestionKeys/getAllIngestionKeys.ts
Normal file
21
frontend/src/api/IngestionKeys/getAllIngestionKeys.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { GatewayApiV1Instance } from 'api';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import {
|
||||
AllIngestionKeyProps,
|
||||
GetIngestionKeyProps,
|
||||
} from 'types/api/ingestionKeys/types';
|
||||
|
||||
export const getAllIngestionKeys = (
|
||||
props: GetIngestionKeyProps,
|
||||
): Promise<AxiosResponse<AllIngestionKeyProps>> => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const { search, per_page, page } = props;
|
||||
|
||||
const BASE_URL = '/workspaces/me/keys';
|
||||
const URL_QUERY_PARAMS =
|
||||
search && search.length > 0
|
||||
? `/search?name=${search}&page=1&per_page=100`
|
||||
: `?page=${page}&per_page=${per_page}`;
|
||||
|
||||
return GatewayApiV1Instance.get(`${BASE_URL}${URL_QUERY_PARAMS}`);
|
||||
};
|
||||
65
frontend/src/api/IngestionKeys/limits/createLimitsForKey.ts
Normal file
65
frontend/src/api/IngestionKeys/limits/createLimitsForKey.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
/* eslint-disable @typescript-eslint/no-throw-literal */
|
||||
import { GatewayApiV1Instance } from 'api';
|
||||
import axios from 'axios';
|
||||
import {
|
||||
AddLimitProps,
|
||||
LimitSuccessProps,
|
||||
} from 'types/api/ingestionKeys/limits/types';
|
||||
|
||||
interface SuccessResponse<T> {
|
||||
statusCode: number;
|
||||
error: null;
|
||||
message: string;
|
||||
payload: T;
|
||||
}
|
||||
|
||||
interface ErrorResponse {
|
||||
statusCode: number;
|
||||
error: string;
|
||||
message: string;
|
||||
payload: null;
|
||||
}
|
||||
|
||||
const createLimitForIngestionKey = async (
|
||||
props: AddLimitProps,
|
||||
): Promise<SuccessResponse<LimitSuccessProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await GatewayApiV1Instance.post(
|
||||
`/workspaces/me/keys/${props.keyID}/limits`,
|
||||
{
|
||||
...props,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
// Axios error
|
||||
const errResponse: ErrorResponse = {
|
||||
statusCode: error.response?.status || 500,
|
||||
error: error.response?.data?.error,
|
||||
message: error.response?.data?.status || 'An error occurred',
|
||||
payload: null,
|
||||
};
|
||||
|
||||
throw errResponse;
|
||||
} else {
|
||||
// Non-Axios error
|
||||
const errResponse: ErrorResponse = {
|
||||
statusCode: 500,
|
||||
error: 'Unknown error',
|
||||
message: 'An unknown error occurred',
|
||||
payload: null,
|
||||
};
|
||||
|
||||
throw errResponse;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default createLimitForIngestionKey;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { GatewayApiV1Instance } from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { AllIngestionKeyProps } from 'types/api/ingestionKeys/types';
|
||||
|
||||
const deleteLimitsForIngestionKey = async (
|
||||
id: string,
|
||||
): Promise<SuccessResponse<AllIngestionKeyProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await GatewayApiV1Instance.delete(
|
||||
`/workspaces/me/limits/${id}`,
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
|
||||
export default deleteLimitsForIngestionKey;
|
||||
@@ -0,0 +1,65 @@
|
||||
/* eslint-disable @typescript-eslint/no-throw-literal */
|
||||
import { GatewayApiV1Instance } from 'api';
|
||||
import axios from 'axios';
|
||||
import {
|
||||
LimitSuccessProps,
|
||||
UpdateLimitProps,
|
||||
} from 'types/api/ingestionKeys/limits/types';
|
||||
|
||||
interface SuccessResponse<T> {
|
||||
statusCode: number;
|
||||
error: null;
|
||||
message: string;
|
||||
payload: T;
|
||||
}
|
||||
|
||||
interface ErrorResponse {
|
||||
statusCode: number;
|
||||
error: string;
|
||||
message: string;
|
||||
payload: null;
|
||||
}
|
||||
|
||||
const updateLimitForIngestionKey = async (
|
||||
props: UpdateLimitProps,
|
||||
): Promise<SuccessResponse<LimitSuccessProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await GatewayApiV1Instance.patch(
|
||||
`/workspaces/me/limits/${props.limitID}`,
|
||||
{
|
||||
config: props.config,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
// Axios error
|
||||
const errResponse: ErrorResponse = {
|
||||
statusCode: error.response?.status || 500,
|
||||
error: error.response?.data?.error,
|
||||
message: error.response?.data?.status || 'An error occurred',
|
||||
payload: null,
|
||||
};
|
||||
|
||||
throw errResponse;
|
||||
} else {
|
||||
// Non-Axios error
|
||||
const errResponse: ErrorResponse = {
|
||||
statusCode: 500,
|
||||
error: 'Unknown error',
|
||||
message: 'An unknown error occurred',
|
||||
payload: null,
|
||||
};
|
||||
|
||||
throw errResponse;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default updateLimitForIngestionKey;
|
||||
32
frontend/src/api/IngestionKeys/updateIngestionKey.ts
Normal file
32
frontend/src/api/IngestionKeys/updateIngestionKey.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { GatewayApiV1Instance } from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import {
|
||||
IngestionKeysPayloadProps,
|
||||
UpdateIngestionKeyProps,
|
||||
} from 'types/api/ingestionKeys/types';
|
||||
|
||||
const updateIngestionKey = async (
|
||||
props: UpdateIngestionKeyProps,
|
||||
): Promise<SuccessResponse<IngestionKeysPayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await GatewayApiV1Instance.patch(
|
||||
`/workspaces/me/keys/${props.id}`,
|
||||
{
|
||||
...props.data,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
|
||||
export default updateIngestionKey;
|
||||
@@ -4,6 +4,8 @@ export const apiV2 = '/api/v2/';
|
||||
export const apiV3 = '/api/v3/';
|
||||
export const apiV4 = '/api/v4/';
|
||||
export const apiV5 = '/api/v5/';
|
||||
export const gatewayApiV1 = '/api/gateway/v1/';
|
||||
export const gatewayApiV2 = '/api/gateway/v2/';
|
||||
export const apiAlertManager = '/api/alertmanager/';
|
||||
|
||||
export default apiV1;
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import type {
|
||||
MutationFunction,
|
||||
UseMutationOptions,
|
||||
UseMutationResult,
|
||||
} from 'react-query';
|
||||
import { useMutation } from 'react-query';
|
||||
|
||||
import { GeneratedAPIInstance } from '../../../index';
|
||||
import type {
|
||||
AuthtypesTransactionDTO,
|
||||
AuthzCheck200,
|
||||
RenderErrorResponseDTO,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
type AwaitedInput<T> = PromiseLike<T> | T;
|
||||
|
||||
type Awaited<O> = O extends AwaitedInput<infer T> ? T : never;
|
||||
|
||||
/**
|
||||
* Checks if the authenticated user has permissions for given transactions
|
||||
* @summary Check permissions
|
||||
*/
|
||||
export const authzCheck = (
|
||||
authtypesTransactionDTO: AuthtypesTransactionDTO[],
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<AuthzCheck200>({
|
||||
url: `/api/v1/authz/check`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: authtypesTransactionDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getAuthzCheckMutationOptions = <
|
||||
TError = RenderErrorResponseDTO,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof authzCheck>>,
|
||||
TError,
|
||||
{ data: AuthtypesTransactionDTO[] },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof authzCheck>>,
|
||||
TError,
|
||||
{ data: AuthtypesTransactionDTO[] },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['authzCheck'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof authzCheck>>,
|
||||
{ data: AuthtypesTransactionDTO[] }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return authzCheck(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type AuthzCheckMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof authzCheck>>
|
||||
>;
|
||||
export type AuthzCheckMutationBody = AuthtypesTransactionDTO[];
|
||||
export type AuthzCheckMutationError = RenderErrorResponseDTO;
|
||||
|
||||
/**
|
||||
* @summary Check permissions
|
||||
*/
|
||||
export const useAuthzCheck = <
|
||||
TError = RenderErrorResponseDTO,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof authzCheck>>,
|
||||
TError,
|
||||
{ data: AuthtypesTransactionDTO[] },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof authzCheck>>,
|
||||
TError,
|
||||
{ data: AuthtypesTransactionDTO[] },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getAuthzCheckMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
@@ -21,18 +21,11 @@ import { GeneratedAPIInstance } from '../../../index';
|
||||
import type {
|
||||
CreateRole201,
|
||||
DeleteRolePathParameters,
|
||||
GetObjects200,
|
||||
GetObjectsPathParameters,
|
||||
GetResources200,
|
||||
GetRole200,
|
||||
GetRolePathParameters,
|
||||
ListRoles200,
|
||||
PatchObjectsPathParameters,
|
||||
PatchRolePathParameters,
|
||||
RenderErrorResponseDTO,
|
||||
RoletypesPatchableObjectsDTO,
|
||||
RoletypesPatchableRoleDTO,
|
||||
RoletypesPostableRoleDTO,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
type AwaitedInput<T> = PromiseLike<T> | T;
|
||||
@@ -121,15 +114,10 @@ export const invalidateListRoles = async (
|
||||
* This endpoint creates a role
|
||||
* @summary Create role
|
||||
*/
|
||||
export const createRole = (
|
||||
roletypesPostableRoleDTO: RoletypesPostableRoleDTO,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
export const createRole = (signal?: AbortSignal) => {
|
||||
return GeneratedAPIInstance<CreateRole201>({
|
||||
url: `/api/v1/roles`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: roletypesPostableRoleDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -141,13 +129,13 @@ export const getCreateRoleMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createRole>>,
|
||||
TError,
|
||||
{ data: RoletypesPostableRoleDTO },
|
||||
void,
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createRole>>,
|
||||
TError,
|
||||
{ data: RoletypesPostableRoleDTO },
|
||||
void,
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createRole'];
|
||||
@@ -161,11 +149,9 @@ export const getCreateRoleMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createRole>>,
|
||||
{ data: RoletypesPostableRoleDTO }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return createRole(data);
|
||||
void
|
||||
> = () => {
|
||||
return createRole();
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
@@ -174,7 +160,7 @@ export const getCreateRoleMutationOptions = <
|
||||
export type CreateRoleMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createRole>>
|
||||
>;
|
||||
export type CreateRoleMutationBody = RoletypesPostableRoleDTO;
|
||||
|
||||
export type CreateRoleMutationError = RenderErrorResponseDTO;
|
||||
|
||||
/**
|
||||
@@ -187,13 +173,13 @@ export const useCreateRole = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createRole>>,
|
||||
TError,
|
||||
{ data: RoletypesPostableRoleDTO },
|
||||
void,
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createRole>>,
|
||||
TError,
|
||||
{ data: RoletypesPostableRoleDTO },
|
||||
void,
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateRoleMutationOptions(options);
|
||||
@@ -372,15 +358,10 @@ export const invalidateGetRole = async (
|
||||
* This endpoint patches a role
|
||||
* @summary Patch role
|
||||
*/
|
||||
export const patchRole = (
|
||||
{ id }: PatchRolePathParameters,
|
||||
roletypesPatchableRoleDTO: RoletypesPatchableRoleDTO,
|
||||
) => {
|
||||
export const patchRole = ({ id }: PatchRolePathParameters) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v1/roles/${id}`,
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: roletypesPatchableRoleDTO,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -391,13 +372,13 @@ export const getPatchRoleMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof patchRole>>,
|
||||
TError,
|
||||
{ pathParams: PatchRolePathParameters; data: RoletypesPatchableRoleDTO },
|
||||
{ pathParams: PatchRolePathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof patchRole>>,
|
||||
TError,
|
||||
{ pathParams: PatchRolePathParameters; data: RoletypesPatchableRoleDTO },
|
||||
{ pathParams: PatchRolePathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['patchRole'];
|
||||
@@ -411,11 +392,11 @@ export const getPatchRoleMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof patchRole>>,
|
||||
{ pathParams: PatchRolePathParameters; data: RoletypesPatchableRoleDTO }
|
||||
{ pathParams: PatchRolePathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return patchRole(pathParams, data);
|
||||
return patchRole(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
@@ -424,7 +405,7 @@ export const getPatchRoleMutationOptions = <
|
||||
export type PatchRoleMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof patchRole>>
|
||||
>;
|
||||
export type PatchRoleMutationBody = RoletypesPatchableRoleDTO;
|
||||
|
||||
export type PatchRoleMutationError = RenderErrorResponseDTO;
|
||||
|
||||
/**
|
||||
@@ -437,292 +418,16 @@ export const usePatchRole = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof patchRole>>,
|
||||
TError,
|
||||
{ pathParams: PatchRolePathParameters; data: RoletypesPatchableRoleDTO },
|
||||
{ pathParams: PatchRolePathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof patchRole>>,
|
||||
TError,
|
||||
{ pathParams: PatchRolePathParameters; data: RoletypesPatchableRoleDTO },
|
||||
{ pathParams: PatchRolePathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getPatchRoleMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Gets all objects connected to the specified role via a given relation type
|
||||
* @summary Get objects for a role by relation
|
||||
*/
|
||||
export const getObjects = (
|
||||
{ id, relation }: GetObjectsPathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<GetObjects200>({
|
||||
url: `/api/v1/roles/${id}/relation/${relation}/objects`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetObjectsQueryKey = ({
|
||||
id,
|
||||
relation,
|
||||
}: GetObjectsPathParameters) => {
|
||||
return ['getObjects'] as const;
|
||||
};
|
||||
|
||||
export const getGetObjectsQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getObjects>>,
|
||||
TError = RenderErrorResponseDTO
|
||||
>(
|
||||
{ id, relation }: GetObjectsPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getObjects>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getGetObjectsQueryKey({ id, relation });
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof getObjects>>> = ({
|
||||
signal,
|
||||
}) => getObjects({ id, relation }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!(id && relation),
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<Awaited<ReturnType<typeof getObjects>>, TError, TData> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
};
|
||||
|
||||
export type GetObjectsQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getObjects>>
|
||||
>;
|
||||
export type GetObjectsQueryError = RenderErrorResponseDTO;
|
||||
|
||||
/**
|
||||
* @summary Get objects for a role by relation
|
||||
*/
|
||||
|
||||
export function useGetObjects<
|
||||
TData = Awaited<ReturnType<typeof getObjects>>,
|
||||
TError = RenderErrorResponseDTO
|
||||
>(
|
||||
{ id, relation }: GetObjectsPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getObjects>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetObjectsQueryOptions({ id, relation }, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get objects for a role by relation
|
||||
*/
|
||||
export const invalidateGetObjects = async (
|
||||
queryClient: QueryClient,
|
||||
{ id, relation }: GetObjectsPathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetObjectsQueryKey({ id, relation }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* Patches the objects connected to the specified role via a given relation type
|
||||
* @summary Patch objects for a role by relation
|
||||
*/
|
||||
export const patchObjects = (
|
||||
{ id, relation }: PatchObjectsPathParameters,
|
||||
roletypesPatchableObjectsDTO: RoletypesPatchableObjectsDTO,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v1/roles/${id}/relation/${relation}/objects`,
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: roletypesPatchableObjectsDTO,
|
||||
});
|
||||
};
|
||||
|
||||
export const getPatchObjectsMutationOptions = <
|
||||
TError = RenderErrorResponseDTO,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof patchObjects>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: PatchObjectsPathParameters;
|
||||
data: RoletypesPatchableObjectsDTO;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof patchObjects>>,
|
||||
TError,
|
||||
{ pathParams: PatchObjectsPathParameters; data: RoletypesPatchableObjectsDTO },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['patchObjects'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof patchObjects>>,
|
||||
{ pathParams: PatchObjectsPathParameters; data: RoletypesPatchableObjectsDTO }
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return patchObjects(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type PatchObjectsMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof patchObjects>>
|
||||
>;
|
||||
export type PatchObjectsMutationBody = RoletypesPatchableObjectsDTO;
|
||||
export type PatchObjectsMutationError = RenderErrorResponseDTO;
|
||||
|
||||
/**
|
||||
* @summary Patch objects for a role by relation
|
||||
*/
|
||||
export const usePatchObjects = <
|
||||
TError = RenderErrorResponseDTO,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof patchObjects>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: PatchObjectsPathParameters;
|
||||
data: RoletypesPatchableObjectsDTO;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof patchObjects>>,
|
||||
TError,
|
||||
{ pathParams: PatchObjectsPathParameters; data: RoletypesPatchableObjectsDTO },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getPatchObjectsMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Gets all the available resources for role assignment
|
||||
* @summary Get resources
|
||||
*/
|
||||
export const getResources = (signal?: AbortSignal) => {
|
||||
return GeneratedAPIInstance<GetResources200>({
|
||||
url: `/api/v1/roles/resources`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetResourcesQueryKey = () => {
|
||||
return ['getResources'] as const;
|
||||
};
|
||||
|
||||
export const getGetResourcesQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getResources>>,
|
||||
TError = RenderErrorResponseDTO
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getResources>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
}) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getGetResourcesQueryKey();
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof getResources>>> = ({
|
||||
signal,
|
||||
}) => getResources(signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getResources>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetResourcesQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getResources>>
|
||||
>;
|
||||
export type GetResourcesQueryError = RenderErrorResponseDTO;
|
||||
|
||||
/**
|
||||
* @summary Get resources
|
||||
*/
|
||||
|
||||
export function useGetResources<
|
||||
TData = Awaited<ReturnType<typeof getResources>>,
|
||||
TError = RenderErrorResponseDTO
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getResources>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
}): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetResourcesQueryOptions(options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get resources
|
||||
*/
|
||||
export const invalidateGetResources = async (
|
||||
queryClient: QueryClient,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetResourcesQueryKey() },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
@@ -127,18 +127,6 @@ export interface AuthtypesGettableTokenDTO {
|
||||
tokenType?: string;
|
||||
}
|
||||
|
||||
export interface AuthtypesGettableTransactionDTO {
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
authorized: boolean;
|
||||
object: AuthtypesObjectDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
relation: string;
|
||||
}
|
||||
|
||||
export type AuthtypesGoogleConfigDTODomainToAdminEmail = {
|
||||
[key: string]: string;
|
||||
};
|
||||
@@ -182,10 +170,6 @@ export interface AuthtypesGoogleConfigDTO {
|
||||
serviceAccountJson?: string;
|
||||
}
|
||||
|
||||
export interface AuthtypesNameDTO {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface AuthtypesOIDCConfigDTO {
|
||||
claimMapping?: AuthtypesAttributeMappingDTO;
|
||||
/**
|
||||
@@ -214,11 +198,6 @@ export interface AuthtypesOIDCConfigDTO {
|
||||
issuerAlias?: string;
|
||||
}
|
||||
|
||||
export interface AuthtypesObjectDTO {
|
||||
resource: AuthtypesResourceDTO;
|
||||
selector: AuthtypesSelectorDTO;
|
||||
}
|
||||
|
||||
export interface AuthtypesOrgSessionContextDTO {
|
||||
authNSupport?: AuthtypesAuthNSupportDTO;
|
||||
/**
|
||||
@@ -269,14 +248,6 @@ export interface AuthtypesPostableRotateTokenDTO {
|
||||
refreshToken?: string;
|
||||
}
|
||||
|
||||
export interface AuthtypesResourceDTO {
|
||||
name: AuthtypesNameDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
@@ -320,10 +291,6 @@ export interface AuthtypesSamlConfigDTO {
|
||||
samlIdp?: string;
|
||||
}
|
||||
|
||||
export interface AuthtypesSelectorDTO {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface AuthtypesSessionContextDTO {
|
||||
/**
|
||||
* @type boolean
|
||||
@@ -336,18 +303,6 @@ export interface AuthtypesSessionContextDTO {
|
||||
orgs?: AuthtypesOrgSessionContextDTO[] | null;
|
||||
}
|
||||
|
||||
export interface AuthtypesTransactionDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id?: string;
|
||||
object: AuthtypesObjectDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
relation: string;
|
||||
}
|
||||
|
||||
export interface AuthtypesUpdateableAuthDomainDTO {
|
||||
config?: AuthtypesAuthDomainConfigDTO;
|
||||
}
|
||||
@@ -1992,57 +1947,6 @@ export interface RenderErrorResponseDTO {
|
||||
status?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type RoletypesGettableResourcesDTORelations = {
|
||||
[key: string]: string[];
|
||||
} | null;
|
||||
|
||||
export interface RoletypesGettableResourcesDTO {
|
||||
/**
|
||||
* @type object
|
||||
* @nullable true
|
||||
*/
|
||||
relations: RoletypesGettableResourcesDTORelations;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
resources: AuthtypesResourceDTO[] | null;
|
||||
}
|
||||
|
||||
export interface RoletypesPatchableObjectsDTO {
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
additions: AuthtypesObjectDTO[] | null;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
deletions: AuthtypesObjectDTO[] | null;
|
||||
}
|
||||
|
||||
export interface RoletypesPatchableRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface RoletypesPostableRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface RoletypesRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -2052,7 +1956,7 @@ export interface RoletypesRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description: string;
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2060,15 +1964,15 @@ export interface RoletypesRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
name?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
orgId: string;
|
||||
orgId?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
type: string;
|
||||
type?: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
@@ -2595,17 +2499,6 @@ export interface ZeustypesPostableProfileDTO {
|
||||
where_did_you_discover_signoz: string;
|
||||
}
|
||||
|
||||
export type AuthzCheck200 = {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
data?: AuthtypesGettableTransactionDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status?: string;
|
||||
};
|
||||
|
||||
export type ChangePasswordPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
@@ -3009,33 +2902,6 @@ export type GetRole200 = {
|
||||
export type PatchRolePathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type GetObjectsPathParameters = {
|
||||
id: string;
|
||||
relation: string;
|
||||
};
|
||||
export type GetObjects200 = {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
data?: AuthtypesObjectDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status?: string;
|
||||
};
|
||||
|
||||
export type PatchObjectsPathParameters = {
|
||||
id: string;
|
||||
relation: string;
|
||||
};
|
||||
export type GetResources200 = {
|
||||
data?: RoletypesGettableResourcesDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status?: string;
|
||||
};
|
||||
|
||||
export type ListUsers200 = {
|
||||
/**
|
||||
* @type array
|
||||
|
||||
@@ -15,7 +15,15 @@ import { Events } from 'constants/events';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { eventEmitter } from 'utils/getEventEmitter';
|
||||
|
||||
import apiV1, { apiAlertManager, apiV2, apiV3, apiV4, apiV5 } from './apiV1';
|
||||
import apiV1, {
|
||||
apiAlertManager,
|
||||
apiV2,
|
||||
apiV3,
|
||||
apiV4,
|
||||
apiV5,
|
||||
gatewayApiV1,
|
||||
gatewayApiV2,
|
||||
} from './apiV1';
|
||||
import { Logout } from './utils';
|
||||
|
||||
const RESPONSE_TIMEOUT_THRESHOLD = 5000; // 5 seconds
|
||||
@@ -203,6 +211,24 @@ LogEventAxiosInstance.interceptors.response.use(
|
||||
LogEventAxiosInstance.interceptors.request.use(interceptorsRequestResponse);
|
||||
//
|
||||
|
||||
// gateway Api V1
|
||||
export const GatewayApiV1Instance = axios.create({
|
||||
baseURL: `${ENVIRONMENT.baseURL}${gatewayApiV1}`,
|
||||
});
|
||||
|
||||
GatewayApiV1Instance.interceptors.response.use(
|
||||
interceptorsResponse,
|
||||
interceptorRejected,
|
||||
);
|
||||
|
||||
GatewayApiV1Instance.interceptors.request.use(interceptorsRequestResponse);
|
||||
//
|
||||
|
||||
// gateway Api V2
|
||||
export const GatewayApiV2Instance = axios.create({
|
||||
baseURL: `${ENVIRONMENT.baseURL}${gatewayApiV2}`,
|
||||
});
|
||||
|
||||
// generated API Instance
|
||||
export const GeneratedAPIInstance = axios.create({
|
||||
baseURL: ENVIRONMENT.baseURL,
|
||||
@@ -214,6 +240,14 @@ GeneratedAPIInstance.interceptors.response.use(
|
||||
interceptorRejected,
|
||||
);
|
||||
|
||||
GatewayApiV2Instance.interceptors.response.use(
|
||||
interceptorsResponse,
|
||||
interceptorRejected,
|
||||
);
|
||||
|
||||
GatewayApiV2Instance.interceptors.request.use(interceptorsRequestResponse);
|
||||
//
|
||||
|
||||
AxiosAlertManagerInstance.interceptors.response.use(
|
||||
interceptorsResponse,
|
||||
interceptorRejected,
|
||||
|
||||
@@ -27,7 +27,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { FeatureKeys } from '../../../constants/features';
|
||||
import { useAppContext } from '../../../providers/App/App';
|
||||
import { getOrderByFromParams, safeParseJSON } from '../commonUtils';
|
||||
import { getOrderByFromParams } from '../commonUtils';
|
||||
import {
|
||||
GetK8sEntityToAggregateAttribute,
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
@@ -103,10 +103,9 @@ function K8sClustersList({
|
||||
const [groupBy, setGroupBy] = useState<IBuilderQuery['groupBy']>(() => {
|
||||
const groupBy = searchParams.get(INFRA_MONITORING_K8S_PARAMS_KEYS.GROUP_BY);
|
||||
if (groupBy) {
|
||||
const parsed = safeParseJSON<IBuilderQuery['groupBy']>(groupBy);
|
||||
if (parsed) {
|
||||
return parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(groupBy);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as IBuilderQuery['groupBy'];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { FeatureKeys } from '../../../constants/features';
|
||||
import { useAppContext } from '../../../providers/App/App';
|
||||
import { getOrderByFromParams, safeParseJSON } from '../commonUtils';
|
||||
import { getOrderByFromParams } from '../commonUtils';
|
||||
import {
|
||||
GetK8sEntityToAggregateAttribute,
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
@@ -105,10 +105,9 @@ function K8sDaemonSetsList({
|
||||
const [groupBy, setGroupBy] = useState<IBuilderQuery['groupBy']>(() => {
|
||||
const groupBy = searchParams.get(INFRA_MONITORING_K8S_PARAMS_KEYS.GROUP_BY);
|
||||
if (groupBy) {
|
||||
const parsed = safeParseJSON<IBuilderQuery['groupBy']>(groupBy);
|
||||
if (parsed) {
|
||||
return parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(groupBy);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as IBuilderQuery['groupBy'];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { FeatureKeys } from '../../../constants/features';
|
||||
import { useAppContext } from '../../../providers/App/App';
|
||||
import { getOrderByFromParams, safeParseJSON } from '../commonUtils';
|
||||
import { getOrderByFromParams } from '../commonUtils';
|
||||
import {
|
||||
GetK8sEntityToAggregateAttribute,
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
@@ -106,10 +106,9 @@ function K8sDeploymentsList({
|
||||
const [groupBy, setGroupBy] = useState<IBuilderQuery['groupBy']>(() => {
|
||||
const groupBy = searchParams.get(INFRA_MONITORING_K8S_PARAMS_KEYS.GROUP_BY);
|
||||
if (groupBy) {
|
||||
const parsed = safeParseJSON<IBuilderQuery['groupBy']>(groupBy);
|
||||
if (parsed) {
|
||||
return parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(groupBy);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as IBuilderQuery['groupBy'];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { FeatureKeys } from '../../../constants/features';
|
||||
import { useAppContext } from '../../../providers/App/App';
|
||||
import { getOrderByFromParams, safeParseJSON } from '../commonUtils';
|
||||
import { getOrderByFromParams } from '../commonUtils';
|
||||
import {
|
||||
GetK8sEntityToAggregateAttribute,
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
@@ -101,10 +101,9 @@ function K8sJobsList({
|
||||
const [groupBy, setGroupBy] = useState<IBuilderQuery['groupBy']>(() => {
|
||||
const groupBy = searchParams.get(INFRA_MONITORING_K8S_PARAMS_KEYS.GROUP_BY);
|
||||
if (groupBy) {
|
||||
const parsed = safeParseJSON<IBuilderQuery['groupBy']>(groupBy);
|
||||
if (parsed) {
|
||||
return parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(groupBy);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as IBuilderQuery['groupBy'];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
@@ -10,7 +10,6 @@ import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteRe
|
||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import { safeParseJSON } from './commonUtils';
|
||||
import { INFRA_MONITORING_K8S_PARAMS_KEYS, K8sCategory } from './constants';
|
||||
import K8sFiltersSidePanel from './K8sFiltersSidePanel/K8sFiltersSidePanel';
|
||||
import { IEntityColumn } from './utils';
|
||||
@@ -59,10 +58,9 @@ function K8sHeader({
|
||||
const urlFilters = searchParams.get(INFRA_MONITORING_K8S_PARAMS_KEYS.FILTERS);
|
||||
let { filters } = currentQuery.builder.queryData[0];
|
||||
if (urlFilters) {
|
||||
const parsed = safeParseJSON<IBuilderQuery['filters']>(urlFilters);
|
||||
if (parsed) {
|
||||
filters = parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(urlFilters);
|
||||
const parsed = JSON.parse(decoded);
|
||||
filters = parsed;
|
||||
}
|
||||
return {
|
||||
...currentQuery,
|
||||
|
||||
@@ -27,7 +27,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { FeatureKeys } from '../../../constants/features';
|
||||
import { useAppContext } from '../../../providers/App/App';
|
||||
import { getOrderByFromParams, safeParseJSON } from '../commonUtils';
|
||||
import { getOrderByFromParams } from '../commonUtils';
|
||||
import {
|
||||
GetK8sEntityToAggregateAttribute,
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
@@ -104,10 +104,9 @@ function K8sNamespacesList({
|
||||
const [groupBy, setGroupBy] = useState<IBuilderQuery['groupBy']>(() => {
|
||||
const groupBy = searchParams.get(INFRA_MONITORING_K8S_PARAMS_KEYS.GROUP_BY);
|
||||
if (groupBy) {
|
||||
const parsed = safeParseJSON<IBuilderQuery['groupBy']>(groupBy);
|
||||
if (parsed) {
|
||||
return parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(groupBy);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as IBuilderQuery['groupBy'];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { FeatureKeys } from '../../../constants/features';
|
||||
import { useAppContext } from '../../../providers/App/App';
|
||||
import { getOrderByFromParams, safeParseJSON } from '../commonUtils';
|
||||
import { getOrderByFromParams } from '../commonUtils';
|
||||
import {
|
||||
GetK8sEntityToAggregateAttribute,
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
@@ -99,10 +99,9 @@ function K8sNodesList({
|
||||
const [groupBy, setGroupBy] = useState<IBuilderQuery['groupBy']>(() => {
|
||||
const groupBy = searchParams.get(INFRA_MONITORING_K8S_PARAMS_KEYS.GROUP_BY);
|
||||
if (groupBy) {
|
||||
const parsed = safeParseJSON<IBuilderQuery['groupBy']>(groupBy);
|
||||
if (parsed) {
|
||||
return parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(groupBy);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as IBuilderQuery['groupBy'];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
@@ -29,7 +29,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { FeatureKeys } from '../../../constants/features';
|
||||
import { useAppContext } from '../../../providers/App/App';
|
||||
import { getOrderByFromParams, safeParseJSON } from '../commonUtils';
|
||||
import { getOrderByFromParams } from '../commonUtils';
|
||||
import {
|
||||
GetK8sEntityToAggregateAttribute,
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
@@ -92,10 +92,9 @@ function K8sPodsList({
|
||||
const [groupBy, setGroupBy] = useState<IBuilderQuery['groupBy']>(() => {
|
||||
const groupBy = searchParams.get(INFRA_MONITORING_K8S_PARAMS_KEYS.GROUP_BY);
|
||||
if (groupBy) {
|
||||
const parsed = safeParseJSON<IBuilderQuery['groupBy']>(groupBy);
|
||||
if (parsed) {
|
||||
return parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(groupBy);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as IBuilderQuery['groupBy'];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { FeatureKeys } from '../../../constants/features';
|
||||
import { useAppContext } from '../../../providers/App/App';
|
||||
import { getOrderByFromParams, safeParseJSON } from '../commonUtils';
|
||||
import { getOrderByFromParams } from '../commonUtils';
|
||||
import {
|
||||
GetK8sEntityToAggregateAttribute,
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
@@ -105,10 +105,9 @@ function K8sStatefulSetsList({
|
||||
const [groupBy, setGroupBy] = useState<IBuilderQuery['groupBy']>(() => {
|
||||
const groupBy = searchParams.get(INFRA_MONITORING_K8S_PARAMS_KEYS.GROUP_BY);
|
||||
if (groupBy) {
|
||||
const parsed = safeParseJSON<IBuilderQuery['groupBy']>(groupBy);
|
||||
if (parsed) {
|
||||
return parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(groupBy);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as IBuilderQuery['groupBy'];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { FeatureKeys } from '../../../constants/features';
|
||||
import { useAppContext } from '../../../providers/App/App';
|
||||
import { getOrderByFromParams, safeParseJSON } from '../commonUtils';
|
||||
import { getOrderByFromParams } from '../commonUtils';
|
||||
import {
|
||||
GetK8sEntityToAggregateAttribute,
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS,
|
||||
@@ -105,10 +105,9 @@ function K8sVolumesList({
|
||||
const [groupBy, setGroupBy] = useState<IBuilderQuery['groupBy']>(() => {
|
||||
const groupBy = searchParams.get(INFRA_MONITORING_K8S_PARAMS_KEYS.GROUP_BY);
|
||||
if (groupBy) {
|
||||
const parsed = safeParseJSON<IBuilderQuery['groupBy']>(groupBy);
|
||||
if (parsed) {
|
||||
return parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(groupBy);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as IBuilderQuery['groupBy'];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
/* eslint-disable prefer-destructuring */
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Table, Tooltip, Typography } from 'antd';
|
||||
import { Progress } from 'antd/lib';
|
||||
@@ -261,27 +260,6 @@ export const filterDuplicateFilters = (
|
||||
return uniqueFilters;
|
||||
};
|
||||
|
||||
export const safeParseJSON = <T,>(value: string): T | null => {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Attempting to parse potentially untrusted user input from the URL.
|
||||
// If the user pastes a corrupted link or modifies the URL manually (e.g., ?filters=invalidJSON),
|
||||
// JSON.parse() will throw a SyntaxError. Without this try/catch block, that unhandled
|
||||
// exception would bubble up during the React component render cycle and crash.
|
||||
return JSON.parse(value) as T;
|
||||
} catch (e) {
|
||||
// By catching the SyntaxError, we gracefully degrade the user experience.
|
||||
// Instead of crashing, the app ignores the malformed URL parameter and cleanly
|
||||
// falls back to the default state (e.g., no filters applied).
|
||||
console.error('Error parsing JSON from URL parameter:', e);
|
||||
// TODO: Should we capture this error in Sentry?
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const getOrderByFromParams = (
|
||||
searchParams: URLSearchParams,
|
||||
returnNullAsDefault = false,
|
||||
@@ -293,12 +271,9 @@ export const getOrderByFromParams = (
|
||||
INFRA_MONITORING_K8S_PARAMS_KEYS.ORDER_BY,
|
||||
);
|
||||
if (orderByFromParams) {
|
||||
const parsed = safeParseJSON<{ columnName: string; order: 'asc' | 'desc' }>(
|
||||
orderByFromParams,
|
||||
);
|
||||
if (parsed) {
|
||||
return parsed;
|
||||
}
|
||||
const decoded = decodeURIComponent(orderByFromParams);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as { columnName: string; order: 'asc' | 'desc' };
|
||||
}
|
||||
if (returnNullAsDefault) {
|
||||
return null;
|
||||
@@ -312,7 +287,13 @@ export const getFiltersFromParams = (
|
||||
): IBuilderQuery['filters'] | null => {
|
||||
const filtersFromParams = searchParams.get(queryKey);
|
||||
if (filtersFromParams) {
|
||||
return safeParseJSON<IBuilderQuery['filters']>(filtersFromParams);
|
||||
try {
|
||||
const decoded = decodeURIComponent(filtersFromParams);
|
||||
const parsed = JSON.parse(decoded);
|
||||
return parsed as IBuilderQuery['filters'];
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
15
frontend/src/hooks/IngestionKeys/useGetAllIngestionKeys.ts
Normal file
15
frontend/src/hooks/IngestionKeys/useGetAllIngestionKeys.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useQuery, UseQueryResult } from 'react-query';
|
||||
import { getAllIngestionKeys } from 'api/IngestionKeys/getAllIngestionKeys';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import {
|
||||
AllIngestionKeyProps,
|
||||
GetIngestionKeyProps,
|
||||
} from 'types/api/ingestionKeys/types';
|
||||
|
||||
export const useGetAllIngestionsKeys = (
|
||||
props: GetIngestionKeyProps,
|
||||
): UseQueryResult<AxiosResponse<AllIngestionKeyProps>, AxiosError> =>
|
||||
useQuery<AxiosResponse<AllIngestionKeyProps>, AxiosError>({
|
||||
queryKey: [`IngestionKeys-${props.page}-${props.search}`],
|
||||
queryFn: () => getAllIngestionKeys(props),
|
||||
});
|
||||
287
go.mod
287
go.mod
@@ -3,23 +3,22 @@ module github.com/SigNoz/signoz
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.1
|
||||
dario.cat/mergo v1.0.2
|
||||
github.com/AfterShip/clickhouse-sql-parser v0.4.16
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.40.1
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd
|
||||
github.com/SigNoz/signoz-otel-collector v0.129.10-rc.9
|
||||
github.com/SigNoz/signoz-otel-collector v0.142.1-rc.1
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1
|
||||
github.com/antonmedv/expr v1.15.3
|
||||
github.com/bytedance/sonic v1.14.1
|
||||
github.com/cespare/xxhash/v2 v2.3.0
|
||||
github.com/coreos/go-oidc/v3 v3.14.1
|
||||
github.com/coreos/go-oidc/v3 v3.16.0
|
||||
github.com/dgraph-io/ristretto/v2 v2.3.0
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/gin-gonic/gin v1.11.0
|
||||
github.com/go-co-op/gocron v1.30.1
|
||||
github.com/go-openapi/runtime v0.28.0
|
||||
github.com/go-openapi/strfmt v0.23.0
|
||||
github.com/go-openapi/strfmt v0.24.0
|
||||
github.com/go-redis/redismock/v9 v9.2.0
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0
|
||||
github.com/gojek/heimdall/v7 v7.0.3
|
||||
@@ -30,22 +29,22 @@ require (
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
|
||||
github.com/huandu/go-sqlbuilder v1.35.0
|
||||
github.com/jackc/pgx/v5 v5.7.6
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12
|
||||
github.com/knadh/koanf v1.5.0
|
||||
github.com/knadh/koanf/v2 v2.2.0
|
||||
github.com/mailru/easyjson v0.7.7
|
||||
github.com/open-telemetry/opamp-go v0.19.0
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.128.0
|
||||
github.com/knadh/koanf/v2 v2.3.0
|
||||
github.com/mailru/easyjson v0.9.0
|
||||
github.com/open-telemetry/opamp-go v0.22.0
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.142.0
|
||||
github.com/openfga/api/proto v0.0.0-20250909172242-b4b2a12f5c67
|
||||
github.com/openfga/language/pkg/go v0.2.0-beta.2.0.20250428093642-7aeebe78bbfe
|
||||
github.com/opentracing/opentracing-go v1.2.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/alertmanager v0.28.1
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/prometheus/common v0.66.1
|
||||
github.com/prometheus/prometheus v0.304.1
|
||||
github.com/prometheus/common v0.67.4
|
||||
github.com/prometheus/prometheus v0.308.0
|
||||
github.com/redis/go-redis/extra/redisotel/v9 v9.15.1
|
||||
github.com/redis/go-redis/v9 v9.15.1
|
||||
github.com/redis/go-redis/v9 v9.17.2
|
||||
github.com/rs/cors v1.11.1
|
||||
github.com/russellhaering/gosaml2 v0.9.0
|
||||
github.com/russellhaering/goxmldsig v1.2.0
|
||||
@@ -54,7 +53,7 @@ require (
|
||||
github.com/sethvargo/go-password v0.2.0
|
||||
github.com/smartystreets/goconvey v1.8.1
|
||||
github.com/soheilhy/cmux v0.1.5
|
||||
github.com/spf13/cobra v1.10.1
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/srikanthccv/ClickHouse-go-mock v0.13.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/swaggest/jsonschema-go v0.3.78
|
||||
@@ -64,43 +63,59 @@ require (
|
||||
github.com/uptrace/bun/dialect/pgdialect v1.2.9
|
||||
github.com/uptrace/bun/dialect/sqlitedialect v1.2.9
|
||||
github.com/uptrace/bun/extra/bunotel v1.2.9
|
||||
go.opentelemetry.io/collector/confmap v1.34.0
|
||||
go.opentelemetry.io/collector/otelcol v0.128.0
|
||||
go.opentelemetry.io/collector/pdata v1.34.0
|
||||
go.opentelemetry.io/collector/confmap v1.48.0
|
||||
go.opentelemetry.io/collector/otelcol v0.142.0
|
||||
go.opentelemetry.io/collector/pdata v1.48.0
|
||||
go.opentelemetry.io/contrib/config v0.10.0
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.63.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0
|
||||
go.opentelemetry.io/otel v1.38.0
|
||||
go.opentelemetry.io/otel/metric v1.38.0
|
||||
go.opentelemetry.io/otel/sdk v1.38.0
|
||||
go.opentelemetry.io/otel/trace v1.38.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0
|
||||
go.opentelemetry.io/otel v1.39.0
|
||||
go.opentelemetry.io/otel/metric v1.39.0
|
||||
go.opentelemetry.io/otel/sdk v1.39.0
|
||||
go.opentelemetry.io/otel/trace v1.39.0
|
||||
go.uber.org/multierr v1.11.0
|
||||
go.uber.org/zap v1.27.0
|
||||
go.uber.org/zap v1.27.1
|
||||
golang.org/x/crypto v0.46.0
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
|
||||
golang.org/x/net v0.47.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6
|
||||
golang.org/x/net v0.48.0
|
||||
golang.org/x/oauth2 v0.33.0
|
||||
golang.org/x/sync v0.19.0
|
||||
golang.org/x/text v0.32.0
|
||||
google.golang.org/protobuf v1.36.9
|
||||
google.golang.org/protobuf v1.36.10
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/apimachinery v0.34.0
|
||||
k8s.io/apimachinery v0.35.0-alpha.0
|
||||
modernc.org/sqlite v1.39.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go-v2 v1.40.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.41.1 // indirect
|
||||
github.com/aws/smithy-go v1.23.2 // indirect
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
github.com/bytedance/sonic v1.14.1 // indirect
|
||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/goccy/go-yaml v1.19.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/prometheus/client_golang/exp v0.0.0-20250914183048-a974e0d45e0a // indirect
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.15.1 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/swaggest/refl v1.4.0 // indirect
|
||||
@@ -108,24 +123,27 @@ require (
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||
github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.2 // indirect
|
||||
go.opentelemetry.io/collector/config/configretry v1.34.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
go.opentelemetry.io/collector/client v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/config/configoptional v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/config/configretry v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/exporter/exporterhelper v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata/xpdata v0.142.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
golang.org/x/arch v0.20.0 // indirect
|
||||
golang.org/x/tools/godoc v0.1.0-deprecated // indirect
|
||||
modernc.org/libc v1.66.10 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.24.0 // indirect
|
||||
cloud.google.com/go/auth v0.16.1 // indirect
|
||||
cel.dev/expr v0.25.1 // indirect
|
||||
cloud.google.com/go/auth v0.17.0 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.8.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect
|
||||
github.com/ClickHouse/ch-go v0.67.0 // indirect
|
||||
github.com/Masterminds/squirrel v1.5.4 // indirect
|
||||
github.com/Yiling-J/theine-go v0.6.2 // indirect
|
||||
@@ -133,35 +151,35 @@ require (
|
||||
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go v1.55.7 // indirect
|
||||
github.com/aws/aws-sdk-go v1.55.8 // indirect
|
||||
github.com/beevik/etree v1.1.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/coder/quartz v0.1.2 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.6.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dennwc/varint v1.0.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/ebitengine/purego v0.8.4 // indirect
|
||||
github.com/ebitengine/purego v0.9.1 // indirect
|
||||
github.com/edsrzf/mmap-go v1.2.0 // indirect
|
||||
github.com/elastic/lunes v0.1.0 // indirect
|
||||
github.com/elastic/lunes v0.2.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
|
||||
github.com/expr-lang/expr v1.17.5
|
||||
github.com/expr-lang/expr v1.17.7
|
||||
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-faster/city v1.0.1 // indirect
|
||||
github.com/go-faster/errors v0.7.1 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.1 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/loads v0.22.0 // indirect
|
||||
@@ -178,19 +196,19 @@ require (
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/cel-go v0.26.1 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
|
||||
github.com/gopherjs/gopherjs v1.17.2 // indirect
|
||||
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
|
||||
github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/go-version v1.8.0 // indirect
|
||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/memberlist v0.5.1 // indirect
|
||||
@@ -206,21 +224,21 @@ require (
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/jpillora/backoff v1.0.0 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/compress v1.18.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
github.com/leodido/go-syslog/v4 v4.2.0 // indirect
|
||||
github.com/leodido/go-syslog/v4 v4.3.0 // indirect
|
||||
github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
|
||||
github.com/magefile/mage v1.15.0 // indirect
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mdlayher/socket v0.4.1 // indirect
|
||||
github.com/mdlayher/socket v0.5.1 // indirect
|
||||
github.com/mdlayher/vsock v1.2.1 // indirect
|
||||
github.com/mfridman/interpolate v0.0.2 // indirect
|
||||
github.com/miekg/dns v1.1.65 // indirect
|
||||
github.com/miekg/dns v1.1.68 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
@@ -229,14 +247,14 @@ require (
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
|
||||
github.com/natefinch/wrap v0.2.0 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/oklog/run v1.2.0 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.1
|
||||
github.com/open-feature/go-sdk v1.17.0
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.128.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.128.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.128.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.128.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.142.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.142.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.142.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.142.0 // indirect
|
||||
github.com/openfga/openfga v1.10.1
|
||||
github.com/paulmach/orb v0.11.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
@@ -246,10 +264,10 @@ require (
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/pressly/goose/v3 v3.25.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/exporter-toolkit v0.14.0 // indirect
|
||||
github.com/prometheus/otlptranslator v0.0.0-20250320144820-d800c8b0eb07 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/prometheus/sigv4 v0.1.2 // indirect
|
||||
github.com/prometheus/exporter-toolkit v0.15.0 // indirect
|
||||
github.com/prometheus/otlptranslator v1.0.0 // indirect
|
||||
github.com/prometheus/procfs v0.19.2 // indirect
|
||||
github.com/prometheus/sigv4 v0.3.0 // indirect
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.9.0 // indirect
|
||||
@@ -257,7 +275,7 @@ require (
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/segmentio/backo-go v1.0.1 // indirect
|
||||
github.com/sethvargo/go-retry v0.3.0 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.25.5 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.25.11 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
|
||||
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 // indirect
|
||||
@@ -272,9 +290,9 @@ require (
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/swaggest/openapi-go v0.2.60
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
||||
github.com/tklauser/numcpus v0.10.0 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.16 // indirect
|
||||
github.com/tklauser/numcpus v0.11.0 // indirect
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
|
||||
github.com/trivago/tgo v1.0.7 // indirect
|
||||
github.com/valyala/fastjson v1.6.4 // indirect
|
||||
@@ -283,83 +301,82 @@ require (
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
github.com/zeebo/xxh3 v1.0.2 // indirect
|
||||
go.mongodb.org/mongo-driver v1.17.1 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/collector/component v1.34.0 // indirect
|
||||
go.opentelemetry.io/collector/component/componentstatus v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/component/componenttest v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/config/configtelemetry v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/confmap/provider/envprovider v1.34.0 // indirect
|
||||
go.opentelemetry.io/collector/confmap/provider/fileprovider v1.34.0 // indirect
|
||||
go.opentelemetry.io/collector/confmap/xconfmap v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/connector v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/connector/connectortest v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/connector/xconnector v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/consumer v1.34.0 // indirect
|
||||
go.opentelemetry.io/collector/consumer/consumererror v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/consumer/consumertest v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/consumer/xconsumer v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/exporter v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/exporter/exportertest v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/exporter/xexporter v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/extension v1.34.0 // indirect
|
||||
go.opentelemetry.io/collector/extension/extensioncapabilities v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/extension/extensiontest v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/extension/xextension v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/featuregate v1.34.0 // indirect
|
||||
go.opentelemetry.io/collector/internal/fanoutconsumer v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/internal/telemetry v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata/pprofile v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata/testdata v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/pipeline v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/pipeline/xpipeline v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/processor v1.34.0 // indirect
|
||||
go.opentelemetry.io/collector/processor/processorhelper v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/processor/processortest v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/processor/xprocessor v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/receiver v1.34.0 // indirect
|
||||
go.opentelemetry.io/collector/receiver/receiverhelper v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/receiver/receivertest v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/receiver/xreceiver v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/semconv v0.128.0
|
||||
go.opentelemetry.io/collector/service v0.128.0 // indirect
|
||||
go.opentelemetry.io/collector/service/hostcapabilities v0.128.0 // indirect
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.11.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 // indirect
|
||||
go.opentelemetry.io/contrib/otelconf v0.16.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.58.0
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.12.2 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/log v0.12.2 // indirect
|
||||
go.opentelemetry.io/otel/sdk/log v0.12.2 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0
|
||||
go.opentelemetry.io/proto/otlp v1.8.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.17.4 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/collector/component v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/component/componentstatus v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/component/componenttest v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/config/configtelemetry v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/confmap/provider/envprovider v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/confmap/provider/fileprovider v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/confmap/xconfmap v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/connector v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/connector/connectortest v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/connector/xconnector v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/consumer v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/consumer/consumererror v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/consumer/consumertest v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/consumer/xconsumer v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/exporter v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/exporter/exportertest v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/exporter/xexporter v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/extension v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/extension/extensioncapabilities v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/extension/extensiontest v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/extension/xextension v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/featuregate v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/internal/fanoutconsumer v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/internal/telemetry v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata/pprofile v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata/testdata v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/pipeline v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/pipeline/xpipeline v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/processor v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/processor/processorhelper v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/processor/processortest v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/processor/xprocessor v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/receiver v1.48.0 // indirect
|
||||
go.opentelemetry.io/collector/receiver/receiverhelper v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/receiver/receivertest v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/receiver/xreceiver v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/semconv v0.128.1-0.20250610090210-188191247685
|
||||
go.opentelemetry.io/collector/service v0.142.0 // indirect
|
||||
go.opentelemetry.io/collector/service/hostcapabilities v0.142.0 // indirect
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.13.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 // indirect
|
||||
go.opentelemetry.io/contrib/otelconf v0.18.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.14.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.14.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.60.0
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.14.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/log v0.15.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/log v0.14.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.39.0
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
golang.org/x/tools v0.39.0 // indirect
|
||||
gonum.org/v1/gonum v0.16.0 // indirect
|
||||
google.golang.org/api v0.236.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/grpc v1.75.1 // indirect
|
||||
google.golang.org/api v0.257.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||
google.golang.org/grpc v1.77.0 // indirect
|
||||
gopkg.in/telebot.v3 v3.3.8 // indirect
|
||||
k8s.io/client-go v0.34.0 // indirect
|
||||
k8s.io/client-go v0.34.2 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
|
||||
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/expr-lang/expr => github.com/SigNoz/expr v1.17.7-beta
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package signozapiserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (provider *provider) addAuthzRoutes(router *mux.Router) error {
|
||||
if err := router.Handle("/api/v1/authz/check", handler.New(provider.authzHandler.Check, handler.OpenAPIDef{
|
||||
ID: "AuthzCheck",
|
||||
Tags: []string{"authz"},
|
||||
Summary: "Check permissions",
|
||||
Description: "Checks if the authenticated user has permissions for given transactions",
|
||||
Request: make([]*authtypes.Transaction, 0),
|
||||
RequestContentType: "",
|
||||
Response: make([]*authtypes.GettableTransaction, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: nil,
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -207,10 +207,6 @@ func (provider *provider) AddToRouter(router *mux.Router) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := provider.addAuthzRoutes(router); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := provider.addFieldsRoutes(router); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -16,12 +15,12 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
Tags: []string{"role"},
|
||||
Summary: "Create role",
|
||||
Description: "This endpoint creates a role",
|
||||
Request: new(roletypes.PostableRole),
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(types.Identifiable),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
@@ -45,23 +44,6 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/roles/resources", handler.New(provider.authZ.AdminAccess(provider.authzHandler.GetResources), handler.OpenAPIDef{
|
||||
ID: "GetResources",
|
||||
Tags: []string{"role"},
|
||||
Summary: "Get resources",
|
||||
Description: "Gets all the available resources for role assignment",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(roletypes.GettableResources),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/roles/{id}", handler.New(provider.authZ.AdminAccess(provider.authzHandler.Get), handler.OpenAPIDef{
|
||||
ID: "GetRole",
|
||||
Tags: []string{"role"},
|
||||
@@ -79,51 +61,17 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/roles/{id}/relation/{relation}/objects", handler.New(provider.authZ.AdminAccess(provider.authzHandler.GetObjects), handler.OpenAPIDef{
|
||||
ID: "GetObjects",
|
||||
Tags: []string{"role"},
|
||||
Summary: "Get objects for a role by relation",
|
||||
Description: "Gets all objects connected to the specified role via a given relation type",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: make([]*authtypes.Object, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/roles/{id}", handler.New(provider.authZ.AdminAccess(provider.authzHandler.Patch), handler.OpenAPIDef{
|
||||
ID: "PatchRole",
|
||||
Tags: []string{"role"},
|
||||
Summary: "Patch role",
|
||||
Description: "This endpoint patches a role",
|
||||
Request: new(roletypes.PatchableRole),
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPatch).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/roles/{id}/relation/{relation}/objects", handler.New(provider.authZ.AdminAccess(provider.authzHandler.PatchObjects), handler.OpenAPIDef{
|
||||
ID: "PatchObjects",
|
||||
Tags: []string{"role"},
|
||||
Summary: "Patch objects for a role by relation",
|
||||
Description: "Patches the objects connected to the specified role via a given relation type",
|
||||
Request: new(roletypes.PatchableObjects),
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusBadRequest, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPatch).GetError(); err != nil {
|
||||
@@ -140,7 +88,7 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
Response: nil,
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
|
||||
@@ -14,14 +14,17 @@ import (
|
||||
type AuthZ interface {
|
||||
factory.Service
|
||||
|
||||
// Check returns error when the upstream authorization server is unavailable or the subject (s) doesn't have relation (r) on object (o).
|
||||
Check(context.Context, *openfgav1.TupleKey) error
|
||||
|
||||
// CheckWithTupleCreation takes upon the responsibility for generating the tuples alongside everything Check does.
|
||||
CheckWithTupleCreation(context.Context, authtypes.Claims, valuer.UUID, authtypes.Relation, authtypes.Typeable, []authtypes.Selector, []authtypes.Selector) error
|
||||
|
||||
// CheckWithTupleCreationWithoutClaims checks permissions for anonymous users.
|
||||
CheckWithTupleCreationWithoutClaims(context.Context, valuer.UUID, authtypes.Relation, authtypes.Typeable, []authtypes.Selector, []authtypes.Selector) error
|
||||
|
||||
// BatchCheck accepts a map of ID → tuple and returns a map of ID → authorization result.
|
||||
BatchCheck(context.Context, map[string]*openfgav1.TupleKey) (map[string]*authtypes.TupleKeyAuthorization, error)
|
||||
// Batch Check returns error when the upstream authorization server is unavailable or for all the tuples of subject (s) doesn't have relation (r) on object (o).
|
||||
BatchCheck(context.Context, []*openfgav1.TupleKey) error
|
||||
|
||||
// Write accepts the insertion tuples and the deletion tuples.
|
||||
Write(context.Context, []*openfgav1.TupleKey, []*openfgav1.TupleKey) error
|
||||
@@ -99,7 +102,5 @@ type Handler interface {
|
||||
|
||||
PatchObjects(http.ResponseWriter, *http.Request)
|
||||
|
||||
Check(http.ResponseWriter, *http.Request)
|
||||
|
||||
Delete(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ func (store *store) Create(ctx context.Context, role *roletypes.StorableRole) er
|
||||
Model(role).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, errors.CodeAlreadyExists, "role with name: %s already exists", role.Name)
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, errors.CodeAlreadyExists, "role with id: %s already exists", role.ID)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -48,7 +48,11 @@ func (provider *provider) Stop(ctx context.Context) error {
|
||||
return provider.server.Stop(ctx)
|
||||
}
|
||||
|
||||
func (provider *provider) BatchCheck(ctx context.Context, tupleReq map[string]*openfgav1.TupleKey) (map[string]*authtypes.TupleKeyAuthorization, error) {
|
||||
func (provider *provider) Check(ctx context.Context, tupleReq *openfgav1.TupleKey) error {
|
||||
return provider.server.Check(ctx, tupleReq)
|
||||
}
|
||||
|
||||
func (provider *provider) BatchCheck(ctx context.Context, tupleReq []*openfgav1.TupleKey) error {
|
||||
return provider.server.BatchCheck(ctx, tupleReq)
|
||||
}
|
||||
|
||||
@@ -177,6 +181,10 @@ func (provider *provider) CreateManagedRoles(ctx context.Context, _ valuer.UUID,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *provider) SetManagedRoleTransactions(context.Context, valuer.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *provider) CreateManagedUserRoleTransactions(ctx context.Context, orgID valuer.UUID, userID valuer.UUID) error {
|
||||
return provider.Grant(ctx, orgID, roletypes.SigNozAdminRoleName, authtypes.MustNewSubject(authtypes.TypeableUser, userID.String(), orgID, nil))
|
||||
}
|
||||
|
||||
@@ -90,18 +90,42 @@ func (server *Server) Stop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) BatchCheck(ctx context.Context, tupleReq map[string]*openfgav1.TupleKey) (map[string]*authtypes.TupleKeyAuthorization, error) {
|
||||
func (server *Server) Check(ctx context.Context, tupleReq *openfgav1.TupleKey) error {
|
||||
storeID, modelID := server.getStoreIDandModelID()
|
||||
batchCheckItems := make([]*openfgav1.BatchCheckItem, 0, len(tupleReq))
|
||||
for id, tuple := range tupleReq {
|
||||
checkResponse, err := server.openfgaServer.Check(
|
||||
ctx,
|
||||
&openfgav1.CheckRequest{
|
||||
StoreId: storeID,
|
||||
AuthorizationModelId: modelID,
|
||||
TupleKey: &openfgav1.CheckRequestTupleKey{
|
||||
User: tupleReq.User,
|
||||
Relation: tupleReq.Relation,
|
||||
Object: tupleReq.Object,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Newf(errors.TypeInternal, authtypes.ErrCodeAuthZUnavailable, "authorization server is unavailable").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
if !checkResponse.Allowed {
|
||||
return errors.Newf(errors.TypeForbidden, authtypes.ErrCodeAuthZForbidden, "subject %s cannot %s object %s", tupleReq.User, tupleReq.Relation, tupleReq.Object)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) BatchCheck(ctx context.Context, tupleReq []*openfgav1.TupleKey) error {
|
||||
storeID, modelID := server.getStoreIDandModelID()
|
||||
batchCheckItems := make([]*openfgav1.BatchCheckItem, 0)
|
||||
for idx, tuple := range tupleReq {
|
||||
batchCheckItems = append(batchCheckItems, &openfgav1.BatchCheckItem{
|
||||
TupleKey: &openfgav1.CheckRequestTupleKey{
|
||||
User: tuple.User,
|
||||
Relation: tuple.Relation,
|
||||
Object: tuple.Object,
|
||||
},
|
||||
// Use transaction ID as correlation ID for deterministic mapping
|
||||
CorrelationId: id,
|
||||
// the batch check response is map[string] keyed by correlationID.
|
||||
CorrelationId: strconv.Itoa(idx),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -113,18 +137,17 @@ func (server *Server) BatchCheck(ctx context.Context, tupleReq map[string]*openf
|
||||
Checks: batchCheckItems,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Newf(errors.TypeInternal, authtypes.ErrCodeAuthZUnavailable, "authorization server is unavailable").WithAdditional(err.Error())
|
||||
return errors.Newf(errors.TypeInternal, authtypes.ErrCodeAuthZUnavailable, "authorization server is unavailable").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
response := make(map[string]*authtypes.TupleKeyAuthorization, len(tupleReq))
|
||||
for id, tuple := range tupleReq {
|
||||
response[id] = &authtypes.TupleKeyAuthorization{
|
||||
Tuple: tuple,
|
||||
Authorized: checkResponse.Result[id].GetAllowed(),
|
||||
for _, checkResponse := range checkResponse.Result {
|
||||
if checkResponse.GetAllowed() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return response, nil
|
||||
return errors.Newf(errors.TypeForbidden, authtypes.ErrCodeAuthZForbidden, "subjects are not authorized for requested access")
|
||||
|
||||
}
|
||||
|
||||
func (server *Server) CheckWithTupleCreation(ctx context.Context, claims authtypes.Claims, orgID valuer.UUID, _ authtypes.Relation, _ authtypes.Typeable, _ []authtypes.Selector, roleSelectors []authtypes.Selector) error {
|
||||
@@ -133,29 +156,17 @@ func (server *Server) CheckWithTupleCreation(ctx context.Context, claims authtyp
|
||||
return err
|
||||
}
|
||||
|
||||
tupleSlice, err := authtypes.TypeableRole.Tuples(subject, authtypes.RelationAssignee, roleSelectors, orgID)
|
||||
tuples, err := authtypes.TypeableRole.Tuples(subject, authtypes.RelationAssignee, roleSelectors, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Convert slice to map with generated IDs for internal use
|
||||
tuples := make(map[string]*openfgav1.TupleKey, len(tupleSlice))
|
||||
for idx, tuple := range tupleSlice {
|
||||
tuples[strconv.Itoa(idx)] = tuple
|
||||
}
|
||||
|
||||
response, err := server.BatchCheck(ctx, tuples)
|
||||
err = server.BatchCheck(ctx, tuples)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, resp := range response {
|
||||
if resp.Authorized {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Newf(errors.TypeForbidden, authtypes.ErrCodeAuthZForbidden, "subjects are not authorized for requested access")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) CheckWithTupleCreationWithoutClaims(ctx context.Context, orgID valuer.UUID, _ authtypes.Relation, _ authtypes.Typeable, _ []authtypes.Selector, roleSelectors []authtypes.Selector) error {
|
||||
@@ -164,29 +175,17 @@ func (server *Server) CheckWithTupleCreationWithoutClaims(ctx context.Context, o
|
||||
return err
|
||||
}
|
||||
|
||||
tupleSlice, err := authtypes.TypeableRole.Tuples(subject, authtypes.RelationAssignee, roleSelectors, orgID)
|
||||
tuples, err := authtypes.TypeableRole.Tuples(subject, authtypes.RelationAssignee, roleSelectors, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Convert slice to map with generated IDs for internal use
|
||||
tuples := make(map[string]*openfgav1.TupleKey, len(tupleSlice))
|
||||
for idx, tuple := range tupleSlice {
|
||||
tuples[strconv.Itoa(idx)] = tuple
|
||||
}
|
||||
|
||||
response, err := server.BatchCheck(ctx, tuples)
|
||||
err = server.BatchCheck(ctx, tuples)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, resp := range response {
|
||||
if resp.Authorized {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Newf(errors.TypeForbidden, authtypes.ErrCodeAuthZForbidden, "subjects are not authorized for requested access")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) Write(ctx context.Context, additions []*openfgav1.TupleKey, deletions []*openfgav1.TupleKey) error {
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/http/binding"
|
||||
"github.com/SigNoz/signoz/pkg/http/render"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
@@ -36,14 +35,13 @@ func (handler *handler) Create(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
role := roletypes.NewRole(req.Name, req.Description, roletypes.RoleTypeCustom, valuer.MustNewUUID(claims.OrgID))
|
||||
err = handler.authz.Create(ctx, valuer.MustNewUUID(claims.OrgID), role)
|
||||
err = handler.authz.Create(ctx, valuer.MustNewUUID(claims.OrgID), roletypes.NewRole(req.Name, req.Description, roletypes.RoleTypeCustom, valuer.MustNewUUID(claims.OrgID)))
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusCreated, types.Identifiable{ID: role.ID})
|
||||
render.Success(rw, http.StatusCreated, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) Get(rw http.ResponseWriter, r *http.Request) {
|
||||
@@ -114,9 +112,17 @@ func (handler *handler) GetObjects(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (handler *handler) GetResources(rw http.ResponseWriter, r *http.Request) {
|
||||
resources := handler.authz.GetResources(r.Context())
|
||||
ctx := r.Context()
|
||||
resources := handler.authz.GetResources(ctx)
|
||||
|
||||
render.Success(rw, http.StatusOK, roletypes.NewGettableResources(resources))
|
||||
var resourceRelations = struct {
|
||||
Resources []*authtypes.Resource `json:"resources"`
|
||||
Relations map[authtypes.Type][]authtypes.Relation `json:"relations"`
|
||||
}{
|
||||
Resources: resources,
|
||||
Relations: authtypes.TypeableRelations,
|
||||
}
|
||||
render.Success(rw, http.StatusOK, resourceRelations)
|
||||
}
|
||||
|
||||
func (handler *handler) List(rw http.ResponseWriter, r *http.Request) {
|
||||
@@ -221,7 +227,7 @@ func (handler *handler) PatchObjects(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
render.Success(rw, http.StatusAccepted, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) Delete(rw http.ResponseWriter, r *http.Request) {
|
||||
@@ -246,39 +252,3 @@ func (handler *handler) Delete(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) Check(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
transactions := make([]*authtypes.Transaction, 0)
|
||||
if err := binding.JSON.BindBody(r.Body, &transactions); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID := valuer.MustNewUUID(claims.OrgID)
|
||||
subject, err := authtypes.NewSubject(authtypes.TypeableUser, claims.UserID, orgID, nil)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
tuples, err := authtypes.NewTuplesFromTransactions(transactions, subject, orgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
results, err := handler.authz.BatchCheck(ctx, tuples)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, authtypes.NewGettableTransaction(transactions, results))
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ func (m *module) ListPromotedAndIndexedPaths(ctx context.Context) ([]promotetype
|
||||
|
||||
// add the paths that are not promoted but have indexes
|
||||
for path, indexes := range aggr {
|
||||
path := strings.TrimPrefix(path, telemetrylogs.BodyJSONColumnPrefix)
|
||||
path := strings.TrimPrefix(path, telemetrylogs.BodyV2ColumnPrefix)
|
||||
path = telemetrytypes.BodyJSONStringSearchPrefix + path
|
||||
response = append(response, promotetypes.PromotePath{
|
||||
Path: path,
|
||||
@@ -156,7 +156,7 @@ func (m *module) PromoteAndIndexPaths(
|
||||
}
|
||||
}
|
||||
if len(it.Indexes) > 0 {
|
||||
parentColumn := telemetrylogs.LogsV2BodyJSONColumn
|
||||
parentColumn := telemetrylogs.LogsV2BodyV2Column
|
||||
// if the path is already promoted or is being promoted, add it to the promoted column
|
||||
if _, promoted := existingPromotedPaths[it.Path]; promoted || it.Promote {
|
||||
parentColumn = telemetrylogs.LogsV2BodyPromotedColumn
|
||||
|
||||
@@ -87,6 +87,24 @@ func (client *client) Read(ctx context.Context, query *prompb.Query, sortSeries
|
||||
return remote.FromQueryResult(sortSeries, res), nil
|
||||
}
|
||||
|
||||
func (c *client) ReadMultiple(ctx context.Context, queries []*prompb.Query, sortSeries bool) (storage.SeriesSet, error) {
|
||||
if len(queries) == 0 {
|
||||
return storage.EmptySeriesSet(), nil
|
||||
}
|
||||
if len(queries) == 1 {
|
||||
return c.Read(ctx, queries[0], sortSeries)
|
||||
}
|
||||
sets := make([]storage.SeriesSet, 0, len(queries))
|
||||
for _, q := range queries {
|
||||
ss, err := c.Read(ctx, q, sortSeries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sets = append(sets, ss)
|
||||
}
|
||||
return storage.NewMergeSeriesSet(sets, 0, storage.ChainedSeriesMerge), nil
|
||||
}
|
||||
|
||||
func (client *client) queryToClickhouseQuery(_ context.Context, query *prompb.Query, metricName string, subQuery bool) (string, []any, error) {
|
||||
var clickHouseQuery string
|
||||
var conditions []string
|
||||
|
||||
@@ -2,6 +2,7 @@ package prometheus
|
||||
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
"github.com/prometheus/prometheus/promql"
|
||||
)
|
||||
|
||||
@@ -15,30 +16,24 @@ func RemoveExtraLabels(res *promql.Result, labelsToRemove ...string) error {
|
||||
toRemove[l] = struct{}{}
|
||||
}
|
||||
|
||||
dropLabels := func(metric labels.Labels) labels.Labels {
|
||||
b := labels.NewBuilder(metric)
|
||||
for name := range toRemove {
|
||||
b.Del(name)
|
||||
}
|
||||
return b.Labels()
|
||||
}
|
||||
|
||||
switch res.Value.(type) {
|
||||
case promql.Vector:
|
||||
value := res.Value.(promql.Vector)
|
||||
for i := range value {
|
||||
series := &(value)[i]
|
||||
dst := series.Metric[:0]
|
||||
for _, lbl := range series.Metric {
|
||||
if _, drop := toRemove[lbl.Name]; !drop {
|
||||
dst = append(dst, lbl)
|
||||
}
|
||||
}
|
||||
series.Metric = dst
|
||||
(value)[i].Metric = dropLabels((value)[i].Metric)
|
||||
}
|
||||
case promql.Matrix:
|
||||
value := res.Value.(promql.Matrix)
|
||||
for i := range value {
|
||||
series := &(value)[i]
|
||||
dst := series.Metric[:0]
|
||||
for _, lbl := range series.Metric {
|
||||
if _, drop := toRemove[lbl.Name]; !drop {
|
||||
dst = append(dst, lbl)
|
||||
}
|
||||
}
|
||||
series.Metric = dst
|
||||
(value)[i].Metric = dropLabels((value)[i].Metric)
|
||||
}
|
||||
case promql.Scalar:
|
||||
return nil
|
||||
|
||||
@@ -10,11 +10,9 @@ import (
|
||||
|
||||
"github.com/ClickHouse/clickhouse-go/v2"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrylogs"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
||||
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
"github.com/bytedance/sonic"
|
||||
)
|
||||
|
||||
type builderQuery[T any] struct {
|
||||
@@ -250,40 +248,6 @@ func (q *builderQuery[T]) executeWithContext(ctx context.Context, query string,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// merge body_json and promoted into body
|
||||
if q.spec.Signal == telemetrytypes.SignalLogs {
|
||||
switch typedPayload := payload.(type) {
|
||||
case *qbtypes.RawData:
|
||||
for _, rr := range typedPayload.Rows {
|
||||
seeder := func() error {
|
||||
body, ok := rr.Data[telemetrylogs.LogsV2BodyJSONColumn].(map[string]any)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
promoted, ok := rr.Data[telemetrylogs.LogsV2BodyPromotedColumn].(map[string]any)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
seed(promoted, body)
|
||||
str, err := sonic.MarshalString(body)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to marshal body")
|
||||
}
|
||||
rr.Data["body"] = str
|
||||
return nil
|
||||
}
|
||||
err := seeder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
delete(rr.Data, telemetrylogs.LogsV2BodyJSONColumn)
|
||||
delete(rr.Data, telemetrylogs.LogsV2BodyPromotedColumn)
|
||||
}
|
||||
payload = typedPayload
|
||||
}
|
||||
}
|
||||
|
||||
return &qbtypes.Result{
|
||||
Type: q.kind,
|
||||
Value: payload,
|
||||
@@ -411,18 +375,3 @@ func decodeCursor(cur string) (int64, error) {
|
||||
}
|
||||
return strconv.ParseInt(string(b), 10, 64)
|
||||
}
|
||||
|
||||
func seed(promoted map[string]any, body map[string]any) {
|
||||
for key, fromValue := range promoted {
|
||||
if toValue, ok := body[key]; !ok {
|
||||
body[key] = fromValue
|
||||
} else {
|
||||
if fromValue, ok := fromValue.(map[string]any); ok {
|
||||
if toValue, ok := toValue.(map[string]any); ok {
|
||||
seed(fromValue, toValue)
|
||||
body[key] = toValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
|
||||
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
"github.com/bytedance/sonic"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -394,17 +393,11 @@ func readAsRaw(rows driver.Rows, queryName string) (*qbtypes.RawData, error) {
|
||||
|
||||
// de-reference the typed pointer to any
|
||||
val := reflect.ValueOf(cellPtr).Elem().Interface()
|
||||
|
||||
// Post-process JSON columns: normalize into structured values
|
||||
// Post-process JSON columns: normalize into String value
|
||||
if strings.HasPrefix(strings.ToUpper(colTypes[i].DatabaseTypeName()), "JSON") {
|
||||
switch x := val.(type) {
|
||||
case []byte:
|
||||
if len(x) > 0 {
|
||||
var v any
|
||||
if err := sonic.Unmarshal(x, &v); err == nil {
|
||||
val = v
|
||||
}
|
||||
}
|
||||
val = string(x)
|
||||
default:
|
||||
// already a structured type (map[string]any, []any, etc.)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/querybuilder"
|
||||
qbv5 "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
"github.com/prometheus/prometheus/promql"
|
||||
"github.com/prometheus/prometheus/promql/parser"
|
||||
)
|
||||
@@ -240,13 +241,13 @@ func (q *promqlQuery) Execute(ctx context.Context) (*qbv5.Result, error) {
|
||||
var series []*qbv5.TimeSeries
|
||||
for _, v := range matrix {
|
||||
var s qbv5.TimeSeries
|
||||
lbls := make([]*qbv5.Label, 0, len(v.Metric))
|
||||
for name, value := range v.Metric.Copy().Map() {
|
||||
lbls := make([]*qbv5.Label, 0, v.Metric.Len())
|
||||
v.Metric.Range(func(l labels.Label) {
|
||||
lbls = append(lbls, &qbv5.Label{
|
||||
Key: telemetrytypes.TelemetryFieldKey{Name: name},
|
||||
Value: value,
|
||||
Key: telemetrytypes.TelemetryFieldKey{Name: l.Name},
|
||||
Value: l.Value,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
s.Labels = lbls
|
||||
|
||||
|
||||
@@ -1913,7 +1913,7 @@ func (r *ClickHouseReader) GetCustomRetentionTTL(ctx context.Context, orgID stri
|
||||
// No V2 configuration found, return defaults
|
||||
response.DefaultTTLDays = 15
|
||||
response.TTLConditions = []model.CustomRetentionRule{}
|
||||
response.Status = constants.StatusSuccess
|
||||
response.Status = constants.StatusFailed
|
||||
response.ColdStorageTTLDays = -1
|
||||
return response, nil
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/types/ruletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
"github.com/prometheus/prometheus/promql"
|
||||
)
|
||||
|
||||
@@ -461,12 +462,12 @@ func toCommonSeries(series promql.Series) v3.Series {
|
||||
Points: make([]v3.Point, 0),
|
||||
}
|
||||
|
||||
for _, lbl := range series.Metric {
|
||||
commonSeries.Labels[lbl.Name] = lbl.Value
|
||||
series.Metric.Range(func(l labels.Label) {
|
||||
commonSeries.Labels[l.Name] = l.Value
|
||||
commonSeries.LabelsArray = append(commonSeries.LabelsArray, map[string]string{
|
||||
lbl.Name: lbl.Value,
|
||||
l.Name: l.Value,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
for _, f := range series.Floats {
|
||||
commonSeries.Points = append(commonSeries.Points, v3.Point{
|
||||
|
||||
@@ -204,7 +204,10 @@ func DataTypeCollisionHandledFieldName(key *telemetrytypes.TelemetryFieldKey, va
|
||||
// While we expect user not to send the mixed data types, it inevitably happens
|
||||
// So we handle the data type collisions here
|
||||
switch key.FieldDataType {
|
||||
case telemetrytypes.FieldDataTypeString, telemetrytypes.FieldDataTypeArrayString:
|
||||
case telemetrytypes.FieldDataTypeString, telemetrytypes.FieldDataTypeArrayString, telemetrytypes.FieldDataTypeJSON:
|
||||
if key.FieldDataType == telemetrytypes.FieldDataTypeJSON {
|
||||
tblFieldName = fmt.Sprintf("toString(%s)", tblFieldName)
|
||||
}
|
||||
switch v := value.(type) {
|
||||
case float64:
|
||||
// try to convert the string value to to number
|
||||
@@ -219,7 +222,6 @@ func DataTypeCollisionHandledFieldName(key *telemetrytypes.TelemetryFieldKey, va
|
||||
// we don't have a toBoolOrNull in ClickHouse, so we need to convert the bool to a string
|
||||
value = fmt.Sprintf("%t", v)
|
||||
}
|
||||
|
||||
case telemetrytypes.FieldDataTypeInt64,
|
||||
telemetrytypes.FieldDataTypeArrayInt64,
|
||||
telemetrytypes.FieldDataTypeNumber,
|
||||
|
||||
@@ -313,37 +313,31 @@ func (v *filterExpressionVisitor) VisitPrimary(ctx *grammar.PrimaryContext) any
|
||||
return ""
|
||||
}
|
||||
child := ctx.GetChild(0)
|
||||
var searchText string
|
||||
if keyCtx, ok := child.(*grammar.KeyContext); ok {
|
||||
// create a full text search condition on the body field
|
||||
|
||||
keyText := keyCtx.GetText()
|
||||
cond, err := v.conditionBuilder.ConditionFor(context.Background(), v.fullTextColumn, qbtypes.FilterOperatorRegexp, FormatFullTextSearch(keyText), v.builder, v.startNs, v.endNs)
|
||||
if err != nil {
|
||||
v.errors = append(v.errors, fmt.Sprintf("failed to build full text search condition: %s", err.Error()))
|
||||
return ""
|
||||
}
|
||||
return cond
|
||||
searchText = keyCtx.GetText()
|
||||
} else if valCtx, ok := child.(*grammar.ValueContext); ok {
|
||||
var text string
|
||||
if valCtx.QUOTED_TEXT() != nil {
|
||||
text = trimQuotes(valCtx.QUOTED_TEXT().GetText())
|
||||
searchText = trimQuotes(valCtx.QUOTED_TEXT().GetText())
|
||||
} else if valCtx.NUMBER() != nil {
|
||||
text = valCtx.NUMBER().GetText()
|
||||
searchText = valCtx.NUMBER().GetText()
|
||||
} else if valCtx.BOOL() != nil {
|
||||
text = valCtx.BOOL().GetText()
|
||||
searchText = valCtx.BOOL().GetText()
|
||||
} else if valCtx.KEY() != nil {
|
||||
text = valCtx.KEY().GetText()
|
||||
searchText = valCtx.KEY().GetText()
|
||||
} else {
|
||||
v.errors = append(v.errors, fmt.Sprintf("unsupported value type: %s", valCtx.GetText()))
|
||||
return ""
|
||||
}
|
||||
cond, err := v.conditionBuilder.ConditionFor(context.Background(), v.fullTextColumn, qbtypes.FilterOperatorRegexp, FormatFullTextSearch(text), v.builder, v.startNs, v.endNs)
|
||||
if err != nil {
|
||||
v.errors = append(v.errors, fmt.Sprintf("failed to build full text search condition: %s", err.Error()))
|
||||
return ""
|
||||
}
|
||||
return cond
|
||||
}
|
||||
cond, err := v.conditionBuilder.ConditionFor(context.Background(), v.fullTextColumn, qbtypes.FilterOperatorRegexp, FormatFullTextSearch(searchText), v.builder, v.startNs, v.endNs)
|
||||
if err != nil {
|
||||
v.errors = append(v.errors, fmt.Sprintf("failed to build full text search condition: %s", err.Error()))
|
||||
return ""
|
||||
}
|
||||
v.warnings = append(v.warnings, v.fullTextColumn.Warnings...)
|
||||
return cond
|
||||
}
|
||||
|
||||
return "" // Should not happen with valid input
|
||||
@@ -383,9 +377,11 @@ func (v *filterExpressionVisitor) VisitComparison(ctx *grammar.ComparisonContext
|
||||
for _, key := range keys {
|
||||
condition, err := v.conditionBuilder.ConditionFor(context.Background(), key, op, nil, v.builder, v.startNs, v.endNs)
|
||||
if err != nil {
|
||||
v.errors = append(v.errors, fmt.Sprintf("failed to build condition: %s", err.Error()))
|
||||
return ""
|
||||
}
|
||||
conds = append(conds, condition)
|
||||
v.warnings = append(v.warnings, key.Warnings...)
|
||||
}
|
||||
// if there is only one condition, return it directly, one less `()` wrapper
|
||||
if len(conds) == 1 {
|
||||
@@ -458,6 +454,7 @@ func (v *filterExpressionVisitor) VisitComparison(ctx *grammar.ComparisonContext
|
||||
return ""
|
||||
}
|
||||
conds = append(conds, condition)
|
||||
v.warnings = append(v.warnings, key.Warnings...)
|
||||
}
|
||||
if len(conds) == 1 {
|
||||
return conds[0]
|
||||
@@ -506,6 +503,7 @@ func (v *filterExpressionVisitor) VisitComparison(ctx *grammar.ComparisonContext
|
||||
return ""
|
||||
}
|
||||
conds = append(conds, condition)
|
||||
v.warnings = append(v.warnings, key.Warnings...)
|
||||
}
|
||||
if len(conds) == 1 {
|
||||
return conds[0]
|
||||
@@ -592,6 +590,7 @@ func (v *filterExpressionVisitor) VisitComparison(ctx *grammar.ComparisonContext
|
||||
return ""
|
||||
}
|
||||
conds = append(conds, condition)
|
||||
v.warnings = append(v.warnings, key.Warnings...)
|
||||
}
|
||||
if len(conds) == 1 {
|
||||
return conds[0]
|
||||
@@ -648,7 +647,6 @@ func (v *filterExpressionVisitor) VisitValueList(ctx *grammar.ValueListContext)
|
||||
|
||||
// VisitFullText handles standalone quoted strings for full-text search
|
||||
func (v *filterExpressionVisitor) VisitFullText(ctx *grammar.FullTextContext) any {
|
||||
|
||||
if v.skipFullTextFilter {
|
||||
return ""
|
||||
}
|
||||
@@ -670,6 +668,8 @@ func (v *filterExpressionVisitor) VisitFullText(ctx *grammar.FullTextContext) an
|
||||
v.errors = append(v.errors, fmt.Sprintf("failed to build full text search condition: %s", err.Error()))
|
||||
return ""
|
||||
}
|
||||
v.warnings = append(v.warnings, v.fullTextColumn.Warnings...)
|
||||
|
||||
return cond
|
||||
}
|
||||
|
||||
|
||||
@@ -35,13 +35,19 @@ func (c *conditionBuilder) conditionFor(
|
||||
return "", err
|
||||
}
|
||||
|
||||
if column.IsJSONColumn() && querybuilder.BodyJSONQueryEnabled {
|
||||
valueType, value := InferDataType(value, operator, key)
|
||||
cond, err := NewJSONConditionBuilder(key, valueType).buildJSONCondition(operator, value, sb)
|
||||
if err != nil {
|
||||
return "", err
|
||||
if column.Type.GetType() == schema.ColumnTypeEnumJSON {
|
||||
// If field data is Not JSON Column Itself, then we need to build a JSON condition
|
||||
if querybuilder.BodyJSONQueryEnabled && key.MustBuildJSONCondition() {
|
||||
valueType, value := InferDataType(value, operator, key)
|
||||
cond, err := NewJSONConditionBuilder(key, valueType).buildJSONCondition(operator, value, sb)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cond, nil
|
||||
} else if key.FieldDataType == telemetrytypes.FieldDataTypeJSON && !operator.IsOpValidForJSON() {
|
||||
// Skip building condition for invalid operators on JSON columns
|
||||
return "", nil
|
||||
}
|
||||
return cond, nil
|
||||
}
|
||||
|
||||
if operator.IsStringSearchOperator() {
|
||||
@@ -108,7 +114,6 @@ func (c *conditionBuilder) conditionFor(
|
||||
return sb.ILike(tblFieldName, fmt.Sprintf("%%%s%%", value)), nil
|
||||
case qbtypes.FilterOperatorNotContains:
|
||||
return sb.NotILike(tblFieldName, fmt.Sprintf("%%%s%%", value)), nil
|
||||
|
||||
case qbtypes.FilterOperatorRegexp:
|
||||
// Note: Escape $$ to $$$$ to avoid sqlbuilder interpreting materialized $ signs
|
||||
// Only needed because we are using sprintf instead of sb.Match (not implemented in sqlbuilder)
|
||||
@@ -176,9 +181,16 @@ func (c *conditionBuilder) conditionFor(
|
||||
var value any
|
||||
switch column.Type.GetType() {
|
||||
case schema.ColumnTypeEnumJSON:
|
||||
if operator == qbtypes.FilterOperatorExists {
|
||||
return sb.IsNotNull(tblFieldName), nil
|
||||
} else {
|
||||
switch key.FieldDataType {
|
||||
case telemetrytypes.FieldDataTypeJSON:
|
||||
if operator == qbtypes.FilterOperatorExists {
|
||||
return sb.EQ(fmt.Sprintf("empty(%s)", tblFieldName), false), nil
|
||||
}
|
||||
return sb.EQ(fmt.Sprintf("empty(%s)", tblFieldName), true), nil
|
||||
default:
|
||||
if operator == qbtypes.FilterOperatorExists {
|
||||
return sb.IsNotNull(tblFieldName), nil
|
||||
}
|
||||
return sb.IsNull(tblFieldName), nil
|
||||
}
|
||||
case schema.ColumnTypeEnumLowCardinality:
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package telemetrylogs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/SigNoz/signoz-otel-collector/constants"
|
||||
"github.com/SigNoz/signoz/pkg/querybuilder"
|
||||
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
)
|
||||
@@ -17,7 +20,7 @@ const (
|
||||
LogsV2TimestampColumn = "timestamp"
|
||||
LogsV2ObservedTimestampColumn = "observed_timestamp"
|
||||
LogsV2BodyColumn = "body"
|
||||
LogsV2BodyJSONColumn = constants.BodyJSONColumn
|
||||
LogsV2BodyV2Column = constants.BodyV2Column
|
||||
LogsV2BodyPromotedColumn = constants.BodyPromotedColumn
|
||||
LogsV2TraceIDColumn = "trace_id"
|
||||
LogsV2SpanIDColumn = "span_id"
|
||||
@@ -34,11 +37,23 @@ const (
|
||||
LogsV2ResourcesStringColumn = "resources_string"
|
||||
LogsV2ScopeStringColumn = "scope_string"
|
||||
|
||||
BodyJSONColumnPrefix = constants.BodyJSONColumnPrefix
|
||||
BodyV2ColumnPrefix = constants.BodyV2ColumnPrefix
|
||||
BodyPromotedColumnPrefix = constants.BodyPromotedColumnPrefix
|
||||
MessageSubColumn = "message"
|
||||
bodySearchDefaultWarning = "When you search on `body` (full text or by field), Query Builder uses body.message:string by default. Check that this matches what you want to search."
|
||||
)
|
||||
|
||||
var (
|
||||
// mapping for body logical field to message sub column
|
||||
// TODO(Piyush): Add description for detailed explanation of remapping of body to message
|
||||
BodyLogicalFieldJSONMapping = &telemetrytypes.TelemetryFieldKey{
|
||||
Name: MessageSubColumn,
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
FieldContext: telemetrytypes.FieldContextBody,
|
||||
FieldDataType: telemetrytypes.FieldDataTypeString,
|
||||
JSONDataType: &telemetrytypes.String,
|
||||
Warnings: []string{bodySearchDefaultWarning},
|
||||
}
|
||||
DefaultFullTextColumn = &telemetrytypes.TelemetryFieldKey{
|
||||
Name: "body",
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
@@ -118,3 +133,29 @@ var (
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func bodyAliasExpression() string {
|
||||
if !querybuilder.BodyJSONQueryEnabled {
|
||||
return LogsV2BodyColumn
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s as body", LogsV2BodyV2Column)
|
||||
}
|
||||
|
||||
func init() {
|
||||
// body logical field is mapped to message field in the body context that too only with String data type
|
||||
err := BodyLogicalFieldJSONMapping.SetJSONAccessPlan(telemetrytypes.JSONColumnMetadata{
|
||||
BaseColumn: LogsV2BodyV2Column,
|
||||
PromotedColumn: LogsV2BodyPromotedColumn,
|
||||
}, map[string][]telemetrytypes.JSONDataType{
|
||||
MessageSubColumn: {telemetrytypes.String},
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if querybuilder.BodyJSONQueryEnabled {
|
||||
DefaultFullTextColumn = BodyLogicalFieldJSONMapping
|
||||
IntrinsicFields["body"] = *BodyLogicalFieldJSONMapping
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ var (
|
||||
"severity_text": {Name: "severity_text", Type: schema.LowCardinalityColumnType{ElementType: schema.ColumnTypeString}},
|
||||
"severity_number": {Name: "severity_number", Type: schema.ColumnTypeUInt8},
|
||||
"body": {Name: "body", Type: schema.ColumnTypeString},
|
||||
LogsV2BodyJSONColumn: {Name: LogsV2BodyJSONColumn, Type: schema.JSONColumnType{
|
||||
LogsV2BodyV2Column: {Name: LogsV2BodyV2Column, Type: schema.JSONColumnType{
|
||||
MaxDynamicTypes: utils.ToPointer(uint(32)),
|
||||
MaxDynamicPaths: utils.ToPointer(uint(0)),
|
||||
}},
|
||||
@@ -89,9 +89,9 @@ func (m *fieldMapper) getColumn(_ context.Context, key *telemetrytypes.Telemetry
|
||||
}
|
||||
case telemetrytypes.FieldContextBody:
|
||||
// Body context is for JSON body fields
|
||||
// Use body_json if feature flag is enabled
|
||||
// Use body_v2 if feature flag is enabled
|
||||
if querybuilder.BodyJSONQueryEnabled {
|
||||
return logsV2Columns[LogsV2BodyJSONColumn], nil
|
||||
return logsV2Columns[LogsV2BodyV2Column], nil
|
||||
}
|
||||
// Fall back to legacy body column
|
||||
return logsV2Columns["body"], nil
|
||||
@@ -100,9 +100,9 @@ func (m *fieldMapper) getColumn(_ context.Context, key *telemetrytypes.Telemetry
|
||||
if !ok {
|
||||
// check if the key has body JSON search
|
||||
if strings.HasPrefix(key.Name, telemetrytypes.BodyJSONStringSearchPrefix) {
|
||||
// Use body_json if feature flag is enabled and we have a body condition builder
|
||||
// Use body_v2 if feature flag is enabled and we have a body condition builder
|
||||
if querybuilder.BodyJSONQueryEnabled {
|
||||
return logsV2Columns[LogsV2BodyJSONColumn], nil
|
||||
return logsV2Columns[LogsV2BodyV2Column], nil
|
||||
}
|
||||
// Fall back to legacy body column
|
||||
return logsV2Columns["body"], nil
|
||||
@@ -147,6 +147,9 @@ func (m *fieldMapper) FieldFor(ctx context.Context, key *telemetrytypes.Telemetr
|
||||
}
|
||||
|
||||
return m.buildFieldForJSON(key)
|
||||
case telemetrytypes.FieldContextLog:
|
||||
// return the column name as is for log context fields
|
||||
return column.Name, nil
|
||||
default:
|
||||
return "", errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "only resource/body context fields are supported for json columns, got %s", key.FieldContext.String)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func NewJSONConditionBuilder(key *telemetrytypes.TelemetryFieldKey, valueType te
|
||||
return &jsonConditionBuilder{key: key, valueType: telemetrytypes.MappingFieldDataTypeToJSONDataType[valueType]}
|
||||
}
|
||||
|
||||
// BuildCondition builds the full WHERE condition for body_json JSON paths
|
||||
// BuildCondition builds the full WHERE condition for body_v2 JSON paths
|
||||
func (c *jsonConditionBuilder) buildJSONCondition(operator qbtypes.FilterOperator, value any, sb *sqlbuilder.SelectBuilder) (string, error) {
|
||||
conditions := []string{}
|
||||
for _, node := range c.key.JSONPlan {
|
||||
@@ -40,6 +40,7 @@ func (c *jsonConditionBuilder) buildJSONCondition(operator qbtypes.FilterOperato
|
||||
}
|
||||
conditions = append(conditions, condition)
|
||||
}
|
||||
|
||||
return sb.Or(conditions...), nil
|
||||
}
|
||||
|
||||
@@ -288,9 +289,9 @@ func (c *jsonConditionBuilder) applyOperator(sb *sqlbuilder.SelectBuilder, field
|
||||
}
|
||||
return sb.NotIn(fieldExpr, values...), nil
|
||||
case qbtypes.FilterOperatorExists:
|
||||
return fmt.Sprintf("%s IS NOT NULL", fieldExpr), nil
|
||||
return sb.IsNotNull(fieldExpr), nil
|
||||
case qbtypes.FilterOperatorNotExists:
|
||||
return fmt.Sprintf("%s IS NULL", fieldExpr), nil
|
||||
return sb.IsNull(fieldExpr), nil
|
||||
// between and not between
|
||||
case qbtypes.FilterOperatorBetween, qbtypes.FilterOperatorNotBetween:
|
||||
values, ok := value.([]any)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -203,7 +203,6 @@ func (b *logQueryStatementBuilder) adjustKeys(ctx context.Context, keys map[stri
|
||||
}
|
||||
|
||||
func (b *logQueryStatementBuilder) adjustKey(key *telemetrytypes.TelemetryFieldKey, keys map[string][]*telemetrytypes.TelemetryFieldKey) []string {
|
||||
|
||||
// First check if it matches with any intrinsic fields
|
||||
var intrinsicOrCalculatedField telemetrytypes.TelemetryFieldKey
|
||||
if _, ok := IntrinsicFields[key.Name]; ok {
|
||||
@@ -212,7 +211,6 @@ func (b *logQueryStatementBuilder) adjustKey(key *telemetrytypes.TelemetryFieldK
|
||||
}
|
||||
|
||||
return querybuilder.AdjustKey(key, keys, nil)
|
||||
|
||||
}
|
||||
|
||||
// buildListQuery builds a query for list panel type
|
||||
@@ -249,11 +247,7 @@ func (b *logQueryStatementBuilder) buildListQuery(
|
||||
sb.SelectMore(LogsV2SeverityNumberColumn)
|
||||
sb.SelectMore(LogsV2ScopeNameColumn)
|
||||
sb.SelectMore(LogsV2ScopeVersionColumn)
|
||||
sb.SelectMore(LogsV2BodyColumn)
|
||||
if querybuilder.BodyJSONQueryEnabled {
|
||||
sb.SelectMore(LogsV2BodyJSONColumn)
|
||||
sb.SelectMore(LogsV2BodyPromotedColumn)
|
||||
}
|
||||
sb.SelectMore(bodyAliasExpression())
|
||||
sb.SelectMore(LogsV2AttributesStringColumn)
|
||||
sb.SelectMore(LogsV2AttributesNumberColumn)
|
||||
sb.SelectMore(LogsV2AttributesBoolColumn)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
||||
"github.com/SigNoz/signoz/pkg/querybuilder"
|
||||
"github.com/SigNoz/signoz/pkg/querybuilder/resourcefilter"
|
||||
@@ -886,3 +887,154 @@ func TestAdjustKey(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStmtBuilderBodyField(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
requestType qbtypes.RequestType
|
||||
query qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]
|
||||
enableBodyJSONQuery bool
|
||||
expected qbtypes.Statement
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
name: "body_exists",
|
||||
requestType: qbtypes.RequestTypeRaw,
|
||||
query: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
Filter: &qbtypes.Filter{Expression: "body Exists"},
|
||||
Limit: 10,
|
||||
},
|
||||
enableBodyJSONQuery: true,
|
||||
expected: qbtypes.Statement{
|
||||
Query: "WITH __resource_filter AS (SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE true AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ?) SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body_v2 as body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string FROM signoz_logs.distributed_logs_v2 WHERE resource_fingerprint GLOBAL IN (SELECT fingerprint FROM __resource_filter) AND (dynamicElement(body_v2.`message`, 'String') IS NOT NULL) AND timestamp >= ? AND ts_bucket_start >= ? AND timestamp < ? AND ts_bucket_start <= ? LIMIT ?",
|
||||
Args: []any{uint64(1747945619), uint64(1747983448), "1747947419000000000", uint64(1747945619), "1747983448000000000", uint64(1747983448), 10},
|
||||
Warnings: []string{bodySearchDefaultWarning},
|
||||
},
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "body_exists_disabled",
|
||||
requestType: qbtypes.RequestTypeRaw,
|
||||
query: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
Filter: &qbtypes.Filter{Expression: "body Exists"},
|
||||
Limit: 10,
|
||||
},
|
||||
enableBodyJSONQuery: false,
|
||||
expected: qbtypes.Statement{
|
||||
Query: "WITH __resource_filter AS (SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE true AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ?) SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string FROM signoz_logs.distributed_logs_v2 WHERE resource_fingerprint GLOBAL IN (SELECT fingerprint FROM __resource_filter) AND body <> ? AND timestamp >= ? AND ts_bucket_start >= ? AND timestamp < ? AND ts_bucket_start <= ? LIMIT ?",
|
||||
Args: []any{uint64(1747945619), uint64(1747983448), "", "1747947419000000000", uint64(1747945619), "1747983448000000000", uint64(1747983448), 10},
|
||||
},
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "body_empty",
|
||||
requestType: qbtypes.RequestTypeRaw,
|
||||
query: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
Filter: &qbtypes.Filter{Expression: "body == ''"},
|
||||
Limit: 10,
|
||||
},
|
||||
enableBodyJSONQuery: true,
|
||||
expected: qbtypes.Statement{
|
||||
Query: "WITH __resource_filter AS (SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE true AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ?) SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body_v2 as body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string FROM signoz_logs.distributed_logs_v2 WHERE resource_fingerprint GLOBAL IN (SELECT fingerprint FROM __resource_filter) AND (dynamicElement(body_v2.`message`, 'String') = ?) AND timestamp >= ? AND ts_bucket_start >= ? AND timestamp < ? AND ts_bucket_start <= ? LIMIT ?",
|
||||
Args: []any{uint64(1747945619), uint64(1747983448), "", "1747947419000000000", uint64(1747945619), "1747983448000000000", uint64(1747983448), 10},
|
||||
Warnings: []string{bodySearchDefaultWarning},
|
||||
},
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "body_empty_disabled",
|
||||
requestType: qbtypes.RequestTypeRaw,
|
||||
query: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
Filter: &qbtypes.Filter{Expression: "body == ''"},
|
||||
Limit: 10,
|
||||
},
|
||||
enableBodyJSONQuery: false,
|
||||
expected: qbtypes.Statement{
|
||||
Query: "WITH __resource_filter AS (SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE true AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ?) SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string FROM signoz_logs.distributed_logs_v2 WHERE resource_fingerprint GLOBAL IN (SELECT fingerprint FROM __resource_filter) AND body = ? AND timestamp >= ? AND ts_bucket_start >= ? AND timestamp < ? AND ts_bucket_start <= ? LIMIT ?",
|
||||
Args: []any{uint64(1747945619), uint64(1747983448), "", "1747947419000000000", uint64(1747945619), "1747983448000000000", uint64(1747983448), 10},
|
||||
},
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "body_contains",
|
||||
requestType: qbtypes.RequestTypeRaw,
|
||||
query: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
Filter: &qbtypes.Filter{Expression: "body CONTAINS 'error'"},
|
||||
Limit: 10,
|
||||
},
|
||||
enableBodyJSONQuery: true,
|
||||
expected: qbtypes.Statement{
|
||||
Query: "WITH __resource_filter AS (SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE true AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ?) SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body_v2 as body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string FROM signoz_logs.distributed_logs_v2 WHERE resource_fingerprint GLOBAL IN (SELECT fingerprint FROM __resource_filter) AND (LOWER(dynamicElement(body_v2.`message`, 'String')) LIKE LOWER(?)) AND timestamp >= ? AND ts_bucket_start >= ? AND timestamp < ? AND ts_bucket_start <= ? LIMIT ?",
|
||||
Args: []any{uint64(1747945619), uint64(1747983448), "%error%", "1747947419000000000", uint64(1747945619), "1747983448000000000", uint64(1747983448), 10},
|
||||
Warnings: []string{bodySearchDefaultWarning},
|
||||
},
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "body_contains_disabled",
|
||||
requestType: qbtypes.RequestTypeRaw,
|
||||
query: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
Filter: &qbtypes.Filter{Expression: "body CONTAINS 'error'"},
|
||||
Limit: 10,
|
||||
},
|
||||
enableBodyJSONQuery: false,
|
||||
expected: qbtypes.Statement{
|
||||
Query: "WITH __resource_filter AS (SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE true AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ?) SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string FROM signoz_logs.distributed_logs_v2 WHERE resource_fingerprint GLOBAL IN (SELECT fingerprint FROM __resource_filter) AND LOWER(body) LIKE LOWER(?) AND timestamp >= ? AND ts_bucket_start >= ? AND timestamp < ? AND ts_bucket_start <= ? LIMIT ?",
|
||||
Args: []any{uint64(1747945619), uint64(1747983448), "%error%", "1747947419000000000", uint64(1747945619), "1747983448000000000", uint64(1747983448), 10},
|
||||
},
|
||||
expectedErr: nil,
|
||||
},
|
||||
}
|
||||
|
||||
fm := NewFieldMapper()
|
||||
cb := NewConditionBuilder(fm)
|
||||
|
||||
enable, disable := jsonQueryTestUtil(t)
|
||||
defer disable()
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
if c.enableBodyJSONQuery {
|
||||
enable()
|
||||
} else {
|
||||
disable()
|
||||
}
|
||||
// build the key map after enabling/disabling body JSON query
|
||||
mockMetadataStore := telemetrytypestest.NewMockMetadataStore()
|
||||
mockMetadataStore.KeysMap = buildCompleteFieldKeyMap()
|
||||
|
||||
aggExprRewriter := querybuilder.NewAggExprRewriter(instrumentationtest.New().ToProviderSettings(), nil, fm, cb, nil)
|
||||
resourceFilterStmtBuilder := resourceFilterStmtBuilder()
|
||||
statementBuilder := NewLogQueryStatementBuilder(
|
||||
instrumentationtest.New().ToProviderSettings(),
|
||||
mockMetadataStore,
|
||||
fm,
|
||||
cb,
|
||||
resourceFilterStmtBuilder,
|
||||
aggExprRewriter,
|
||||
DefaultFullTextColumn,
|
||||
GetBodyJSONKey,
|
||||
)
|
||||
|
||||
q, err := statementBuilder.Build(context.Background(), 1747947419000, 1747983448000, c.requestType, c.query, nil)
|
||||
if c.expectedErr != nil {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), c.expectedErr.Error())
|
||||
} else {
|
||||
if err != nil {
|
||||
_, _, _, _, _, add := errors.Unwrapb(err)
|
||||
t.Logf("error additionals: %v", add)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, c.expected.Query, q.Query)
|
||||
require.Equal(t, c.expected.Args, q.Args)
|
||||
require.Equal(t, c.expected.Warnings, q.Warnings)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,13 +27,6 @@ func buildCompleteFieldKeyMap() map[string][]*telemetrytypes.TelemetryFieldKey {
|
||||
FieldDataType: telemetrytypes.FieldDataTypeString,
|
||||
},
|
||||
},
|
||||
"body": {
|
||||
{
|
||||
Name: "body",
|
||||
FieldContext: telemetrytypes.FieldContextLog,
|
||||
FieldDataType: telemetrytypes.FieldDataTypeString,
|
||||
},
|
||||
},
|
||||
"http.status_code": {
|
||||
{
|
||||
Name: "http.status_code",
|
||||
@@ -945,6 +938,11 @@ func buildCompleteFieldKeyMap() map[string][]*telemetrytypes.TelemetryFieldKey {
|
||||
key.Signal = telemetrytypes.SignalLogs
|
||||
}
|
||||
}
|
||||
|
||||
// add intrinsic fields to the map
|
||||
for fieldName, key := range IntrinsicFields {
|
||||
keysMap[fieldName] = append(keysMap[fieldName], &key)
|
||||
}
|
||||
return keysMap
|
||||
}
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ func buildListLogsJSONIndexesQuery(cluster string, filters ...string) (string, [
|
||||
sb.Where(sb.Equal("database", telemetrylogs.DBName))
|
||||
sb.Where(sb.Equal("table", telemetrylogs.LogsV2LocalTableName))
|
||||
sb.Where(sb.Or(
|
||||
sb.ILike("expr", fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains(constants.BodyJSONColumnPrefix))),
|
||||
sb.ILike("expr", fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains(constants.BodyV2ColumnPrefix))),
|
||||
sb.ILike("expr", fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains(constants.BodyPromotedColumnPrefix))),
|
||||
))
|
||||
|
||||
@@ -338,7 +338,7 @@ func (t *telemetryMetaStore) ListJSONValues(ctx context.Context, path string, li
|
||||
if promoted {
|
||||
path = telemetrylogs.BodyPromotedColumnPrefix + path
|
||||
} else {
|
||||
path = telemetrylogs.BodyJSONColumnPrefix + path
|
||||
path = telemetrylogs.BodyV2ColumnPrefix + path
|
||||
}
|
||||
|
||||
from := fmt.Sprintf("%s.%s", telemetrylogs.DBName, telemetrylogs.LogsV2TableName)
|
||||
@@ -529,7 +529,7 @@ func (t *telemetryMetaStore) GetPromotedPaths(ctx context.Context, paths ...stri
|
||||
// TODO(Piyush): Remove this function
|
||||
func CleanPathPrefixes(path string) string {
|
||||
path = strings.TrimPrefix(path, telemetrytypes.BodyJSONStringSearchPrefix)
|
||||
path = strings.TrimPrefix(path, telemetrylogs.BodyJSONColumnPrefix)
|
||||
path = strings.TrimPrefix(path, telemetrylogs.BodyV2ColumnPrefix)
|
||||
path = strings.TrimPrefix(path, telemetrylogs.BodyPromotedColumnPrefix)
|
||||
return path
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ func TestBuildListLogsJSONIndexesQuery(t *testing.T) {
|
||||
expectedArgs: []any{
|
||||
telemetrylogs.DBName,
|
||||
telemetrylogs.LogsV2LocalTableName,
|
||||
fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains(constants.BodyJSONColumnPrefix)),
|
||||
fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains(constants.BodyV2ColumnPrefix)),
|
||||
fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains(constants.BodyPromotedColumnPrefix)),
|
||||
},
|
||||
},
|
||||
@@ -130,7 +130,7 @@ func TestBuildListLogsJSONIndexesQuery(t *testing.T) {
|
||||
expectedArgs: []any{
|
||||
telemetrylogs.DBName,
|
||||
telemetrylogs.LogsV2LocalTableName,
|
||||
fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains(constants.BodyJSONColumnPrefix)),
|
||||
fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains(constants.BodyV2ColumnPrefix)),
|
||||
fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains(constants.BodyPromotedColumnPrefix)),
|
||||
fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains("foo")),
|
||||
fmt.Sprintf("%%%s%%", querybuilder.FormatValueForContains("bar")),
|
||||
|
||||
@@ -100,7 +100,7 @@ func NewTelemetryMetaStore(
|
||||
jsonColumnMetadata: map[telemetrytypes.Signal]map[telemetrytypes.FieldContext]telemetrytypes.JSONColumnMetadata{
|
||||
telemetrytypes.SignalLogs: {
|
||||
telemetrytypes.FieldContextBody: telemetrytypes.JSONColumnMetadata{
|
||||
BaseColumn: telemetrylogs.LogsV2BodyJSONColumn,
|
||||
BaseColumn: telemetrylogs.LogsV2BodyV2Column,
|
||||
PromotedColumn: telemetrylogs.LogsV2BodyPromotedColumn,
|
||||
},
|
||||
},
|
||||
@@ -333,7 +333,7 @@ func (t *telemetryMetaStore) logsTblStatementToFieldKeys(ctx context.Context) ([
|
||||
}
|
||||
|
||||
// getLogsKeys returns the keys from the spans that match the field selection criteria
|
||||
func (t *telemetryMetaStore) getLogsKeys(ctx context.Context, fieldKeySelectors []*telemetrytypes.FieldKeySelector) ([]*telemetrytypes.TelemetryFieldKey, bool, error) {
|
||||
func (t *telemetryMetaStore) getLogsKeys(ctx context.Context, fieldKeySelectors []*telemetrytypes.FieldKeySelector) (telemetrytypes.TelemetryFieldKeys, bool, error) {
|
||||
if len(fieldKeySelectors) == 0 {
|
||||
return nil, true, nil
|
||||
}
|
||||
@@ -343,9 +343,10 @@ func (t *telemetryMetaStore) getLogsKeys(ctx context.Context, fieldKeySelectors
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
mapOfKeys := make(map[string]*telemetrytypes.TelemetryFieldKey)
|
||||
// setOfKeys to reuse the same key object for qualified names
|
||||
setOfKeys := make(map[string]*telemetrytypes.TelemetryFieldKey)
|
||||
for _, key := range matKeys {
|
||||
mapOfKeys[key.Name+";"+key.FieldContext.StringValue()+";"+key.FieldDataType.StringValue()] = key
|
||||
setOfKeys[key.QualifiedName()] = key
|
||||
}
|
||||
|
||||
// queries for both attribute and resource keys tables
|
||||
@@ -446,7 +447,7 @@ func (t *telemetryMetaStore) getLogsKeys(ctx context.Context, fieldKeySelectors
|
||||
|
||||
if len(queries) == 0 {
|
||||
// No matching contexts, return empty result
|
||||
return []*telemetrytypes.TelemetryFieldKey{}, true, nil
|
||||
return nil, true, nil
|
||||
}
|
||||
|
||||
// Combine queries with UNION ALL
|
||||
@@ -474,7 +475,7 @@ func (t *telemetryMetaStore) getLogsKeys(ctx context.Context, fieldKeySelectors
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
keys := []*telemetrytypes.TelemetryFieldKey{}
|
||||
mapOfKeys := make(telemetrytypes.TelemetryFieldKeys)
|
||||
rowCount := 0
|
||||
searchTexts := []string{}
|
||||
dataTypes := []telemetrytypes.FieldDataType{}
|
||||
@@ -502,7 +503,7 @@ func (t *telemetryMetaStore) getLogsKeys(ctx context.Context, fieldKeySelectors
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, errors.TypeInternal, errors.CodeInternal, ErrFailedToGetLogsKeys.Error())
|
||||
}
|
||||
key, ok := mapOfKeys[name+";"+fieldContext.StringValue()+";"+fieldDataType.StringValue()]
|
||||
key, ok := setOfKeys[name+";"+fieldContext.StringValue()+";"+fieldDataType.StringValue()]
|
||||
|
||||
// if there is no materialised column, create a key with the field context and data type
|
||||
if !ok {
|
||||
@@ -514,8 +515,8 @@ func (t *telemetryMetaStore) getLogsKeys(ctx context.Context, fieldKeySelectors
|
||||
}
|
||||
}
|
||||
|
||||
keys = append(keys, key)
|
||||
mapOfKeys[name+";"+fieldContext.StringValue()+";"+fieldDataType.StringValue()] = key
|
||||
mapOfKeys[key.Name] = append(mapOfKeys[key.Name], key)
|
||||
setOfKeys[name+";"+fieldContext.StringValue()+";"+fieldDataType.StringValue()] = key
|
||||
}
|
||||
|
||||
if rows.Err() != nil {
|
||||
@@ -541,17 +542,13 @@ func (t *telemetryMetaStore) getLogsKeys(ctx context.Context, fieldKeySelectors
|
||||
|
||||
if found {
|
||||
if field, exists := telemetrylogs.IntrinsicFields[key]; exists {
|
||||
if _, added := mapOfKeys[field.Name+";"+field.FieldContext.StringValue()+";"+field.FieldDataType.StringValue()]; !added {
|
||||
keys = append(keys, &field)
|
||||
if _, added := setOfKeys[field.Name+";"+field.FieldContext.StringValue()+";"+field.FieldDataType.StringValue()]; !added {
|
||||
mapOfKeys[field.Name] = append(mapOfKeys[field.Name], &field)
|
||||
// intrinsic field can be a logical field mapped to a different physical location
|
||||
mapOfKeys[key] = append(mapOfKeys[key], &field)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
keys = append(keys, &telemetrytypes.TelemetryFieldKey{
|
||||
Name: key,
|
||||
FieldContext: telemetrytypes.FieldContextLog,
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,10 +557,13 @@ func (t *telemetryMetaStore) getLogsKeys(ctx context.Context, fieldKeySelectors
|
||||
if err != nil {
|
||||
t.logger.ErrorContext(ctx, "failed to extract body JSON paths", "error", err)
|
||||
}
|
||||
keys = append(keys, bodyJSONPaths...)
|
||||
for _, key := range bodyJSONPaths {
|
||||
mapOfKeys[key.Name] = append(mapOfKeys[key.Name], key)
|
||||
}
|
||||
complete = complete && finished
|
||||
}
|
||||
return keys, complete, nil
|
||||
|
||||
return mapOfKeys, complete, nil
|
||||
}
|
||||
|
||||
func getPriorityForContext(ctx telemetrytypes.FieldContext) int {
|
||||
@@ -847,12 +847,20 @@ func (t *telemetryMetaStore) GetKeys(ctx context.Context, fieldKeySelector *tele
|
||||
if fieldKeySelector != nil {
|
||||
selectors = []*telemetrytypes.FieldKeySelector{fieldKeySelector}
|
||||
}
|
||||
mapOfKeys := make(map[string][]*telemetrytypes.TelemetryFieldKey)
|
||||
|
||||
switch fieldKeySelector.Signal {
|
||||
case telemetrytypes.SignalTraces:
|
||||
keys, complete, err = t.getTracesKeys(ctx, selectors)
|
||||
case telemetrytypes.SignalLogs:
|
||||
keys, complete, err = t.getLogsKeys(ctx, selectors)
|
||||
mapOfLogKeys, logsComplete, err := t.getLogsKeys(ctx, selectors)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
for keyName, keys := range mapOfLogKeys {
|
||||
mapOfKeys[keyName] = append(mapOfKeys[keyName], keys...)
|
||||
}
|
||||
complete = complete && logsComplete
|
||||
case telemetrytypes.SignalMetrics:
|
||||
if fieldKeySelector.Source == telemetrytypes.SourceMeter {
|
||||
keys, complete, err = t.getMeterSourceMetricKeys(ctx, selectors)
|
||||
@@ -868,11 +876,14 @@ func (t *telemetryMetaStore) GetKeys(ctx context.Context, fieldKeySelector *tele
|
||||
keys = append(keys, tracesKeys...)
|
||||
|
||||
// get logs keys
|
||||
logsKeys, logsComplete, err := t.getLogsKeys(ctx, selectors)
|
||||
mapOfLogKeys, logsComplete, err := t.getLogsKeys(ctx, selectors)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
keys = append(keys, logsKeys...)
|
||||
for keyName, keys := range mapOfLogKeys {
|
||||
mapOfKeys[keyName] = append(mapOfKeys[keyName], keys...)
|
||||
}
|
||||
complete = complete && logsComplete
|
||||
|
||||
// get metrics keys
|
||||
metricsKeys, metricsComplete, err := t.getMetricsKeys(ctx, selectors)
|
||||
@@ -887,7 +898,6 @@ func (t *telemetryMetaStore) GetKeys(ctx context.Context, fieldKeySelector *tele
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
mapOfKeys := make(map[string][]*telemetrytypes.TelemetryFieldKey)
|
||||
for _, key := range keys {
|
||||
mapOfKeys[key.Name] = append(mapOfKeys[key.Name], key)
|
||||
}
|
||||
@@ -924,7 +934,7 @@ func (t *telemetryMetaStore) GetKeysMulti(ctx context.Context, fieldKeySelectors
|
||||
}
|
||||
}
|
||||
|
||||
logsKeys, logsComplete, err := t.getLogsKeys(ctx, logsSelectors)
|
||||
mapOfLogKeys, logsComplete, err := t.getLogsKeys(ctx, logsSelectors)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
@@ -945,8 +955,8 @@ func (t *telemetryMetaStore) GetKeysMulti(ctx context.Context, fieldKeySelectors
|
||||
complete := logsComplete && tracesComplete && metricsComplete
|
||||
|
||||
mapOfKeys := make(map[string][]*telemetrytypes.TelemetryFieldKey)
|
||||
for _, key := range logsKeys {
|
||||
mapOfKeys[key.Name] = append(mapOfKeys[key.Name], key)
|
||||
for keyName, keys := range mapOfLogKeys {
|
||||
mapOfKeys[keyName] = append(mapOfKeys[keyName], keys...)
|
||||
}
|
||||
for _, key := range tracesKeys {
|
||||
mapOfKeys[key.Name] = append(mapOfKeys[key.Name], key)
|
||||
|
||||
@@ -7,6 +7,6 @@ const (
|
||||
AttributesMetadataTableName = "distributed_attributes_metadata"
|
||||
AttributesMetadataLocalTableName = "attributes_metadata"
|
||||
PathTypesTableName = otelcollectorconst.DistributedPathTypesTable
|
||||
PromotedPathsTableName = otelcollectorconst.DistributedPromotedPathsTable
|
||||
PromotedPathsTableName = "distributed_json_promoted_paths"
|
||||
SkipIndexTableName = "system.data_skipping_indices"
|
||||
)
|
||||
|
||||
@@ -15,14 +15,15 @@ var (
|
||||
RelationUpdate = Relation{valuer.NewString("update")}
|
||||
RelationDelete = Relation{valuer.NewString("delete")}
|
||||
RelationList = Relation{valuer.NewString("list")}
|
||||
RelationBlock = Relation{valuer.NewString("block")}
|
||||
RelationAssignee = Relation{valuer.NewString("assignee")}
|
||||
)
|
||||
|
||||
var TypeableRelations = map[Type][]Relation{
|
||||
TypeUser: {RelationRead, RelationUpdate, RelationDelete},
|
||||
TypeRole: {RelationAssignee, RelationRead, RelationUpdate, RelationDelete},
|
||||
TypeOrganization: {RelationRead, RelationUpdate, RelationDelete},
|
||||
TypeMetaResource: {RelationRead, RelationUpdate, RelationDelete},
|
||||
TypeOrganization: {RelationCreate, RelationRead, RelationUpdate, RelationDelete, RelationList},
|
||||
TypeMetaResource: {RelationRead, RelationUpdate, RelationDelete, RelationBlock},
|
||||
TypeMetaResources: {RelationCreate, RelationList},
|
||||
}
|
||||
|
||||
@@ -40,6 +41,8 @@ func NewRelation(relation string) (Relation, error) {
|
||||
return RelationDelete, nil
|
||||
case "list":
|
||||
return RelationList, nil
|
||||
case "block":
|
||||
return RelationBlock, nil
|
||||
case "assignee":
|
||||
return RelationAssignee, nil
|
||||
default:
|
||||
|
||||
@@ -6,29 +6,21 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type Resource struct {
|
||||
Name Name `json:"name" required:"true"`
|
||||
Type Type `json:"type" required:"true"`
|
||||
Name Name `json:"name"`
|
||||
Type Type `json:"type"`
|
||||
}
|
||||
|
||||
type Object struct {
|
||||
Resource Resource `json:"resource" required:"true"`
|
||||
Selector Selector `json:"selector" required:"true"`
|
||||
Resource Resource `json:"resource"`
|
||||
Selector Selector `json:"selector"`
|
||||
}
|
||||
|
||||
type Transaction struct {
|
||||
ID valuer.UUID `json:"id"`
|
||||
Relation Relation `json:"relation" required:"true"`
|
||||
Object Object `json:"object" required:"true"`
|
||||
}
|
||||
|
||||
type GettableTransaction struct {
|
||||
Relation Relation `json:"relation" required:"true"`
|
||||
Object Object `json:"object" required:"true"`
|
||||
Authorized bool `json:"authorized" required:"true"`
|
||||
Relation Relation `json:"relation"`
|
||||
Object Object `json:"object"`
|
||||
}
|
||||
|
||||
func NewObject(resource Resource, selector Selector) (*Object, error) {
|
||||
@@ -83,21 +75,7 @@ func NewTransaction(relation Relation, object Object) (*Transaction, error) {
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, ErrCodeAuthZInvalidRelation, "invalid relation %s for type %s", relation.StringValue(), object.Resource.Type.StringValue())
|
||||
}
|
||||
|
||||
return &Transaction{ID: valuer.GenerateUUID(), Relation: relation, Object: object}, nil
|
||||
}
|
||||
|
||||
func NewGettableTransaction(transactions []*Transaction, results map[string]*TupleKeyAuthorization) []*GettableTransaction {
|
||||
gettableTransactions := make([]*GettableTransaction, len(transactions))
|
||||
for i, txn := range transactions {
|
||||
result := results[txn.ID.StringValue()]
|
||||
gettableTransactions[i] = &GettableTransaction{
|
||||
Relation: txn.Relation,
|
||||
Object: txn.Object,
|
||||
Authorized: result.Authorized,
|
||||
}
|
||||
}
|
||||
|
||||
return gettableTransactions
|
||||
return &Transaction{Relation: relation, Object: object}, nil
|
||||
}
|
||||
|
||||
func (object *Object) UnmarshalJSON(data []byte) error {
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
package authtypes
|
||||
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
openfgav1 "github.com/openfga/api/proto/openfga/v1"
|
||||
)
|
||||
|
||||
type TupleKeyAuthorization struct {
|
||||
Tuple *openfgav1.TupleKey
|
||||
Authorized bool
|
||||
}
|
||||
|
||||
func NewTuplesFromTransactions(transactions []*Transaction, subject string, orgID valuer.UUID) (map[string]*openfgav1.TupleKey, error) {
|
||||
tuples := make(map[string]*openfgav1.TupleKey, len(transactions))
|
||||
for _, txn := range transactions {
|
||||
typeable, err := NewTypeableFromType(txn.Object.Resource.Type, txn.Object.Resource.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txnTuples, err := typeable.Tuples(subject, txn.Relation, []Selector{txn.Object.Selector}, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Each transaction produces one tuple, keyed by transaction ID
|
||||
tuples[txn.ID.StringValue()] = txnTuples[0]
|
||||
}
|
||||
|
||||
return tuples, nil
|
||||
}
|
||||
@@ -36,8 +36,8 @@ func (i *PromotePath) ValidateAndSetDefaults() error {
|
||||
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "array paths can not be promoted or indexed")
|
||||
}
|
||||
|
||||
if strings.HasPrefix(i.Path, constants.BodyJSONColumnPrefix) || strings.HasPrefix(i.Path, constants.BodyPromotedColumnPrefix) {
|
||||
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "`%s`, `%s` don't add these prefixes to the path", constants.BodyJSONColumnPrefix, constants.BodyPromotedColumnPrefix)
|
||||
if strings.HasPrefix(i.Path, constants.BodyV2ColumnPrefix) || strings.HasPrefix(i.Path, constants.BodyPromotedColumnPrefix) {
|
||||
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "`%s`, `%s` don't add these prefixes to the path", constants.BodyV2ColumnPrefix, constants.BodyPromotedColumnPrefix)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(i.Path, telemetrytypes.BodyJSONStringSearchPrefix) {
|
||||
|
||||
@@ -197,6 +197,15 @@ func (f FilterOperator) IsArrayOperator() bool {
|
||||
}
|
||||
}
|
||||
|
||||
func (f FilterOperator) IsOpValidForJSON() bool {
|
||||
switch f {
|
||||
case FilterOperatorExists, FilterOperatorNotExists, FilterOperatorContains, FilterOperatorNotContains:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type OrderDirection struct {
|
||||
valuer.String
|
||||
}
|
||||
|
||||
@@ -69,29 +69,24 @@ type StorableRole struct {
|
||||
type Role struct {
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
Name string `json:"name" required:"true"`
|
||||
Description string `json:"description" required:"true"`
|
||||
Type valuer.String `json:"type" required:"true"`
|
||||
OrgID valuer.UUID `json:"orgId" required:"true"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Type valuer.String `json:"type"`
|
||||
OrgID valuer.UUID `json:"orgId"`
|
||||
}
|
||||
|
||||
type PostableRole struct {
|
||||
Name string `json:"name" required:"true"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type PatchableRole struct {
|
||||
Description string `json:"description" required:"true"`
|
||||
Description *string `json:"description"`
|
||||
}
|
||||
|
||||
type PatchableObjects struct {
|
||||
Additions []*authtypes.Object `json:"additions" required:"true"`
|
||||
Deletions []*authtypes.Object `json:"deletions" required:"true"`
|
||||
}
|
||||
|
||||
type GettableResources struct {
|
||||
Resources []*authtypes.Resource `json:"resources" required:"true"`
|
||||
Relations map[authtypes.Type][]authtypes.Relation `json:"relations" required:"true"`
|
||||
Additions []*authtypes.Object `json:"additions"`
|
||||
Deletions []*authtypes.Object `json:"deletions"`
|
||||
}
|
||||
|
||||
func NewStorableRoleFromRole(role *Role) *StorableRole {
|
||||
@@ -142,20 +137,15 @@ func NewManagedRoles(orgID valuer.UUID) []*Role {
|
||||
|
||||
}
|
||||
|
||||
func NewGettableResources(resources []*authtypes.Resource) *GettableResources {
|
||||
return &GettableResources{
|
||||
Resources: resources,
|
||||
Relations: authtypes.TypeableRelations,
|
||||
}
|
||||
}
|
||||
|
||||
func (role *Role) PatchMetadata(description string) error {
|
||||
func (role *Role) PatchMetadata(description *string) error {
|
||||
err := role.CanEditDelete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
role.Description = description
|
||||
if description != nil {
|
||||
role.Description = *description
|
||||
}
|
||||
role.UpdatedAt = time.Now()
|
||||
return nil
|
||||
}
|
||||
@@ -220,7 +210,7 @@ func (role *PostableRole) UnmarshalJSON(data []byte) error {
|
||||
|
||||
func (role *PatchableRole) UnmarshalJSON(data []byte) error {
|
||||
type shadowPatchableRole struct {
|
||||
Description string `json:"description"`
|
||||
Description *string `json:"description"`
|
||||
}
|
||||
|
||||
var shadowRole shadowPatchableRole
|
||||
@@ -228,7 +218,7 @@ func (role *PatchableRole) UnmarshalJSON(data []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if shadowRole.Description == "" {
|
||||
if shadowRole.Description == nil {
|
||||
return errors.New(errors.TypeInvalidInput, ErrCodeRoleEmptyPatch, "empty role patch request received, description must be present")
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ const (
|
||||
ArrayAnyIndexSuffix = "[*]"
|
||||
)
|
||||
|
||||
type TelemetryFieldKeys map[string][]*TelemetryFieldKey
|
||||
|
||||
type TelemetryFieldKey struct {
|
||||
Name string `json:"name" required:"true"`
|
||||
Description string `json:"description,omitempty"`
|
||||
@@ -41,6 +43,7 @@ type TelemetryFieldKey struct {
|
||||
JSONPlan JSONAccessPlan `json:"-"`
|
||||
Indexes []JSONDataTypeIndex `json:"-"`
|
||||
Materialized bool `json:"-"` // refers to promoted in case of body.... fields
|
||||
Warnings []string `json:"-"` // warnings attached to using a particular field key
|
||||
}
|
||||
|
||||
func (f *TelemetryFieldKey) KeyNameContainsArray() bool {
|
||||
@@ -62,6 +65,10 @@ func (f *TelemetryFieldKey) ArrayParentPaths() []string {
|
||||
return paths
|
||||
}
|
||||
|
||||
func (f *TelemetryFieldKey) MustBuildJSONCondition() bool {
|
||||
return f.FieldDataType != FieldDataTypeJSON && f.JSONDataType != nil
|
||||
}
|
||||
|
||||
func (f *TelemetryFieldKey) ArrayParentSelectors() []*FieldKeySelector {
|
||||
paths := f.ArrayParentPaths()
|
||||
selectors := make([]*FieldKeySelector, 0, len(paths))
|
||||
@@ -169,6 +176,10 @@ func (f *TelemetryFieldKey) Normalize() {
|
||||
|
||||
}
|
||||
|
||||
func (f *TelemetryFieldKey) QualifiedName() string {
|
||||
return f.Name + ";" + f.FieldContext.StringValue() + ";" + f.FieldDataType.StringValue()
|
||||
}
|
||||
|
||||
// GetFieldKeyFromKeyText returns a TelemetryFieldKey from a key text.
|
||||
// The key text is expected to be in the format of `fieldContext.fieldName:fieldDataType` in the search query.
|
||||
// Both fieldContext and :fieldDataType are optional.
|
||||
|
||||
@@ -21,6 +21,7 @@ var (
|
||||
// int64 and number are synonyms for float64
|
||||
FieldDataTypeInt64 = FieldDataType{valuer.NewString("int64")}
|
||||
FieldDataTypeNumber = FieldDataType{valuer.NewString("number")}
|
||||
FieldDataTypeJSON = FieldDataType{valuer.NewString("json")}
|
||||
FieldDataTypeUnspecified = FieldDataType{valuer.NewString("")}
|
||||
|
||||
FieldDataTypeArrayString = FieldDataType{valuer.NewString("[]string")}
|
||||
|
||||
@@ -40,7 +40,7 @@ type JSONAccessNode struct {
|
||||
// Node information
|
||||
Name string
|
||||
IsTerminal bool
|
||||
isRoot bool // marked true for only body_json and body_json_promoted
|
||||
isRoot bool // marked true for only body_v2 and body_promoted
|
||||
|
||||
// Precomputed type information (single source of truth)
|
||||
AvailableTypes []JSONDataType
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
package telemetrytypes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
otelconstants "github.com/SigNoz/signoz-otel-collector/constants"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const (
|
||||
bodyV2Column = otelconstants.BodyV2Column
|
||||
bodyPromotedColumn = otelconstants.BodyPromotedColumn
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// Helper Functions for Test Data Creation
|
||||
// ============================================================================
|
||||
@@ -109,8 +116,8 @@ func TestNode_Alias(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "Root node returns name as-is",
|
||||
node: NewRootJSONAccessNode("body_json", 32, 0),
|
||||
expected: "body_json",
|
||||
node: NewRootJSONAccessNode(bodyV2Column, 32, 0),
|
||||
expected: bodyV2Column,
|
||||
},
|
||||
{
|
||||
name: "Node without parent returns backticked name",
|
||||
@@ -124,9 +131,9 @@ func TestNode_Alias(t *testing.T) {
|
||||
name: "Node with root parent uses dot separator",
|
||||
node: &JSONAccessNode{
|
||||
Name: "age",
|
||||
Parent: NewRootJSONAccessNode("body_json", 32, 0),
|
||||
Parent: NewRootJSONAccessNode(bodyV2Column, 32, 0),
|
||||
},
|
||||
expected: "`" + "body_json" + ".age`",
|
||||
expected: "`" + bodyV2Column + ".age`",
|
||||
},
|
||||
{
|
||||
name: "Node with non-root parent uses array separator",
|
||||
@@ -134,10 +141,10 @@ func TestNode_Alias(t *testing.T) {
|
||||
Name: "name",
|
||||
Parent: &JSONAccessNode{
|
||||
Name: "education",
|
||||
Parent: NewRootJSONAccessNode("body_json", 32, 0),
|
||||
Parent: NewRootJSONAccessNode(bodyV2Column, 32, 0),
|
||||
},
|
||||
},
|
||||
expected: "`" + "body_json" + ".education[].name`",
|
||||
expected: "`" + bodyV2Column + ".education[].name`",
|
||||
},
|
||||
{
|
||||
name: "Nested array path with multiple levels",
|
||||
@@ -147,11 +154,11 @@ func TestNode_Alias(t *testing.T) {
|
||||
Name: "awards",
|
||||
Parent: &JSONAccessNode{
|
||||
Name: "education",
|
||||
Parent: NewRootJSONAccessNode("body_json", 32, 0),
|
||||
Parent: NewRootJSONAccessNode(bodyV2Column, 32, 0),
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "`" + "body_json" + ".education[].awards[].type`",
|
||||
expected: "`" + bodyV2Column + ".education[].awards[].type`",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -173,18 +180,18 @@ func TestNode_FieldPath(t *testing.T) {
|
||||
name: "Simple field path from root",
|
||||
node: &JSONAccessNode{
|
||||
Name: "user",
|
||||
Parent: NewRootJSONAccessNode("body_json", 32, 0),
|
||||
Parent: NewRootJSONAccessNode(bodyV2Column, 32, 0),
|
||||
},
|
||||
// FieldPath() always wraps the field name in backticks
|
||||
expected: "body_json" + ".`user`",
|
||||
expected: bodyV2Column + ".`user`",
|
||||
},
|
||||
{
|
||||
name: "Field path with backtick-required key",
|
||||
node: &JSONAccessNode{
|
||||
Name: "user-name", // requires backtick
|
||||
Parent: NewRootJSONAccessNode("body_json", 32, 0),
|
||||
Parent: NewRootJSONAccessNode(bodyV2Column, 32, 0),
|
||||
},
|
||||
expected: "body_json" + ".`user-name`",
|
||||
expected: bodyV2Column + ".`user-name`",
|
||||
},
|
||||
{
|
||||
name: "Nested field path",
|
||||
@@ -192,11 +199,11 @@ func TestNode_FieldPath(t *testing.T) {
|
||||
Name: "age",
|
||||
Parent: &JSONAccessNode{
|
||||
Name: "user",
|
||||
Parent: NewRootJSONAccessNode("body_json", 32, 0),
|
||||
Parent: NewRootJSONAccessNode(bodyV2Column, 32, 0),
|
||||
},
|
||||
},
|
||||
// FieldPath() always wraps the field name in backticks
|
||||
expected: "`" + "body_json" + ".user`.`age`",
|
||||
expected: "`" + bodyV2Column + ".user`.`age`",
|
||||
},
|
||||
{
|
||||
name: "Array element field path",
|
||||
@@ -204,11 +211,11 @@ func TestNode_FieldPath(t *testing.T) {
|
||||
Name: "name",
|
||||
Parent: &JSONAccessNode{
|
||||
Name: "education",
|
||||
Parent: NewRootJSONAccessNode("body_json", 32, 0),
|
||||
Parent: NewRootJSONAccessNode(bodyV2Column, 32, 0),
|
||||
},
|
||||
},
|
||||
// FieldPath() always wraps the field name in backticks
|
||||
expected: "`" + "body_json" + ".education`.`name`",
|
||||
expected: "`" + bodyV2Column + ".education`.`name`",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -236,36 +243,36 @@ func TestPlanJSON_BasicStructure(t *testing.T) {
|
||||
{
|
||||
name: "Simple path not promoted",
|
||||
key: makeKey("user.name", String, false),
|
||||
expectedYAML: `
|
||||
expectedYAML: fmt.Sprintf(`
|
||||
- name: user.name
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- String
|
||||
maxDynamicTypes: 16
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`,
|
||||
`, bodyV2Column),
|
||||
},
|
||||
{
|
||||
name: "Simple path promoted",
|
||||
key: makeKey("user.name", String, true),
|
||||
expectedYAML: `
|
||||
expectedYAML: fmt.Sprintf(`
|
||||
- name: user.name
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- String
|
||||
maxDynamicTypes: 16
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
- name: user.name
|
||||
column: body_json_promoted
|
||||
column: %s
|
||||
availableTypes:
|
||||
- String
|
||||
maxDynamicTypes: 16
|
||||
maxDynamicPaths: 256
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`,
|
||||
`, bodyV2Column, bodyPromotedColumn),
|
||||
},
|
||||
{
|
||||
name: "Empty path returns error",
|
||||
@@ -278,8 +285,8 @@ func TestPlanJSON_BasicStructure(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.key.SetJSONAccessPlan(JSONColumnMetadata{
|
||||
BaseColumn: "body_json",
|
||||
PromotedColumn: "body_json_promoted",
|
||||
BaseColumn: bodyV2Column,
|
||||
PromotedColumn: bodyPromotedColumn,
|
||||
}, types)
|
||||
if tt.expectErr {
|
||||
require.Error(t, err)
|
||||
@@ -304,9 +311,9 @@ func TestPlanJSON_ArrayPaths(t *testing.T) {
|
||||
{
|
||||
name: "Single array level - JSON branch only",
|
||||
path: "education[].name",
|
||||
expectedYAML: `
|
||||
expectedYAML: fmt.Sprintf(`
|
||||
- name: education
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
@@ -318,14 +325,14 @@ func TestPlanJSON_ArrayPaths(t *testing.T) {
|
||||
maxDynamicTypes: 8
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`,
|
||||
`, bodyV2Column),
|
||||
},
|
||||
{
|
||||
name: "Single array level - both JSON and Dynamic branches",
|
||||
path: "education[].awards[].type",
|
||||
expectedYAML: `
|
||||
expectedYAML: fmt.Sprintf(`
|
||||
- name: education
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
@@ -352,14 +359,14 @@ func TestPlanJSON_ArrayPaths(t *testing.T) {
|
||||
maxDynamicPaths: 256
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`,
|
||||
`, bodyV2Column),
|
||||
},
|
||||
{
|
||||
name: "Deeply nested array path",
|
||||
path: "interests[].entities[].reviews[].entries[].metadata[].positions[].name",
|
||||
expectedYAML: `
|
||||
expectedYAML: fmt.Sprintf(`
|
||||
- name: interests
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
@@ -399,14 +406,14 @@ func TestPlanJSON_ArrayPaths(t *testing.T) {
|
||||
- String
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`,
|
||||
`, bodyV2Column),
|
||||
},
|
||||
{
|
||||
name: "ArrayAnyIndex replacement [*] to []",
|
||||
path: "education[*].name",
|
||||
expectedYAML: `
|
||||
expectedYAML: fmt.Sprintf(`
|
||||
- name: education
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
@@ -418,7 +425,7 @@ func TestPlanJSON_ArrayPaths(t *testing.T) {
|
||||
maxDynamicTypes: 8
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`,
|
||||
`, bodyV2Column),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -426,8 +433,8 @@ func TestPlanJSON_ArrayPaths(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
key := makeKey(tt.path, String, false)
|
||||
err := key.SetJSONAccessPlan(JSONColumnMetadata{
|
||||
BaseColumn: "body_json",
|
||||
PromotedColumn: "body_json_promoted",
|
||||
BaseColumn: bodyV2Column,
|
||||
PromotedColumn: bodyPromotedColumn,
|
||||
}, types)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, key.JSONPlan)
|
||||
@@ -445,15 +452,15 @@ func TestPlanJSON_PromotedVsNonPromoted(t *testing.T) {
|
||||
t.Run("Non-promoted plan", func(t *testing.T) {
|
||||
key := makeKey(path, String, false)
|
||||
err := key.SetJSONAccessPlan(JSONColumnMetadata{
|
||||
BaseColumn: "body_json",
|
||||
PromotedColumn: "body_json_promoted",
|
||||
BaseColumn: bodyV2Column,
|
||||
PromotedColumn: bodyPromotedColumn,
|
||||
}, types)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, key.JSONPlan, 1)
|
||||
|
||||
expectedYAML := `
|
||||
expectedYAML := fmt.Sprintf(`
|
||||
- name: education
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
@@ -480,7 +487,7 @@ func TestPlanJSON_PromotedVsNonPromoted(t *testing.T) {
|
||||
maxDynamicPaths: 256
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`
|
||||
`, bodyV2Column)
|
||||
got := plansToYAML(t, key.JSONPlan)
|
||||
require.YAMLEq(t, expectedYAML, got)
|
||||
})
|
||||
@@ -488,15 +495,15 @@ func TestPlanJSON_PromotedVsNonPromoted(t *testing.T) {
|
||||
t.Run("Promoted plan", func(t *testing.T) {
|
||||
key := makeKey(path, String, true)
|
||||
err := key.SetJSONAccessPlan(JSONColumnMetadata{
|
||||
BaseColumn: "body_json",
|
||||
PromotedColumn: "body_json_promoted",
|
||||
BaseColumn: bodyV2Column,
|
||||
PromotedColumn: bodyPromotedColumn,
|
||||
}, types)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, key.JSONPlan, 2)
|
||||
|
||||
expectedYAML := `
|
||||
expectedYAML := fmt.Sprintf(`
|
||||
- name: education
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
@@ -524,7 +531,7 @@ func TestPlanJSON_PromotedVsNonPromoted(t *testing.T) {
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
- name: education
|
||||
column: body_json_promoted
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
@@ -554,7 +561,7 @@ func TestPlanJSON_PromotedVsNonPromoted(t *testing.T) {
|
||||
maxDynamicPaths: 256
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`
|
||||
`, bodyV2Column, bodyPromotedColumn)
|
||||
got := plansToYAML(t, key.JSONPlan)
|
||||
require.YAMLEq(t, expectedYAML, got)
|
||||
})
|
||||
@@ -575,11 +582,11 @@ func TestPlanJSON_EdgeCases(t *testing.T) {
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Very deep nesting - validates progression doesn't go negative",
|
||||
path: "interests[].entities[].reviews[].entries[].metadata[].positions[].name",
|
||||
expectedYAML: `
|
||||
name: "Very deep nesting - validates progression doesn't go negative",
|
||||
path: "interests[].entities[].reviews[].entries[].metadata[].positions[].name",
|
||||
expectedYAML: fmt.Sprintf(`
|
||||
- name: interests
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
@@ -619,14 +626,14 @@ func TestPlanJSON_EdgeCases(t *testing.T) {
|
||||
- String
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`,
|
||||
`, bodyV2Column),
|
||||
},
|
||||
{
|
||||
name: "Path with mixed scalar and array types",
|
||||
path: "education[].type",
|
||||
expectedYAML: `
|
||||
name: "Path with mixed scalar and array types",
|
||||
path: "education[].type",
|
||||
expectedYAML: fmt.Sprintf(`
|
||||
- name: education
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
@@ -639,20 +646,20 @@ func TestPlanJSON_EdgeCases(t *testing.T) {
|
||||
maxDynamicTypes: 8
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`,
|
||||
`, bodyV2Column),
|
||||
},
|
||||
{
|
||||
name: "Exists with only array types available",
|
||||
path: "education",
|
||||
expectedYAML: `
|
||||
name: "Exists with only array types available",
|
||||
path: "education",
|
||||
expectedYAML: fmt.Sprintf(`
|
||||
- name: education
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
isTerminal: true
|
||||
elemType: Array(JSON)
|
||||
`,
|
||||
`, bodyV2Column),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -668,8 +675,8 @@ func TestPlanJSON_EdgeCases(t *testing.T) {
|
||||
}
|
||||
key := makeKey(tt.path, keyType, false)
|
||||
err := key.SetJSONAccessPlan(JSONColumnMetadata{
|
||||
BaseColumn: "body_json",
|
||||
PromotedColumn: "body_json_promoted",
|
||||
BaseColumn: bodyV2Column,
|
||||
PromotedColumn: bodyPromotedColumn,
|
||||
}, types)
|
||||
if tt.expectErr {
|
||||
require.Error(t, err)
|
||||
@@ -687,15 +694,15 @@ func TestPlanJSON_TreeStructure(t *testing.T) {
|
||||
path := "education[].awards[].participated[].team[].branch"
|
||||
key := makeKey(path, String, false)
|
||||
err := key.SetJSONAccessPlan(JSONColumnMetadata{
|
||||
BaseColumn: "body_json",
|
||||
PromotedColumn: "body_json_promoted",
|
||||
BaseColumn: bodyV2Column,
|
||||
PromotedColumn: bodyPromotedColumn,
|
||||
}, types)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, key.JSONPlan, 1)
|
||||
|
||||
expectedYAML := `
|
||||
expectedYAML := fmt.Sprintf(`
|
||||
- name: education
|
||||
column: body_json
|
||||
column: %s
|
||||
availableTypes:
|
||||
- Array(JSON)
|
||||
maxDynamicTypes: 16
|
||||
@@ -780,7 +787,7 @@ func TestPlanJSON_TreeStructure(t *testing.T) {
|
||||
maxDynamicPaths: 64
|
||||
isTerminal: true
|
||||
elemType: String
|
||||
`
|
||||
`, bodyV2Column)
|
||||
|
||||
got := plansToYAML(t, key.JSONPlan)
|
||||
require.YAMLEq(t, expectedYAML, got)
|
||||
|
||||
@@ -2,6 +2,7 @@ package telemetrytypestest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
schemamigrator "github.com/SigNoz/signoz-otel-collector/cmd/signozschemamigrator/schema_migrator"
|
||||
@@ -176,8 +177,9 @@ func matchesKey(selector *telemetrytypes.FieldKeySelector, key *telemetrytypes.T
|
||||
return true
|
||||
}
|
||||
|
||||
matchNameExceptions := []string{"body"}
|
||||
// Check name (already checked in matchesName, but double-check here)
|
||||
if selector.Name != "" && !matchesName(selector, key.Name) {
|
||||
if selector.Name != "" && !matchesName(selector, key.Name) && slices.Contains(matchNameExceptions, key.Name) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user