mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-07 02:50:31 +01:00
Compare commits
4 Commits
fix/lint-s
...
issue_4361
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
884120ba1f | ||
|
|
a61cbf45db | ||
|
|
c26c875cbf | ||
|
|
9499228398 |
@@ -4919,8 +4919,6 @@ components:
|
||||
type: object
|
||||
SpantypesPostableSpanMapperGroup:
|
||||
properties:
|
||||
category:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperGroupCategory'
|
||||
condition:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperGroupCondition'
|
||||
enabled:
|
||||
@@ -4929,7 +4927,6 @@ components:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- category
|
||||
- condition
|
||||
type: object
|
||||
SpantypesSpanMapper:
|
||||
@@ -4976,8 +4973,6 @@ components:
|
||||
type: object
|
||||
SpantypesSpanMapperGroup:
|
||||
properties:
|
||||
category:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperGroupCategory'
|
||||
condition:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperGroupCondition'
|
||||
createdAt:
|
||||
@@ -5002,13 +4997,11 @@ components:
|
||||
- id
|
||||
- orgId
|
||||
- name
|
||||
- category
|
||||
- condition
|
||||
- enabled
|
||||
type: object
|
||||
SpantypesSpanMapperGroupCategory:
|
||||
type: object
|
||||
SpantypesSpanMapperGroupCondition:
|
||||
nullable: true
|
||||
properties:
|
||||
attributes:
|
||||
items:
|
||||
@@ -10099,12 +10092,6 @@ paths:
|
||||
org.
|
||||
operationId: ListSpanMapperGroups
|
||||
parameters:
|
||||
- explode: true
|
||||
in: query
|
||||
name: category
|
||||
schema:
|
||||
$ref: '#/components/schemas/SpantypesSpanMapperGroupCategory'
|
||||
style: deepObject
|
||||
- in: query
|
||||
name: enabled
|
||||
schema:
|
||||
|
||||
@@ -239,12 +239,10 @@
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(js|jsx|ts|tsx)": [
|
||||
"oxlint --fix",
|
||||
"oxfmt --write",
|
||||
"sh -c tsgo --noEmit"
|
||||
],
|
||||
"*.(js|jsx|ts|tsx|scss|css)": [
|
||||
"oxlint --fix --quiet --no-error-on-unmatched-pattern",
|
||||
"oxfmt --write"
|
||||
],
|
||||
"*.(scss|css)": [
|
||||
"stylelint"
|
||||
]
|
||||
|
||||
@@ -7200,7 +7200,6 @@ export interface SpantypesPostableSpanMapperDTO {
|
||||
}
|
||||
|
||||
export interface SpantypesPostableSpanMapperGroupDTO {
|
||||
category: SpantypesSpanMapperGroupCategoryDTO;
|
||||
condition: SpantypesSpanMapperGroupConditionDTO;
|
||||
/**
|
||||
* @type boolean
|
||||
@@ -7260,7 +7259,6 @@ export interface SpantypesSpanMapperConfigDTO {
|
||||
}
|
||||
|
||||
export interface SpantypesSpanMapperGroupDTO {
|
||||
category: SpantypesSpanMapperGroupCategoryDTO;
|
||||
condition: SpantypesSpanMapperGroupConditionDTO;
|
||||
/**
|
||||
* @type string
|
||||
@@ -7298,11 +7296,10 @@ export interface SpantypesSpanMapperGroupDTO {
|
||||
updatedBy?: string;
|
||||
}
|
||||
|
||||
export interface SpantypesSpanMapperGroupCategoryDTO {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface SpantypesSpanMapperGroupConditionDTO {
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type SpantypesSpanMapperGroupConditionDTO = {
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
@@ -7313,7 +7310,7 @@ export interface SpantypesSpanMapperGroupConditionDTO {
|
||||
* @nullable true
|
||||
*/
|
||||
resource: string[] | null;
|
||||
}
|
||||
} | null;
|
||||
|
||||
export enum SpantypesSpanMapperOperationDTO {
|
||||
move = 'move',
|
||||
@@ -8887,10 +8884,6 @@ export type GetMyServiceAccount200 = {
|
||||
};
|
||||
|
||||
export type ListSpanMapperGroupsParams = {
|
||||
/**
|
||||
* @description undefined
|
||||
*/
|
||||
category?: SpantypesSpanMapperGroupCategoryDTO;
|
||||
/**
|
||||
* @type boolean
|
||||
* @nullable true
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
import { act, render } from '@testing-library/react';
|
||||
import { Modal } from 'antd';
|
||||
import { useDashboardBootstrap } from 'hooks/dashboard/useDashboardBootstrap';
|
||||
import { useTransformDashboardVariables } from 'hooks/dashboard/useTransformDashboardVariables';
|
||||
import useTabVisibility from 'hooks/useTabFocus';
|
||||
import { getMinMaxForSelectedTime } from 'lib/getMinMax';
|
||||
import { useDashboardStore } from 'providers/Dashboard/store/useDashboardStore';
|
||||
import { useDashboardQuery } from './useDashboardQuery';
|
||||
|
||||
const mockDispatch = jest.fn();
|
||||
const mockSetDashboardData = jest.fn();
|
||||
const mockSetLayouts = jest.fn();
|
||||
const mockSetPanelMap = jest.fn();
|
||||
const mockResetDashboardStore = jest.fn();
|
||||
const mockGetUrlVariables = jest.fn();
|
||||
const mockUpdateUrlVariable = jest.fn();
|
||||
const mockRefetch = jest.fn();
|
||||
|
||||
let mockGlobalTime = {
|
||||
selectedTime: 'custom',
|
||||
minTime: 1710000000000000000,
|
||||
maxTime: 1710000300000000000,
|
||||
isAutoRefreshDisabled: true,
|
||||
};
|
||||
|
||||
let currentQueryData: unknown;
|
||||
|
||||
jest.mock('react-i18next', () => ({
|
||||
useTranslation: (): { t: (key: string) => string } => ({
|
||||
t: (key: string): string => key,
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('react-redux', () => ({
|
||||
useDispatch: jest.fn(() => mockDispatch),
|
||||
useSelector: jest.fn(
|
||||
(
|
||||
selectorFn: (state: { globalTime: typeof mockGlobalTime }) => unknown,
|
||||
): unknown => selectorFn({ globalTime: mockGlobalTime }),
|
||||
),
|
||||
}));
|
||||
|
||||
jest.mock('hooks/useTabFocus', () => jest.fn(() => true));
|
||||
jest.mock('hooks/dashboard/useDashboardVariablesSync', () => ({
|
||||
useDashboardVariablesSync: jest.fn(),
|
||||
}));
|
||||
jest.mock('./useDashboardQuery', () => ({
|
||||
useDashboardQuery: jest.fn(),
|
||||
}));
|
||||
jest.mock('hooks/dashboard/useTransformDashboardVariables', () => ({
|
||||
useTransformDashboardVariables: jest.fn(),
|
||||
}));
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: jest.fn(),
|
||||
}));
|
||||
jest.mock('providers/Dashboard/initializeDefaultVariables', () => ({
|
||||
initializeDefaultVariables: jest.fn(),
|
||||
}));
|
||||
jest.mock('lib/dashboard/getUpdatedLayout', () => ({
|
||||
getUpdatedLayout: jest.fn(() => []),
|
||||
}));
|
||||
jest.mock('providers/Dashboard/util', () => ({
|
||||
sortLayout: jest.fn((layout) => layout),
|
||||
}));
|
||||
jest.mock('lib/getMinMax', () => ({
|
||||
getMinMaxForSelectedTime: jest.fn(),
|
||||
}));
|
||||
|
||||
function TestComponent({ confirm }: { confirm: typeof Modal.confirm }): null {
|
||||
useDashboardBootstrap('dashboard-1', { confirm });
|
||||
return null;
|
||||
}
|
||||
|
||||
describe('useDashboardBootstrap', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
mockGlobalTime = {
|
||||
selectedTime: 'custom',
|
||||
minTime: 1710000000000000000,
|
||||
maxTime: 1710000300000000000,
|
||||
isAutoRefreshDisabled: true,
|
||||
};
|
||||
|
||||
jest.mocked(useDashboardStore as unknown as jest.Mock).mockReturnValue({
|
||||
setDashboardData: mockSetDashboardData,
|
||||
setLayouts: mockSetLayouts,
|
||||
setPanelMap: mockSetPanelMap,
|
||||
resetDashboardStore: mockResetDashboardStore,
|
||||
});
|
||||
|
||||
jest
|
||||
.mocked(useTransformDashboardVariables as unknown as jest.Mock)
|
||||
.mockReturnValue({
|
||||
getUrlVariables: mockGetUrlVariables,
|
||||
updateUrlVariable: mockUpdateUrlVariable,
|
||||
transformDashboardVariables: <T,>(data: T): T => data,
|
||||
});
|
||||
|
||||
jest.mocked(useTabVisibility as unknown as jest.Mock).mockReturnValue(true);
|
||||
jest
|
||||
.mocked(useDashboardQuery as unknown as jest.Mock)
|
||||
.mockImplementation(() => ({
|
||||
data: currentQueryData,
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
isFetching: false,
|
||||
error: null,
|
||||
refetch: mockRefetch,
|
||||
}));
|
||||
});
|
||||
|
||||
it('keeps minTime and maxTime unchanged for custom range on refresh confirm', () => {
|
||||
const initialDashboard = {
|
||||
id: 'dashboard-1',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
data: { layout: [], panelMap: {}, variables: {} },
|
||||
};
|
||||
|
||||
const updatedDashboard = {
|
||||
id: 'dashboard-1',
|
||||
updatedAt: '2024-01-01T01:00:00.000Z',
|
||||
data: { layout: [], panelMap: {}, variables: {} },
|
||||
};
|
||||
|
||||
const mockConfirm = jest.fn<
|
||||
ReturnType<typeof Modal.confirm>,
|
||||
Parameters<typeof Modal.confirm>
|
||||
>(() => ({ destroy: jest.fn(), update: jest.fn() }));
|
||||
|
||||
currentQueryData = { data: initialDashboard };
|
||||
const { rerender } = render(<TestComponent confirm={mockConfirm} />);
|
||||
|
||||
expect(mockConfirm).not.toHaveBeenCalled();
|
||||
|
||||
currentQueryData = { data: updatedDashboard };
|
||||
rerender(<TestComponent confirm={mockConfirm} />);
|
||||
|
||||
expect(mockConfirm).toHaveBeenCalledTimes(1);
|
||||
const firstCall = mockConfirm.mock.calls[0];
|
||||
expect(firstCall).toBeDefined();
|
||||
const [confirmProps] = firstCall as Parameters<typeof Modal.confirm>;
|
||||
|
||||
act(() => {
|
||||
confirmProps.onOk?.();
|
||||
});
|
||||
|
||||
expect(getMinMaxForSelectedTime).not.toHaveBeenCalled();
|
||||
expect(mockDispatch).toHaveBeenCalledWith({
|
||||
type: 'UPDATE_TIME_INTERVAL',
|
||||
payload: {
|
||||
selectedTime: 'custom',
|
||||
minTime: mockGlobalTime.minTime,
|
||||
maxTime: mockGlobalTime.maxTime,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -102,19 +102,11 @@ export function useDashboardBootstrap(
|
||||
onOk() {
|
||||
setDashboardData(updatedDashboardData);
|
||||
|
||||
const { maxTime, minTime } =
|
||||
globalTime.selectedTime === 'custom'
|
||||
? {
|
||||
// For custom ranges, min/max are already stored in nanoseconds.
|
||||
// Recomputing via getMinMaxForSelectedTime would multiply them again.
|
||||
maxTime: globalTime.maxTime,
|
||||
minTime: globalTime.minTime,
|
||||
}
|
||||
: getMinMaxForSelectedTime(
|
||||
globalTime.selectedTime,
|
||||
globalTime.minTime,
|
||||
globalTime.maxTime,
|
||||
);
|
||||
const { maxTime, minTime } = getMinMaxForSelectedTime(
|
||||
globalTime.selectedTime,
|
||||
globalTime.minTime,
|
||||
globalTime.maxTime,
|
||||
);
|
||||
dispatch({
|
||||
type: UPDATE_TIME_INTERVAL,
|
||||
payload: { maxTime, minTime, selectedTime: globalTime.selectedTime },
|
||||
|
||||
@@ -7,12 +7,7 @@ export const topTracesTableColumns = [
|
||||
dataIndex: 'trace_id',
|
||||
key: 'trace_id',
|
||||
render: (traceId: string): JSX.Element => (
|
||||
<Link
|
||||
to={`/trace/${traceId}`}
|
||||
className="trace-id-cell"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Link to={`/trace/${traceId}`} className="trace-id-cell">
|
||||
{traceId}
|
||||
</Link>
|
||||
),
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/http/binding"
|
||||
"github.com/SigNoz/signoz/pkg/http/render"
|
||||
"github.com/SigNoz/signoz/pkg/modules/spanmapper"
|
||||
@@ -17,12 +16,11 @@ import (
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
module spanmapper.Module
|
||||
providerSettings factory.ProviderSettings
|
||||
module spanmapper.Module
|
||||
}
|
||||
|
||||
func NewHandler(module spanmapper.Module, providerSettings factory.ProviderSettings) spanmapper.Handler {
|
||||
return &handler{module: module, providerSettings: providerSettings}
|
||||
func NewHandler(module spanmapper.Module) spanmapper.Handler {
|
||||
return &handler{module: module}
|
||||
}
|
||||
|
||||
// ListGroups handles GET /api/v1/span_mapper_groups.
|
||||
@@ -72,10 +70,9 @@ func (h *handler) CreateGroup(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
group := spantypes.NewSpanMapperGroupFromPostable(req)
|
||||
group := spantypes.NewSpanMapperGroup(orgID, claims.Email, req)
|
||||
|
||||
err = h.module.CreateGroup(ctx, orgID, claims.Email, group)
|
||||
if err != nil {
|
||||
if err := h.module.CreateGroup(ctx, orgID, group); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
@@ -107,11 +104,17 @@ func (h *handler) UpdateGroup(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err = h.module.UpdateGroup(ctx, orgID, id, claims.Email, spantypes.NewSpanMapperGroupFromUpdatable(req))
|
||||
group, err := h.module.GetGroup(ctx, orgID, id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
group.Update(req, claims.Email)
|
||||
|
||||
if err := h.module.UpdateGroup(ctx, orgID, id, group); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
@@ -195,10 +198,9 @@ func (h *handler) CreateMapper(rw http.ResponseWriter, r *http.Request) {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
mapper := spantypes.NewSpanMapperFromPostable(req)
|
||||
mapper := spantypes.NewSpanMapper(groupID, claims.Email, req)
|
||||
|
||||
err = h.module.CreateMapper(ctx, orgID, groupID, claims.Email, mapper)
|
||||
if err != nil {
|
||||
if err := h.module.CreateMapper(ctx, orgID, groupID, mapper); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
@@ -237,11 +239,17 @@ func (h *handler) UpdateMapper(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err = h.module.UpdateMapper(ctx, orgID, groupID, mapperID, claims.Email, spantypes.NewSpanMapperFromUpdatable(req))
|
||||
mapper, err := h.module.GetMapper(ctx, orgID, groupID, mapperID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
mapper.Update(req, claims.Email)
|
||||
|
||||
if err := h.module.UpdateMapper(ctx, orgID, groupID, mapperID, mapper); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
64
pkg/modules/spanmapper/implspanmapper/module.go
Normal file
64
pkg/modules/spanmapper/implspanmapper/module.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package implspanmapper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/modules/spanmapper"
|
||||
"github.com/SigNoz/signoz/pkg/types/spantypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type module struct {
|
||||
store spantypes.SpanMapperStore
|
||||
}
|
||||
|
||||
func NewModule(store spantypes.SpanMapperStore) spanmapper.Module {
|
||||
return &module{store: store}
|
||||
}
|
||||
|
||||
func (module *module) ListGroups(ctx context.Context, orgID valuer.UUID, q *spantypes.ListSpanMapperGroupsQuery) ([]*spantypes.SpanMapperGroup, error) {
|
||||
return module.store.ListGroups(ctx, orgID, q)
|
||||
}
|
||||
|
||||
func (module *module) GetGroup(ctx context.Context, orgID, id valuer.UUID) (*spantypes.SpanMapperGroup, error) {
|
||||
return module.store.GetGroup(ctx, orgID, id)
|
||||
}
|
||||
|
||||
func (module *module) CreateGroup(ctx context.Context, orgID valuer.UUID, group *spantypes.SpanMapperGroup) error {
|
||||
return module.store.CreateGroup(ctx, group)
|
||||
}
|
||||
|
||||
func (module *module) UpdateGroup(ctx context.Context, orgID, id valuer.UUID, group *spantypes.SpanMapperGroup) error {
|
||||
return module.store.UpdateGroup(ctx, group)
|
||||
}
|
||||
|
||||
func (module *module) DeleteGroup(ctx context.Context, orgID, id valuer.UUID) error {
|
||||
return module.store.DeleteGroup(ctx, orgID, id)
|
||||
}
|
||||
|
||||
func (module *module) ListMappers(ctx context.Context, orgID, groupID valuer.UUID) ([]*spantypes.SpanMapper, error) {
|
||||
return module.store.ListMappers(ctx, orgID, groupID)
|
||||
}
|
||||
|
||||
func (module *module) GetMapper(ctx context.Context, orgID, groupID, id valuer.UUID) (*spantypes.SpanMapper, error) {
|
||||
return module.store.GetMapper(ctx, orgID, groupID, id)
|
||||
}
|
||||
|
||||
func (module *module) CreateMapper(ctx context.Context, orgID, groupID valuer.UUID, mapper *spantypes.SpanMapper) error {
|
||||
// Ensure the group belongs to the org before inserting the child row.
|
||||
if _, err := module.store.GetGroup(ctx, orgID, groupID); err != nil {
|
||||
return err
|
||||
}
|
||||
return module.store.CreateMapper(ctx, mapper)
|
||||
}
|
||||
|
||||
func (module *module) UpdateMapper(ctx context.Context, orgID, groupID, id valuer.UUID, mapper *spantypes.SpanMapper) error {
|
||||
if _, err := module.store.GetGroup(ctx, orgID, groupID); err != nil {
|
||||
return err
|
||||
}
|
||||
return module.store.UpdateMapper(ctx, mapper)
|
||||
}
|
||||
|
||||
func (module *module) DeleteMapper(ctx context.Context, orgID, groupID, id valuer.UUID) error {
|
||||
return module.store.DeleteMapper(ctx, orgID, groupID, id)
|
||||
}
|
||||
227
pkg/modules/spanmapper/implspanmapper/store.go
Normal file
227
pkg/modules/spanmapper/implspanmapper/store.go
Normal file
@@ -0,0 +1,227 @@
|
||||
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) 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.
|
||||
BunDB().
|
||||
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) ListGroups(ctx context.Context, orgID valuer.UUID, q *spantypes.ListSpanMapperGroupsQuery) ([]*spantypes.SpanMapperGroup, error) {
|
||||
storables := make([]*spantypes.StorableSpanMapperGroup, 0)
|
||||
|
||||
sel := s.sqlstore.
|
||||
BunDB().
|
||||
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 {
|
||||
tx, err := s.sqlstore.BunDBCtx(ctx).BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
// Cascade: remove mappers belonging to this group first.
|
||||
if _, err := tx.NewDelete().
|
||||
Model((*spantypes.StorableSpanMapper)(nil)).
|
||||
Where("group_id = ?", id).
|
||||
Exec(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := tx.NewDelete().
|
||||
Model((*spantypes.StorableSpanMapperGroup)(nil)).
|
||||
Where("org_id = ?", orgID).
|
||||
Where("id = ?", 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", id)
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
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.
|
||||
BunDB().
|
||||
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.
|
||||
BunDB().
|
||||
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) 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).
|
||||
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", id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -12,17 +12,17 @@ import (
|
||||
type Module interface {
|
||||
// Group operations
|
||||
ListGroups(ctx context.Context, orgID valuer.UUID, q *spantypes.ListSpanMapperGroupsQuery) ([]*spantypes.SpanMapperGroup, error)
|
||||
GetGroup(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*spantypes.SpanMapperGroup, error)
|
||||
CreateGroup(ctx context.Context, orgID valuer.UUID, createdBy string, group *spantypes.SpanMapperGroup) error
|
||||
UpdateGroup(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, group *spantypes.SpanMapperGroup) error
|
||||
DeleteGroup(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
||||
GetGroup(ctx context.Context, orgID, id valuer.UUID) (*spantypes.SpanMapperGroup, error)
|
||||
CreateGroup(ctx context.Context, orgID valuer.UUID, group *spantypes.SpanMapperGroup) error
|
||||
UpdateGroup(ctx context.Context, orgID, id valuer.UUID, group *spantypes.SpanMapperGroup) error
|
||||
DeleteGroup(ctx context.Context, orgID, id valuer.UUID) error
|
||||
|
||||
// Mapper operations
|
||||
ListMappers(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID) ([]*spantypes.SpanMapper, error)
|
||||
GetMapper(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, id valuer.UUID) (*spantypes.SpanMapper, error)
|
||||
CreateMapper(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, createdBy string, mapper *spantypes.SpanMapper) error
|
||||
UpdateMapper(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, id valuer.UUID, updatedBy string, mapper *spantypes.SpanMapper) error
|
||||
DeleteMapper(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, id valuer.UUID) error
|
||||
ListMappers(ctx context.Context, orgID, groupID valuer.UUID) ([]*spantypes.SpanMapper, error)
|
||||
GetMapper(ctx context.Context, orgID, groupID, id valuer.UUID) (*spantypes.SpanMapper, error)
|
||||
CreateMapper(ctx context.Context, orgID, groupID valuer.UUID, mapper *spantypes.SpanMapper) error
|
||||
UpdateMapper(ctx context.Context, orgID, groupID, id valuer.UUID, mapper *spantypes.SpanMapper) error
|
||||
DeleteMapper(ctx context.Context, orgID, groupID, id valuer.UUID) error
|
||||
}
|
||||
|
||||
// Handler defines the HTTP handler interface for mapping group and mapper endpoints.
|
||||
|
||||
@@ -120,7 +120,7 @@ func NewHandlers(
|
||||
RegistryHandler: registryHandler,
|
||||
RuleStateHistory: implrulestatehistory.NewHandler(modules.RuleStateHistory),
|
||||
CloudIntegrationHandler: implcloudintegration.NewHandler(modules.CloudIntegration),
|
||||
SpanMapperHandler: implspanmapper.NewHandler(nil, providerSettings), // todo(nitya): will update this in future PR
|
||||
SpanMapperHandler: implspanmapper.NewHandler(modules.SpanMapper),
|
||||
AlertmanagerHandler: signozalertmanager.NewHandler(alertmanagerService),
|
||||
TraceDetail: impltracedetail.NewHandler(modules.TraceDetail),
|
||||
RulerHandler: signozruler.NewHandler(rulerService),
|
||||
|
||||
@@ -38,6 +38,8 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/services/implservices"
|
||||
"github.com/SigNoz/signoz/pkg/modules/session"
|
||||
"github.com/SigNoz/signoz/pkg/modules/session/implsession"
|
||||
"github.com/SigNoz/signoz/pkg/modules/spanmapper"
|
||||
"github.com/SigNoz/signoz/pkg/modules/spanmapper/implspanmapper"
|
||||
"github.com/SigNoz/signoz/pkg/modules/spanpercentile"
|
||||
"github.com/SigNoz/signoz/pkg/modules/spanpercentile/implspanpercentile"
|
||||
"github.com/SigNoz/signoz/pkg/modules/tracedetail"
|
||||
@@ -80,6 +82,7 @@ type Modules struct {
|
||||
CloudIntegration cloudintegration.Module
|
||||
RuleStateHistory rulestatehistory.Module
|
||||
TraceDetail tracedetail.Module
|
||||
SpanMapper spanmapper.Module
|
||||
}
|
||||
|
||||
func NewModules(
|
||||
@@ -133,5 +136,6 @@ func NewModules(
|
||||
RuleStateHistory: implrulestatehistory.NewModule(implrulestatehistory.NewStore(telemetryStore, telemetryMetadataStore, providerSettings.Logger)),
|
||||
CloudIntegration: cloudIntegrationModule,
|
||||
TraceDetail: impltracedetail.NewModule(impltracedetail.NewTraceStore(telemetryStore), providerSettings, config.TraceDetail),
|
||||
SpanMapper: implspanmapper.NewModule(implspanmapper.NewStore(sqlstore)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,6 +195,7 @@ func NewSQLMigrationProviderFactories(
|
||||
sqlmigration.NewServiceAccountAuthzactory(sqlstore),
|
||||
sqlmigration.NewDropUserDeletedAtFactory(sqlstore, sqlschema),
|
||||
sqlmigration.NewMigrateAWSAllRegionsFactory(sqlstore),
|
||||
sqlmigration.NewAddSpanMapperFactory(sqlstore, sqlschema),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
118
pkg/sqlmigration/078_add_span_mapper.go
Normal file
118
pkg/sqlmigration/078_add_span_mapper.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package sqlmigration
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/sqlschema"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/migrate"
|
||||
)
|
||||
|
||||
type addSpanMapper struct {
|
||||
sqlschema sqlschema.SQLSchema
|
||||
sqlstore sqlstore.SQLStore
|
||||
}
|
||||
|
||||
func NewAddSpanMapperFactory(sqlstore sqlstore.SQLStore, sqlschema sqlschema.SQLSchema) factory.ProviderFactory[SQLMigration, Config] {
|
||||
return factory.NewProviderFactory(factory.MustNewName("add_span_mapper"), func(_ context.Context, _ factory.ProviderSettings, _ Config) (SQLMigration, error) {
|
||||
return &addSpanMapper{sqlschema: sqlschema, sqlstore: sqlstore}, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (migration *addSpanMapper) Register(migrations *migrate.Migrations) error {
|
||||
return migrations.Register(migration.Up, migration.Down)
|
||||
}
|
||||
|
||||
func (migration *addSpanMapper) Up(ctx context.Context, db *bun.DB) error {
|
||||
tx, err := db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
sqls := [][]byte{}
|
||||
|
||||
groupSQLs := migration.sqlschema.Operator().CreateTable(&sqlschema.Table{
|
||||
Name: "span_mapper_group",
|
||||
Columns: []*sqlschema.Column{
|
||||
{Name: "id", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "created_at", DataType: sqlschema.DataTypeTimestamp, Nullable: false},
|
||||
{Name: "updated_at", DataType: sqlschema.DataTypeTimestamp, Nullable: false},
|
||||
{Name: "created_by", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "updated_by", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "org_id", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "name", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "condition", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "enabled", DataType: sqlschema.DataTypeBoolean, Nullable: false, Default: "true"},
|
||||
},
|
||||
PrimaryKeyConstraint: &sqlschema.PrimaryKeyConstraint{
|
||||
ColumnNames: []sqlschema.ColumnName{"id"},
|
||||
},
|
||||
ForeignKeyConstraints: []*sqlschema.ForeignKeyConstraint{
|
||||
{
|
||||
ReferencingColumnName: sqlschema.ColumnName("org_id"),
|
||||
ReferencedTableName: sqlschema.TableName("organizations"),
|
||||
ReferencedColumnName: sqlschema.ColumnName("id"),
|
||||
},
|
||||
},
|
||||
})
|
||||
sqls = append(sqls, groupSQLs...)
|
||||
|
||||
groupIdxSQLs := migration.sqlschema.Operator().CreateIndex(
|
||||
&sqlschema.UniqueIndex{
|
||||
TableName: "span_mapper_group",
|
||||
ColumnNames: []sqlschema.ColumnName{"org_id", "name"},
|
||||
})
|
||||
sqls = append(sqls, groupIdxSQLs...)
|
||||
|
||||
mapperSQLs := migration.sqlschema.Operator().CreateTable(&sqlschema.Table{
|
||||
Name: "span_mapper",
|
||||
Columns: []*sqlschema.Column{
|
||||
{Name: "id", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "created_at", DataType: sqlschema.DataTypeTimestamp, Nullable: false},
|
||||
{Name: "updated_at", DataType: sqlschema.DataTypeTimestamp, Nullable: false},
|
||||
{Name: "created_by", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "updated_by", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "group_id", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "name", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "field_context", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "config", DataType: sqlschema.DataTypeText, Nullable: false},
|
||||
{Name: "enabled", DataType: sqlschema.DataTypeBoolean, Nullable: false, Default: "true"},
|
||||
},
|
||||
PrimaryKeyConstraint: &sqlschema.PrimaryKeyConstraint{
|
||||
ColumnNames: []sqlschema.ColumnName{"id"},
|
||||
},
|
||||
ForeignKeyConstraints: []*sqlschema.ForeignKeyConstraint{
|
||||
{
|
||||
ReferencingColumnName: sqlschema.ColumnName("group_id"),
|
||||
ReferencedTableName: sqlschema.TableName("span_mapper_group"),
|
||||
ReferencedColumnName: sqlschema.ColumnName("id"),
|
||||
},
|
||||
},
|
||||
})
|
||||
sqls = append(sqls, mapperSQLs...)
|
||||
|
||||
mapperIdxSQLs := migration.sqlschema.Operator().CreateIndex(
|
||||
&sqlschema.UniqueIndex{
|
||||
TableName: "span_mapper",
|
||||
ColumnNames: []sqlschema.ColumnName{"group_id", "name"},
|
||||
})
|
||||
sqls = append(sqls, mapperIdxSQLs...)
|
||||
|
||||
for _, sql := range sqls {
|
||||
if _, err := tx.ExecContext(ctx, string(sql)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (migration *addSpanMapper) Down(context.Context, *bun.DB) error {
|
||||
return nil
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package spantypes
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
@@ -69,9 +71,9 @@ type PostableSpanMapper struct {
|
||||
// UpdatableSpanMapper is the HTTP request body for updating a span mapper.
|
||||
// All fields are optional; only non-nil fields are applied.
|
||||
type UpdatableSpanMapper struct {
|
||||
FieldContext FieldContext `json:"field_context,omitempty"`
|
||||
Config *SpanMapperConfig `json:"config,omitempty"`
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
FieldContext FieldContext `json:"field_context"`
|
||||
Config *SpanMapperConfig `json:"config"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type GettableSpanMapper = SpanMapper
|
||||
@@ -88,7 +90,53 @@ func (SpanMapperOperation) Enum() []any {
|
||||
return []any{SpanMapperOperationMove, SpanMapperOperationCopy}
|
||||
}
|
||||
|
||||
func NewSpanMapperFromStorable(s *StorableSpanMapper) *SpanMapper {
|
||||
func NewSpanMapper(groupID valuer.UUID, createdBy string, p *PostableSpanMapper) *SpanMapper {
|
||||
now := time.Now()
|
||||
return &SpanMapper{
|
||||
ID: valuer.GenerateUUID(),
|
||||
GroupID: groupID,
|
||||
Name: p.Name,
|
||||
FieldContext: p.FieldContext,
|
||||
Config: p.Config,
|
||||
Enabled: p.Enabled,
|
||||
TimeAuditable: types.TimeAuditable{
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
},
|
||||
UserAuditable: types.UserAuditable{
|
||||
CreatedBy: createdBy,
|
||||
UpdatedBy: createdBy,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *SpanMapper) Update(u *UpdatableSpanMapper, updatedBy string) {
|
||||
m.FieldContext = u.FieldContext
|
||||
|
||||
if u.Config != nil {
|
||||
m.Config = *u.Config
|
||||
}
|
||||
if u.Enabled != nil {
|
||||
m.Enabled = *u.Enabled
|
||||
}
|
||||
m.UpdatedAt = time.Now()
|
||||
m.UpdatedBy = updatedBy
|
||||
}
|
||||
|
||||
func (m *SpanMapper) ToStorable() *StorableSpanMapper {
|
||||
return &StorableSpanMapper{
|
||||
Identifiable: types.Identifiable{ID: m.ID},
|
||||
TimeAuditable: m.TimeAuditable,
|
||||
UserAuditable: m.UserAuditable,
|
||||
GroupID: m.GroupID,
|
||||
Name: m.Name,
|
||||
FieldContext: m.FieldContext,
|
||||
Config: m.Config,
|
||||
Enabled: m.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StorableSpanMapper) ToSpanMapper() *SpanMapper {
|
||||
return &SpanMapper{
|
||||
TimeAuditable: s.TimeAuditable,
|
||||
UserAuditable: s.UserAuditable,
|
||||
@@ -101,33 +149,10 @@ func NewSpanMapperFromStorable(s *StorableSpanMapper) *SpanMapper {
|
||||
}
|
||||
}
|
||||
|
||||
func NewSpanMapperFromPostable(req *PostableSpanMapper) *SpanMapper {
|
||||
return &SpanMapper{
|
||||
Name: req.Name,
|
||||
FieldContext: req.FieldContext,
|
||||
Config: req.Config,
|
||||
Enabled: req.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSpanMapperFromUpdatable(req *UpdatableSpanMapper) *SpanMapper {
|
||||
m := &SpanMapper{}
|
||||
if req.FieldContext != (FieldContext{}) {
|
||||
m.FieldContext = req.FieldContext
|
||||
}
|
||||
if req.Config != nil {
|
||||
m.Config = *req.Config
|
||||
}
|
||||
if req.Enabled != nil {
|
||||
m.Enabled = *req.Enabled
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func NewSpanMappersFromStorableSpanMappers(ss []*StorableSpanMapper) []*SpanMapper {
|
||||
func NewSpanMappersFromStorable(ss []*StorableSpanMapper) []*SpanMapper {
|
||||
mappers := make([]*SpanMapper, len(ss))
|
||||
for i, s := range ss {
|
||||
mappers[i] = NewSpanMapperFromStorable(s)
|
||||
mappers[i] = s.ToSpanMapper()
|
||||
}
|
||||
return mappers
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package spantypes
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
@@ -11,9 +13,6 @@ var (
|
||||
ErrCodeMappingGroupAlreadyExists = errors.MustNewCode("span_attribute_mapping_group_already_exists")
|
||||
)
|
||||
|
||||
// SpanMapperGroupCategory defaults will be llm, tool, agent but user can configure more as they want.
|
||||
type SpanMapperGroupCategory valuer.String
|
||||
|
||||
// A group runs when any of the listed attribute/resource key patterns match.
|
||||
type SpanMapperGroupCondition struct {
|
||||
Attributes []string `json:"attributes" required:"true" nullable:"true"`
|
||||
@@ -28,7 +27,6 @@ type SpanMapperGroup struct {
|
||||
ID valuer.UUID `json:"id" required:"true"`
|
||||
OrgID valuer.UUID `json:"orgId" required:"true"`
|
||||
Name string `json:"name" required:"true"`
|
||||
Category SpanMapperGroupCategory `json:"category" required:"true"`
|
||||
Condition SpanMapperGroupCondition `json:"condition" required:"true"`
|
||||
Enabled bool `json:"enabled" required:"true"`
|
||||
}
|
||||
@@ -38,7 +36,6 @@ type GettableSpanMapperGroup = SpanMapperGroup
|
||||
|
||||
type PostableSpanMapperGroup struct {
|
||||
Name string `json:"name" required:"true"`
|
||||
Category SpanMapperGroupCategory `json:"category" required:"true"`
|
||||
Condition SpanMapperGroupCondition `json:"condition" required:"true"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
@@ -46,44 +43,39 @@ type PostableSpanMapperGroup struct {
|
||||
// UpdatableSpanMapperGroup is the HTTP request body for updating a mapping group.
|
||||
// All fields are optional; only non-nil fields are applied.
|
||||
type UpdatableSpanMapperGroup struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Condition *SpanMapperGroupCondition `json:"condition,omitempty"`
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
Name *string `json:"name" nullable:"true"`
|
||||
Condition *SpanMapperGroupCondition `json:"condition" nullable:"true"`
|
||||
Enabled *bool `json:"enabled" nullable:"true"`
|
||||
}
|
||||
|
||||
type ListSpanMapperGroupsQuery struct {
|
||||
Category *SpanMapperGroupCategory `query:"category"`
|
||||
Enabled *bool `query:"enabled"`
|
||||
Enabled *bool `query:"enabled"`
|
||||
}
|
||||
|
||||
type GettableSpanMapperGroups struct {
|
||||
Items []*GettableSpanMapperGroup `json:"items" required:"true" nullable:"false"`
|
||||
}
|
||||
|
||||
func NewSpanMapperGroupFromStorable(s *StorableSpanMapperGroup) *SpanMapperGroup {
|
||||
return &SpanMapperGroup{
|
||||
TimeAuditable: s.TimeAuditable,
|
||||
UserAuditable: s.UserAuditable,
|
||||
ID: s.ID,
|
||||
OrgID: s.OrgID,
|
||||
Name: s.Name,
|
||||
Category: s.Category,
|
||||
Condition: s.Condition,
|
||||
Enabled: s.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSpanMapperGroupFromPostable(p *PostableSpanMapperGroup) *SpanMapperGroup {
|
||||
func NewSpanMapperGroup(orgID valuer.UUID, createdBy string, p *PostableSpanMapperGroup) *SpanMapperGroup {
|
||||
now := time.Now()
|
||||
return &SpanMapperGroup{
|
||||
ID: valuer.GenerateUUID(),
|
||||
OrgID: orgID,
|
||||
Name: p.Name,
|
||||
Category: p.Category,
|
||||
Condition: p.Condition,
|
||||
Enabled: p.Enabled,
|
||||
TimeAuditable: types.TimeAuditable{
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
},
|
||||
UserAuditable: types.UserAuditable{
|
||||
CreatedBy: createdBy,
|
||||
UpdatedBy: createdBy,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewSpanMapperGroupFromUpdatable(u *UpdatableSpanMapperGroup) *SpanMapperGroup {
|
||||
g := &SpanMapperGroup{}
|
||||
func (g *SpanMapperGroup) Update(u *UpdatableSpanMapperGroup, updatedBy string) {
|
||||
if u.Name != nil {
|
||||
g.Name = *u.Name
|
||||
}
|
||||
@@ -93,13 +85,38 @@ func NewSpanMapperGroupFromUpdatable(u *UpdatableSpanMapperGroup) *SpanMapperGro
|
||||
if u.Enabled != nil {
|
||||
g.Enabled = *u.Enabled
|
||||
}
|
||||
return g
|
||||
g.UpdatedAt = time.Now()
|
||||
g.UpdatedBy = updatedBy
|
||||
}
|
||||
|
||||
func NewSpanMapperGroupsFromStorableGroups(ss []*StorableSpanMapperGroup) []*SpanMapperGroup {
|
||||
func (g *SpanMapperGroup) ToStorable() *StorableSpanMapperGroup {
|
||||
return &StorableSpanMapperGroup{
|
||||
Identifiable: types.Identifiable{ID: g.ID},
|
||||
TimeAuditable: g.TimeAuditable,
|
||||
UserAuditable: g.UserAuditable,
|
||||
OrgID: g.OrgID,
|
||||
Name: g.Name,
|
||||
Condition: g.Condition,
|
||||
Enabled: g.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StorableSpanMapperGroup) ToSpanMapperGroup() *SpanMapperGroup {
|
||||
return &SpanMapperGroup{
|
||||
TimeAuditable: s.TimeAuditable,
|
||||
UserAuditable: s.UserAuditable,
|
||||
ID: s.ID,
|
||||
OrgID: s.OrgID,
|
||||
Name: s.Name,
|
||||
Condition: s.Condition,
|
||||
Enabled: s.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSpanMapperGroupsFromStorable(ss []*StorableSpanMapperGroup) []*SpanMapperGroup {
|
||||
groups := make([]*SpanMapperGroup, len(ss))
|
||||
for i, s := range ss {
|
||||
groups[i] = NewSpanMapperGroupFromStorable(s)
|
||||
groups[i] = s.ToSpanMapperGroup()
|
||||
}
|
||||
return groups
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ type StorableSpanMapperGroup struct {
|
||||
|
||||
OrgID valuer.UUID `bun:"org_id,type:text,notnull"`
|
||||
Name string `bun:"name,type:text,notnull"`
|
||||
Category SpanMapperGroupCategory `bun:"category,type:text,notnull"`
|
||||
Condition SpanMapperGroupCondition `bun:"condition,type:jsonb,notnull"`
|
||||
Enabled bool `bun:"enabled,notnull,default:true"`
|
||||
}
|
||||
|
||||
@@ -6,18 +6,18 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
type SpanMapperStore interface {
|
||||
// Group operations
|
||||
ListSpanMapperGroups(ctx context.Context, orgID valuer.UUID, q *ListSpanMapperGroupsQuery) ([]*StorableSpanMapperGroup, error)
|
||||
GetSpanMapperGroup(ctx context.Context, orgID, id valuer.UUID) (*StorableSpanMapperGroup, error)
|
||||
CreateSpanMapperGroup(ctx context.Context, group *StorableSpanMapperGroup) error
|
||||
UpdateSpanMapperGroup(ctx context.Context, group *StorableSpanMapperGroup) error
|
||||
DeleteSpanMapperGroup(ctx context.Context, orgID, id valuer.UUID) error
|
||||
ListGroups(ctx context.Context, orgID valuer.UUID, q *ListSpanMapperGroupsQuery) ([]*SpanMapperGroup, error)
|
||||
GetGroup(ctx context.Context, orgID, id valuer.UUID) (*SpanMapperGroup, error)
|
||||
CreateGroup(ctx context.Context, group *SpanMapperGroup) error
|
||||
UpdateGroup(ctx context.Context, group *SpanMapperGroup) error
|
||||
DeleteGroup(ctx context.Context, orgID, id valuer.UUID) error
|
||||
|
||||
// Mapper operations
|
||||
ListSpanMappers(ctx context.Context, orgID, groupID valuer.UUID) ([]*StorableSpanMapper, error)
|
||||
GetSpanMapper(ctx context.Context, orgID, groupID, id valuer.UUID) (*StorableSpanMapper, error)
|
||||
CreateSpanMapper(ctx context.Context, mapper *StorableSpanMapper) error
|
||||
UpdateSpanMapper(ctx context.Context, mapper *StorableSpanMapper) error
|
||||
DeleteSpanMapper(ctx context.Context, orgID, groupID, id valuer.UUID) error
|
||||
ListMappers(ctx context.Context, orgID, groupID valuer.UUID) ([]*SpanMapper, error)
|
||||
GetMapper(ctx context.Context, orgID, groupID, id valuer.UUID) (*SpanMapper, error)
|
||||
CreateMapper(ctx context.Context, mapper *SpanMapper) error
|
||||
UpdateMapper(ctx context.Context, mapper *SpanMapper) error
|
||||
DeleteMapper(ctx context.Context, orgID, groupID, id valuer.UUID) error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user