mirror of
https://github.com/SigNoz/signoz.git
synced 2026-09-22 03:10:41 +01:00
<!--A few plain bullets saying what changed and why, for a reviewer skimming it - not a wall of text, not a restatement of the diff, not generated boilerplate.--> #### Description Until now every org started with no span mapper groups and we had to create `llm`, `agent` and `tool` by hand. This PR ships them as defaults. - The three groups live as JSON in the binary. On startup and when a new org is created, they get seeded. When we change a definition and bump its version, the next release updates the org's copy in place. - Anything SigNoz ships is marked `origin: system` and can only be switched on or off. Users can't rename or delete these groups and mappers, and can't take their names. Anything the user adds is theirs to edit or remove, including new mappers in a shipped group or new sources on a shipped mapper. - Upgrades keep the user's on/off choices and never touch their items. - Condition substrings and sources now carry `enabled` and `origin`, so a substring is an object instead of a plain string. Disabled ones are left out of the collector config. - - Migration 127 only adds the `origin` and `version` columns. Stored JSON is not rewritten because these tables are empty on every instance. - Fixes creating a group or mapper with `enabled: false` being saved as true (the bun `default:true` tag turned false into SQL `DEFAULT`) Frontend: no UI changes. Generated client regenerated; drafts carry `enabled` and `origin` so saves from the existing screens round-trip shipped items intact. <!--Reference issues using `Closes #issue-number` to enable automatic closure on merge. --> #### Issues closed by this PR Closes https://github.com/SigNoz/engineering-pod/issues/5329 <!--Anything reviewers should keep in mind while reviewing --> #### Additional Information * Frontend follow-up: toggles for sources and substrings, "Default" badge and read-only rows for shipped items, hide rename/delete on system groups and mappers. * Deferred: per-group upgrade changelog ( will come back to this later) --------- Co-authored-by: Gaurav Tewari <gauravtewari111@gmail.com> Co-authored-by: Gaurav Tewari <tewarig@users.noreply.github.com>
261 lines
6.8 KiB
Go
261 lines
6.8 KiB
Go
package implspanmapper
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/SigNoz/signoz/pkg/errors"
|
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
|
"github.com/SigNoz/signoz/pkg/types/spantypes"
|
|
"github.com/SigNoz/signoz/pkg/valuer"
|
|
)
|
|
|
|
type store struct {
|
|
sqlstore sqlstore.SQLStore
|
|
}
|
|
|
|
func NewStore(sqlstore sqlstore.SQLStore) spantypes.SpanMapperStore {
|
|
return &store{sqlstore: sqlstore}
|
|
}
|
|
|
|
func (s *store) RunInTx(ctx context.Context, cb func(ctx context.Context) error) error {
|
|
return s.sqlstore.RunInTxCtx(ctx, nil, cb)
|
|
}
|
|
|
|
func (s *store) CreateGroup(ctx context.Context, group *spantypes.SpanMapperGroup) error {
|
|
storable := group.ToStorable()
|
|
_, err := s.sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewInsert().
|
|
Model(storable).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return s.sqlstore.WrapAlreadyExistsErrf(err, spantypes.ErrCodeMappingGroupAlreadyExists, "span mapper group %q already exists", group.Name)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *store) GetGroup(ctx context.Context, orgID, id valuer.UUID) (*spantypes.SpanMapperGroup, error) {
|
|
storable := new(spantypes.StorableSpanMapperGroup)
|
|
|
|
err := s.sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewSelect().
|
|
Model(storable).
|
|
Where("org_id = ?", orgID).
|
|
Where("id = ?", id).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, spantypes.ErrCodeMappingGroupNotFound, "span mapper group %s not found", id)
|
|
}
|
|
return storable.ToSpanMapperGroup(), nil
|
|
}
|
|
|
|
func (s *store) GetGroupByName(ctx context.Context, orgID valuer.UUID, name string) (*spantypes.SpanMapperGroup, error) {
|
|
storable := new(spantypes.StorableSpanMapperGroup)
|
|
|
|
err := s.sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewSelect().
|
|
Model(storable).
|
|
Where("org_id = ?", orgID).
|
|
Where("name = ?", name).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, spantypes.ErrCodeMappingGroupNotFound, "span mapper group %q not found", name)
|
|
}
|
|
return storable.ToSpanMapperGroup(), nil
|
|
}
|
|
|
|
func (s *store) ListGroups(ctx context.Context, orgID valuer.UUID, q *spantypes.ListSpanMapperGroupsQuery) ([]*spantypes.SpanMapperGroup, error) {
|
|
storables := make([]*spantypes.StorableSpanMapperGroup, 0)
|
|
|
|
sel := s.sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewSelect().
|
|
Model(&storables).
|
|
Where("org_id = ?", orgID)
|
|
|
|
if q != nil {
|
|
if q.Enabled != nil {
|
|
sel = sel.Where("enabled = ?", *q.Enabled)
|
|
}
|
|
}
|
|
|
|
if err := sel.Order("created_at DESC").Scan(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
return spantypes.NewSpanMapperGroupsFromStorable(storables), nil
|
|
}
|
|
|
|
func (s *store) UpdateGroup(ctx context.Context, group *spantypes.SpanMapperGroup) error {
|
|
storable := group.ToStorable()
|
|
res, err := s.sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewUpdate().
|
|
Model(storable).
|
|
Where("org_id = ?", storable.OrgID).
|
|
Where("id = ?", storable.ID).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rowsAffected, err := res.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if rowsAffected == 0 {
|
|
return errors.Newf(errors.TypeNotFound, spantypes.ErrCodeMappingGroupNotFound, "span mapper group %s not found", group.ID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *store) DeleteGroup(ctx context.Context, orgID, id valuer.UUID) error {
|
|
return s.RunInTx(ctx, func(ctx context.Context) error {
|
|
db := s.sqlstore.BunDBCtx(ctx)
|
|
|
|
// Cascade: remove mappers belonging to this group first.
|
|
if _, err := db.NewDelete().
|
|
Model((*spantypes.StorableSpanMapper)(nil)).
|
|
Where("group_id = ?", id).
|
|
Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
res, err := db.NewDelete().
|
|
Model((*spantypes.StorableSpanMapperGroup)(nil)).
|
|
Where("org_id = ?", orgID).
|
|
Where("id = ?", id).
|
|
Where("origin = ?", spantypes.SpanMapperOriginUser).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rowsAffected, err := res.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if rowsAffected == 0 {
|
|
group, err := s.GetGroup(ctx, orgID, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := group.ErrIfNotDeletable(); err != nil {
|
|
return err
|
|
}
|
|
return errors.Newf(errors.TypeNotFound, spantypes.ErrCodeMappingGroupNotFound, "span mapper group %s not found", id)
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (s *store) CreateMapper(ctx context.Context, mapper *spantypes.SpanMapper) error {
|
|
storable := mapper.ToStorable()
|
|
_, err := s.sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewInsert().
|
|
Model(storable).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return s.sqlstore.WrapAlreadyExistsErrf(err, spantypes.ErrCodeMapperAlreadyExists, "span mapper %q already exists", mapper.Name)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *store) GetMapper(ctx context.Context, orgID, groupID, id valuer.UUID) (*spantypes.SpanMapper, error) {
|
|
// Ensure the group belongs to the org.
|
|
if _, err := s.GetGroup(ctx, orgID, groupID); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
storable := new(spantypes.StorableSpanMapper)
|
|
err := s.sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewSelect().
|
|
Model(storable).
|
|
Where("group_id = ?", groupID).
|
|
Where("id = ?", id).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, spantypes.ErrCodeMapperNotFound, "span mapper %s not found", id)
|
|
}
|
|
return storable.ToSpanMapper(), nil
|
|
}
|
|
|
|
func (s *store) ListMappers(ctx context.Context, orgID, groupID valuer.UUID) ([]*spantypes.SpanMapper, error) {
|
|
// Scope by org via the parent group's org_id.
|
|
if _, err := s.GetGroup(ctx, orgID, groupID); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
storables := make([]*spantypes.StorableSpanMapper, 0)
|
|
if err := s.sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewSelect().
|
|
Model(&storables).
|
|
Where("group_id = ?", groupID).
|
|
Order("created_at DESC").
|
|
Scan(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
return spantypes.NewSpanMappersFromStorable(storables), nil
|
|
}
|
|
|
|
func (s *store) UpdateMapper(ctx context.Context, mapper *spantypes.SpanMapper) error {
|
|
storable := mapper.ToStorable()
|
|
res, err := s.sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewUpdate().
|
|
Model(storable).
|
|
Where("group_id = ?", storable.GroupID).
|
|
Where("id = ?", storable.ID).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rowsAffected, err := res.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if rowsAffected == 0 {
|
|
return errors.Newf(errors.TypeNotFound, spantypes.ErrCodeMapperNotFound, "span mapper %s not found", mapper.ID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *store) DeleteMapper(ctx context.Context, orgID, groupID, id valuer.UUID, origin spantypes.SpanMapperOrigin) error {
|
|
if _, err := s.GetGroup(ctx, orgID, groupID); err != nil {
|
|
return err
|
|
}
|
|
|
|
res, err := s.sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewDelete().
|
|
Model((*spantypes.StorableSpanMapper)(nil)).
|
|
Where("group_id = ?", groupID).
|
|
Where("id = ?", id).
|
|
Where("origin = ?", origin).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rowsAffected, err := res.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if rowsAffected == 0 {
|
|
mapper, err := s.GetMapper(ctx, orgID, groupID, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := mapper.ErrIfNotDeletable(); err != nil {
|
|
return err
|
|
}
|
|
return errors.Newf(errors.TypeNotFound, spantypes.ErrCodeMapperNotFound, "span mapper %s not found", id)
|
|
}
|
|
return nil
|
|
}
|