Compare commits

..

6 Commits

Author SHA1 Message Date
Ashwin Bhatkal
dd7a9f283a test: format file 2026-05-13 16:58:34 +05:30
Ashwin Bhatkal
e787d9df55 test: move from fixtures to seeder 2026-05-13 15:36:59 +05:30
Ashwin Bhatkal
5a9f8b249b test: add teardown bits 2026-05-13 15:34:25 +05:30
Ashwin Bhatkal
52432cbf54 test: new playwright project to seed data 2026-05-13 15:34:25 +05:30
Nityananda Gohain
b55c009c31 fix: disable opamp integration for llm (#11284) 2026-05-13 08:38:29 +00:00
Gaurav Tewari
9cb6228da5 fix: replace logs with list icon (#11283)
Co-authored-by: Gaurav Tewari <tewarig@users.noreply.github.com>
2026-05-13 08:11:45 +00:00
36 changed files with 7883 additions and 1449 deletions

View File

@@ -66,9 +66,10 @@ func runGenerateAuthz(_ context.Context) error {
registry := coretypes.NewRegistry()
allowedResources := map[string]bool{
coretypes.NewResourceRef(coretypes.ResourceServiceAccount).String(): true,
coretypes.NewResourceRef(coretypes.ResourceRole).String(): true,
coretypes.NewResourceRef(coretypes.ResourceMetaResourceFactorAPIKey).String(): true,
coretypes.NewResourceRef(coretypes.ResourceServiceAccount).String(): true,
coretypes.NewResourceRef(coretypes.ResourceMetaResourcesServiceAccount).String(): true,
coretypes.NewResourceRef(coretypes.ResourceRole).String(): true,
coretypes.NewResourceRef(coretypes.ResourceMetaResourcesRole).String(): true,
}
allowedTypes := map[string]bool{}

View File

@@ -449,7 +449,6 @@ components:
- list
- assignee
- attach
- detach
type: string
AuthtypesRole:
properties:
@@ -2207,6 +2206,7 @@ components:
- role
- organization
- metaresource
- metaresources
type: string
DashboardtypesDashboard:
properties:
@@ -9098,9 +9098,9 @@ paths:
description: Internal Server Error
security:
- api_key:
- role:list
- ADMIN
- tokenizer:
- role:list
- ADMIN
summary: List roles
tags:
- role
@@ -9172,9 +9172,9 @@ paths:
description: Not Implemented
security:
- api_key:
- role:create
- ADMIN
- tokenizer:
- role:create
- ADMIN
summary: Create role
tags:
- role
@@ -9234,9 +9234,9 @@ paths:
description: Not Implemented
security:
- api_key:
- role:delete
- ADMIN
- tokenizer:
- role:delete
- ADMIN
summary: Delete role
tags:
- role
@@ -9285,9 +9285,9 @@ paths:
description: Internal Server Error
security:
- api_key:
- role:read
- ADMIN
- tokenizer:
- role:read
- ADMIN
summary: Get role
tags:
- role
@@ -9351,9 +9351,9 @@ paths:
description: Not Implemented
security:
- api_key:
- role:update
- ADMIN
- tokenizer:
- role:update
- ADMIN
summary: Patch role
tags:
- role
@@ -9429,9 +9429,9 @@ paths:
description: Not Implemented
security:
- api_key:
- role:read
- ADMIN
- tokenizer:
- role:read
- ADMIN
summary: Get objects for a role by relation
tags:
- role
@@ -9507,9 +9507,9 @@ paths:
description: Not Implemented
security:
- api_key:
- role:update
- ADMIN
- tokenizer:
- role:update
- ADMIN
summary: Patch objects for a role by relation
tags:
- role
@@ -10113,9 +10113,9 @@ paths:
description: Internal Server Error
security:
- api_key:
- factor-api-key:list
- serviceaccount:read
- tokenizer:
- factor-api-key:list
- serviceaccount:read
summary: List service account keys
tags:
- serviceaccount
@@ -10181,11 +10181,9 @@ paths:
description: Internal Server Error
security:
- api_key:
- factor-api-key:create
- serviceaccount:attach
- serviceaccount:update
- tokenizer:
- factor-api-key:create
- serviceaccount:attach
- serviceaccount:update
summary: Create a service account key
tags:
- serviceaccount
@@ -10238,11 +10236,9 @@ paths:
description: Internal Server Error
security:
- api_key:
- factor-api-key:delete
- serviceaccount:detach
- serviceaccount:update
- tokenizer:
- factor-api-key:delete
- serviceaccount:detach
- serviceaccount:update
summary: Revoke a service account key
tags:
- serviceaccount
@@ -10305,9 +10301,9 @@ paths:
description: Internal Server Error
security:
- api_key:
- factor-api-key:update
- serviceaccount:update
- tokenizer:
- factor-api-key:update
- serviceaccount:update
summary: Updates a service account key
tags:
- serviceaccount
@@ -10479,11 +10475,11 @@ paths:
description: Internal Server Error
security:
- api_key:
- serviceaccount:detach
- role:detach
- serviceaccount:attach
- role:attach
- tokenizer:
- serviceaccount:detach
- role:detach
- serviceaccount:attach
- role:attach
summary: Delete service account role
tags:
- serviceaccount

View File

@@ -7,27 +7,17 @@ type organization
type user
relations
define create: [user, serviceaccount, role#assignee]
define list: [user, serviceaccount, role#assignee]
define read: [user, serviceaccount, role#assignee]
define update: [user, serviceaccount, role#assignee]
define delete: [user, serviceaccount, role#assignee]
define attach: [user, serviceaccount, role#assignee]
define detach: [user, serviceaccount, role#assignee]
type serviceaccount
relations
define create: [user, serviceaccount, role#assignee]
define list: [user, serviceaccount, role#assignee]
define read: [user, serviceaccount, role#assignee]
define update: [user, serviceaccount, role#assignee]
define delete: [user, serviceaccount, role#assignee]
define attach: [user, serviceaccount, role#assignee]
define detach: [user, serviceaccount, role#assignee]
type anonymous
@@ -35,28 +25,25 @@ type role
relations
define assignee: [user, serviceaccount, anonymous]
define create: [user, serviceaccount, role#assignee]
define list: [user, serviceaccount, role#assignee]
define read: [user, serviceaccount, role#assignee]
define update: [user, serviceaccount, role#assignee]
define delete: [user, serviceaccount, role#assignee]
define attach: [user, serviceaccount, role#assignee]
define detach: [user, serviceaccount, role#assignee]
type metaresource
type metaresources
relations
define create: [user, serviceaccount, role#assignee]
define list: [user, serviceaccount, role#assignee]
define read: [user, serviceaccount, anonymous, role#assignee]
define update: [user, serviceaccount, role#assignee]
define delete: [user, serviceaccount, role#assignee]
type metaresource
relations
define read: [user, serviceaccount, anonymous, role#assignee]
define update: [user, serviceaccount, role#assignee]
define delete: [user, serviceaccount, role#assignee]
define block: [user, serviceaccount, role#assignee]
define block: [user, serviceaccount, role#assignee]
type telemetryresource
relations
define read: [user, serviceaccount, role#assignee]
define read: [user, serviceaccount, role#assignee]

View File

@@ -114,7 +114,7 @@ func NewServer(config signoz.Config, signoz *signoz.SigNoz) (*Server, error) {
// initiate agent config handler
agentConfMgr, err := agentConf.Initiate(&agentConf.ManagerOptions{
Store: signoz.SQLStore,
AgentFeatures: []agentConf.AgentFeature{logParsingPipelineController, signoz.Modules.LLMPricingRule},
AgentFeatures: []agentConf.AgentFeature{logParsingPipelineController},
})
if err != nil {
return nil, err

View File

@@ -1840,7 +1840,6 @@ export enum AuthtypesRelationDTO {
list = 'list',
assignee = 'assignee',
attach = 'attach',
detach = 'detach',
}
export interface AuthtypesRoleDTO {
/**
@@ -4162,6 +4161,7 @@ export enum CoretypesTypeDTO {
role = 'role',
organization = 'organization',
metaresource = 'metaresource',
metaresources = 'metaresources',
}
export interface DashboardtypesDashboardDTO {
/**

View File

@@ -360,7 +360,8 @@ describe('createGuardedRoute', () => {
const obj = payload[0]?.object;
const kind = obj?.resource?.kind;
const selector = obj?.selector ?? '*';
const objectStr = `${kind}:${selector}`;
const objectStr =
obj?.resource?.type === 'metaresources' ? kind : `${kind}:${selector}`;
requestedObjects.push(objectStr ?? '');
return res(ctx.status(200), ctx.json(authzMockResponse(payload, [true])));

View File

@@ -53,7 +53,7 @@ import {
GitCommitVertical,
GripVertical,
LampDesk,
Logs,
List,
MousePointerClick,
PackagePlus,
ScrollText,
@@ -1085,7 +1085,7 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element {
setIsReorderShortcutNavItemsModalOpen(true);
}}
>
<Logs size={16} />
<List size={16} />
</div>
</Tooltip>
)}

View File

@@ -4,8 +4,12 @@ export default {
data: {
resources: [
{
kind: 'factor-api-key',
type: 'metaresource',
kind: 'role',
type: 'metaresources',
},
{
kind: 'serviceaccount',
type: 'metaresources',
},
{
kind: 'role',
@@ -18,13 +22,12 @@ export default {
],
relations: {
assignee: ['role'],
attach: ['metaresource', 'role', 'serviceaccount'],
create: ['metaresource', 'role', 'serviceaccount'],
delete: ['metaresource', 'role', 'serviceaccount'],
detach: ['metaresource', 'role', 'serviceaccount'],
list: ['metaresource', 'role', 'serviceaccount'],
read: ['metaresource', 'role', 'serviceaccount'],
update: ['metaresource', 'role', 'serviceaccount'],
attach: ['role', 'serviceaccount'],
create: ['metaresources'],
delete: ['role', 'serviceaccount'],
list: ['metaresources'],
read: ['role', 'serviceaccount'],
update: ['role', 'serviceaccount'],
},
},
} as const;

View File

@@ -80,6 +80,19 @@ export function permissionToTransactionDto(
permission: BrandedPermission,
): AuthtypesTransactionDTO {
const { relation, object: objectStr } = parsePermission(permission);
const directType = resolveType(relation, objectStr);
if (directType === 'metaresources') {
return {
relation: relation as AuthtypesRelationDTO,
object: {
resource: {
kind: objectStr as ResourceName,
type: directType as CoretypesTypeDTO,
},
selector: '*',
},
};
}
const { resourceName, selector } = splitObjectString(objectStr);
const type = resolveType(relation, resourceName) ?? 'metaresource';
@@ -104,6 +117,9 @@ export function gettableTransactionToPermission(
} = item;
const resourceName = String(resource.kind);
const selectorStr = typeof selector === 'string' ? selector : '*';
const objectStr = `${resourceName}${ObjectSeparator}${selectorStr}`;
const objectStr =
resource.type === 'metaresources'
? resourceName
: `${resourceName}${ObjectSeparator}${selectorStr}`;
return `${relation}${PermissionSeparator}${objectStr}` as BrandedPermission;
}

View File

@@ -18,7 +18,7 @@ import {
ChartColumnBig,
Dock,
Link2,
Logs,
List,
PanelBottom,
ScrollText,
Timer,
@@ -393,7 +393,7 @@ function SpanDetailsContent({
<ScrollText size={14} /> Events ({selectedSpan.events?.length || 0})
</TabsTrigger>
<TabsTrigger value="logs" variant="secondary">
<Logs size={14} /> Logs
<List size={14} /> Logs
</TabsTrigger>
{infraMetadata && (
<TabsTrigger value="metrics" variant="secondary">

View File

@@ -7,14 +7,11 @@ import (
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/authtypes"
"github.com/SigNoz/signoz/pkg/types/coretypes"
"github.com/SigNoz/signoz/pkg/valuer"
"github.com/gorilla/mux"
)
func (provider *provider) addRoleRoutes(router *mux.Router) error {
if err := router.Handle("/api/v1/roles", handler.New(provider.authzMiddleware.Check(provider.authzHandler.Create, authtypes.Relation{Verb: coretypes.VerbCreate}, coretypes.ResourceRole, roleCollectionSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
if err := router.Handle("/api/v1/roles", handler.New(provider.authzMiddleware.AdminAccess(provider.authzHandler.Create), handler.OpenAPIDef{
ID: "CreateRole",
Tags: []string{"role"},
Summary: "Create role",
@@ -26,14 +23,12 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusCreated,
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceRole.Scope(coretypes.VerbCreate)}),
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
})).Methods(http.MethodPost).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v1/roles", handler.New(provider.authzMiddleware.Check(provider.authzHandler.List, authtypes.Relation{Verb: coretypes.VerbList}, coretypes.ResourceRole, roleCollectionSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
if err := router.Handle("/api/v1/roles", handler.New(provider.authzMiddleware.AdminAccess(provider.authzHandler.List), handler.OpenAPIDef{
ID: "ListRoles",
Tags: []string{"role"},
Summary: "List roles",
@@ -45,14 +40,12 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusOK,
ErrorStatusCodes: []int{},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceRole.Scope(coretypes.VerbList)}),
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
})).Methods(http.MethodGet).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v1/roles/{id}", handler.New(provider.authzMiddleware.Check(provider.authzHandler.Get, authtypes.Relation{Verb: coretypes.VerbRead}, coretypes.ResourceRole, provider.roleInstanceSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
if err := router.Handle("/api/v1/roles/{id}", handler.New(provider.authzMiddleware.AdminAccess(provider.authzHandler.Get), handler.OpenAPIDef{
ID: "GetRole",
Tags: []string{"role"},
Summary: "Get role",
@@ -64,14 +57,12 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusOK,
ErrorStatusCodes: []int{},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceRole.Scope(coretypes.VerbRead)}),
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
})).Methods(http.MethodGet).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v1/roles/{id}/relations/{relation}/objects", handler.New(provider.authzMiddleware.Check(provider.authzHandler.GetObjects, authtypes.Relation{Verb: coretypes.VerbRead}, coretypes.ResourceRole, provider.roleInstanceSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
if err := router.Handle("/api/v1/roles/{id}/relations/{relation}/objects", handler.New(provider.authzMiddleware.AdminAccess(provider.authzHandler.GetObjects), handler.OpenAPIDef{
ID: "GetObjects",
Tags: []string{"role"},
Summary: "Get objects for a role by relation",
@@ -83,14 +74,12 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusOK,
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceRole.Scope(coretypes.VerbRead)}),
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
})).Methods(http.MethodGet).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v1/roles/{id}", handler.New(provider.authzMiddleware.Check(provider.authzHandler.Patch, authtypes.Relation{Verb: coretypes.VerbUpdate}, coretypes.ResourceRole, provider.roleInstanceSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
if err := router.Handle("/api/v1/roles/{id}", handler.New(provider.authzMiddleware.AdminAccess(provider.authzHandler.Patch), handler.OpenAPIDef{
ID: "PatchRole",
Tags: []string{"role"},
Summary: "Patch role",
@@ -102,14 +91,12 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusNoContent,
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceRole.Scope(coretypes.VerbUpdate)}),
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
})).Methods(http.MethodPatch).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v1/roles/{id}/relations/{relation}/objects", handler.New(provider.authzMiddleware.Check(provider.authzHandler.PatchObjects, authtypes.Relation{Verb: coretypes.VerbUpdate}, coretypes.ResourceRole, provider.roleInstanceSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
if err := router.Handle("/api/v1/roles/{id}/relations/{relation}/objects", handler.New(provider.authzMiddleware.AdminAccess(provider.authzHandler.PatchObjects), handler.OpenAPIDef{
ID: "PatchObjects",
Tags: []string{"role"},
Summary: "Patch objects for a role by relation",
@@ -121,14 +108,12 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusNoContent,
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusBadRequest, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceRole.Scope(coretypes.VerbUpdate)}),
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
})).Methods(http.MethodPatch).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v1/roles/{id}", handler.New(provider.authzMiddleware.Check(provider.authzHandler.Delete, authtypes.Relation{Verb: coretypes.VerbDelete}, coretypes.ResourceRole, provider.roleInstanceSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
if err := router.Handle("/api/v1/roles/{id}", handler.New(provider.authzMiddleware.AdminAccess(provider.authzHandler.Delete), handler.OpenAPIDef{
ID: "DeleteRole",
Tags: []string{"role"},
Summary: "Delete role",
@@ -140,33 +125,10 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusNoContent,
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceRole.Scope(coretypes.VerbDelete)}),
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
})).Methods(http.MethodDelete).GetError(); err != nil {
return err
}
return nil
}
func roleCollectionSelectorCallback(_ *http.Request, _ authtypes.Claims) ([]coretypes.Selector, error) {
return []coretypes.Selector{
coretypes.TypeRole.MustSelector(coretypes.WildCardSelectorString),
}, nil
}
func (provider *provider) roleInstanceSelectorCallback(req *http.Request, claims authtypes.Claims) ([]coretypes.Selector, error) {
roleID, err := valuer.NewUUID(mux.Vars(req)["id"])
if err != nil {
return nil, err
}
role, err := provider.authzService.Get(req.Context(), valuer.MustNewUUID(claims.OrgID), roleID)
if err != nil {
return nil, err
}
return []coretypes.Selector{
coretypes.TypeRole.MustSelector(role.Name),
coretypes.TypeRole.MustSelector(coretypes.WildCardSelectorString),
}, nil
}

View File

@@ -17,7 +17,7 @@ import (
)
func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
if err := router.Handle("/api/v1/service_accounts", handler.New(provider.authzMiddleware.Check(provider.serviceAccountHandler.Create, authtypes.Relation{Verb: coretypes.VerbCreate}, coretypes.ResourceServiceAccount, serviceAccountCollectionSelectorCallback, []string{
if err := router.Handle("/api/v1/service_accounts", handler.New(provider.authzMiddleware.Check(provider.serviceAccountHandler.Create, authtypes.Relation{Verb: coretypes.VerbCreate}, coretypes.ResourceMetaResourcesServiceAccount, serviceAccountCollectionSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
ID: "CreateServiceAccount",
@@ -31,12 +31,12 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusCreated,
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceServiceAccount.Scope(coretypes.VerbCreate)}),
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceMetaResourcesServiceAccount.Scope(coretypes.VerbCreate)}),
})).Methods(http.MethodPost).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v1/service_accounts", handler.New(provider.authzMiddleware.Check(provider.serviceAccountHandler.List, authtypes.Relation{Verb: coretypes.VerbList}, coretypes.ResourceServiceAccount, serviceAccountCollectionSelectorCallback, []string{
if err := router.Handle("/api/v1/service_accounts", handler.New(provider.authzMiddleware.Check(provider.serviceAccountHandler.List, authtypes.Relation{Verb: coretypes.VerbList}, coretypes.ResourceMetaResourcesServiceAccount, serviceAccountCollectionSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
ID: "ListServiceAccounts",
@@ -50,7 +50,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusOK,
ErrorStatusCodes: []int{},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceServiceAccount.Scope(coretypes.VerbList)}),
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceMetaResourcesServiceAccount.Scope(coretypes.VerbList)}),
})).Methods(http.MethodGet).GetError(); err != nil {
return err
}
@@ -135,10 +135,10 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
}
if err := router.Handle("/api/v1/service_accounts/{id}/roles/{rid}", handler.New(provider.authzMiddleware.CheckAll(provider.serviceAccountHandler.DeleteRole, []middleware.AuthZCheckGroup{
{{Relation: authtypes.Relation{Verb: coretypes.VerbDetach}, Resource: coretypes.ResourceServiceAccount, SelectorCallback: serviceAccountInstanceSelectorCallback, Roles: []string{
{{Relation: authtypes.Relation{Verb: coretypes.VerbAttach}, Resource: coretypes.ResourceServiceAccount, SelectorCallback: serviceAccountInstanceSelectorCallback, Roles: []string{
authtypes.SigNozAdminRoleName,
}}},
{{Relation: authtypes.Relation{Verb: coretypes.VerbDetach}, Resource: coretypes.ResourceRole, SelectorCallback: provider.roleDetachSelectorFromPath, Roles: []string{
{{Relation: authtypes.Relation{Verb: coretypes.VerbAttach}, Resource: coretypes.ResourceRole, SelectorCallback: provider.roleAttachSelectorFromPath, Roles: []string{
authtypes.SigNozAdminRoleName,
}}},
}), handler.OpenAPIDef{
@@ -153,7 +153,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusNoContent,
ErrorStatusCodes: []int{},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceServiceAccount.Scope(coretypes.VerbDetach), coretypes.ResourceRole.Scope(coretypes.VerbDetach)}),
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceServiceAccount.Scope(coretypes.VerbAttach), coretypes.ResourceRole.Scope(coretypes.VerbAttach)}),
})).Methods(http.MethodDelete).GetError(); err != nil {
return err
}
@@ -213,13 +213,8 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
return err
}
if err := router.Handle("/api/v1/service_accounts/{id}/keys", handler.New(provider.authzMiddleware.CheckAll(provider.serviceAccountHandler.CreateFactorAPIKey, []middleware.AuthZCheckGroup{
{{Relation: authtypes.Relation{Verb: coretypes.VerbCreate}, Resource: coretypes.ResourceMetaResourceFactorAPIKey, SelectorCallback: factorAPIKeyCollectionSelectorCallback, Roles: []string{
authtypes.SigNozAdminRoleName,
}}},
{{Relation: authtypes.Relation{Verb: coretypes.VerbAttach}, Resource: coretypes.ResourceServiceAccount, SelectorCallback: serviceAccountInstanceSelectorCallback, Roles: []string{
authtypes.SigNozAdminRoleName,
}}},
if err := router.Handle("/api/v1/service_accounts/{id}/keys", handler.New(provider.authzMiddleware.Check(provider.serviceAccountHandler.CreateFactorAPIKey, authtypes.Relation{Verb: coretypes.VerbUpdate}, coretypes.ResourceServiceAccount, serviceAccountInstanceSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
ID: "CreateServiceAccountKey",
Tags: []string{"serviceaccount"},
@@ -232,12 +227,12 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusCreated,
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceMetaResourceFactorAPIKey.Scope(coretypes.VerbCreate), coretypes.ResourceServiceAccount.Scope(coretypes.VerbAttach)}),
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceServiceAccount.Scope(coretypes.VerbUpdate)}),
})).Methods(http.MethodPost).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v1/service_accounts/{id}/keys", handler.New(provider.authzMiddleware.Check(provider.serviceAccountHandler.ListFactorAPIKey, authtypes.Relation{Verb: coretypes.VerbList}, coretypes.ResourceMetaResourceFactorAPIKey, factorAPIKeyCollectionSelectorCallback, []string{
if err := router.Handle("/api/v1/service_accounts/{id}/keys", handler.New(provider.authzMiddleware.Check(provider.serviceAccountHandler.ListFactorAPIKey, authtypes.Relation{Verb: coretypes.VerbRead}, coretypes.ResourceServiceAccount, serviceAccountInstanceSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
ID: "ListServiceAccountKeys",
@@ -251,12 +246,12 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusOK,
ErrorStatusCodes: []int{},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceMetaResourceFactorAPIKey.Scope(coretypes.VerbList)}),
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceServiceAccount.Scope(coretypes.VerbRead)}),
})).Methods(http.MethodGet).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v1/service_accounts/{id}/keys/{fid}", handler.New(provider.authzMiddleware.Check(provider.serviceAccountHandler.UpdateFactorAPIKey, authtypes.Relation{Verb: coretypes.VerbUpdate}, coretypes.ResourceMetaResourceFactorAPIKey, factorAPIKeyInstanceSelectorCallback, []string{
if err := router.Handle("/api/v1/service_accounts/{id}/keys/{fid}", handler.New(provider.authzMiddleware.Check(provider.serviceAccountHandler.UpdateFactorAPIKey, authtypes.Relation{Verb: coretypes.VerbUpdate}, coretypes.ResourceServiceAccount, serviceAccountInstanceSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
ID: "UpdateServiceAccountKey",
@@ -270,18 +265,13 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusNoContent,
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceMetaResourceFactorAPIKey.Scope(coretypes.VerbUpdate)}),
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceServiceAccount.Scope(coretypes.VerbUpdate)}),
})).Methods(http.MethodPut).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v1/service_accounts/{id}/keys/{fid}", handler.New(provider.authzMiddleware.CheckAll(provider.serviceAccountHandler.RevokeFactorAPIKey, []middleware.AuthZCheckGroup{
{{Relation: authtypes.Relation{Verb: coretypes.VerbDelete}, Resource: coretypes.ResourceMetaResourceFactorAPIKey, SelectorCallback: factorAPIKeyInstanceSelectorCallback, Roles: []string{
authtypes.SigNozAdminRoleName,
}}},
{{Relation: authtypes.Relation{Verb: coretypes.VerbDetach}, Resource: coretypes.ResourceServiceAccount, SelectorCallback: serviceAccountInstanceSelectorCallback, Roles: []string{
authtypes.SigNozAdminRoleName,
}}},
if err := router.Handle("/api/v1/service_accounts/{id}/keys/{fid}", handler.New(provider.authzMiddleware.Check(provider.serviceAccountHandler.RevokeFactorAPIKey, authtypes.Relation{Verb: coretypes.VerbUpdate}, coretypes.ResourceServiceAccount, serviceAccountInstanceSelectorCallback, []string{
authtypes.SigNozAdminRoleName,
}), handler.OpenAPIDef{
ID: "RevokeServiceAccountKey",
Tags: []string{"serviceaccount"},
@@ -294,7 +284,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
SuccessStatusCode: http.StatusNoContent,
ErrorStatusCodes: []int{http.StatusNotFound},
Deprecated: false,
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceMetaResourceFactorAPIKey.Scope(coretypes.VerbDelete), coretypes.ResourceServiceAccount.Scope(coretypes.VerbDetach)}),
SecuritySchemes: newScopedSecuritySchemes([]string{coretypes.ResourceServiceAccount.Scope(coretypes.VerbUpdate)}),
})).Methods(http.MethodDelete).GetError(); err != nil {
return err
}
@@ -302,7 +292,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
return nil
}
func (provider *provider) roleDetachSelectorFromPath(req *http.Request, claims authtypes.Claims) ([]coretypes.Selector, error) {
func (provider *provider) roleAttachSelectorFromPath(req *http.Request, claims authtypes.Claims) ([]coretypes.Selector, error) {
roleID, err := valuer.NewUUID(mux.Vars(req)["rid"])
if err != nil {
return nil, err
@@ -343,28 +333,9 @@ func (provider *provider) roleAttachSelectorFromBody(req *http.Request, claims a
}, nil
}
func factorAPIKeyCollectionSelectorCallback(_ *http.Request, _ authtypes.Claims) ([]coretypes.Selector, error) {
return []coretypes.Selector{
coretypes.TypeMetaResource.MustSelector(coretypes.WildCardSelectorString),
}, nil
}
func factorAPIKeyInstanceSelectorCallback(req *http.Request, _ authtypes.Claims) ([]coretypes.Selector, error) {
fid := mux.Vars(req)["fid"]
fidSelector, err := coretypes.TypeMetaResource.Selector(fid)
if err != nil {
return nil, err
}
return []coretypes.Selector{
fidSelector,
coretypes.TypeMetaResource.MustSelector(coretypes.WildCardSelectorString),
}, nil
}
func serviceAccountCollectionSelectorCallback(_ *http.Request, _ authtypes.Claims) ([]coretypes.Selector, error) {
return []coretypes.Selector{
coretypes.TypeServiceAccount.MustSelector(coretypes.WildCardSelectorString),
coretypes.TypeMetaResources.MustSelector(coretypes.WildCardSelectorString),
}, nil
}

View File

@@ -135,7 +135,6 @@ func NewServer(config signoz.Config, signoz *signoz.SigNoz) (*Server, error) {
Store: signoz.SQLStore,
AgentFeatures: []agentConf.AgentFeature{
logParsingPipelineController,
signoz.Modules.LLMPricingRule,
},
},
)

View File

@@ -200,7 +200,6 @@ func NewSQLMigrationProviderFactories(
sqlmigration.NewAddServiceAccountManagedRoleTransactionsFactory(sqlstore),
sqlmigration.NewAddSpanMapperFactory(sqlstore, sqlschema),
sqlmigration.NewAddLLMPricingRulesFactory(sqlstore, sqlschema),
sqlmigration.NewMigrateMetaresourcesTuplesFactory(sqlstore),
)
}

View File

@@ -1,277 +0,0 @@
package sqlmigration
import (
"context"
"time"
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/sqlstore"
"github.com/SigNoz/signoz/pkg/types/authtypes"
"github.com/oklog/ulid/v2"
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect"
"github.com/uptrace/bun/migrate"
)
type migrateMetaresourcesTuples struct {
sqlstore sqlstore.SQLStore
}
func NewMigrateMetaresourcesTuplesFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] {
return factory.NewProviderFactory(factory.MustNewName("migrate_metaresources_tuples"), func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) {
return &migrateMetaresourcesTuples{sqlstore: sqlstore}, nil
})
}
func (migration *migrateMetaresourcesTuples) Register(migrations *migrate.Migrations) error {
return migrations.Register(migration.Up, migration.Down)
}
// migrationTuple describes a single FGA tuple to insert.
type migrationTuple struct {
roleName string // "signoz-admin", "signoz-editor", "signoz-viewer"
objectType string // "serviceaccount", "user", "role", "metaresource"
objectName string // "serviceaccount", "user", "role", etc.
relation string // "create", "list", "detach", etc.
}
func (migration *migrateMetaresourcesTuples) Up(ctx context.Context, db *bun.DB) error {
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer func() { _ = tx.Rollback() }()
var storeID string
err = tx.QueryRowContext(ctx, `SELECT id FROM store WHERE name = ? LIMIT 1`, "signoz").Scan(&storeID)
if err != nil {
return err
}
// Fetch all orgs.
var orgIDs []string
rows, err := tx.QueryContext(ctx, `SELECT id FROM organizations`)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var orgID string
if err := rows.Scan(&orgID); err != nil {
return err
}
orgIDs = append(orgIDs, orgID)
}
isPG := migration.sqlstore.BunDB().Dialect().Name() == dialect.PG
// Step 1: Delete all tuples with the old "metaresources" object_type.
for _, orgID := range orgIDs {
if isPG {
_, err = tx.ExecContext(ctx, `DELETE FROM tuple WHERE store = ? AND object_type = ? AND object_id LIKE ?`,
storeID, "metaresources", "organization/"+orgID+"/%")
} else {
_, err = tx.ExecContext(ctx, `DELETE FROM tuple WHERE store = ? AND object_type = ? AND object_id LIKE ?`,
storeID, "metaresources", "organization/"+orgID+"/%")
}
if err != nil {
return err
}
// Also clean up changelog entries for the old type.
if isPG {
_, err = tx.ExecContext(ctx, `DELETE FROM changelog WHERE store = ? AND object_type = ?`,
storeID, "metaresources")
} else {
_, err = tx.ExecContext(ctx, `DELETE FROM changelog WHERE store = ? AND object_type = ?`,
storeID, "metaresources")
}
if err != nil {
return err
}
}
// Step 2: Insert replacement tuples.
// For types with their own FGA type (user, serviceaccount, role), create/list
// go on the type directly. For all other resources, create/list go on "metaresource".
// Also add new detach tuples for role/user/serviceaccount.
tuples := []migrationTuple{
// New detach tuples for admin
{authtypes.SigNozAdminRoleName, "role", "role", "detach"},
{authtypes.SigNozAdminRoleName, "user", "user", "detach"},
{authtypes.SigNozAdminRoleName, "serviceaccount", "serviceaccount", "detach"},
// Replacement create/list for user/serviceaccount/role (moved from metaresources to own types)
{authtypes.SigNozAdminRoleName, "serviceaccount", "serviceaccount", "create"},
{authtypes.SigNozAdminRoleName, "serviceaccount", "serviceaccount", "list"},
{authtypes.SigNozAdminRoleName, "user", "user", "create"},
{authtypes.SigNozAdminRoleName, "user", "user", "list"},
{authtypes.SigNozAdminRoleName, "role", "role", "create"},
{authtypes.SigNozAdminRoleName, "role", "role", "list"},
// Replacement create/list for resources that move from "metaresources" to "metaresource"
{authtypes.SigNozAdminRoleName, "metaresource", "auth-domain", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "auth-domain", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "cloud-integration", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "cloud-integration", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "cloud-integration-service", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "cloud-integration-service", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "integration", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "integration", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "factor-api-key", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "factor-api-key", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "factor-password", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "factor-password", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "license", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "license", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "subscription", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "subscription", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "organization", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "organization", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "org-preference", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "org-preference", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "public-dashboard", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "public-dashboard", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "session", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "dashboard", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "dashboard", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "pipeline", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "pipeline", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "planned-maintenance", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "planned-maintenance", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "rule", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "rule", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "saved-view", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "saved-view", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "trace-funnel", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "trace-funnel", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "ingestion-key", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "ingestion-key", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "ingestion-limit", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "ingestion-limit", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "notification-channel", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "notification-channel", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "route-policy", "create"},
{authtypes.SigNozAdminRoleName, "metaresource", "route-policy", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "apdex-setting", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "quick-filter", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "ttl-setting", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "user-preference", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "logs-field", "list"},
{authtypes.SigNozAdminRoleName, "metaresource", "traces-field", "list"},
// Editor role: create/list replacements from metaresources → metaresource
{authtypes.SigNozEditorRoleName, "metaresource", "dashboard", "create"},
{authtypes.SigNozEditorRoleName, "metaresource", "dashboard", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "pipeline", "create"},
{authtypes.SigNozEditorRoleName, "metaresource", "pipeline", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "planned-maintenance", "create"},
{authtypes.SigNozEditorRoleName, "metaresource", "planned-maintenance", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "rule", "create"},
{authtypes.SigNozEditorRoleName, "metaresource", "rule", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "saved-view", "create"},
{authtypes.SigNozEditorRoleName, "metaresource", "saved-view", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "trace-funnel", "create"},
{authtypes.SigNozEditorRoleName, "metaresource", "trace-funnel", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "integration", "create"},
{authtypes.SigNozEditorRoleName, "metaresource", "integration", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "ingestion-key", "create"},
{authtypes.SigNozEditorRoleName, "metaresource", "ingestion-key", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "ingestion-limit", "create"},
{authtypes.SigNozEditorRoleName, "metaresource", "ingestion-limit", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "notification-channel", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "route-policy", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "apdex-setting", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "quick-filter", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "ttl-setting", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "user-preference", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "logs-field", "list"},
{authtypes.SigNozEditorRoleName, "metaresource", "traces-field", "list"},
// Viewer role: create/list replacements from metaresources → metaresource
{authtypes.SigNozViewerRoleName, "metaresource", "dashboard", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "pipeline", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "planned-maintenance", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "rule", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "saved-view", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "trace-funnel", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "integration", "create"},
{authtypes.SigNozViewerRoleName, "metaresource", "integration", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "notification-channel", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "route-policy", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "apdex-setting", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "quick-filter", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "ttl-setting", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "user-preference", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "logs-field", "list"},
{authtypes.SigNozViewerRoleName, "metaresource", "traces-field", "list"},
}
for _, orgID := range orgIDs {
for _, tuple := range tuples {
entropy := ulid.DefaultEntropy()
now := time.Now().UTC()
tupleID := ulid.MustNew(ulid.Timestamp(now), entropy).String()
objectID := "organization/" + orgID + "/" + tuple.objectName + "/*"
roleSubject := "organization/" + orgID + "/role/" + tuple.roleName
if isPG {
user := "role:" + roleSubject + "#assignee"
result, err := tx.ExecContext(ctx, `
INSERT INTO tuple (store, object_type, object_id, relation, _user, user_type, ulid, inserted_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (store, object_type, object_id, relation, _user) DO NOTHING`,
storeID, tuple.objectType, objectID, tuple.relation, user, "userset", tupleID, now,
)
if err != nil {
return err
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return err
}
if rowsAffected == 0 {
continue
}
_, err = tx.ExecContext(ctx, `
INSERT INTO changelog (store, object_type, object_id, relation, _user, operation, ulid, inserted_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (store, ulid, object_type) DO NOTHING`,
storeID, tuple.objectType, objectID, tuple.relation, user, "TUPLE_OPERATION_WRITE", tupleID, now,
)
if err != nil {
return err
}
} else {
result, err := tx.ExecContext(ctx, `
INSERT INTO tuple (store, object_type, object_id, relation, user_object_type, user_object_id, user_relation, user_type, ulid, inserted_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (store, object_type, object_id, relation, user_object_type, user_object_id, user_relation) DO NOTHING`,
storeID, tuple.objectType, objectID, tuple.relation, "role", roleSubject, "assignee", "userset", tupleID, now,
)
if err != nil {
return err
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return err
}
if rowsAffected == 0 {
continue
}
_, err = tx.ExecContext(ctx, `
INSERT INTO changelog (store, object_type, object_id, relation, user_object_type, user_object_id, user_relation, operation, ulid, inserted_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (store, ulid, object_type) DO NOTHING`,
storeID, tuple.objectType, objectID, tuple.relation, "role", roleSubject, "assignee", 0, tupleID, now,
)
if err != nil {
return err
}
}
}
}
return tx.Commit()
}
func (migration *migrateMetaresourcesTuples) Down(context.Context, *bun.DB) error {
return nil
}

View File

@@ -18,49 +18,46 @@ const (
var ManagedRoleToTransactions = map[string][]Transaction{
SigNozAdminRoleName: {
// role attach/detach — admin can attach/detach role assignments
// role attach — admin can attach/detach role assignments
{Verb: VerbAttach, Object: *MustNewObject(ResourceRef{Type: TypeRole, Kind: KindRole}, WildCardSelectorString)},
{Verb: VerbDetach, Object: *MustNewObject(ResourceRef{Type: TypeRole, Kind: KindRole}, WildCardSelectorString)},
// user attach/detach — admin can attach/detach roles to any user
// user attach — admin can attach roles to any user
{Verb: VerbAttach, Object: *MustNewObject(ResourceRef{Type: TypeUser, Kind: KindUser}, WildCardSelectorString)},
{Verb: VerbDetach, Object: *MustNewObject(ResourceRef{Type: TypeUser, Kind: KindUser}, WildCardSelectorString)},
// serviceaccount attach/detach — admin can attach/detach roles to any SA
// serviceaccount attach — admin can attach roles to any SA
{Verb: VerbAttach, Object: *MustNewObject(ResourceRef{Type: TypeServiceAccount, Kind: KindServiceAccount}, WildCardSelectorString)},
{Verb: VerbDetach, Object: *MustNewObject(ResourceRef{Type: TypeServiceAccount, Kind: KindServiceAccount}, WildCardSelectorString)},
// auth-domain — admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindAuthDomain}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindAuthDomain}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindAuthDomain}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindAuthDomain}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindAuthDomain}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindAuthDomain}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindAuthDomain}, WildCardSelectorString)},
// cloud-integration — admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindCloudIntegration}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindCloudIntegration}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindCloudIntegration}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindCloudIntegration}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindCloudIntegration}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindCloudIntegration}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindCloudIntegration}, WildCardSelectorString)},
// cloud-integration-service — admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindCloudIntegrationService}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindCloudIntegrationService}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindCloudIntegrationService}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindCloudIntegrationService}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindCloudIntegrationService}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindCloudIntegrationService}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindCloudIntegrationService}, WildCardSelectorString)},
// integration — viewer/editor/admin (install/uninstall via ViewAccess)
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIntegration}, WildCardSelectorString)},
// factor-api-key — admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindFactorAPIKey}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindFactorAPIKey}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindFactorAPIKey}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindFactorAPIKey}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindFactorAPIKey}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindFactorAPIKey}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindFactorAPIKey}, WildCardSelectorString)},
// factor-password — admin can issue and inspect reset tokens; users change their own password via OpenAccess
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindFactorPassword}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindFactorPassword}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindFactorPassword}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindFactorPassword}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindFactorPassword}, WildCardSelectorString)},
// license — admin only.
// Uniform LCRUD shape; actual ee routes are POST /api/v3/licenses (create
// = Activate), PUT /api/v3/licenses (update = Refresh), GET
@@ -70,8 +67,8 @@ var ManagedRoleToTransactions = map[string][]Transaction{
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLicense}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLicense}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLicense}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLicense}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLicense}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindLicense}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindLicense}, WildCardSelectorString)},
// subscription — admin only.
// Uniform LCRUD shape; actual ee routes are POST /api/v1/checkout
// (create), POST /api/v1/portal (update — opens Stripe portal), GET
@@ -81,123 +78,123 @@ var ManagedRoleToTransactions = map[string][]Transaction{
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSubscription}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSubscription}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSubscription}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSubscription}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSubscription}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindSubscription}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindSubscription}, WildCardSelectorString)},
// organization — admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeOrganization, Kind: KindOrganization}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeOrganization, Kind: KindOrganization}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindOrganization}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindOrganization}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindOrganization}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindOrganization}, WildCardSelectorString)},
// org-preference — admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindOrgPreference}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindOrgPreference}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindOrgPreference}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindOrgPreference}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindOrgPreference}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindOrgPreference}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindOrgPreference}, WildCardSelectorString)},
// public-dashboard — admin manages, anonymous reads
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPublicDashboard}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPublicDashboard}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPublicDashboard}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPublicDashboard}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPublicDashboard}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPublicDashboard}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPublicDashboard}, WildCardSelectorString)},
// role — admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeRole, Kind: KindRole}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeRole, Kind: KindRole}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeRole, Kind: KindRole}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeRole, Kind: KindRole}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeRole, Kind: KindRole}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRole}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRole}, WildCardSelectorString)},
// serviceaccount — admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeServiceAccount, Kind: KindServiceAccount}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeServiceAccount, Kind: KindServiceAccount}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeServiceAccount, Kind: KindServiceAccount}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeServiceAccount, Kind: KindServiceAccount}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeServiceAccount, Kind: KindServiceAccount}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindServiceAccount}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindServiceAccount}, WildCardSelectorString)},
// session — admin can revoke and list
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSession}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSession}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSession}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindSession}, WildCardSelectorString)},
// user — admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeUser, Kind: KindUser}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeUser, Kind: KindUser}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeUser, Kind: KindUser}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeUser, Kind: KindUser}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeUser, Kind: KindUser}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindUser}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindUser}, WildCardSelectorString)},
// dashboard — full CRUD (also held by editor)
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindDashboard}, WildCardSelectorString)},
// pipeline — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPipeline}, WildCardSelectorString)},
// planned-maintenance — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
// rule — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRule}, WildCardSelectorString)},
// saved-view — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindSavedView}, WildCardSelectorString)},
// trace-funnel — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTraceFunnel}, WildCardSelectorString)},
// ingestion-key — editor+admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIngestionKey}, WildCardSelectorString)},
// ingestion-limit — editor+admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIngestionLimit}, WildCardSelectorString)},
// notification-channel — admin writes, viewer reads
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindNotificationChannel}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindNotificationChannel}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindNotificationChannel}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindNotificationChannel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindNotificationChannel}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindNotificationChannel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindNotificationChannel}, WildCardSelectorString)},
// route-policy — admin writes, viewer reads
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRoutePolicy}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRoutePolicy}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRoutePolicy}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRoutePolicy}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRoutePolicy}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRoutePolicy}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRoutePolicy}, WildCardSelectorString)},
// apdex-setting — admin updates, viewer reads
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindApdexSetting}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindApdexSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindApdexSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindApdexSetting}, WildCardSelectorString)},
// quick-filter — admin updates, viewer reads
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindQuickFilter}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindQuickFilter}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindQuickFilter}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindQuickFilter}, WildCardSelectorString)},
// ttl-setting — admin updates, viewer reads
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTTLSetting}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTTLSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTTLSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTTLSetting}, WildCardSelectorString)},
// user-preference — every authenticated user can read+update their own
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindUserPreference}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindUserPreference}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindUserPreference}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindUserPreference}, WildCardSelectorString)},
// telemetry — read on each signal (logs/traces/metrics); schema permits read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeTelemetryResource, Kind: KindLogs}, WildCardSelectorString)},
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeTelemetryResource, Kind: KindTraces}, WildCardSelectorString)},
@@ -210,86 +207,86 @@ var ManagedRoleToTransactions = map[string][]Transaction{
// logs-field — editor+admin update (POST overwrites field config), viewer reads
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLogsField}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLogsField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLogsField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindLogsField}, WildCardSelectorString)},
// traces-field — editor+admin update, viewer reads
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTracesField}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTracesField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTracesField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTracesField}, WildCardSelectorString)},
},
SigNozEditorRoleName: {
// dashboard — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindDashboard}, WildCardSelectorString)},
// pipeline — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPipeline}, WildCardSelectorString)},
// planned-maintenance — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
// rule — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRule}, WildCardSelectorString)},
// saved-view — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindSavedView}, WildCardSelectorString)},
// trace-funnel — full CRUD
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTraceFunnel}, WildCardSelectorString)},
// integration — viewer/editor/admin
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIntegration}, WildCardSelectorString)},
// ingestion-key — editor+admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIngestionKey}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIngestionKey}, WildCardSelectorString)},
// ingestion-limit — editor+admin only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIngestionLimit}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIngestionLimit}, WildCardSelectorString)},
// notification-channel — read only (admin writes)
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindNotificationChannel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindNotificationChannel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindNotificationChannel}, WildCardSelectorString)},
// route-policy — read only (admin writes)
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRoutePolicy}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRoutePolicy}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRoutePolicy}, WildCardSelectorString)},
// apdex-setting — read only (admin updates)
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindApdexSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindApdexSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindApdexSetting}, WildCardSelectorString)},
// quick-filter — read only (admin updates)
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindQuickFilter}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindQuickFilter}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindQuickFilter}, WildCardSelectorString)},
// ttl-setting — read only (admin updates)
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTTLSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTTLSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTTLSetting}, WildCardSelectorString)},
// user-preference — every authenticated user can read+update their own
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindUserPreference}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindUserPreference}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindUserPreference}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindUserPreference}, WildCardSelectorString)},
// telemetry — read on each signal
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeTelemetryResource, Kind: KindLogs}, WildCardSelectorString)},
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeTelemetryResource, Kind: KindTraces}, WildCardSelectorString)},
@@ -297,66 +294,66 @@ var ManagedRoleToTransactions = map[string][]Transaction{
// logs-field — editor reads+updates
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLogsField}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLogsField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLogsField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindLogsField}, WildCardSelectorString)},
// traces-field — editor reads+updates
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTracesField}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTracesField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTracesField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTracesField}, WildCardSelectorString)},
},
SigNozViewerRoleName: {
// dashboard — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindDashboard}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindDashboard}, WildCardSelectorString)},
// pipeline — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPipeline}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPipeline}, WildCardSelectorString)},
// planned-maintenance — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindPlannedMaintenance}, WildCardSelectorString)},
// rule — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRule}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRule}, WildCardSelectorString)},
// saved-view — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSavedView}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindSavedView}, WildCardSelectorString)},
// trace-funnel — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTraceFunnel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTraceFunnel}, WildCardSelectorString)},
// integration — viewer/editor/admin (install/uninstall via ViewAccess)
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIntegration}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindIntegration}, WildCardSelectorString)},
// notification-channel — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindNotificationChannel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindNotificationChannel}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindNotificationChannel}, WildCardSelectorString)},
// route-policy — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRoutePolicy}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindRoutePolicy}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindRoutePolicy}, WildCardSelectorString)},
// apdex-setting — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindApdexSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindApdexSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindApdexSetting}, WildCardSelectorString)},
// quick-filter — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindQuickFilter}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindQuickFilter}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindQuickFilter}, WildCardSelectorString)},
// ttl-setting — read only
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTTLSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTTLSetting}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTTLSetting}, WildCardSelectorString)},
// user-preference — every authenticated user can read+update their own
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindUserPreference}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindUserPreference}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindUserPreference}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindUserPreference}, WildCardSelectorString)},
// telemetry — read on each signal
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeTelemetryResource, Kind: KindLogs}, WildCardSelectorString)},
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeTelemetryResource, Kind: KindTraces}, WildCardSelectorString)},
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeTelemetryResource, Kind: KindMetrics}, WildCardSelectorString)},
// logs-field — viewer reads
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLogsField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLogsField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindLogsField}, WildCardSelectorString)},
// traces-field — viewer reads
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTracesField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindTracesField}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResources, Kind: KindTracesField}, WildCardSelectorString)},
},
SigNozAnonymousRoleName: {
// public-dashboard — anonymous read

View File

@@ -6,76 +6,138 @@ var Resources = []Resource{
ResourceRole,
ResourceServiceAccount,
ResourceUser,
ResourceMetaResourcesRole,
ResourceMetaResourcesOrganization,
ResourceMetaResourcesServiceAccount,
ResourceMetaResourcesUser,
ResourceMetaResourceNotificationChannel,
ResourceMetaResourcesNotificationChannel,
ResourceMetaResourceRoutePolicy,
ResourceMetaResourcesRoutePolicy,
ResourceMetaResourceApdexSetting,
ResourceMetaResourcesApdexSetting,
ResourceMetaResourceAuthDomain,
ResourceMetaResourcesAuthDomain,
ResourceMetaResourceSession,
ResourceMetaResourcesSession,
ResourceMetaResourceCloudIntegration,
ResourceMetaResourcesCloudIntegration,
ResourceMetaResourceCloudIntegrationService,
ResourceMetaResourcesCloudIntegrationService,
ResourceMetaResourceIntegration,
ResourceMetaResourcesIntegration,
ResourceMetaResourceDashboard,
ResourceMetaResourcesDashboard,
ResourceMetaResourcePublicDashboard,
ResourceMetaResourcesPublicDashboard,
ResourceMetaResourceIngestionKey,
ResourceMetaResourcesIngestionKey,
ResourceMetaResourceIngestionLimit,
ResourceMetaResourcesIngestionLimit,
ResourceMetaResourcePipeline,
ResourceMetaResourcesPipeline,
ResourceMetaResourceUserPreference,
ResourceMetaResourcesUserPreference,
ResourceMetaResourceOrgPreference,
ResourceMetaResourcesOrgPreference,
ResourceMetaResourceQuickFilter,
ResourceMetaResourcesQuickFilter,
ResourceMetaResourceTTLSetting,
ResourceMetaResourcesTTLSetting,
ResourceMetaResourceRule,
ResourceMetaResourcesRule,
ResourceMetaResourcePlannedMaintenance,
ResourceMetaResourcesPlannedMaintenance,
ResourceMetaResourceSavedView,
ResourceMetaResourcesSavedView,
ResourceMetaResourceTraceFunnel,
ResourceMetaResourcesTraceFunnel,
ResourceMetaResourceFactorPassword,
ResourceMetaResourcesFactorPassword,
ResourceMetaResourceFactorAPIKey,
ResourceMetaResourcesFactorAPIKey,
ResourceMetaResourceLicense,
ResourceMetaResourcesLicense,
ResourceMetaResourceSubscription,
ResourceMetaResourcesSubscription,
ResourceTelemetryResourceLogs,
ResourceTelemetryResourceTraces,
ResourceTelemetryResourceMetrics,
ResourceTelemetryResourceAuditLogs,
ResourceTelemetryResourceMeterMetrics,
ResourceMetaResourceLogsField,
ResourceMetaResourcesLogsField,
ResourceMetaResourceTracesField,
ResourceMetaResourcesTracesField,
}
var (
ResourceAnonymous Resource = NewResourceAnonymous()
ResourceOrganization = NewResourceOrganization()
ResourceRole = NewResourceRole()
ResourceServiceAccount = NewResourceServiceAccount()
ResourceUser = NewResourceUser()
ResourceMetaResourceNotificationChannel = NewResourceMetaResource(KindNotificationChannel)
ResourceMetaResourceRoutePolicy = NewResourceMetaResource(KindRoutePolicy)
ResourceMetaResourceApdexSetting = NewResourceMetaResource(KindApdexSetting)
ResourceMetaResourceAuthDomain = NewResourceMetaResource(KindAuthDomain)
ResourceMetaResourceSession = NewResourceMetaResource(KindSession)
ResourceMetaResourceCloudIntegration = NewResourceMetaResource(KindCloudIntegration)
ResourceMetaResourceCloudIntegrationService = NewResourceMetaResource(KindCloudIntegrationService)
ResourceMetaResourceIntegration = NewResourceMetaResource(KindIntegration)
ResourceMetaResourceDashboard = NewResourceMetaResource(KindDashboard)
ResourceMetaResourcePublicDashboard = NewResourceMetaResource(KindPublicDashboard)
ResourceMetaResourceIngestionKey = NewResourceMetaResource(KindIngestionKey)
ResourceMetaResourceIngestionLimit = NewResourceMetaResource(KindIngestionLimit)
ResourceMetaResourcePipeline = NewResourceMetaResource(KindPipeline)
ResourceMetaResourceUserPreference = NewResourceMetaResource(KindUserPreference)
ResourceMetaResourceOrgPreference = NewResourceMetaResource(KindOrgPreference)
ResourceMetaResourceQuickFilter = NewResourceMetaResource(KindQuickFilter)
ResourceMetaResourceTTLSetting = NewResourceMetaResource(KindTTLSetting)
ResourceMetaResourceRule = NewResourceMetaResource(KindRule)
ResourceMetaResourcePlannedMaintenance = NewResourceMetaResource(KindPlannedMaintenance)
ResourceMetaResourceSavedView = NewResourceMetaResource(KindSavedView)
ResourceMetaResourceTraceFunnel = NewResourceMetaResource(KindTraceFunnel)
ResourceMetaResourceFactorPassword = NewResourceMetaResource(KindFactorPassword)
ResourceMetaResourceFactorAPIKey = NewResourceMetaResource(KindFactorAPIKey)
ResourceMetaResourceLicense = NewResourceMetaResource(KindLicense)
ResourceMetaResourceSubscription = NewResourceMetaResource(KindSubscription)
ResourceTelemetryResourceLogs = NewResourceTelemetryResource(KindLogs)
ResourceTelemetryResourceTraces = NewResourceTelemetryResource(KindTraces)
ResourceTelemetryResourceMetrics = NewResourceTelemetryResource(KindMetrics)
ResourceTelemetryResourceAuditLogs = NewResourceTelemetryResource(KindAuditLogs)
ResourceTelemetryResourceMeterMetrics = NewResourceTelemetryResource(KindMeterMetrics)
ResourceMetaResourceLogsField = NewResourceMetaResource(KindLogsField)
ResourceMetaResourceTracesField = NewResourceMetaResource(KindTracesField)
ResourceAnonymous Resource = NewResourceAnonymous()
ResourceOrganization = NewResourceOrganization()
ResourceRole = NewResourceRole()
ResourceServiceAccount = NewResourceServiceAccount()
ResourceUser = NewResourceUser()
ResourceMetaResourcesRole = NewResourceMetaResources(KindRole)
ResourceMetaResourcesOrganization = NewResourceMetaResources(KindOrganization)
ResourceMetaResourcesServiceAccount = NewResourceMetaResources(KindServiceAccount)
ResourceMetaResourcesUser = NewResourceMetaResources(KindUser)
ResourceMetaResourceNotificationChannel = NewResourceMetaResource(KindNotificationChannel)
ResourceMetaResourcesNotificationChannel = NewResourceMetaResources(KindNotificationChannel)
ResourceMetaResourceRoutePolicy = NewResourceMetaResource(KindRoutePolicy)
ResourceMetaResourcesRoutePolicy = NewResourceMetaResources(KindRoutePolicy)
ResourceMetaResourceApdexSetting = NewResourceMetaResource(KindApdexSetting)
ResourceMetaResourcesApdexSetting = NewResourceMetaResources(KindApdexSetting)
ResourceMetaResourceAuthDomain = NewResourceMetaResource(KindAuthDomain)
ResourceMetaResourcesAuthDomain = NewResourceMetaResources(KindAuthDomain)
ResourceMetaResourceSession = NewResourceMetaResource(KindSession)
ResourceMetaResourcesSession = NewResourceMetaResources(KindSession)
ResourceMetaResourceCloudIntegration = NewResourceMetaResource(KindCloudIntegration)
ResourceMetaResourcesCloudIntegration = NewResourceMetaResources(KindCloudIntegration)
ResourceMetaResourceCloudIntegrationService = NewResourceMetaResource(KindCloudIntegrationService)
ResourceMetaResourcesCloudIntegrationService = NewResourceMetaResources(KindCloudIntegrationService)
ResourceMetaResourceIntegration = NewResourceMetaResource(KindIntegration)
ResourceMetaResourcesIntegration = NewResourceMetaResources(KindIntegration)
ResourceMetaResourceDashboard = NewResourceMetaResource(KindDashboard)
ResourceMetaResourcesDashboard = NewResourceMetaResources(KindDashboard)
ResourceMetaResourcePublicDashboard = NewResourceMetaResource(KindPublicDashboard)
ResourceMetaResourcesPublicDashboard = NewResourceMetaResources(KindPublicDashboard)
ResourceMetaResourceIngestionKey = NewResourceMetaResource(KindIngestionKey)
ResourceMetaResourcesIngestionKey = NewResourceMetaResources(KindIngestionKey)
ResourceMetaResourceIngestionLimit = NewResourceMetaResource(KindIngestionLimit)
ResourceMetaResourcesIngestionLimit = NewResourceMetaResources(KindIngestionLimit)
ResourceMetaResourcePipeline = NewResourceMetaResource(KindPipeline)
ResourceMetaResourcesPipeline = NewResourceMetaResources(KindPipeline)
ResourceMetaResourceUserPreference = NewResourceMetaResource(KindUserPreference)
ResourceMetaResourcesUserPreference = NewResourceMetaResources(KindUserPreference)
ResourceMetaResourceOrgPreference = NewResourceMetaResource(KindOrgPreference)
ResourceMetaResourcesOrgPreference = NewResourceMetaResources(KindOrgPreference)
ResourceMetaResourceQuickFilter = NewResourceMetaResource(KindQuickFilter)
ResourceMetaResourcesQuickFilter = NewResourceMetaResources(KindQuickFilter)
ResourceMetaResourceTTLSetting = NewResourceMetaResource(KindTTLSetting)
ResourceMetaResourcesTTLSetting = NewResourceMetaResources(KindTTLSetting)
ResourceMetaResourceRule = NewResourceMetaResource(KindRule)
ResourceMetaResourcesRule = NewResourceMetaResources(KindRule)
ResourceMetaResourcePlannedMaintenance = NewResourceMetaResource(KindPlannedMaintenance)
ResourceMetaResourcesPlannedMaintenance = NewResourceMetaResources(KindPlannedMaintenance)
ResourceMetaResourceSavedView = NewResourceMetaResource(KindSavedView)
ResourceMetaResourcesSavedView = NewResourceMetaResources(KindSavedView)
ResourceMetaResourceTraceFunnel = NewResourceMetaResource(KindTraceFunnel)
ResourceMetaResourcesTraceFunnel = NewResourceMetaResources(KindTraceFunnel)
ResourceMetaResourceFactorPassword = NewResourceMetaResource(KindFactorPassword)
ResourceMetaResourcesFactorPassword = NewResourceMetaResources(KindFactorPassword)
ResourceMetaResourceFactorAPIKey = NewResourceMetaResource(KindFactorAPIKey)
ResourceMetaResourcesFactorAPIKey = NewResourceMetaResources(KindFactorAPIKey)
ResourceMetaResourceLicense = NewResourceMetaResource(KindLicense)
ResourceMetaResourcesLicense = NewResourceMetaResources(KindLicense)
ResourceMetaResourceSubscription = NewResourceMetaResource(KindSubscription)
ResourceMetaResourcesSubscription = NewResourceMetaResources(KindSubscription)
ResourceTelemetryResourceLogs = NewResourceTelemetryResource(KindLogs)
ResourceTelemetryResourceTraces = NewResourceTelemetryResource(KindTraces)
ResourceTelemetryResourceMetrics = NewResourceTelemetryResource(KindMetrics)
ResourceTelemetryResourceAuditLogs = NewResourceTelemetryResource(KindAuditLogs)
ResourceTelemetryResourceMeterMetrics = NewResourceTelemetryResource(KindMeterMetrics)
ResourceMetaResourceLogsField = NewResourceMetaResource(KindLogsField)
ResourceMetaResourcesLogsField = NewResourceMetaResources(KindLogsField)
ResourceMetaResourceTracesField = NewResourceMetaResource(KindTracesField)
ResourceMetaResourcesTracesField = NewResourceMetaResources(KindTracesField)
)

View File

@@ -13,15 +13,17 @@ var Types = []Type{
TypeRole,
TypeOrganization,
TypeMetaResource,
TypeMetaResources,
TypeTelemetryResource,
}
var (
TypeUser = Type{valuer.NewString("user"), regexp.MustCompile(`^(^[0-9a-f]{8}(?:\-[0-9a-f]{4}){3}-[0-9a-f]{12}$|\*)$`), []Verb{VerbCreate, VerbList, VerbRead, VerbUpdate, VerbDelete, VerbAttach, VerbDetach}}
TypeServiceAccount = Type{valuer.NewString("serviceaccount"), regexp.MustCompile(`^(^[0-9a-f]{8}(?:\-[0-9a-f]{4}){3}-[0-9a-f]{12}$|\*)$`), []Verb{VerbCreate, VerbList, VerbRead, VerbUpdate, VerbDelete, VerbAttach, VerbDetach}}
TypeUser = Type{valuer.NewString("user"), regexp.MustCompile(`^(^[0-9a-f]{8}(?:\-[0-9a-f]{4}){3}-[0-9a-f]{12}$|\*)$`), []Verb{VerbAttach, VerbRead, VerbUpdate, VerbDelete}}
TypeServiceAccount = Type{valuer.NewString("serviceaccount"), regexp.MustCompile(`^(^[0-9a-f]{8}(?:\-[0-9a-f]{4}){3}-[0-9a-f]{12}$|\*)$`), []Verb{VerbAttach, VerbRead, VerbUpdate, VerbDelete}}
TypeAnonymous = Type{valuer.NewString("anonymous"), regexp.MustCompile(`^\*$`), []Verb{}}
TypeRole = Type{valuer.NewString("role"), regexp.MustCompile(`^([a-z-]{1,50}|\*)$`), []Verb{VerbAssignee, VerbCreate, VerbList, VerbRead, VerbUpdate, VerbDelete, VerbAttach, VerbDetach}}
TypeRole = Type{valuer.NewString("role"), regexp.MustCompile(`^([a-z-]{1,50}|\*)$`), []Verb{VerbAssignee, VerbAttach, VerbRead, VerbUpdate, VerbDelete}}
TypeOrganization = Type{valuer.NewString("organization"), regexp.MustCompile(`^(^[0-9a-f]{8}(?:\-[0-9a-f]{4}){3}-[0-9a-f]{12}$|\*)$`), []Verb{VerbRead, VerbUpdate, VerbDelete}}
TypeMetaResource = Type{valuer.NewString("metaresource"), regexp.MustCompile(`^(^[0-9a-f]{8}(?:\-[0-9a-f]{4}){3}-[0-9a-f]{12}$|\*)$`), []Verb{VerbCreate, VerbList, VerbRead, VerbUpdate, VerbDelete, VerbAttach, VerbDetach}}
TypeMetaResource = Type{valuer.NewString("metaresource"), regexp.MustCompile(`^(^[0-9a-f]{8}(?:\-[0-9a-f]{4}){3}-[0-9a-f]{12}$|\*)$`), []Verb{VerbRead, VerbUpdate, VerbDelete}}
TypeMetaResources = Type{valuer.NewString("metaresources"), regexp.MustCompile(`^\*$`), []Verb{VerbCreate, VerbList}}
TypeTelemetryResource = Type{valuer.NewString("telemetryresource"), regexp.MustCompile(`^\*$`), []Verb{VerbRead}}
)

View File

@@ -10,7 +10,6 @@ var Verbs = []Verb{
VerbList,
VerbAssignee,
VerbAttach,
VerbDetach,
}
var (
@@ -21,5 +20,4 @@ var (
VerbList = Verb{valuer.NewString("list"), "listed"}
VerbAssignee = Verb{valuer.NewString("assignee"), "assigned"}
VerbAttach = Verb{valuer.NewString("attach"), "attached"}
VerbDetach = Verb{valuer.NewString("detach"), "detached"}
)

View File

@@ -0,0 +1,34 @@
package coretypes
import (
"github.com/SigNoz/signoz/pkg/valuer"
)
type resourceMetaResources struct {
kind Kind
}
func NewResourceMetaResources(kind Kind) Resource {
return &resourceMetaResources{kind: kind}
}
func (*resourceMetaResources) Type() Type {
return TypeMetaResources
}
func (resourceMetaResources *resourceMetaResources) Kind() Kind {
return resourceMetaResources.kind
}
// example: metaresources:organization/0199c47d-f61b-7833-bc5f-c0730f12f046/dashboards
func (resourceMetaResources *resourceMetaResources) Prefix(orgID valuer.UUID) string {
return resourceMetaResources.Type().StringValue() + ":" + "organization" + "/" + orgID.StringValue() + "/" + resourceMetaResources.Kind().String()
}
func (resourceMetaResources *resourceMetaResources) Object(orgID valuer.UUID, selector string) string {
return resourceMetaResources.Prefix(orgID) + "/" + selector
}
func (resourceMetaResources *resourceMetaResources) Scope(verb Verb) string {
return resourceMetaResources.Kind().String() + ":" + verb.StringValue()
}

View File

@@ -33,6 +33,8 @@ func NewType(input string) (Type, error) {
return TypeOrganization, nil
case "metaresource":
return TypeMetaResource, nil
case "metaresources":
return TypeMetaResources, nil
default:
return Type{}, errors.Newf(errors.TypeInvalidInput, ErrCodeInvalidType, "invalid type: %s", input)
}
@@ -78,6 +80,7 @@ func (typed Type) Enum() []any {
TypeRole,
TypeOrganization,
TypeMetaResource,
TypeMetaResources,
}
}

View File

@@ -30,8 +30,6 @@ func NewVerb(verb string) (Verb, error) {
return VerbAssignee, nil
case "attach":
return VerbAttach, nil
case "detach":
return VerbDetach, nil
default:
return Verb{}, errors.Newf(errors.TypeInvalidInput, ErrCodeInvalidVerb, "verb %s is invalid, valid verbs are: %s", verb, Verb{}.Enum())
}
@@ -46,7 +44,6 @@ func (Verb) Enum() []any {
VerbList,
VerbAssignee,
VerbAttach,
VerbDetach,
}
}

View File

@@ -27,6 +27,7 @@ pytest_plugins = [
"fixtures.seeder",
"fixtures.serviceaccount",
"fixtures.role",
"fixtures.seed_golden_dataset",
]

View File

@@ -0,0 +1,13 @@
import { expect, test as setup } from '@playwright/test';
const seederUrl = process.env.SIGNOZ_E2E_SEEDER_URL ?? '';
setup('refresh golden dataset', async ({ request }) => {
expect(seederUrl, 'SIGNOZ_E2E_SEEDER_URL not set').not.toBe('');
const response = await request.post(`${seederUrl}/seed/golden`, {
timeout: 120_000,
});
expect(response.ok()).toBeTruthy();
// eslint-disable-next-line no-console
console.log(`[setup] refreshed golden dataset: ${await response.text()}`);
});

View File

@@ -0,0 +1,13 @@
import { expect, test as teardown } from '@playwright/test';
const seederUrl = process.env.SIGNOZ_E2E_SEEDER_URL ?? '';
teardown('clear seeded telemetry', async ({ request }) => {
expect(seederUrl, 'SIGNOZ_E2E_SEEDER_URL not set').not.toBe('');
for (const signal of ['metrics', 'traces', 'logs'] as const) {
const response = await request.delete(`${seederUrl}/telemetry/${signal}`, {
timeout: 60_000,
});
expect(response.ok()).toBeTruthy();
}
});

View File

@@ -2,6 +2,7 @@ import os
from pathlib import Path
import pytest
import requests
from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
@@ -38,6 +39,13 @@ def test_teardown(
signoz: types.SigNoz, # pylint: disable=unused-argument
create_user_admin: types.Operation, # pylint: disable=unused-argument
apply_license: types.Operation, # pylint: disable=unused-argument
seeder: types.TestContainerDocker, # pylint: disable=unused-argument
seeder: types.TestContainerDocker,
) -> None:
"""Fixture dependencies trigger container teardown via --teardown."""
"""Truncate seeded telemetry; containers come down via fixture
dependency under `--teardown`."""
base = seeder.host_configs["8080"].base().rstrip("/")
for signal in ("metrics", "traces", "logs"):
try:
requests.delete(f"{base}/telemetry/{signal}", timeout=30).raise_for_status()
except Exception as e: # pylint: disable=broad-exception-caught
print(f"seeder DELETE /telemetry/{signal} failed: {e}")

View File

@@ -50,12 +50,36 @@ export default defineConfig({
viewport: { width: 1280, height: 720 },
},
// Browser projects. No project-level auth — specs opt in via the
// authedPage fixture in tests/e2e/fixtures/auth.ts, which logs a user
// in on first use and caches the resulting storageState per worker.
// `setup` runs `bootstrap/global.setup.ts` once before any browser
// project — refreshes the golden dataset so chart-data assertions
// land inside default panel time windows. Per
// https://playwright.dev/docs/test-global-setup-teardown#option-1-project-dependencies.
projects: [
{ name: 'chromium', use: devices['Desktop Chrome'] },
{ name: 'firefox', use: devices['Desktop Firefox'] },
{ name: 'webkit', use: devices['Desktop Safari'] },
{
name: 'setup',
testDir: './bootstrap',
testMatch: /global\.setup\.ts/,
teardown: 'teardown',
},
{
name: 'teardown',
testDir: './bootstrap',
testMatch: /global\.teardown\.ts/,
},
{
name: 'chromium',
use: devices['Desktop Chrome'],
dependencies: ['setup'],
},
{
name: 'firefox',
use: devices['Desktop Firefox'],
dependencies: ['setup'],
},
{
name: 'webkit',
use: devices['Desktop Safari'],
dependencies: ['setup'],
},
],
});

View File

@@ -18,6 +18,6 @@
"outDir": "./dist",
"rootDir": "."
},
"include": ["tests/**/*.ts", "helpers/**/*.ts", "fixtures/**/*.ts", "playwright.config.ts"],
"include": ["tests/**/*.ts", "helpers/**/*.ts", "fixtures/**/*.ts", "bootstrap/**/*.ts", "playwright.config.ts"],
"exclude": ["node_modules", "dist"]
}

View File

@@ -1,352 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@oxfmt/binding-android-arm-eabi@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.41.0.tgz#09438448ab9479730582cd00fb86e4c33795a364"
integrity sha512-REfrqeMKGkfMP+m/ScX4f5jJBSmVNYcpoDF8vP8f8eYPDuPGZmzp56NIUsYmx3h7f6NzC6cE3gqh8GDWrJHCKw==
"@oxfmt/binding-android-arm64@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.41.0.tgz#b01eef08ff2a6be90f5805fe28339ec0130a955c"
integrity sha512-s0b1dxNgb2KomspFV2LfogC2XtSJB42POXF4bMCLJyvQmAGos4ZtjGPfQreToQEaY0FQFjz3030ggI36rF1q5g==
"@oxfmt/binding-darwin-arm64@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.41.0.tgz#a2e24b7c52d40e3bb01939fa9c994d56923294ce"
integrity sha512-EGXGualADbv/ZmamE7/2DbsrYmjoPlAmHEpTL4vapLF4EfVD6fr8/uQDFnPJkUBjiSWFJZtFNsGeN1B6V3owmA==
"@oxfmt/binding-darwin-x64@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.41.0.tgz#c114c0a30195a65cfe0247e2ffd000416df4d4bc"
integrity sha512-WxySJEvdQQYMmyvISH3qDpTvoS0ebnIP63IMxLLWowJyPp/AAH0hdWtlo+iGNK5y3eVfa5jZguwNaQkDKWpGSw==
"@oxfmt/binding-freebsd-x64@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.41.0.tgz#a9057a31860ec79970a16b5a0a801a51fab99168"
integrity sha512-Y2kzMkv3U3oyuYaR4wTfGjOTYTXiFC/hXmG0yVASKkbh02BJkvD98Ij8bIevr45hNZ0DmZEgqiXF+9buD4yMYQ==
"@oxfmt/binding-linux-arm-gnueabihf@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.41.0.tgz#1a2be3cbbf2d9e90808858ba8fc38b24023ac44c"
integrity sha512-ptazDjdUyhket01IjPTT6ULS1KFuBfTUU97osTP96X5y/0oso+AgAaJzuH81oP0+XXyrWIHbRzozSAuQm4p48g==
"@oxfmt/binding-linux-arm-musleabihf@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.41.0.tgz#f0a12feca29bfaf7437d94c32919ff3ac60c213f"
integrity sha512-UkoL2OKxFD+56bPEBcdGn+4juTW4HRv/T6w1dIDLnvKKWr6DbarB/mtHXlADKlFiJubJz8pRkttOR7qjYR6lTA==
"@oxfmt/binding-linux-arm64-gnu@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.41.0.tgz#b304c7ede72119f7fe7ce7861007c0ee6eb60c08"
integrity sha512-gofu0PuumSOHYczD8p62CPY4UF6ee+rSLZJdUXkpwxg6pILiwSDBIouPskjF/5nF3A7QZTz2O9KFNkNxxFN9tA==
"@oxfmt/binding-linux-arm64-musl@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.41.0.tgz#295d6ce8d846ca1a287165bf4ff6e7b3cd51f823"
integrity sha512-VfVZxL0+6RU86T8F8vKiDBa+iHsr8PAjQmKGBzSCAX70b6x+UOMFl+2dNihmKmUwqkCazCPfYjt6SuAPOeQJ3g==
"@oxfmt/binding-linux-ppc64-gnu@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.41.0.tgz#6c702f37bd69bb88bf78264eef5df9dbcdcada49"
integrity sha512-bwzokz2eGvdfJbc0i+zXMJ4BBjQPqg13jyWpEEZDOrBCQ91r8KeY2Mi2kUeuMTZNFXju+jcAbAbpyJxRGla0eg==
"@oxfmt/binding-linux-riscv64-gnu@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.41.0.tgz#9dac4f7f4cf10d94ade5a109554f810a43525595"
integrity sha512-POLM//PCH9uqDeNDwWL3b3DkMmI3oI2cU6hwc2lnztD1o7dzrQs3R9nq555BZ6wI7t2lyhT9CS+CRaz5X0XqLA==
"@oxfmt/binding-linux-riscv64-musl@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.41.0.tgz#ddd573ad4fc8e5d017ab27177eaabea700d68754"
integrity sha512-NNK7PzhFqLUwx/G12Xtm6scGv7UITvyGdAR5Y+TlqsG+essnuRWR4jRNODWRjzLZod0T3SayRbnkSIWMBov33w==
"@oxfmt/binding-linux-s390x-gnu@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.41.0.tgz#3300ee81681382c1ec0a4013807c362c27ef4821"
integrity sha512-qVf/zDC5cN9eKe4qI/O/m445er1IRl6swsSl7jHkqmOSVfknwCe5JXitYjZca+V/cNJSU/xPlC5EFMabMMFDpw==
"@oxfmt/binding-linux-x64-gnu@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.41.0.tgz#be9068d48bb521eea83ea6bea2b0e08b39d7638b"
integrity sha512-ojxYWu7vUb6ysYqVCPHuAPVZHAI40gfZ0PDtZAMwVmh2f0V8ExpPIKoAKr7/8sNbAXJBBpZhs2coypIo2jJX4w==
"@oxfmt/binding-linux-x64-musl@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.41.0.tgz#e0232abd879874823213b71016042d001a740acb"
integrity sha512-O2exZLBxoCMIv2vlvcbkdedazJPTdG0VSup+0QUCfYQtx751zCZNboX2ZUOiQ/gDTdhtXvSiot0h6GEGkOyalA==
"@oxfmt/binding-openharmony-arm64@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.41.0.tgz#3e5893cde8cae02494cbb5493de9c46613e77058"
integrity sha512-N+31/VoL+z+NNBt8viy3I4NaIdPbiYeOnB884LKqvXldaE2dRztdPv3q5ipfZYv0RwFp7JfqS4I27K/DSHCakg==
"@oxfmt/binding-win32-arm64-msvc@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.41.0.tgz#31d8dfeeddc855dbecc9f45d11cd892635d2e42f"
integrity sha512-Z7NAtu/RN8kjCQ1y5oDD0nTAeRswh3GJ93qwcW51srmidP7XPBmZbLlwERu1W5veCevQJtPS9xmkpcDTYsGIwQ==
"@oxfmt/binding-win32-ia32-msvc@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.41.0.tgz#873fb408a3e8952fae67763b225e4ea77356e926"
integrity sha512-uNxxP3l4bJ6VyzIeRqCmBU2Q0SkCFgIhvx9/9dJ9V8t/v+jP1IBsuaLwCXGR8JPHtkj4tFp+RHtUmU2ZYAUpMA==
"@oxfmt/binding-win32-x64-msvc@0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.41.0.tgz#0adf46bca6908c6b49c790e598f4972b6f4cd191"
integrity sha512-49ZSpbZ1noozyPapE8SUOSm3IN0Ze4b5nkO+4+7fq6oEYQQJFhE0saj5k/Gg4oewVPdjn0L3ZFeWk2Vehjcw7A==
"@oxlint-tsgolint/darwin-arm64@0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@oxlint-tsgolint/darwin-arm64/-/darwin-arm64-0.20.0.tgz#6d704883904fa6e5fc922a7cef882bad4c734a0b"
integrity sha512-KKQcIHZHMxqpHUA1VXIbOG6chNCFkUWbQy6M+AFVtPKkA/3xAeJkJ3njoV66bfzwPHRcWQO+kcj5XqtbkjakoA==
"@oxlint-tsgolint/darwin-x64@0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@oxlint-tsgolint/darwin-x64/-/darwin-x64-0.20.0.tgz#676d7a1cf82216d91e9bc143f676e7dbe59ce596"
integrity sha512-7HeVMuclGfG+NLZi2ybY0T4fMI7/XxO/208rJk+zEIloKkVnlh11Wd241JMGwgNFXn+MLJbOqOfojDb2Dt4L1g==
"@oxlint-tsgolint/linux-arm64@0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@oxlint-tsgolint/linux-arm64/-/linux-arm64-0.20.0.tgz#5a2e67cf18394b6b868301cf3d84c8b8be7ab6b9"
integrity sha512-zxhUwz+WSxE6oWlZLK2z2ps9yC6ebmgoYmjAl0Oa48+GqkZ56NVgo+wb8DURNv6xrggzHStQxqQxe3mK51HZag==
"@oxlint-tsgolint/linux-x64@0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@oxlint-tsgolint/linux-x64/-/linux-x64-0.20.0.tgz#68468ad9253668748736191b6a7af51ae737c0a4"
integrity sha512-/1l6FnahC9im8PK+Ekkx/V3yetO/PzZnJegE2FXcv/iXEhbeVxP/ouiTYcUQu9shT1FWJCSNti1VJHH+21Y1dg==
"@oxlint-tsgolint/win32-arm64@0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@oxlint-tsgolint/win32-arm64/-/win32-arm64-0.20.0.tgz#32a0eba60f0a88cd6d6d53cc03eb1b2e43ca0c50"
integrity sha512-oPZ5Yz8sVdo7P/5q+i3IKeix31eFZ55JAPa1+RGPoe9PoaYVsdMvR6Jvib6YtrqoJnFPlg3fjEjlEPL8VBKYJA==
"@oxlint-tsgolint/win32-x64@0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@oxlint-tsgolint/win32-x64/-/win32-x64-0.20.0.tgz#90d5582b1df2ae877b2c5d7620e3a55acf9cc45f"
integrity sha512-4stx8RHj3SP9vQyRF/yZbz5igtPvYMEUR8CUoha4BVNZihi39DpCR8qkU7lpjB5Ga1DRMo2pHaA4bdTOMaY4mw==
"@oxlint/binding-android-arm-eabi@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.61.0.tgz#c7a8fb22ac3084d6f4c873cdc9779f4f9e38b805"
integrity sha512-6eZBPgiigK5txqoVgRqxbaxiom4lM8AP8CyKPPvpzKnQ3iFRFOIDc+0AapF+qsUSwjOzr5SGk4SxQDpQhkSJMQ==
"@oxlint/binding-android-arm64@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-android-arm64/-/binding-android-arm64-1.61.0.tgz#5fe7c707e12513ede292da015d13e93781771e9f"
integrity sha512-CkwLR69MUnyv5wjzebvbbtTSUwqLxM35CXE79bHqDIK+NtKmPEUpStTcLQRZMCo4MP0qRT6TXIQVpK0ZVScnMA==
"@oxlint/binding-darwin-arm64@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.61.0.tgz#1f58a4c592b76e293e5b9072cc0e4e7a5bef8191"
integrity sha512-8JbefTkbmvqkqWjmQrHke+MdpgT2UghhD/ktM4FOQSpGeCgbMToJEKdl9zwhr/YWTl92i4QI1KiTwVExpcUN8A==
"@oxlint/binding-darwin-x64@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.61.0.tgz#eade7425cc943c3146f3e0f0fb4d08d615ee78a9"
integrity sha512-uWpoxDT47hTnDLcdEh5jVbso8rlTTu5o0zuqa9J8E0JAKmIWn7kGFEIB03Pycn2hd2vKxybPGLhjURy/9We5FQ==
"@oxlint/binding-freebsd-x64@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.61.0.tgz#8d82382a07ce4895c91694a810dee7f39866951b"
integrity sha512-K/o4hEyW7flfMel0iBVznmMBt7VIMHGdjADocHKpK1DUF9erpWnJ+BSSWd2W0c8K3mPtpph+CuHzRU6CI3l9jQ==
"@oxlint/binding-linux-arm-gnueabihf@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.61.0.tgz#df76a5700651cda73ca5578de7308f9479b7cb1b"
integrity sha512-P6040ZkcyweJ0Po9yEFqJCdvZnf3VNCGs1SIHgXDf8AAQNC6ID/heXQs9iSgo2FH7gKaKq32VWc59XZwL34C5Q==
"@oxlint/binding-linux-arm-musleabihf@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.61.0.tgz#b198e5697cfb6cc55eff5ab5b9766732e143492d"
integrity sha512-bwxrGCzTZkuB+THv2TQ1aTkVEfv5oz8sl+0XZZCpoYzErJD8OhPQOTA0ENPd1zJz8QsVdSzSrS2umKtPq4/JXg==
"@oxlint/binding-linux-arm64-gnu@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.61.0.tgz#a5cdae7ef9f9b79526ef764fb174bb362c3737ee"
integrity sha512-vkhb9/wKguMkLlrm3FoJW/Xmdv31GgYAE+x8lxxQ+7HeOxXUySI0q36a3NTVIuQUdLzxCI1zzMGsk1o37FOe3w==
"@oxlint/binding-linux-arm64-musl@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.61.0.tgz#227f6d94a3c00140a88ea338436783bd9da6f4ae"
integrity sha512-bl1dQh8LnVqsj6oOQAcxwbuOmNJkwc4p6o//HTBZhNTzJy21TLDwAviMqUFNUxDHkPGpmdKTSN4tWTjLryP8xg==
"@oxlint/binding-linux-ppc64-gnu@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.61.0.tgz#e504e6cd8691fe460b202599d4c962fc7ad98f94"
integrity sha512-QoOX6KB2IiEpyOj/HKqaxi+NQHPnOgNgnr22n9N4ANJCzXkUlj1UmeAbFb4PpqdlHIzvGDM5xZ0OKtcLq9RhiQ==
"@oxlint/binding-linux-riscv64-gnu@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.61.0.tgz#efe70d9e570756fe19fb60d05a39dd58e9e0f32d"
integrity sha512-1TGcTerjY6p152wCof3oKElccq3xHljS/Mucp04gV/4ATpP6nO7YNnp7opEg6SHkv2a57/b4b8Ndm9znJ1/qAw==
"@oxlint/binding-linux-riscv64-musl@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.61.0.tgz#f9c42095192f235b03a5d3d1f1fbfb45002d5a93"
integrity sha512-65wXEmZIrX2ADwC8i/qFL4EWLSbeuBpAm3suuX1vu4IQkKd+wLT/HU/BOl84kp91u2SxPkPDyQgu4yrqp8vwVA==
"@oxlint/binding-linux-s390x-gnu@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.61.0.tgz#23773cd6f8087f98c54383caccb98808fab6cca0"
integrity sha512-TVvhgMvor7Qa6COeXxCJ7ENOM+lcAOGsQ0iUdPSCv2hxb9qSHLQ4XF1h50S6RE1gBOJ0WV3rNukg4JJJP1LWRA==
"@oxlint/binding-linux-x64-gnu@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.61.0.tgz#f46b036cf74b382c03f6a00e18cd1ae53096517f"
integrity sha512-SjpS5uYuFoDnDdZPwZE59ndF95AsY47R5MliuneTWR1pDm2CxGJaYXbKULI71t5TVfLQUWmrHEGRL9xvuq6dnA==
"@oxlint/binding-linux-x64-musl@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.61.0.tgz#cff6c4c24de0863cecbce1c1f43adcafacd9011d"
integrity sha512-gGfAeGD4sNJGILZbc/yKcIimO9wQnPMoYp9swAaKeEtwsSQAbU+rsdQze5SBtIP6j0QDzeYd4XSSUCRCF+LIeQ==
"@oxlint/binding-openharmony-arm64@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.61.0.tgz#9fdd87fc10c2c51c510470f7c4136ab2df9ee7b3"
integrity sha512-OlVT0LrG/ct33EVtWRyR+B/othwmDWeRxfi13wUdPeb3lAT5TgTcFDcfLfarZtzB4W1nWF/zICMgYdkggX2WmQ==
"@oxlint/binding-win32-arm64-msvc@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.61.0.tgz#25a87f62859a6703f2520d665f98f6c0f88a70e0"
integrity sha512-vI//NZPJk6DToiovPtaiwD4iQ7kO1r5ReWQD0sOOyKRtP3E2f6jxin4uvwi3OvDzHA2EFfd7DcZl5dtkQh7g1w==
"@oxlint/binding-win32-ia32-msvc@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.61.0.tgz#06f7df42b074f28ef27540d38be69875e5d5afcb"
integrity sha512-0ySj4/4zd2XjePs3XAQq7IigIstN4LPQZgCyigX5/ERMLjdWAJfnxcTsrtxZxuij8guJW8foXuHmhGxW0H4dDA==
"@oxlint/binding-win32-x64-msvc@1.61.0":
version "1.61.0"
resolved "https://registry.yarnpkg.com/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.61.0.tgz#7bc84b261bb8b515ade20f1044547cc8bbee44ce"
integrity sha512-0xgSiyeqDLDZxXoe9CVJrOx3TUVsfyoOY7cNi03JbItNcC9WCZqrSNdrAbHONxhSPaVh/lzfnDcON1RqSUMhHw==
"@playwright/test@^1.57.0-alpha-2025-10-09":
version "1.57.0-alpha-2025-10-11"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.57.0-alpha-2025-10-11.tgz#75f6fac2f98fcff6e4bae1c907b48ad0b1a33bea"
integrity sha512-xqp2RNcLCPSUAYCrP3+rYZ4LFlESvWqjjpFegjNbun7wLcGvUt9Mh+RHBvgeZAhMxxuVde78XO9Y888UYFH9ew==
dependencies:
playwright "1.57.0-alpha-2025-10-11"
"@types/node@^20.0.0":
version "20.19.20"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.20.tgz#116f5432a1e6383415a57cf5e00b5ac9b2a2ad03"
integrity sha512-2Q7WS25j4pS1cS8yw3d6buNCVJukOTeQ39bAnwR6sOJbaxvyCGebzTMypDFN82CxBLnl+lSWVdCCWbRY6y9yZQ==
dependencies:
undici-types "~6.21.0"
dotenv@^16.0.0:
version "16.6.1"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020"
integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==
eslint-plugin-playwright@^2.10.2:
version "2.10.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-2.10.2.tgz#1f0bef35c0b9f996a6987a401e6d4e6a3a015861"
integrity sha512-0N+2OWc3NZbOZ0gK8mp2TK6Qu3UWcJTQ9rqU0UM2yRJXgT758pvpY0lsOLIySfbyFrLqn3TcXjixbmcK90VnuQ==
dependencies:
globals "^17.3.0"
fsevents@2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
globals@^17.3.0:
version "17.5.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-17.5.0.tgz#a82c641d898f8dfbe0e81f66fdff7d0de43f88c6"
integrity sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==
oxfmt@^0.41.0:
version "0.41.0"
resolved "https://registry.yarnpkg.com/oxfmt/-/oxfmt-0.41.0.tgz#7dbfb63d19704a85412f36678c3ace092ce88673"
integrity sha512-sKLdJZdQ3bw6x9qKiT7+eID4MNEXlDHf5ZacfIircrq6Qwjk0L6t2/JQlZZrVHTXJawK3KaMuBoJnEJPcqCEdg==
dependencies:
tinypool "2.1.0"
optionalDependencies:
"@oxfmt/binding-android-arm-eabi" "0.41.0"
"@oxfmt/binding-android-arm64" "0.41.0"
"@oxfmt/binding-darwin-arm64" "0.41.0"
"@oxfmt/binding-darwin-x64" "0.41.0"
"@oxfmt/binding-freebsd-x64" "0.41.0"
"@oxfmt/binding-linux-arm-gnueabihf" "0.41.0"
"@oxfmt/binding-linux-arm-musleabihf" "0.41.0"
"@oxfmt/binding-linux-arm64-gnu" "0.41.0"
"@oxfmt/binding-linux-arm64-musl" "0.41.0"
"@oxfmt/binding-linux-ppc64-gnu" "0.41.0"
"@oxfmt/binding-linux-riscv64-gnu" "0.41.0"
"@oxfmt/binding-linux-riscv64-musl" "0.41.0"
"@oxfmt/binding-linux-s390x-gnu" "0.41.0"
"@oxfmt/binding-linux-x64-gnu" "0.41.0"
"@oxfmt/binding-linux-x64-musl" "0.41.0"
"@oxfmt/binding-openharmony-arm64" "0.41.0"
"@oxfmt/binding-win32-arm64-msvc" "0.41.0"
"@oxfmt/binding-win32-ia32-msvc" "0.41.0"
"@oxfmt/binding-win32-x64-msvc" "0.41.0"
oxlint-tsgolint@^0.20.0:
version "0.20.0"
resolved "https://registry.yarnpkg.com/oxlint-tsgolint/-/oxlint-tsgolint-0.20.0.tgz#e011319219faa572faf340c40d65708404b37e10"
integrity sha512-/Uc9TQyN1l8w9QNvXtVHYtz+SzDJHKpb5X0UnHodl0BVzijUPk0LPlDOHAvogd1UI+iy9ZSF6gQxEqfzUxCULQ==
optionalDependencies:
"@oxlint-tsgolint/darwin-arm64" "0.20.0"
"@oxlint-tsgolint/darwin-x64" "0.20.0"
"@oxlint-tsgolint/linux-arm64" "0.20.0"
"@oxlint-tsgolint/linux-x64" "0.20.0"
"@oxlint-tsgolint/win32-arm64" "0.20.0"
"@oxlint-tsgolint/win32-x64" "0.20.0"
oxlint@^1.59.0:
version "1.61.0"
resolved "https://registry.yarnpkg.com/oxlint/-/oxlint-1.61.0.tgz#e714742cfe7b815713feb14600b0ffe963d539a4"
integrity sha512-ZC0ALuhDZ6ivOFG+sy0D0pEDN49EvsId98zVlmYdkcXHsEM14m/qTNUEsUpiFiCVbpIxYtVBmmLE87nsbUHohQ==
optionalDependencies:
"@oxlint/binding-android-arm-eabi" "1.61.0"
"@oxlint/binding-android-arm64" "1.61.0"
"@oxlint/binding-darwin-arm64" "1.61.0"
"@oxlint/binding-darwin-x64" "1.61.0"
"@oxlint/binding-freebsd-x64" "1.61.0"
"@oxlint/binding-linux-arm-gnueabihf" "1.61.0"
"@oxlint/binding-linux-arm-musleabihf" "1.61.0"
"@oxlint/binding-linux-arm64-gnu" "1.61.0"
"@oxlint/binding-linux-arm64-musl" "1.61.0"
"@oxlint/binding-linux-ppc64-gnu" "1.61.0"
"@oxlint/binding-linux-riscv64-gnu" "1.61.0"
"@oxlint/binding-linux-riscv64-musl" "1.61.0"
"@oxlint/binding-linux-s390x-gnu" "1.61.0"
"@oxlint/binding-linux-x64-gnu" "1.61.0"
"@oxlint/binding-linux-x64-musl" "1.61.0"
"@oxlint/binding-openharmony-arm64" "1.61.0"
"@oxlint/binding-win32-arm64-msvc" "1.61.0"
"@oxlint/binding-win32-ia32-msvc" "1.61.0"
"@oxlint/binding-win32-x64-msvc" "1.61.0"
playwright-core@1.57.0-alpha-2025-10-11:
version "1.57.0-alpha-2025-10-11"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.57.0-alpha-2025-10-11.tgz#b444b75542a43bc354e512d076344d9258997e9c"
integrity sha512-X6KAunryZlslAdEdlN5gIIP3sFU6Uot3vzLoGCZ9SNv0JvXd6e2g7ArjnpOQld36yKszq8J+wQJRlIvdXkIvRw==
playwright@1.57.0-alpha-2025-10-11:
version "1.57.0-alpha-2025-10-11"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.57.0-alpha-2025-10-11.tgz#af67a28d64b39fe57eea454b2b312e98bfff02a5"
integrity sha512-a80kAd59up/kURcKE7THLzx3lN6a1G9RhsgP9ZfLGL7WtnOhOdRLxbHwmjWUG11ybEDeYNpj1qwT02MT4R+rew==
dependencies:
playwright-core "1.57.0-alpha-2025-10-11"
optionalDependencies:
fsevents "2.3.2"
tinypool@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-2.1.0.tgz#303a671d6ef68d03c9512cdc9a47c86b8a85f20c"
integrity sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==
typescript@^5.0.0:
version "5.9.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
undici-types@~6.21.0:
version "6.21.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==

389
tests/fixtures/seed_golden_dataset.py vendored Normal file
View File

@@ -0,0 +1,389 @@
"""Golden dataset fixture — seeds OTel-demo-shaped metrics, traces, and
logs into ClickHouse via the seeder on every test_setup invocation.
Timestamps are rebased to `now` so panels with default time windows
always find data. To refresh the dataset shape on disk, run
`uv run python -m fixtures.seed_golden_dataset regenerate`.
"""
from __future__ import annotations
import datetime
import json
import logging
import os
import random
from collections.abc import Iterator
from pathlib import Path
import pytest
import requests
from fixtures import types
logger = logging.getLogger(__name__)
_GOLDEN_DIR = Path(__file__).resolve().parent.parent / "seeder" / "golden"
METRICS_PATH = _GOLDEN_DIR / "otel-demo-metrics-golden.jsonl"
TRACES_PATH = _GOLDEN_DIR / "otel-demo-traces-golden.jsonl"
LOGS_PATH = _GOLDEN_DIR / "otel-demo-logs-golden.jsonl"
# ─── Generator ───────────────────────────────────────────────────────────
_SERVICES = [
"adservice",
"cartservice",
"checkoutservice",
"currencyservice",
"frontend",
"paymentservice",
"productcatalogservice",
"shippingservice",
]
_OPERATIONS = {
"adservice": ["/ads/get", "/ads/list"],
"cartservice": ["/cart/add", "/cart/get", "/cart/empty"],
"checkoutservice": ["/checkout"],
"currencyservice": ["/currency/convert"],
"frontend": ["/", "/product", "/checkout"],
"paymentservice": ["/payment/charge"],
"productcatalogservice": ["/products/list", "/products/get"],
"shippingservice": ["/shipping/quote", "/shipping/ship"],
}
_DB_SERVICES = {"cartservice", "productcatalogservice"}
_ENV = "production"
_BUCKET_MINUTES = 5
_WINDOW_HOURS = 6
def _generate_metrics() -> list[dict]:
rng = random.Random(20260511)
samples: list[dict] = []
n_buckets = (_WINDOW_HOURS * 60) // _BUCKET_MINUTES
base_counter = 1000
for service in _SERVICES:
for operation in _OPERATIONS[service]:
for status in ("STATUS_CODE_OK", "STATUS_CODE_ERROR"):
weight = 9 if status == "STATUS_CODE_OK" else 1
counter = base_counter
latency_sum = 0
for i in range(n_buckets):
minutes_ago = (_WINDOW_HOURS * 60) - (i + 1) * _BUCKET_MINUTES
bucket_calls = int(
weight
* (50 + 20 * (1 + i % 12 / 12.0) + rng.randint(0, 10))
)
counter += bucket_calls
latency_sum += bucket_calls * rng.randint(100_000, 500_000)
resource_attrs = {
"service.name": service,
"deployment.environment": _ENV,
"k8s.namespace.name": f"signoz-{service}",
}
point_attrs = {
"operation": operation,
"status_code": status,
"span_kind": "SPAN_KIND_SERVER",
}
for name, value in (
("signoz_calls_total", counter),
("signoz_latency_count", counter),
("signoz_latency_sum", latency_sum),
):
samples.append(
{
"metric_name": name,
"minutes_ago": minutes_ago,
"value": value,
"resource_attributes": resource_attrs,
"attributes": point_attrs,
"is_monotonic": True,
}
)
if service in _DB_SERVICES:
db_counter = 0
for i in range(n_buckets):
minutes_ago = (_WINDOW_HOURS * 60) - (i + 1) * _BUCKET_MINUTES
db_counter += 20 + rng.randint(0, 15)
samples.append(
{
"metric_name": "signoz_db_latency_count",
"minutes_ago": minutes_ago,
"value": db_counter,
"resource_attributes": {
"service.name": service,
"deployment.environment": _ENV,
"k8s.namespace.name": f"signoz-{service}",
},
"attributes": {
"db.system": "postgresql"
if service == "cartservice"
else "mongodb",
},
"is_monotonic": True,
}
)
return samples
def _generate_traces() -> list[dict]:
rng = random.Random(20260512)
samples: list[dict] = []
n_buckets = 12
for service in _SERVICES:
for operation in _OPERATIONS[service]:
for i in range(n_buckets):
minutes_ago = int(
(_WINDOW_HOURS * 60) - i * (_WINDOW_HOURS * 60 / n_buckets)
)
http_status = "500" if rng.random() < 0.05 else "200"
samples.append(
{
"name": f"{service} {operation}",
"kind": "SERVER",
"minutes_ago": minutes_ago,
"duration_ms": rng.randint(50, 500),
"status": "ERROR" if http_status == "500" else "OK",
"resource_attributes": {
"service.name": service,
"deployment.environment": _ENV,
"k8s.namespace.name": f"signoz-{service}",
},
"attributes": {
"http.method": "GET"
if "get" in operation.lower() or operation == "/"
else "POST",
"http.route": operation,
"http.status_code": http_status,
},
}
)
return samples
_LOG_SEVERITIES = [("INFO", 0.85), ("WARN", 0.10), ("ERROR", 0.05)]
_LOG_BODIES = {
"INFO": ["Handled request", "Cache hit", "Connection established"],
"WARN": ["Slow response detected", "Cache miss", "Retrying upstream call"],
"ERROR": ["Upstream call failed", "Database query timed out", "Auth failed"],
}
def _generate_logs() -> list[dict]:
rng = random.Random(20260512)
samples: list[dict] = []
n_buckets = 24
for service in _SERVICES:
for i in range(n_buckets):
minutes_ago = int(
(_WINDOW_HOURS * 60) - i * (_WINDOW_HOURS * 60 / n_buckets)
)
r = rng.random()
cumulative = 0.0
severity = "INFO"
for name, weight in _LOG_SEVERITIES:
cumulative += weight
if r < cumulative:
severity = name
break
samples.append(
{
"body": f"[{service}] {rng.choice(_LOG_BODIES[severity])}",
"severity": severity,
"minutes_ago": minutes_ago,
"resource_attributes": {
"service.name": service,
"deployment.environment": _ENV,
"k8s.namespace.name": f"signoz-{service}",
},
"attributes": {"logger.name": f"{service}.app"},
}
)
return samples
def _write_jsonl(path: Path, samples: list[dict]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w") as f:
for s in samples:
f.write(json.dumps(s, separators=(",", ":")))
f.write("\n")
def regenerate() -> dict[str, int]:
metrics = _generate_metrics()
traces = _generate_traces()
logs = _generate_logs()
_write_jsonl(METRICS_PATH, metrics)
_write_jsonl(TRACES_PATH, traces)
_write_jsonl(LOGS_PATH, logs)
return {"metrics": len(metrics), "traces": len(traces), "logs": len(logs)}
# ─── Loader ──────────────────────────────────────────────────────────────
_KIND_TO_INT = {
"UNSPECIFIED": 0,
"INTERNAL": 1,
"SERVER": 2,
"CLIENT": 3,
"PRODUCER": 4,
"CONSUMER": 5,
}
_STATUS_TO_INT = {"UNSET": 0, "OK": 1, "ERROR": 2}
def _read_jsonl(path: Path) -> Iterator[dict]:
with path.open() as f:
for line in f:
line = line.strip()
if line:
yield json.loads(line)
def _iso_minus_minutes(now: datetime.datetime, minutes: float) -> str:
ts = now - datetime.timedelta(minutes=minutes)
return (
ts.replace(tzinfo=datetime.timezone.utc)
.isoformat()
.replace("+00:00", "Z")
)
def _rebased_metric(sample: dict, now: datetime.datetime) -> dict:
out = {k: v for k, v in sample.items() if k != "minutes_ago"}
out["timestamp"] = _iso_minus_minutes(now, sample["minutes_ago"])
return out
def _rebased_trace(sample: dict, now: datetime.datetime) -> dict:
return {
"timestamp": _iso_minus_minutes(now, sample["minutes_ago"]),
"duration": f"PT{sample['duration_ms'] / 1000:.3f}S",
"trace_id": sample.get("trace_id") or os.urandom(16).hex(),
"span_id": sample.get("span_id") or os.urandom(8).hex(),
"name": sample["name"],
"kind": _KIND_TO_INT.get(str(sample.get("kind", "SERVER")).upper(), 2),
"status_code": _STATUS_TO_INT.get(
str(sample.get("status", "UNSET")).upper(), 0
),
"resources": sample.get("resource_attributes", {}),
"attributes": sample.get("attributes", {}),
}
def _rebased_log(sample: dict, now: datetime.datetime) -> dict:
return {
"timestamp": _iso_minus_minutes(now, sample["minutes_ago"]),
"body": sample["body"],
"severity_text": str(sample.get("severity", "INFO")).upper(),
"resources": sample.get("resource_attributes", {}),
"attributes": sample.get("attributes", {}),
}
def _post_batches(
url: str, rows: Iterator[dict], batch_size: int, timeout: int
) -> int:
batch: list[dict] = []
total = 0
for row in rows:
batch.append(row)
if len(batch) >= batch_size:
response = requests.post(url, json=batch, timeout=timeout)
response.raise_for_status()
total += len(batch)
batch = []
if batch:
response = requests.post(url, json=batch, timeout=timeout)
response.raise_for_status()
total += len(batch)
return total
def seed(
seeder_base_url: str,
*,
batch_size: int = 500,
timeout: int = 60,
clear_first: bool = True,
) -> dict[str, int]:
"""Wipe each signal table (via DELETE /telemetry/<signal>) and replay
the golden dataset with timestamps rebased to `now`. Each call leaves
the stack in the exact state the JSONL files describe — chart-data
assertions are reproducible across sessions regardless of how many
earlier sessions seeded."""
for path in (METRICS_PATH, TRACES_PATH, LOGS_PATH):
if not path.exists():
raise FileNotFoundError(
f"golden dataset missing at {path} — run "
"`uv run python -m fixtures.seed_golden_dataset regenerate`"
)
now = datetime.datetime.now(datetime.timezone.utc).replace(
microsecond=0, tzinfo=None
)
base = seeder_base_url.rstrip("/")
if clear_first:
for signal in ("metrics", "traces", "logs"):
requests.delete(f"{base}/telemetry/{signal}", timeout=timeout).raise_for_status()
counts = {
"metrics": _post_batches(
base + "/telemetry/metrics",
(_rebased_metric(s, now) for s in _read_jsonl(METRICS_PATH)),
batch_size,
timeout,
),
"traces": _post_batches(
base + "/telemetry/traces",
(_rebased_trace(s, now) for s in _read_jsonl(TRACES_PATH)),
batch_size,
timeout,
),
"logs": _post_batches(
base + "/telemetry/logs",
(_rebased_log(s, now) for s in _read_jsonl(LOGS_PATH)),
batch_size,
timeout,
),
}
logger.info("seeded through %s: %s", base, counts)
return counts
# ─── Fixture ─────────────────────────────────────────────────────────────
@pytest.fixture(name="golden_dataset", scope="package")
def golden_dataset(seeder: types.TestContainerDocker) -> dict[str, int]:
"""Seed metrics + traces + logs into the running stack via the
seeder. Runs unconditionally on every test_setup invocation so the
rebased timestamps always anchor against `now`."""
return seed(seeder.host_configs["8080"].base())
if __name__ == "__main__":
import sys
logging.basicConfig(level=logging.INFO)
if len(sys.argv) < 2:
sys.stderr.write(
"usage: seed_golden_dataset.py seed <seeder-base-url> | regenerate\n"
)
sys.exit(2)
cmd = sys.argv[1]
if cmd == "regenerate":
print(f"wrote {regenerate()}")
elif cmd == "seed":
if len(sys.argv) != 3:
sys.stderr.write(
"usage: seed_golden_dataset.py seed <seeder-base-url>\n"
)
sys.exit(2)
print(f"seeded {seed(sys.argv[2])}")
else:
sys.stderr.write(f"unknown command: {cmd}\n")
sys.exit(2)

View File

@@ -1,326 +0,0 @@
"""Tests for resource-level FGA on role endpoints.
Validates that a custom role with specific role permissions gets exactly
the access it was granted — read/list allowed, create/update/delete forbidden
until explicitly granted, and revocation removes access.
"""
from collections.abc import Callable
from http import HTTPStatus
import requests
from wiremock.resources.mappings import Mapping
from fixtures import types
from fixtures.auth import (
USER_ADMIN_EMAIL,
USER_ADMIN_PASSWORD,
add_license,
change_user_role,
create_active_user,
find_user_by_email,
)
from fixtures.role import (
ROLES_BASE,
create_custom_role,
delete_custom_role,
find_role_by_name,
object_group,
patch_role_objects,
)
ROLE_FGA_CUSTOM_ROLE_NAME = "role-fga-readonly"
ROLE_FGA_CUSTOM_USER_EMAIL = "customrole+rolefga@integration.test"
ROLE_FGA_CUSTOM_USER_PASSWORD = "password123Z$"
# ---------------------------------------------------------------------------
# 1. Apply license (required for custom role CRUD)
# ---------------------------------------------------------------------------
def test_apply_license(
signoz: types.SigNoz,
create_user_admin: types.Operation, # pylint: disable=unused-argument
make_http_mocks: Callable[[types.TestContainerDocker, list[Mapping]], None],
get_token: Callable[[str, str], str],
) -> None:
add_license(signoz, make_http_mocks, get_token)
# ---------------------------------------------------------------------------
# 2. Create custom role + user with read/list on roles
# ---------------------------------------------------------------------------
def test_create_custom_role_for_role_fga(
signoz: types.SigNoz,
create_user_admin: types.Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
):
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
# Create the custom role.
role_id = create_custom_role(signoz, admin_token, ROLE_FGA_CUSTOM_ROLE_NAME)
# Grant read on role instances.
patch_role_objects(
signoz,
admin_token,
role_id,
"read",
additions=[
object_group("role", "role", ["*"]),
],
)
# Grant list on role collection.
patch_role_objects(
signoz,
admin_token,
role_id,
"list",
additions=[
object_group("role", "role", ["*"]),
],
)
# Create the custom-role user: invite as VIEWER, activate, change role.
user_id = create_active_user(
signoz,
admin_token,
email=ROLE_FGA_CUSTOM_USER_EMAIL,
role="VIEWER",
password=ROLE_FGA_CUSTOM_USER_PASSWORD,
name="role-fga-test-user",
)
change_user_role(signoz, admin_token, user_id, "signoz-viewer", ROLE_FGA_CUSTOM_ROLE_NAME)
# ---------------------------------------------------------------------------
# 3. Read-only access: allowed operations
# ---------------------------------------------------------------------------
def test_role_readonly_allowed_operations(
signoz: types.SigNoz,
create_user_admin: types.Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
):
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
token = get_token(ROLE_FGA_CUSTOM_USER_EMAIL, ROLE_FGA_CUSTOM_USER_PASSWORD)
target_role_id = find_role_by_name(signoz, admin_token, "signoz-viewer")
# List roles.
resp = requests.get(
signoz.self.host_configs["8080"].get(ROLES_BASE),
headers={"Authorization": f"Bearer {token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.OK, f"list roles: {resp.text}"
# Get role.
resp = requests.get(
signoz.self.host_configs["8080"].get(f"{ROLES_BASE}/{target_role_id}"),
headers={"Authorization": f"Bearer {token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.OK, f"get role: {resp.text}"
# Get objects for role.
resp = requests.get(
signoz.self.host_configs["8080"].get(f"{ROLES_BASE}/{target_role_id}/relations/read/objects"),
headers={"Authorization": f"Bearer {token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.OK, f"get role objects: {resp.text}"
# ---------------------------------------------------------------------------
# 4. Read-only access: forbidden operations
# ---------------------------------------------------------------------------
def test_role_readonly_forbidden_operations(
signoz: types.SigNoz,
create_user_admin: types.Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
):
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
token = get_token(ROLE_FGA_CUSTOM_USER_EMAIL, ROLE_FGA_CUSTOM_USER_PASSWORD)
target_role_id = find_role_by_name(signoz, admin_token, "signoz-viewer")
# Create role — forbidden.
resp = requests.post(
signoz.self.host_configs["8080"].get(ROLES_BASE),
json={"name": "role-fga-should-fail"},
headers={"Authorization": f"Bearer {token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"create role: expected 403, got {resp.status_code}: {resp.text}"
# Patch role — forbidden.
resp = requests.patch(
signoz.self.host_configs["8080"].get(f"{ROLES_BASE}/{target_role_id}"),
json={"name": "role-fga-renamed"},
headers={"Authorization": f"Bearer {token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"patch role: expected 403, got {resp.status_code}: {resp.text}"
# Patch objects — forbidden.
resp = requests.patch(
signoz.self.host_configs["8080"].get(f"{ROLES_BASE}/{target_role_id}/relations/read/objects"),
json={"additions": [object_group("metaresource", "dashboard", ["*"])]},
headers={"Authorization": f"Bearer {token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"patch objects: expected 403, got {resp.status_code}: {resp.text}"
# Delete role — forbidden (cannot delete managed role, but auth check comes first).
# Use the custom role itself as target (non-managed, but user lacks delete permission).
custom_role_id = find_role_by_name(signoz, admin_token, ROLE_FGA_CUSTOM_ROLE_NAME)
resp = requests.delete(
signoz.self.host_configs["8080"].get(f"{ROLES_BASE}/{custom_role_id}"),
headers={"Authorization": f"Bearer {token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"delete role: expected 403, got {resp.status_code}: {resp.text}"
# ---------------------------------------------------------------------------
# 5. Grant write permissions, verify access opens up
# ---------------------------------------------------------------------------
def test_role_grant_write_permissions(
signoz: types.SigNoz,
create_user_admin: types.Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
):
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
role_id = find_role_by_name(signoz, admin_token, ROLE_FGA_CUSTOM_ROLE_NAME)
# Grant create, update, delete on roles.
for verb in ("create", "update", "delete"):
patch_role_objects(
signoz,
admin_token,
role_id,
verb,
additions=[object_group("role", "role", ["*"])],
)
custom_token = get_token(ROLE_FGA_CUSTOM_USER_EMAIL, ROLE_FGA_CUSTOM_USER_PASSWORD)
# Create role — now allowed.
resp = requests.post(
signoz.self.host_configs["8080"].get(ROLES_BASE),
json={"name": "role-fga-write-test"},
headers={"Authorization": f"Bearer {custom_token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.CREATED, f"create role: {resp.text}"
new_role_id = resp.json()["data"]["id"]
# Patch role — now allowed.
resp = requests.patch(
signoz.self.host_configs["8080"].get(f"{ROLES_BASE}/{new_role_id}"),
json={"name": "role-fga-write-renamed"},
headers={"Authorization": f"Bearer {custom_token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.NO_CONTENT, f"patch role: {resp.text}"
# Delete role — now allowed.
resp = requests.delete(
signoz.self.host_configs["8080"].get(f"{ROLES_BASE}/{new_role_id}"),
headers={"Authorization": f"Bearer {custom_token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.NO_CONTENT, f"delete role: {resp.text}"
# ---------------------------------------------------------------------------
# 6. Revoke read/list → verify access lost
# ---------------------------------------------------------------------------
def test_role_revoke_read_permissions(
signoz: types.SigNoz,
create_user_admin: types.Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
):
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
role_id = find_role_by_name(signoz, admin_token, ROLE_FGA_CUSTOM_ROLE_NAME)
target_role_id = find_role_by_name(signoz, admin_token, "signoz-viewer")
# Revoke read.
patch_role_objects(
signoz,
admin_token,
role_id,
"read",
deletions=[object_group("role", "role", ["*"])],
)
# Revoke list.
patch_role_objects(
signoz,
admin_token,
role_id,
"list",
deletions=[object_group("role", "role", ["*"])],
)
custom_token = get_token(ROLE_FGA_CUSTOM_USER_EMAIL, ROLE_FGA_CUSTOM_USER_PASSWORD)
# List roles — forbidden.
resp = requests.get(
signoz.self.host_configs["8080"].get(ROLES_BASE),
headers={"Authorization": f"Bearer {custom_token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"list roles after revoke: expected 403, got {resp.status_code}: {resp.text}"
# Get role — forbidden.
resp = requests.get(
signoz.self.host_configs["8080"].get(f"{ROLES_BASE}/{target_role_id}"),
headers={"Authorization": f"Bearer {custom_token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"get role after revoke: expected 403, got {resp.status_code}: {resp.text}"
# ---------------------------------------------------------------------------
# 7. Clean up: delete custom role
# ---------------------------------------------------------------------------
def test_role_fga_cleanup(
signoz: types.SigNoz,
create_user_admin: types.Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
):
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
role_id = find_role_by_name(signoz, admin_token, ROLE_FGA_CUSTOM_ROLE_NAME)
user = find_user_by_email(signoz, admin_token, ROLE_FGA_CUSTOM_USER_EMAIL)
# Remove the custom role from the user first.
resp = requests.get(
signoz.self.host_configs["8080"].get(f"/api/v2/users/{user['id']}/roles"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.OK, resp.text
roles = resp.json()["data"]
custom_entry = next((r for r in roles if r["name"] == ROLE_FGA_CUSTOM_ROLE_NAME), None)
if custom_entry is not None:
resp = requests.delete(
signoz.self.host_configs["8080"].get(f"/api/v2/users/{user['id']}/roles/{custom_entry['id']}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.NO_CONTENT, f"remove role from user: {resp.text}"
delete_custom_role(signoz, admin_token, role_id)

View File

@@ -1,11 +1,8 @@
"""Tests for resource-level FGA on service account endpoints.
Validates that a custom role with specific SA permissions gets exactly
the access it was granted, and that:
- SA role assignment requires BOTH serviceaccount:attach AND role:attach.
- SA role removal requires BOTH serviceaccount:detach AND role:detach.
- Factor API key creation requires factor-api-key:create AND serviceaccount:attach.
- Factor API key revocation requires factor-api-key:delete AND serviceaccount:detach.
the access it was granted, and that SA role assignment requires BOTH
serviceaccount:attach AND role:attach.
"""
from collections.abc import Callable
@@ -83,36 +80,14 @@ def test_create_custom_role_readonly_sa(
],
)
# Grant list on serviceaccount (now on the serviceaccount type directly).
# Grant list on serviceaccount collection.
patch_role_objects(
signoz,
admin_token,
role_id,
"list",
additions=[
object_group("serviceaccount", "serviceaccount", ["*"]),
],
)
# Grant read on factor-api-key (needed for listing keys).
patch_role_objects(
signoz,
admin_token,
role_id,
"read",
additions=[
object_group("metaresource", "factor-api-key", ["*"]),
],
)
# Grant list on factor-api-key.
patch_role_objects(
signoz,
admin_token,
role_id,
"list",
additions=[
object_group("metaresource", "factor-api-key", ["*"]),
object_group("metaresources", "serviceaccount", ["*"]),
],
)
@@ -228,7 +203,7 @@ def test_readonly_role_forbidden_operations(
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"delete SA: expected 403, got {resp.status_code}: {resp.text}"
# Assign role to SA — forbidden (needs attach on both SA and role).
# Assign role to SA — forbidden.
resp = requests.post(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{sa_id}/roles"),
json={"id": viewer_role_id},
@@ -237,7 +212,7 @@ def test_readonly_role_forbidden_operations(
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"assign SA role: expected 403, got {resp.status_code}: {resp.text}"
# Remove role from SA — forbidden (needs detach on both SA and role).
# Remove role from SA — forbidden.
resp = requests.delete(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{sa_id}/roles/{viewer_role_id}"),
headers={"Authorization": f"Bearer {token}"},
@@ -245,7 +220,7 @@ def test_readonly_role_forbidden_operations(
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"remove SA role: expected 403, got {resp.status_code}: {resp.text}"
# Create key — forbidden (needs factor-api-key:create + serviceaccount:attach).
# Create key — forbidden (needs update).
resp = requests.post(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{sa_id}/keys"),
json={"name": "fga-key-fail", "expiresAt": 0},
@@ -254,7 +229,7 @@ def test_readonly_role_forbidden_operations(
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"create key: expected 403, got {resp.status_code}: {resp.text}"
# Revoke key — forbidden (needs factor-api-key:delete + serviceaccount:detach).
# Revoke key — forbidden (needs update).
resp = requests.delete(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{sa_id}/keys/{key_id}"),
headers={"Authorization": f"Bearer {token}"},
@@ -278,14 +253,14 @@ def test_patch_role_add_write_permissions(
sa_id = find_service_account_by_name(signoz, admin_token, SA_FGA_TARGET_SA_NAME)["id"]
viewer_role_id = find_role_by_name(signoz, admin_token, "signoz-viewer")
# Grant create on serviceaccount (now on serviceaccount type directly).
# Grant create on collection.
patch_role_objects(
signoz,
admin_token,
role_id,
"create",
additions=[
object_group("serviceaccount", "serviceaccount", ["*"]),
object_group("metaresources", "serviceaccount", ["*"]),
],
)
@@ -311,44 +286,6 @@ def test_patch_role_add_write_permissions(
],
)
# Grant factor-api-key create/delete + serviceaccount attach/detach for key operations.
patch_role_objects(
signoz,
admin_token,
role_id,
"create",
additions=[
object_group("metaresource", "factor-api-key", ["*"]),
],
)
patch_role_objects(
signoz,
admin_token,
role_id,
"delete",
additions=[
object_group("metaresource", "factor-api-key", ["*"]),
],
)
patch_role_objects(
signoz,
admin_token,
role_id,
"attach",
additions=[
object_group("serviceaccount", "serviceaccount", ["*"]),
],
)
patch_role_objects(
signoz,
admin_token,
role_id,
"detach",
additions=[
object_group("serviceaccount", "serviceaccount", ["*"]),
],
)
custom_token = get_token(SA_FGA_CUSTOM_USER_EMAIL, SA_FGA_CUSTOM_USER_PASSWORD)
# Create SA — now allowed.
@@ -370,7 +307,7 @@ def test_patch_role_add_write_permissions(
)
assert resp.status_code == HTTPStatus.NO_CONTENT, f"update SA: {resp.text}"
# Create key — now allowed (factor-api-key:create + serviceaccount:attach).
# Create key — now allowed (update permission covers key create).
key_resp = requests.post(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{new_sa_id}/keys"),
json={"name": "fga-write-key", "expiresAt": 0},
@@ -380,7 +317,7 @@ def test_patch_role_add_write_permissions(
assert key_resp.status_code == HTTPStatus.CREATED, f"create key: {key_resp.text}"
new_key_id = key_resp.json()["data"]["id"]
# Revoke key — now allowed (factor-api-key:delete + serviceaccount:detach).
# Revoke key — now allowed (update permission covers key revoke).
resp = requests.delete(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{new_sa_id}/keys/{new_key_id}"),
headers={"Authorization": f"Bearer {custom_token}"},
@@ -396,7 +333,7 @@ def test_patch_role_add_write_permissions(
)
assert resp.status_code == HTTPStatus.NO_CONTENT, f"delete SA: {resp.text}"
# Role assignment still forbidden (has attach on SA but not on role).
# Role assignment still forbidden (no attach).
resp = requests.post(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{sa_id}/roles"),
json={"id": viewer_role_id},
@@ -405,7 +342,6 @@ def test_patch_role_add_write_permissions(
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"assign SA role: expected 403, got {resp.status_code}: {resp.text}"
# Role removal still forbidden (has detach on SA but not on role).
resp = requests.delete(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{sa_id}/roles/{viewer_role_id}"),
headers={"Authorization": f"Bearer {custom_token}"},
@@ -415,7 +351,7 @@ def test_patch_role_add_write_permissions(
# ---------------------------------------------------------------------------
# 6. Dual-attach: SA attach only (no role attach) → assign forbidden
# 6. Dual-attach: SA attach only (no role attach) → forbidden
# ---------------------------------------------------------------------------
@@ -425,10 +361,21 @@ def test_attach_with_only_sa_attach_forbidden(
get_token: Callable[[str, str], str],
):
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
role_id = find_role_by_name(signoz, admin_token, SA_FGA_CUSTOM_ROLE_NAME)
sa_id = find_service_account_by_name(signoz, admin_token, SA_FGA_TARGET_SA_NAME)["id"]
viewer_role_id = find_role_by_name(signoz, admin_token, "signoz-viewer")
# SA attach already granted from previous test; role attach not yet granted.
# Grant attach on serviceaccount only.
patch_role_objects(
signoz,
admin_token,
role_id,
"attach",
additions=[
object_group("serviceaccount", "serviceaccount", ["*"]),
],
)
custom_token = get_token(SA_FGA_CUSTOM_USER_EMAIL, SA_FGA_CUSTOM_USER_PASSWORD)
# Assign role — forbidden (has SA attach, missing role attach).
@@ -440,36 +387,17 @@ def test_attach_with_only_sa_attach_forbidden(
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"assign with only SA attach: expected 403, got {resp.status_code}: {resp.text}"
# ---------------------------------------------------------------------------
# 7. Dual-detach: SA detach only (no role detach) → remove forbidden
# ---------------------------------------------------------------------------
def test_detach_with_only_sa_detach_forbidden(
signoz: types.SigNoz,
create_user_admin: types.Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
):
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
sa_id = find_service_account_by_name(signoz, admin_token, SA_FGA_TARGET_SA_NAME)["id"]
viewer_role_id = find_role_by_name(signoz, admin_token, "signoz-viewer")
# SA detach already granted from test_patch_role_add_write_permissions;
# role detach not yet granted.
custom_token = get_token(SA_FGA_CUSTOM_USER_EMAIL, SA_FGA_CUSTOM_USER_PASSWORD)
# Remove role — forbidden (has SA detach, missing role detach).
# Remove role — forbidden (CheckAll: role attach group fails).
resp = requests.delete(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{sa_id}/roles/{viewer_role_id}"),
headers={"Authorization": f"Bearer {custom_token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"remove with only SA detach: expected 403, got {resp.status_code}: {resp.text}"
assert resp.status_code == HTTPStatus.FORBIDDEN, f"remove with only SA attach: expected 403, got {resp.status_code}: {resp.text}"
# ---------------------------------------------------------------------------
# 8. Dual-attach: role attach only (no SA attach) → assign forbidden
# 7. Dual-attach: role attach only (no SA attach) → forbidden
# ---------------------------------------------------------------------------
@@ -504,49 +432,21 @@ def test_attach_with_only_role_attach_forbidden(
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"assign with only role attach: expected 403, got {resp.status_code}: {resp.text}"
# ---------------------------------------------------------------------------
# 9. Dual-detach: role detach only (no SA detach) → remove forbidden
# ---------------------------------------------------------------------------
def test_detach_with_only_role_detach_forbidden(
signoz: types.SigNoz,
create_user_admin: types.Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
):
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
role_id = find_role_by_name(signoz, admin_token, SA_FGA_CUSTOM_ROLE_NAME)
sa_id = find_service_account_by_name(signoz, admin_token, SA_FGA_TARGET_SA_NAME)["id"]
viewer_role_id = find_role_by_name(signoz, admin_token, "signoz-viewer")
# Remove SA detach, grant role detach.
patch_role_objects(
signoz,
admin_token,
role_id,
"detach",
additions=[object_group("role", "role", ["*"])],
deletions=[object_group("serviceaccount", "serviceaccount", ["*"])],
)
custom_token = get_token(SA_FGA_CUSTOM_USER_EMAIL, SA_FGA_CUSTOM_USER_PASSWORD)
# Remove role — forbidden (SA detach check fails).
# Remove role — forbidden (CheckAll: SA attach group fails).
resp = requests.delete(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{sa_id}/roles/{viewer_role_id}"),
headers={"Authorization": f"Bearer {custom_token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.FORBIDDEN, f"remove with only role detach: expected 403, got {resp.status_code}: {resp.text}"
assert resp.status_code == HTTPStatus.FORBIDDEN, f"remove with only role attach: expected 403, got {resp.status_code}: {resp.text}"
# ---------------------------------------------------------------------------
# 10. Both attach + detach → assign and remove succeed
# 8. Dual-attach: both SA + role attach → succeeds
# ---------------------------------------------------------------------------
def test_attach_detach_with_both_permissions_succeeds(
def test_attach_with_both_permissions_succeeds(
signoz: types.SigNoz,
create_user_admin: types.Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
@@ -555,7 +455,7 @@ def test_attach_detach_with_both_permissions_succeeds(
role_id = find_role_by_name(signoz, admin_token, SA_FGA_CUSTOM_ROLE_NAME)
sa_id = find_service_account_by_name(signoz, admin_token, SA_FGA_TARGET_SA_NAME)["id"]
# Add back SA attach and SA detach (role attach/detach already present from previous tests).
# Add back SA attach (role attach already present from previous test).
patch_role_objects(
signoz,
admin_token,
@@ -565,15 +465,6 @@ def test_attach_detach_with_both_permissions_succeeds(
object_group("serviceaccount", "serviceaccount", ["*"]),
],
)
patch_role_objects(
signoz,
admin_token,
role_id,
"detach",
additions=[
object_group("serviceaccount", "serviceaccount", ["*"]),
],
)
custom_token = get_token(SA_FGA_CUSTOM_USER_EMAIL, SA_FGA_CUSTOM_USER_PASSWORD)
@@ -589,17 +480,17 @@ def test_attach_detach_with_both_permissions_succeeds(
)
assert resp.status_code == HTTPStatus.NO_CONTENT, f"assign with both attach: {resp.text}"
# Remove the editor role — should succeed (both SA detach + role detach).
# Remove the editor role — should succeed (CheckAll: both groups pass).
resp = requests.delete(
signoz.self.host_configs["8080"].get(f"{SERVICE_ACCOUNT_BASE}/{sa_id}/roles/{editor_role_id}"),
headers={"Authorization": f"Bearer {custom_token}"},
timeout=5,
)
assert resp.status_code == HTTPStatus.NO_CONTENT, f"remove with both detach: {resp.text}"
assert resp.status_code == HTTPStatus.NO_CONTENT, f"remove with both attach: {resp.text}"
# ---------------------------------------------------------------------------
# 11. Revoke read/list → verify access lost
# 9. Revoke read/list → verify access lost
# ---------------------------------------------------------------------------
@@ -623,14 +514,14 @@ def test_remove_read_permissions_revokes_access(
],
)
# Revoke list (now on serviceaccount type directly).
# Revoke list.
patch_role_objects(
signoz,
admin_token,
role_id,
"list",
deletions=[
object_group("serviceaccount", "serviceaccount", ["*"]),
object_group("metaresources", "serviceaccount", ["*"]),
],
)
@@ -654,7 +545,7 @@ def test_remove_read_permissions_revokes_access(
# ---------------------------------------------------------------------------
# 12. Clean up: delete custom role
# 10. Clean up: delete custom role
# ---------------------------------------------------------------------------

View File

@@ -0,0 +1,192 @@
{"body":"[adservice] Connection established","severity":"INFO","minutes_ago":360,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Connection established","severity":"INFO","minutes_ago":345,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Background job completed","severity":"INFO","minutes_ago":330,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Cache hit","severity":"INFO","minutes_ago":315,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Background job completed","severity":"INFO","minutes_ago":300,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Cache hit","severity":"INFO","minutes_ago":285,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Database query timed out","severity":"ERROR","minutes_ago":270,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Cache hit","severity":"INFO","minutes_ago":255,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Slow response detected","severity":"WARN","minutes_ago":240,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Cache hit","severity":"INFO","minutes_ago":225,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Connection established","severity":"INFO","minutes_ago":210,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Handled request","severity":"INFO","minutes_ago":195,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Cache miss","severity":"WARN","minutes_ago":180,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Background job completed","severity":"INFO","minutes_ago":165,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Connection established","severity":"INFO","minutes_ago":150,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Connection established","severity":"INFO","minutes_ago":135,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Upstream call failed","severity":"ERROR","minutes_ago":120,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Connection established","severity":"INFO","minutes_ago":105,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Background job completed","severity":"INFO","minutes_ago":90,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Background job completed","severity":"INFO","minutes_ago":75,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Background job completed","severity":"INFO","minutes_ago":60,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Cache hit","severity":"INFO","minutes_ago":45,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Retrying upstream call","severity":"WARN","minutes_ago":30,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[adservice] Cache hit","severity":"INFO","minutes_ago":15,"resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"logger.name":"adservice.app"}}
{"body":"[cartservice] Connection established","severity":"INFO","minutes_ago":360,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Cache hit","severity":"INFO","minutes_ago":345,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Background job completed","severity":"INFO","minutes_ago":330,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Cache hit","severity":"INFO","minutes_ago":315,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Upstream call failed","severity":"ERROR","minutes_ago":300,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Connection established","severity":"INFO","minutes_ago":285,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Retrying upstream call","severity":"WARN","minutes_ago":270,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Cache hit","severity":"INFO","minutes_ago":255,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Background job completed","severity":"INFO","minutes_ago":240,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Background job completed","severity":"INFO","minutes_ago":225,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Connection established","severity":"INFO","minutes_ago":210,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Connection established","severity":"INFO","minutes_ago":195,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Cache hit","severity":"INFO","minutes_ago":180,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Connection established","severity":"INFO","minutes_ago":165,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Cache hit","severity":"INFO","minutes_ago":150,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Connection established","severity":"INFO","minutes_ago":135,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Retrying upstream call","severity":"WARN","minutes_ago":120,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Cache hit","severity":"INFO","minutes_ago":105,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Handled request","severity":"INFO","minutes_ago":90,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Background job completed","severity":"INFO","minutes_ago":75,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Connection established","severity":"INFO","minutes_ago":60,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Background job completed","severity":"INFO","minutes_ago":45,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Cache hit","severity":"INFO","minutes_ago":30,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[cartservice] Handled request","severity":"INFO","minutes_ago":15,"resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"logger.name":"cartservice.app"}}
{"body":"[checkoutservice] Retrying upstream call","severity":"WARN","minutes_ago":360,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Cache hit","severity":"INFO","minutes_ago":345,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Background job completed","severity":"INFO","minutes_ago":330,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Connection established","severity":"INFO","minutes_ago":315,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Connection established","severity":"INFO","minutes_ago":300,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Background job completed","severity":"INFO","minutes_ago":285,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Background job completed","severity":"INFO","minutes_ago":270,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Background job completed","severity":"INFO","minutes_ago":255,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Connection established","severity":"INFO","minutes_ago":240,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Cache hit","severity":"INFO","minutes_ago":225,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Retrying upstream call","severity":"WARN","minutes_ago":210,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Connection established","severity":"INFO","minutes_ago":195,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Handled request","severity":"INFO","minutes_ago":180,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Connection established","severity":"INFO","minutes_ago":165,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Authorization failed","severity":"ERROR","minutes_ago":150,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Cache hit","severity":"INFO","minutes_ago":135,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Cache miss","severity":"WARN","minutes_ago":120,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Background job completed","severity":"INFO","minutes_ago":105,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Connection established","severity":"INFO","minutes_ago":90,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Connection established","severity":"INFO","minutes_ago":75,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Cache hit","severity":"INFO","minutes_ago":60,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Background job completed","severity":"INFO","minutes_ago":45,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Cache hit","severity":"INFO","minutes_ago":30,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[checkoutservice] Slow response detected","severity":"WARN","minutes_ago":15,"resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"logger.name":"checkoutservice.app"}}
{"body":"[currencyservice] Background job completed","severity":"INFO","minutes_ago":360,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Cache hit","severity":"INFO","minutes_ago":345,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Connection established","severity":"INFO","minutes_ago":330,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Handled request","severity":"INFO","minutes_ago":315,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Background job completed","severity":"INFO","minutes_ago":300,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Connection established","severity":"INFO","minutes_ago":285,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Handled request","severity":"INFO","minutes_ago":270,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Connection established","severity":"INFO","minutes_ago":255,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Handled request","severity":"INFO","minutes_ago":240,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Connection established","severity":"INFO","minutes_ago":225,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Background job completed","severity":"INFO","minutes_ago":210,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Background job completed","severity":"INFO","minutes_ago":195,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Cache hit","severity":"INFO","minutes_ago":180,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Cache hit","severity":"INFO","minutes_ago":165,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Cache hit","severity":"INFO","minutes_ago":150,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Cache miss","severity":"WARN","minutes_ago":135,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Background job completed","severity":"INFO","minutes_ago":120,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Cache hit","severity":"INFO","minutes_ago":105,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Background job completed","severity":"INFO","minutes_ago":90,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Cache hit","severity":"INFO","minutes_ago":75,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Cache hit","severity":"INFO","minutes_ago":60,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Cache hit","severity":"INFO","minutes_ago":45,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Handled request","severity":"INFO","minutes_ago":30,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[currencyservice] Cache hit","severity":"INFO","minutes_ago":15,"resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"logger.name":"currencyservice.app"}}
{"body":"[frontend] Slow response detected","severity":"WARN","minutes_ago":360,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Cache hit","severity":"INFO","minutes_ago":345,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Background job completed","severity":"INFO","minutes_ago":330,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Connection established","severity":"INFO","minutes_ago":315,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Background job completed","severity":"INFO","minutes_ago":300,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Connection established","severity":"INFO","minutes_ago":285,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Background job completed","severity":"INFO","minutes_ago":270,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Connection established","severity":"INFO","minutes_ago":255,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Handled request","severity":"INFO","minutes_ago":240,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Slow response detected","severity":"WARN","minutes_ago":225,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Cache hit","severity":"INFO","minutes_ago":210,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Handled request","severity":"INFO","minutes_ago":195,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Background job completed","severity":"INFO","minutes_ago":180,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Cache miss","severity":"WARN","minutes_ago":165,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Authorization failed","severity":"ERROR","minutes_ago":150,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Connection established","severity":"INFO","minutes_ago":135,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Connection established","severity":"INFO","minutes_ago":120,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Handled request","severity":"INFO","minutes_ago":105,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Cache hit","severity":"INFO","minutes_ago":90,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Background job completed","severity":"INFO","minutes_ago":75,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Connection established","severity":"INFO","minutes_ago":60,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Background job completed","severity":"INFO","minutes_ago":45,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Connection established","severity":"INFO","minutes_ago":30,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[frontend] Background job completed","severity":"INFO","minutes_ago":15,"resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"logger.name":"frontend.app"}}
{"body":"[paymentservice] Connection established","severity":"INFO","minutes_ago":360,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Cache hit","severity":"INFO","minutes_ago":345,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Connection established","severity":"INFO","minutes_ago":330,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Handled request","severity":"INFO","minutes_ago":315,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Connection established","severity":"INFO","minutes_ago":300,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Connection established","severity":"INFO","minutes_ago":285,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Slow response detected","severity":"WARN","minutes_ago":270,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Authorization failed","severity":"ERROR","minutes_ago":255,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Handled request","severity":"INFO","minutes_ago":240,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Authorization failed","severity":"ERROR","minutes_ago":225,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Background job completed","severity":"INFO","minutes_ago":210,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Authorization failed","severity":"ERROR","minutes_ago":195,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Cache hit","severity":"INFO","minutes_ago":180,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Cache hit","severity":"INFO","minutes_ago":165,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Retrying upstream call","severity":"WARN","minutes_ago":150,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Handled request","severity":"INFO","minutes_ago":135,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Background job completed","severity":"INFO","minutes_ago":120,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Handled request","severity":"INFO","minutes_ago":105,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Authorization failed","severity":"ERROR","minutes_ago":90,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Connection established","severity":"INFO","minutes_ago":75,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Cache hit","severity":"INFO","minutes_ago":60,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Cache hit","severity":"INFO","minutes_ago":45,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Handled request","severity":"INFO","minutes_ago":30,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[paymentservice] Upstream call failed","severity":"ERROR","minutes_ago":15,"resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"logger.name":"paymentservice.app"}}
{"body":"[productcatalogservice] Cache hit","severity":"INFO","minutes_ago":360,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Connection established","severity":"INFO","minutes_ago":345,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Background job completed","severity":"INFO","minutes_ago":330,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Cache hit","severity":"INFO","minutes_ago":315,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Cache hit","severity":"INFO","minutes_ago":300,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Connection established","severity":"INFO","minutes_ago":285,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Cache miss","severity":"WARN","minutes_ago":270,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Connection established","severity":"INFO","minutes_ago":255,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Background job completed","severity":"INFO","minutes_ago":240,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Background job completed","severity":"INFO","minutes_ago":225,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Cache hit","severity":"INFO","minutes_ago":210,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Cache hit","severity":"INFO","minutes_ago":195,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Background job completed","severity":"INFO","minutes_ago":180,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Cache hit","severity":"INFO","minutes_ago":165,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Background job completed","severity":"INFO","minutes_ago":150,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Background job completed","severity":"INFO","minutes_ago":135,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Cache hit","severity":"INFO","minutes_ago":120,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Handled request","severity":"INFO","minutes_ago":105,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Background job completed","severity":"INFO","minutes_ago":90,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Background job completed","severity":"INFO","minutes_ago":75,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Cache hit","severity":"INFO","minutes_ago":60,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Connection established","severity":"INFO","minutes_ago":45,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Cache hit","severity":"INFO","minutes_ago":30,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[productcatalogservice] Background job completed","severity":"INFO","minutes_ago":15,"resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"logger.name":"productcatalogservice.app"}}
{"body":"[shippingservice] Database query timed out","severity":"ERROR","minutes_ago":360,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Connection established","severity":"INFO","minutes_ago":345,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Background job completed","severity":"INFO","minutes_ago":330,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Cache hit","severity":"INFO","minutes_ago":315,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Background job completed","severity":"INFO","minutes_ago":300,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Connection established","severity":"INFO","minutes_ago":285,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Handled request","severity":"INFO","minutes_ago":270,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Cache hit","severity":"INFO","minutes_ago":255,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Handled request","severity":"INFO","minutes_ago":240,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Cache miss","severity":"WARN","minutes_ago":225,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Connection established","severity":"INFO","minutes_ago":210,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Connection established","severity":"INFO","minutes_ago":195,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Connection established","severity":"INFO","minutes_ago":180,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Background job completed","severity":"INFO","minutes_ago":165,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Cache hit","severity":"INFO","minutes_ago":150,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Database query timed out","severity":"ERROR","minutes_ago":135,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Background job completed","severity":"INFO","minutes_ago":120,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Cache hit","severity":"INFO","minutes_ago":105,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Handled request","severity":"INFO","minutes_ago":90,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Handled request","severity":"INFO","minutes_ago":75,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Cache hit","severity":"INFO","minutes_ago":60,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Connection established","severity":"INFO","minutes_ago":45,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Background job completed","severity":"INFO","minutes_ago":30,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}
{"body":"[shippingservice] Cache miss","severity":"WARN","minutes_ago":15,"resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"logger.name":"shippingservice.app"}}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":360,"duration_ms":380,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":330,"duration_ms":141,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":300,"duration_ms":419,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":270,"duration_ms":421,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":240,"duration_ms":245,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":210,"duration_ms":341,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":180,"duration_ms":403,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":150,"duration_ms":334,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":120,"duration_ms":402,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":90,"duration_ms":140,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":60,"duration_ms":350,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/get","kind":"SERVER","minutes_ago":30,"duration_ms":229,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"GET","http.route":"/ads/get","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":360,"duration_ms":421,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":330,"duration_ms":332,"status":"ERROR","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"500"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":300,"duration_ms":70,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":270,"duration_ms":464,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":240,"duration_ms":77,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":210,"duration_ms":187,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":180,"duration_ms":278,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":150,"duration_ms":191,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":120,"duration_ms":433,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":90,"duration_ms":191,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":60,"duration_ms":104,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"adservice /ads/list","kind":"SERVER","minutes_ago":30,"duration_ms":189,"status":"OK","resource_attributes":{"service.name":"adservice","deployment.environment":"production","k8s.namespace.name":"signoz-adservice"},"attributes":{"http.method":"POST","http.route":"/ads/list","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":360,"duration_ms":303,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":330,"duration_ms":492,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":300,"duration_ms":271,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":270,"duration_ms":114,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":240,"duration_ms":245,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":210,"duration_ms":171,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":180,"duration_ms":145,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":150,"duration_ms":190,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":120,"duration_ms":166,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":90,"duration_ms":391,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":60,"duration_ms":361,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/add","kind":"SERVER","minutes_ago":30,"duration_ms":456,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/add","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":360,"duration_ms":173,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":330,"duration_ms":127,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":300,"duration_ms":342,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":270,"duration_ms":124,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":240,"duration_ms":499,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":210,"duration_ms":168,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":180,"duration_ms":292,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":150,"duration_ms":417,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":120,"duration_ms":107,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":90,"duration_ms":439,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":60,"duration_ms":441,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/get","kind":"SERVER","minutes_ago":30,"duration_ms":223,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"GET","http.route":"/cart/get","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":360,"duration_ms":420,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":330,"duration_ms":244,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":300,"duration_ms":485,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":270,"duration_ms":189,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":240,"duration_ms":134,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":210,"duration_ms":420,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":180,"duration_ms":456,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":150,"duration_ms":485,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":120,"duration_ms":80,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":90,"duration_ms":291,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":60,"duration_ms":158,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"cartservice /cart/empty","kind":"SERVER","minutes_ago":30,"duration_ms":56,"status":"OK","resource_attributes":{"service.name":"cartservice","deployment.environment":"production","k8s.namespace.name":"signoz-cartservice"},"attributes":{"http.method":"POST","http.route":"/cart/empty","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":360,"duration_ms":378,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":330,"duration_ms":82,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":300,"duration_ms":102,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":270,"duration_ms":249,"status":"ERROR","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"500"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":240,"duration_ms":215,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":210,"duration_ms":234,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":180,"duration_ms":301,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":150,"duration_ms":284,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":120,"duration_ms":290,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":90,"duration_ms":212,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":60,"duration_ms":400,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"checkoutservice /checkout","kind":"SERVER","minutes_ago":30,"duration_ms":339,"status":"OK","resource_attributes":{"service.name":"checkoutservice","deployment.environment":"production","k8s.namespace.name":"signoz-checkoutservice"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":360,"duration_ms":205,"status":"ERROR","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"500"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":330,"duration_ms":77,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":300,"duration_ms":217,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":270,"duration_ms":348,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":240,"duration_ms":351,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":210,"duration_ms":288,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":180,"duration_ms":83,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":150,"duration_ms":264,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":120,"duration_ms":111,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":90,"duration_ms":349,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":60,"duration_ms":464,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"currencyservice /currency/convert","kind":"SERVER","minutes_ago":30,"duration_ms":201,"status":"OK","resource_attributes":{"service.name":"currencyservice","deployment.environment":"production","k8s.namespace.name":"signoz-currencyservice"},"attributes":{"http.method":"POST","http.route":"/currency/convert","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":360,"duration_ms":333,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":330,"duration_ms":227,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":300,"duration_ms":487,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":270,"duration_ms":478,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":240,"duration_ms":137,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":210,"duration_ms":215,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":180,"duration_ms":445,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":150,"duration_ms":59,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":120,"duration_ms":254,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":90,"duration_ms":197,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":60,"duration_ms":52,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /","kind":"SERVER","minutes_ago":30,"duration_ms":221,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"GET","http.route":"/","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":360,"duration_ms":72,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":330,"duration_ms":335,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":300,"duration_ms":292,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":270,"duration_ms":286,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":240,"duration_ms":444,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":210,"duration_ms":183,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":180,"duration_ms":123,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":150,"duration_ms":337,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":120,"duration_ms":373,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":90,"duration_ms":248,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":60,"duration_ms":459,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /product","kind":"SERVER","minutes_ago":30,"duration_ms":90,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/product","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":360,"duration_ms":304,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":330,"duration_ms":427,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":300,"duration_ms":130,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":270,"duration_ms":152,"status":"ERROR","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"500"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":240,"duration_ms":163,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":210,"duration_ms":73,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":180,"duration_ms":177,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":150,"duration_ms":80,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":120,"duration_ms":440,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":90,"duration_ms":450,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":60,"duration_ms":481,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"frontend /checkout","kind":"SERVER","minutes_ago":30,"duration_ms":219,"status":"OK","resource_attributes":{"service.name":"frontend","deployment.environment":"production","k8s.namespace.name":"signoz-frontend"},"attributes":{"http.method":"POST","http.route":"/checkout","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":360,"duration_ms":381,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":330,"duration_ms":307,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":300,"duration_ms":351,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":270,"duration_ms":384,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":240,"duration_ms":273,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":210,"duration_ms":499,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":180,"duration_ms":80,"status":"ERROR","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"500"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":150,"duration_ms":186,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":120,"duration_ms":423,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":90,"duration_ms":121,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":60,"duration_ms":451,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"paymentservice /payment/charge","kind":"SERVER","minutes_ago":30,"duration_ms":402,"status":"OK","resource_attributes":{"service.name":"paymentservice","deployment.environment":"production","k8s.namespace.name":"signoz-paymentservice"},"attributes":{"http.method":"POST","http.route":"/payment/charge","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":360,"duration_ms":189,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":330,"duration_ms":229,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":300,"duration_ms":59,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":270,"duration_ms":300,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":240,"duration_ms":439,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":210,"duration_ms":478,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":180,"duration_ms":104,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":150,"duration_ms":336,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":120,"duration_ms":335,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":90,"duration_ms":430,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":60,"duration_ms":116,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/list","kind":"SERVER","minutes_ago":30,"duration_ms":75,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"POST","http.route":"/products/list","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":360,"duration_ms":314,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":330,"duration_ms":303,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":300,"duration_ms":174,"status":"ERROR","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"500"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":270,"duration_ms":238,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":240,"duration_ms":494,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":210,"duration_ms":394,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":180,"duration_ms":71,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":150,"duration_ms":222,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":120,"duration_ms":386,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":90,"duration_ms":227,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":60,"duration_ms":54,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"productcatalogservice /products/get","kind":"SERVER","minutes_ago":30,"duration_ms":456,"status":"OK","resource_attributes":{"service.name":"productcatalogservice","deployment.environment":"production","k8s.namespace.name":"signoz-productcatalogservice"},"attributes":{"http.method":"GET","http.route":"/products/get","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":360,"duration_ms":317,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":330,"duration_ms":111,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":300,"duration_ms":478,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":270,"duration_ms":75,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":240,"duration_ms":413,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":210,"duration_ms":217,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":180,"duration_ms":160,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":150,"duration_ms":170,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":120,"duration_ms":415,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":90,"duration_ms":448,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":60,"duration_ms":340,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/quote","kind":"SERVER","minutes_ago":30,"duration_ms":390,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/quote","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":360,"duration_ms":96,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":330,"duration_ms":414,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":300,"duration_ms":182,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":270,"duration_ms":116,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":240,"duration_ms":489,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":210,"duration_ms":130,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":180,"duration_ms":394,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":150,"duration_ms":59,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":120,"duration_ms":159,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":90,"duration_ms":432,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":60,"duration_ms":87,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}
{"name":"shippingservice /shipping/ship","kind":"SERVER","minutes_ago":30,"duration_ms":59,"status":"OK","resource_attributes":{"service.name":"shippingservice","deployment.environment":"production","k8s.namespace.name":"signoz-shippingservice"},"attributes":{"http.method":"POST","http.route":"/shipping/ship","http.status_code":"200"}}

View File

@@ -1,5 +1,12 @@
"""HTTP seeder — wraps fixtures.{traces,logs,metrics} so Playwright specs
can POST per-test telemetry (tagged `seeder=true`) and DELETE to clear."""
"""HTTP seeder — single entrypoint for e2e/integration telemetry.
POST /telemetry/{metrics,logs,traces} insert into ClickHouse via
fixtures.{metrics,logs,traces}. DELETE truncates the signal tables.
Parallel-safe: every seeded row is tagged `seeder=true`. Tests share
the seeded baseline; per-test mutations live in their own dashboards.
Only test_teardown should call DELETE — workers must finish first.
"""
import os
from collections.abc import AsyncIterator
@@ -10,11 +17,7 @@ import clickhouse_connect
from fastapi import FastAPI, HTTPException, Response, status
from fixtures.logger import setup_logger
from fixtures.logs import (
Logs,
insert_logs_to_clickhouse,
truncate_logs_tables,
)
from fixtures.logs import Logs, insert_logs_to_clickhouse, truncate_logs_tables
from fixtures.metrics import (
Metrics,
insert_metrics_to_clickhouse,
@@ -39,7 +42,9 @@ SEEDER_MARKER = {"seeder": "true"}
@asynccontextmanager
async def lifespan(_: FastAPI) -> AsyncIterator[None]:
conn = clickhouse_connect.get_client(host=CH_HOST, port=CH_PORT, username=CH_USER, password=CH_PASSWORD)
conn = clickhouse_connect.get_client(
host=CH_HOST, port=CH_PORT, username=CH_USER, password=CH_PASSWORD
)
app.state.ch = conn
try:
yield
@@ -64,12 +69,19 @@ def _tag(item: dict[str, Any]) -> dict[str, Any]:
return {**item, "resources": resources}
# Metrics payload carries label dicts at the top level, not a `resources`
# key — tagging goes on the `resource_attrs` wrapper that Metrics.from_dict
# unpacks. Same effect, different key.
def _tag_metrics(item: dict[str, Any]) -> dict[str, Any]:
resource_attrs = {**(item.get("resource_attrs") or {}), **SEEDER_MARKER}
return {**item, "resource_attrs": resource_attrs}
# Accept OTLP-style `resource_attributes` / `attributes` or legacy
# `resource_attrs` / `labels` interchangeably.
resource_attrs = {
**(item.get("resource_attrs") or {}),
**(item.get("resource_attributes") or {}),
**SEEDER_MARKER,
}
labels = {**(item.get("labels") or {}), **(item.get("attributes") or {})}
out = {**item, "resource_attrs": resource_attrs, "labels": labels}
out.pop("resource_attributes", None)
out.pop("attributes", None)
return out
@app.post("/telemetry/traces", status_code=status.HTTP_201_CREATED)
@@ -145,3 +157,17 @@ def delete_metrics() -> Response:
except Exception as e:
logger.exception("truncate failed")
raise HTTPException(status_code=500, detail=str(e)) from e
@app.post("/seed/golden", status_code=status.HTTP_200_OK)
def seed_golden() -> dict[str, int]:
"""Re-seed the golden dataset with timestamps rebased to `now`.
Called by Playwright globalSetup before every test session so chart
assertions land within default panel time windows."""
from fixtures import seed_golden_dataset # local import: fast cold-start
try:
return seed_golden_dataset.seed("http://localhost:8080")
except Exception as e:
logger.exception("golden seed failed")
raise HTTPException(500, str(e)) from e