mirror of
https://github.com/SigNoz/signoz.git
synced 2026-04-13 07:30:21 +01:00
Compare commits
3 Commits
issue_4360
...
issue_4361
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b06b4546f | ||
|
|
526b08a179 | ||
|
|
c7ab610bd8 |
@@ -1,28 +1,66 @@
|
||||
components:
|
||||
schemas:
|
||||
Aio11YtypesCacheMode:
|
||||
Aio11YmappingtypesCondition:
|
||||
properties:
|
||||
attributes:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
resource:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
type: object
|
||||
Aio11YmappingtypesFieldContext:
|
||||
enum:
|
||||
- subtract
|
||||
- additive
|
||||
- unknown
|
||||
- span_attribute
|
||||
- resource
|
||||
nullable: true
|
||||
type: string
|
||||
Aio11YtypesGettablePricingRule:
|
||||
Aio11YmappingtypesGettableMapper:
|
||||
properties:
|
||||
cache_mode:
|
||||
$ref: '#/components/schemas/Aio11YtypesCacheMode'
|
||||
cost_cache_read:
|
||||
format: double
|
||||
type: number
|
||||
cost_cache_write:
|
||||
format: double
|
||||
type: number
|
||||
cost_input:
|
||||
format: double
|
||||
type: number
|
||||
cost_output:
|
||||
format: double
|
||||
type: number
|
||||
config:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesMapperConfig'
|
||||
created_at:
|
||||
format: date-time
|
||||
type: string
|
||||
created_by:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
field_context:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesFieldContext'
|
||||
group_id:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
updated_at:
|
||||
format: date-time
|
||||
type: string
|
||||
updated_by:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- group_id
|
||||
- name
|
||||
- field_context
|
||||
- config
|
||||
- enabled
|
||||
- created_at
|
||||
- updated_at
|
||||
- created_by
|
||||
- updated_by
|
||||
type: object
|
||||
Aio11YmappingtypesGettableMappingGroup:
|
||||
properties:
|
||||
category:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesGroupCategory'
|
||||
condition:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesCondition'
|
||||
created_at:
|
||||
format: date-time
|
||||
type: string
|
||||
@@ -32,21 +70,8 @@ components:
|
||||
type: boolean
|
||||
id:
|
||||
type: string
|
||||
is_override:
|
||||
type: boolean
|
||||
model_name:
|
||||
name:
|
||||
type: string
|
||||
model_pattern:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
synced_at:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
unit:
|
||||
$ref: '#/components/schemas/Aio11YtypesUnit'
|
||||
updated_at:
|
||||
format: date-time
|
||||
type: string
|
||||
@@ -54,115 +79,120 @@ components:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- model_name
|
||||
- model_pattern
|
||||
- unit
|
||||
- cache_mode
|
||||
- cost_input
|
||||
- cost_output
|
||||
- cost_cache_read
|
||||
- cost_cache_write
|
||||
- is_override
|
||||
- name
|
||||
- category
|
||||
- condition
|
||||
- enabled
|
||||
- created_at
|
||||
- updated_at
|
||||
- created_by
|
||||
- updated_by
|
||||
type: object
|
||||
Aio11YtypesListPricingRulesResponse:
|
||||
Aio11YmappingtypesGroupCategory:
|
||||
enum:
|
||||
- llm
|
||||
- tool
|
||||
- agent
|
||||
type: string
|
||||
Aio11YmappingtypesListMappersResponse:
|
||||
properties:
|
||||
items:
|
||||
items:
|
||||
$ref: '#/components/schemas/Aio11YtypesGettablePricingRule'
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesGettableMapper'
|
||||
nullable: true
|
||||
type: array
|
||||
limit:
|
||||
type: integer
|
||||
offset:
|
||||
type: integer
|
||||
total:
|
||||
type: integer
|
||||
required:
|
||||
- items
|
||||
- total
|
||||
- offset
|
||||
- limit
|
||||
type: object
|
||||
Aio11YtypesPostablePricingRule:
|
||||
Aio11YmappingtypesListMappingGroupsResponse:
|
||||
properties:
|
||||
cache_mode:
|
||||
$ref: '#/components/schemas/Aio11YtypesCacheMode'
|
||||
cost_cache_read:
|
||||
format: double
|
||||
type: number
|
||||
cost_cache_write:
|
||||
format: double
|
||||
type: number
|
||||
cost_input:
|
||||
format: double
|
||||
type: number
|
||||
cost_output:
|
||||
format: double
|
||||
type: number
|
||||
enabled:
|
||||
type: boolean
|
||||
model_name:
|
||||
type: string
|
||||
model_pattern:
|
||||
items:
|
||||
items:
|
||||
type: string
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesGettableMappingGroup'
|
||||
nullable: true
|
||||
type: array
|
||||
unit:
|
||||
$ref: '#/components/schemas/Aio11YtypesUnit'
|
||||
required:
|
||||
- model_name
|
||||
- model_pattern
|
||||
- unit
|
||||
- cache_mode
|
||||
- cost_input
|
||||
- cost_output
|
||||
- cost_cache_read
|
||||
- cost_cache_write
|
||||
- enabled
|
||||
- items
|
||||
type: object
|
||||
Aio11YtypesUnit:
|
||||
enum:
|
||||
- per_million_tokens
|
||||
- per_token
|
||||
nullable: true
|
||||
type: string
|
||||
Aio11YtypesUpdatablePricingRule:
|
||||
Aio11YmappingtypesMapperConfig:
|
||||
properties:
|
||||
cache_mode:
|
||||
$ref: '#/components/schemas/Aio11YtypesCacheMode'
|
||||
cost_cache_read:
|
||||
sources:
|
||||
items:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesMapperSource'
|
||||
nullable: true
|
||||
type: number
|
||||
cost_cache_write:
|
||||
nullable: true
|
||||
type: number
|
||||
cost_input:
|
||||
nullable: true
|
||||
type: number
|
||||
cost_output:
|
||||
nullable: true
|
||||
type: number
|
||||
type: array
|
||||
type: object
|
||||
Aio11YmappingtypesMapperOperation:
|
||||
enum:
|
||||
- move
|
||||
- copy
|
||||
type: string
|
||||
Aio11YmappingtypesMapperSource:
|
||||
properties:
|
||||
context:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesSourceContext'
|
||||
key:
|
||||
type: string
|
||||
operation:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesMapperOperation'
|
||||
priority:
|
||||
type: integer
|
||||
type: object
|
||||
Aio11YmappingtypesPostableMapper:
|
||||
properties:
|
||||
config:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesMapperConfig'
|
||||
enabled:
|
||||
type: boolean
|
||||
field_context:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesFieldContext'
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- field_context
|
||||
- config
|
||||
type: object
|
||||
Aio11YmappingtypesPostableMappingGroup:
|
||||
properties:
|
||||
category:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesGroupCategory'
|
||||
condition:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesCondition'
|
||||
enabled:
|
||||
type: boolean
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- category
|
||||
- condition
|
||||
type: object
|
||||
Aio11YmappingtypesSourceContext:
|
||||
enum:
|
||||
- attribute
|
||||
- resource
|
||||
type: string
|
||||
Aio11YmappingtypesUpdatableMapper:
|
||||
properties:
|
||||
config:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesMapperConfig'
|
||||
enabled:
|
||||
nullable: true
|
||||
type: boolean
|
||||
is_override:
|
||||
field_context:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesFieldContext'
|
||||
type: object
|
||||
Aio11YmappingtypesUpdatableMappingGroup:
|
||||
properties:
|
||||
condition:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesCondition'
|
||||
enabled:
|
||||
nullable: true
|
||||
type: boolean
|
||||
model_name:
|
||||
name:
|
||||
nullable: true
|
||||
type: string
|
||||
model_pattern:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
unit:
|
||||
$ref: '#/components/schemas/Aio11YtypesUnit'
|
||||
type: object
|
||||
AuthtypesAttributeMapping:
|
||||
properties:
|
||||
@@ -3222,20 +3252,22 @@ info:
|
||||
version: ""
|
||||
openapi: 3.0.3
|
||||
paths:
|
||||
/api/v1/ai-o11y/pricing/rules:
|
||||
/api/v1/ai-o11y/mapping/groups:
|
||||
get:
|
||||
deprecated: false
|
||||
description: Returns all LLM pricing rules for the authenticated org, with pagination.
|
||||
operationId: ListPricingRules
|
||||
description: Returns all span attribute mapping groups for the authenticated
|
||||
org.
|
||||
operationId: ListMappingGroups
|
||||
parameters:
|
||||
- in: query
|
||||
name: offset
|
||||
name: category
|
||||
schema:
|
||||
type: integer
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesGroupCategory'
|
||||
- in: query
|
||||
name: limit
|
||||
name: enabled
|
||||
schema:
|
||||
type: integer
|
||||
nullable: true
|
||||
type: boolean
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
@@ -3243,7 +3275,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/Aio11YtypesListPricingRulesResponse'
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesListMappingGroupsResponse'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -3280,19 +3312,18 @@ paths:
|
||||
- VIEWER
|
||||
- tokenizer:
|
||||
- VIEWER
|
||||
summary: List pricing rules
|
||||
summary: List mapping groups
|
||||
tags:
|
||||
- ai-o11y
|
||||
post:
|
||||
deprecated: false
|
||||
description: Creates a new LLM pricing rule for the org. Always sets is_override
|
||||
= true.
|
||||
operationId: CreatePricingRule
|
||||
description: Creates a new span attribute mapping group for the org.
|
||||
operationId: CreateMappingGroup
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Aio11YtypesPostablePricingRule'
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesPostableMappingGroup'
|
||||
responses:
|
||||
"201":
|
||||
content:
|
||||
@@ -3300,7 +3331,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/Aio11YtypesGettablePricingRule'
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesGettableMappingGroup'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -3343,18 +3374,22 @@ paths:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Create a pricing rule
|
||||
summary: Create a mapping group
|
||||
tags:
|
||||
- ai-o11y
|
||||
/api/v1/ai-o11y/pricing/rules/{id}:
|
||||
/api/v1/ai-o11y/mapping/groups/{groupId}/mappers/{mapperId}:
|
||||
delete:
|
||||
deprecated: false
|
||||
description: Hard-deletes a pricing rule. If auto-synced, it will be recreated
|
||||
on the next sync cycle.
|
||||
operationId: DeletePricingRule
|
||||
description: Hard-deletes a mapper from a mapping group.
|
||||
operationId: DeleteMapper
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
name: groupId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: mapperId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
@@ -3390,74 +3425,22 @@ paths:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Delete a pricing rule
|
||||
tags:
|
||||
- ai-o11y
|
||||
get:
|
||||
deprecated: false
|
||||
description: Returns a single LLM pricing rule by ID.
|
||||
operationId: GetPricingRule
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/Aio11YtypesGettablePricingRule'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: OK
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- VIEWER
|
||||
- tokenizer:
|
||||
- VIEWER
|
||||
summary: Get a pricing rule
|
||||
summary: Delete a mapper
|
||||
tags:
|
||||
- ai-o11y
|
||||
put:
|
||||
deprecated: false
|
||||
description: Partially updates an existing pricing rule. Changing any cost field
|
||||
sets is_override = true.
|
||||
operationId: UpdatePricingRule
|
||||
description: Partially updates an existing mapper's field context, config, or
|
||||
enabled state.
|
||||
operationId: UpdateMapper
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
name: groupId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: mapperId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
@@ -3465,7 +3448,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Aio11YtypesUpdatablePricingRule'
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesUpdatableMapper'
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
@@ -3473,7 +3456,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/Aio11YtypesGettablePricingRule'
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesGettableMapper'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -3516,7 +3499,265 @@ paths:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Update a pricing rule
|
||||
summary: Update a mapper
|
||||
tags:
|
||||
- ai-o11y
|
||||
/api/v1/ai-o11y/mapping/groups/{id}:
|
||||
delete:
|
||||
deprecated: false
|
||||
description: Hard-deletes a mapping group and cascades to all its mappers.
|
||||
operationId: DeleteMappingGroup
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Delete a mapping group
|
||||
tags:
|
||||
- ai-o11y
|
||||
put:
|
||||
deprecated: false
|
||||
description: Partially updates an existing mapping group's name, condition,
|
||||
or enabled state.
|
||||
operationId: UpdateMappingGroup
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesUpdatableMappingGroup'
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesGettableMappingGroup'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: OK
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Update a mapping group
|
||||
tags:
|
||||
- ai-o11y
|
||||
/api/v1/ai-o11y/mapping/groups/{id}/mappers:
|
||||
get:
|
||||
deprecated: false
|
||||
description: Returns all attribute mappers belonging to a mapping group.
|
||||
operationId: ListMappers
|
||||
parameters:
|
||||
- in: query
|
||||
name: enabled
|
||||
schema:
|
||||
nullable: true
|
||||
type: boolean
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesListMappersResponse'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: OK
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- VIEWER
|
||||
- tokenizer:
|
||||
- VIEWER
|
||||
summary: List mappers for a group
|
||||
tags:
|
||||
- ai-o11y
|
||||
post:
|
||||
deprecated: false
|
||||
description: Adds a new attribute mapper to the specified mapping group.
|
||||
operationId: CreateMapper
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesPostableMapper'
|
||||
responses:
|
||||
"201":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/Aio11YmappingtypesGettableMapper'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: Created
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"409":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Conflict
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Create a mapper
|
||||
tags:
|
||||
- ai-o11y
|
||||
/api/v1/authz/check:
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
package signozapiserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/aio11ypricingruletypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (provider *provider) addAIO11yRoutes(router *mux.Router) error {
|
||||
if err := router.Handle("/api/v1/ai-o11y/pricing/rules", handler.New(
|
||||
provider.authZ.ViewAccess(provider.aiO11yPricingRuleHandler.List),
|
||||
handler.OpenAPIDef{
|
||||
ID: "ListPricingRules",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "List pricing rules",
|
||||
Description: "Returns all LLM pricing rules for the authenticated org, with pagination.",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
RequestQuery: new(aio11ypricingruletypes.ListPricingRulesQuery),
|
||||
Response: new(aio11ypricingruletypes.ListPricingRulesResponse),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
},
|
||||
)).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/pricing/rules", handler.New(
|
||||
provider.authZ.AdminAccess(provider.aiO11yPricingRuleHandler.Create),
|
||||
handler.OpenAPIDef{
|
||||
ID: "CreatePricingRule",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "Create a pricing rule",
|
||||
Description: "Creates a new LLM pricing rule for the org. Always sets is_override = true.",
|
||||
Request: new(aio11ypricingruletypes.PostablePricingRule),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(aio11ypricingruletypes.GettablePricingRule),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/pricing/rules/{id}", handler.New(
|
||||
provider.authZ.ViewAccess(provider.aiO11yPricingRuleHandler.Get),
|
||||
handler.OpenAPIDef{
|
||||
ID: "GetPricingRule",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "Get a pricing rule",
|
||||
Description: "Returns a single LLM pricing rule by ID.",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(aio11ypricingruletypes.GettablePricingRule),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
},
|
||||
)).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/pricing/rules/{id}", handler.New(
|
||||
provider.authZ.AdminAccess(provider.aiO11yPricingRuleHandler.Update),
|
||||
handler.OpenAPIDef{
|
||||
ID: "UpdatePricingRule",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "Update a pricing rule",
|
||||
Description: "Partially updates an existing pricing rule. Changing any cost field sets is_override = true.",
|
||||
Request: new(aio11ypricingruletypes.UpdatablePricingRule),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(aio11ypricingruletypes.GettablePricingRule),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/pricing/rules/{id}", handler.New(
|
||||
provider.authZ.AdminAccess(provider.aiO11yPricingRuleHandler.Delete),
|
||||
handler.OpenAPIDef{
|
||||
ID: "DeletePricingRule",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "Delete a pricing rule",
|
||||
Description: "Hard-deletes a pricing rule. If auto-synced, it will be recreated on the next sync cycle.",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
180
pkg/apiserver/signozapiserver/aio11ymapping.go
Normal file
180
pkg/apiserver/signozapiserver/aio11ymapping.go
Normal file
@@ -0,0 +1,180 @@
|
||||
package signozapiserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/aio11ymappingtypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (provider *provider) addAIO11yMappingRoutes(router *mux.Router) error {
|
||||
// --- Mapping Groups ---
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/mapping/groups", handler.New(
|
||||
provider.authZ.ViewAccess(provider.aio11yMappingHandler.ListGroups),
|
||||
handler.OpenAPIDef{
|
||||
ID: "ListMappingGroups",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "List mapping groups",
|
||||
Description: "Returns all span attribute mapping groups for the authenticated org.",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
RequestQuery: new(aio11ymappingtypes.ListMappingGroupsQuery),
|
||||
Response: new(aio11ymappingtypes.ListMappingGroupsResponse),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
},
|
||||
)).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/mapping/groups", handler.New(
|
||||
provider.authZ.AdminAccess(provider.aio11yMappingHandler.CreateGroup),
|
||||
handler.OpenAPIDef{
|
||||
ID: "CreateMappingGroup",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "Create a mapping group",
|
||||
Description: "Creates a new span attribute mapping group for the org.",
|
||||
Request: new(aio11ymappingtypes.PostableMappingGroup),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(aio11ymappingtypes.GettableMappingGroup),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/mapping/groups/{id}", handler.New(
|
||||
provider.authZ.AdminAccess(provider.aio11yMappingHandler.UpdateGroup),
|
||||
handler.OpenAPIDef{
|
||||
ID: "UpdateMappingGroup",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "Update a mapping group",
|
||||
Description: "Partially updates an existing mapping group's name, condition, or enabled state.",
|
||||
Request: new(aio11ymappingtypes.UpdatableMappingGroup),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(aio11ymappingtypes.GettableMappingGroup),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/mapping/groups/{id}", handler.New(
|
||||
provider.authZ.AdminAccess(provider.aio11yMappingHandler.DeleteGroup),
|
||||
handler.OpenAPIDef{
|
||||
ID: "DeleteMappingGroup",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "Delete a mapping group",
|
||||
Description: "Hard-deletes a mapping group and cascades to all its mappers.",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// --- Mappers ---
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/mapping/groups/{id}/mappers", handler.New(
|
||||
provider.authZ.ViewAccess(provider.aio11yMappingHandler.ListMappers),
|
||||
handler.OpenAPIDef{
|
||||
ID: "ListMappers",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "List mappers for a group",
|
||||
Description: "Returns all attribute mappers belonging to a mapping group.",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
RequestQuery: new(aio11ymappingtypes.ListMappersQuery),
|
||||
Response: new(aio11ymappingtypes.ListMappersResponse),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
},
|
||||
)).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/mapping/groups/{id}/mappers", handler.New(
|
||||
provider.authZ.AdminAccess(provider.aio11yMappingHandler.CreateMapper),
|
||||
handler.OpenAPIDef{
|
||||
ID: "CreateMapper",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "Create a mapper",
|
||||
Description: "Adds a new attribute mapper to the specified mapping group.",
|
||||
Request: new(aio11ymappingtypes.PostableMapper),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(aio11ymappingtypes.GettableMapper),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/mapping/groups/{groupId}/mappers/{mapperId}", handler.New(
|
||||
provider.authZ.AdminAccess(provider.aio11yMappingHandler.UpdateMapper),
|
||||
handler.OpenAPIDef{
|
||||
ID: "UpdateMapper",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "Update a mapper",
|
||||
Description: "Partially updates an existing mapper's field context, config, or enabled state.",
|
||||
Request: new(aio11ymappingtypes.UpdatableMapper),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(aio11ymappingtypes.GettableMapper),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/ai-o11y/mapping/groups/{groupId}/mappers/{mapperId}", handler.New(
|
||||
provider.authZ.AdminAccess(provider.aio11yMappingHandler.DeleteMapper),
|
||||
handler.OpenAPIDef{
|
||||
ID: "DeleteMapper",
|
||||
Tags: []string{"ai-o11y"},
|
||||
Summary: "Delete a mapper",
|
||||
Description: "Hard-deletes a mapper from a mapping group.",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/global"
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/http/middleware"
|
||||
"github.com/SigNoz/signoz/pkg/modules/aio11ypricingrule"
|
||||
"github.com/SigNoz/signoz/pkg/modules/aio11ymapping"
|
||||
"github.com/SigNoz/signoz/pkg/modules/authdomain"
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
@@ -33,32 +33,32 @@ import (
|
||||
)
|
||||
|
||||
type provider struct {
|
||||
config apiserver.Config
|
||||
settings factory.ScopedProviderSettings
|
||||
router *mux.Router
|
||||
authZ *middleware.AuthZ
|
||||
orgHandler organization.Handler
|
||||
userHandler user.Handler
|
||||
sessionHandler session.Handler
|
||||
authDomainHandler authdomain.Handler
|
||||
preferenceHandler preference.Handler
|
||||
globalHandler global.Handler
|
||||
promoteHandler promote.Handler
|
||||
flaggerHandler flagger.Handler
|
||||
dashboardModule dashboard.Module
|
||||
dashboardHandler dashboard.Handler
|
||||
metricsExplorerHandler metricsexplorer.Handler
|
||||
gatewayHandler gateway.Handler
|
||||
fieldsHandler fields.Handler
|
||||
authzHandler authz.Handler
|
||||
rawDataExportHandler rawdataexport.Handler
|
||||
zeusHandler zeus.Handler
|
||||
querierHandler querier.Handler
|
||||
serviceAccountHandler serviceaccount.Handler
|
||||
factoryHandler factory.Handler
|
||||
cloudIntegrationHandler cloudintegration.Handler
|
||||
ruleStateHistoryHandler rulestatehistory.Handler
|
||||
aiO11yPricingRuleHandler aio11ypricingrule.Handler
|
||||
config apiserver.Config
|
||||
settings factory.ScopedProviderSettings
|
||||
router *mux.Router
|
||||
authZ *middleware.AuthZ
|
||||
orgHandler organization.Handler
|
||||
userHandler user.Handler
|
||||
sessionHandler session.Handler
|
||||
authDomainHandler authdomain.Handler
|
||||
preferenceHandler preference.Handler
|
||||
globalHandler global.Handler
|
||||
promoteHandler promote.Handler
|
||||
flaggerHandler flagger.Handler
|
||||
dashboardModule dashboard.Module
|
||||
dashboardHandler dashboard.Handler
|
||||
metricsExplorerHandler metricsexplorer.Handler
|
||||
gatewayHandler gateway.Handler
|
||||
fieldsHandler fields.Handler
|
||||
authzHandler authz.Handler
|
||||
rawDataExportHandler rawdataexport.Handler
|
||||
zeusHandler zeus.Handler
|
||||
querierHandler querier.Handler
|
||||
serviceAccountHandler serviceaccount.Handler
|
||||
factoryHandler factory.Handler
|
||||
cloudIntegrationHandler cloudintegration.Handler
|
||||
ruleStateHistoryHandler rulestatehistory.Handler
|
||||
aio11yMappingHandler aio11ymapping.Handler
|
||||
}
|
||||
|
||||
func NewFactory(
|
||||
@@ -85,7 +85,7 @@ func NewFactory(
|
||||
factoryHandler factory.Handler,
|
||||
cloudIntegrationHandler cloudintegration.Handler,
|
||||
ruleStateHistoryHandler rulestatehistory.Handler,
|
||||
aiO11yPricingRuleHandler aio11ypricingrule.Handler,
|
||||
aio11yMappingHandler aio11ymapping.Handler,
|
||||
) factory.ProviderFactory[apiserver.APIServer, apiserver.Config] {
|
||||
return factory.NewProviderFactory(factory.MustNewName("signoz"), func(ctx context.Context, providerSettings factory.ProviderSettings, config apiserver.Config) (apiserver.APIServer, error) {
|
||||
return newProvider(
|
||||
@@ -115,7 +115,7 @@ func NewFactory(
|
||||
factoryHandler,
|
||||
cloudIntegrationHandler,
|
||||
ruleStateHistoryHandler,
|
||||
aiO11yPricingRuleHandler,
|
||||
aio11yMappingHandler,
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -147,37 +147,37 @@ func newProvider(
|
||||
factoryHandler factory.Handler,
|
||||
cloudIntegrationHandler cloudintegration.Handler,
|
||||
ruleStateHistoryHandler rulestatehistory.Handler,
|
||||
aiO11yPricingRuleHandler aio11ypricingrule.Handler,
|
||||
aio11yMappingHandler aio11ymapping.Handler,
|
||||
) (apiserver.APIServer, error) {
|
||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/apiserver/signozapiserver")
|
||||
router := mux.NewRouter().UseEncodedPath()
|
||||
|
||||
provider := &provider{
|
||||
config: config,
|
||||
settings: settings,
|
||||
router: router,
|
||||
orgHandler: orgHandler,
|
||||
userHandler: userHandler,
|
||||
sessionHandler: sessionHandler,
|
||||
authDomainHandler: authDomainHandler,
|
||||
preferenceHandler: preferenceHandler,
|
||||
globalHandler: globalHandler,
|
||||
promoteHandler: promoteHandler,
|
||||
flaggerHandler: flaggerHandler,
|
||||
dashboardModule: dashboardModule,
|
||||
dashboardHandler: dashboardHandler,
|
||||
metricsExplorerHandler: metricsExplorerHandler,
|
||||
gatewayHandler: gatewayHandler,
|
||||
fieldsHandler: fieldsHandler,
|
||||
authzHandler: authzHandler,
|
||||
rawDataExportHandler: rawDataExportHandler,
|
||||
zeusHandler: zeusHandler,
|
||||
querierHandler: querierHandler,
|
||||
serviceAccountHandler: serviceAccountHandler,
|
||||
factoryHandler: factoryHandler,
|
||||
cloudIntegrationHandler: cloudIntegrationHandler,
|
||||
ruleStateHistoryHandler: ruleStateHistoryHandler,
|
||||
aiO11yPricingRuleHandler: aiO11yPricingRuleHandler,
|
||||
config: config,
|
||||
settings: settings,
|
||||
router: router,
|
||||
orgHandler: orgHandler,
|
||||
userHandler: userHandler,
|
||||
sessionHandler: sessionHandler,
|
||||
authDomainHandler: authDomainHandler,
|
||||
preferenceHandler: preferenceHandler,
|
||||
globalHandler: globalHandler,
|
||||
promoteHandler: promoteHandler,
|
||||
flaggerHandler: flaggerHandler,
|
||||
dashboardModule: dashboardModule,
|
||||
dashboardHandler: dashboardHandler,
|
||||
metricsExplorerHandler: metricsExplorerHandler,
|
||||
gatewayHandler: gatewayHandler,
|
||||
fieldsHandler: fieldsHandler,
|
||||
authzHandler: authzHandler,
|
||||
rawDataExportHandler: rawDataExportHandler,
|
||||
zeusHandler: zeusHandler,
|
||||
querierHandler: querierHandler,
|
||||
serviceAccountHandler: serviceAccountHandler,
|
||||
factoryHandler: factoryHandler,
|
||||
cloudIntegrationHandler: cloudIntegrationHandler,
|
||||
ruleStateHistoryHandler: ruleStateHistoryHandler,
|
||||
aio11yMappingHandler: aio11yMappingHandler,
|
||||
}
|
||||
|
||||
provider.authZ = middleware.NewAuthZ(settings.Logger(), orgGetter, authz)
|
||||
@@ -278,7 +278,7 @@ func (provider *provider) AddToRouter(router *mux.Router) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := provider.addAIO11yRoutes(router); err != nil {
|
||||
if err := provider.addAIO11yMappingRoutes(router); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
43
pkg/modules/aio11ymapping/aio11ymapping.go
Normal file
43
pkg/modules/aio11ymapping/aio11ymapping.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package aio11ymapping
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types/aio11ymappingtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
// Module defines the business logic for span attribute mapping groups and mappers.
|
||||
type Module interface {
|
||||
// Group operations
|
||||
|
||||
ListGroups(ctx context.Context, orgID valuer.UUID, q *aio11ymappingtypes.ListMappingGroupsQuery) ([]*aio11ymappingtypes.MappingGroup, error)
|
||||
GetGroup(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*aio11ymappingtypes.MappingGroup, error)
|
||||
CreateGroup(ctx context.Context, orgID valuer.UUID, createdBy string, req *aio11ymappingtypes.PostableMappingGroup) (*aio11ymappingtypes.MappingGroup, error)
|
||||
UpdateGroup(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, req *aio11ymappingtypes.UpdatableMappingGroup) (*aio11ymappingtypes.MappingGroup, error)
|
||||
DeleteGroup(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
||||
|
||||
// Mapper operations
|
||||
|
||||
ListMappers(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, q *aio11ymappingtypes.ListMappersQuery) ([]*aio11ymappingtypes.Mapper, error)
|
||||
GetMapper(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, id valuer.UUID) (*aio11ymappingtypes.Mapper, error)
|
||||
CreateMapper(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, createdBy string, req *aio11ymappingtypes.PostableMapper) (*aio11ymappingtypes.Mapper, error)
|
||||
UpdateMapper(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, id valuer.UUID, updatedBy string, req *aio11ymappingtypes.UpdatableMapper) (*aio11ymappingtypes.Mapper, error)
|
||||
DeleteMapper(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, id valuer.UUID) error
|
||||
}
|
||||
|
||||
// Handler defines the HTTP handler interface for mapping group and mapper endpoints.
|
||||
type Handler interface {
|
||||
// Group handlers
|
||||
ListGroups(rw http.ResponseWriter, r *http.Request)
|
||||
CreateGroup(rw http.ResponseWriter, r *http.Request)
|
||||
UpdateGroup(rw http.ResponseWriter, r *http.Request)
|
||||
DeleteGroup(rw http.ResponseWriter, r *http.Request)
|
||||
|
||||
// Mapper handlers
|
||||
ListMappers(rw http.ResponseWriter, r *http.Request)
|
||||
CreateMapper(rw http.ResponseWriter, r *http.Request)
|
||||
UpdateMapper(rw http.ResponseWriter, r *http.Request)
|
||||
DeleteMapper(rw http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
356
pkg/modules/aio11ymapping/impiaio11ymapping/handler.go
Normal file
356
pkg/modules/aio11ymapping/impiaio11ymapping/handler.go
Normal file
@@ -0,0 +1,356 @@
|
||||
package impiaio11ymapping
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"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/aio11ymapping"
|
||||
"github.com/SigNoz/signoz/pkg/types/aio11ymappingtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
module aio11ymapping.Module
|
||||
providerSettings factory.ProviderSettings
|
||||
}
|
||||
|
||||
func NewHandler(module aio11ymapping.Module, providerSettings factory.ProviderSettings) aio11ymapping.Handler {
|
||||
return &handler{module: module, providerSettings: providerSettings}
|
||||
}
|
||||
|
||||
// ListGroups handles GET /api/v1/ai-o11y/mapping/groups.
|
||||
func (h *handler) ListGroups(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
var q aio11ymappingtypes.ListMappingGroupsQuery
|
||||
if err := binding.Query.BindQuery(r.URL.Query(), &q); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
groups, err := h.module.ListGroups(ctx, orgID, &q)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
items := make([]*aio11ymappingtypes.GettableMappingGroup, len(groups))
|
||||
for i, g := range groups {
|
||||
items[i] = aio11ymappingtypes.NewGettableMappingGroup(g)
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, &aio11ymappingtypes.ListMappingGroupsResponse{Items: items})
|
||||
}
|
||||
|
||||
// CreateGroup handles POST /api/v1/ai-o11y/mapping/groups.
|
||||
func (h *handler) CreateGroup(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(aio11ymappingtypes.PostableMappingGroup)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
group, err := h.module.CreateGroup(ctx, orgID, claims.Email, req)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusCreated, aio11ymappingtypes.NewGettableMappingGroup(group))
|
||||
}
|
||||
|
||||
// UpdateGroup handles PUT /api/v1/ai-o11y/mapping/groups/{id}.
|
||||
func (h *handler) UpdateGroup(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := groupIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(aio11ymappingtypes.UpdatableMappingGroup)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
group, err := h.module.UpdateGroup(ctx, orgID, id, claims.Email, req)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, aio11ymappingtypes.NewGettableMappingGroup(group))
|
||||
}
|
||||
|
||||
// DeleteGroup handles DELETE /api/v1/ai-o11y/mapping/groups/{id}.
|
||||
func (h *handler) DeleteGroup(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := groupIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.module.DeleteGroup(ctx, orgID, id); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
// ListMappers handles GET /api/v1/ai-o11y/mapping/groups/{id}/mappers.
|
||||
func (h *handler) ListMappers(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
groupID, err := groupIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
var q aio11ymappingtypes.ListMappersQuery
|
||||
if err := binding.Query.BindQuery(r.URL.Query(), &q); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
mappers, err := h.module.ListMappers(ctx, orgID, groupID, &q)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
items := make([]*aio11ymappingtypes.GettableMapper, len(mappers))
|
||||
for i, m := range mappers {
|
||||
items[i] = aio11ymappingtypes.NewGettableMapper(m)
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, &aio11ymappingtypes.ListMappersResponse{Items: items})
|
||||
}
|
||||
|
||||
// CreateMapper handles POST /api/v1/ai-o11y/mapping/groups/{id}/mappers.
|
||||
func (h *handler) CreateMapper(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
groupID, err := groupIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(aio11ymappingtypes.PostableMapper)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
mapper, err := h.module.CreateMapper(ctx, orgID, groupID, claims.Email, req)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusCreated, aio11ymappingtypes.NewGettableMapper(mapper))
|
||||
}
|
||||
|
||||
// UpdateMapper handles PUT /api/v1/ai-o11y/mapping/groups/{groupId}/mappers/{mapperId}.
|
||||
func (h *handler) UpdateMapper(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
groupID, err := groupIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
mapperID, err := mapperIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(aio11ymappingtypes.UpdatableMapper)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
mapper, err := h.module.UpdateMapper(ctx, orgID, groupID, mapperID, claims.Email, req)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, aio11ymappingtypes.NewGettableMapper(mapper))
|
||||
}
|
||||
|
||||
// DeleteMapper handles DELETE /api/v1/ai-o11y/mapping/groups/{groupId}/mappers/{mapperId}.
|
||||
func (h *handler) DeleteMapper(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
groupID, err := groupIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
mapperID, err := mapperIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.module.DeleteMapper(ctx, orgID, groupID, mapperID); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
// groupIDFromPath extracts and validates the {id} or {groupId} path variable.
|
||||
func groupIDFromPath(r *http.Request) (valuer.UUID, error) {
|
||||
vars := mux.Vars(r)
|
||||
raw := vars["groupId"]
|
||||
if raw == "" {
|
||||
raw = vars["id"]
|
||||
}
|
||||
if raw == "" {
|
||||
return valuer.UUID{}, errors.Newf(errors.TypeInvalidInput, aio11ymappingtypes.ErrCodeMappingInvalidInput, "group id is missing from the path")
|
||||
}
|
||||
id, err := valuer.NewUUID(raw)
|
||||
if err != nil {
|
||||
return valuer.UUID{}, errors.Wrapf(err, errors.TypeInvalidInput, aio11ymappingtypes.ErrCodeMappingInvalidInput, "group id is not a valid uuid")
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// mapperIDFromPath extracts and validates the {mapperId} path variable.
|
||||
func mapperIDFromPath(r *http.Request) (valuer.UUID, error) {
|
||||
raw := mux.Vars(r)["mapperId"]
|
||||
if raw == "" {
|
||||
return valuer.UUID{}, errors.Newf(errors.TypeInvalidInput, aio11ymappingtypes.ErrCodeMappingInvalidInput, "mapper id is missing from the path")
|
||||
}
|
||||
id, err := valuer.NewUUID(raw)
|
||||
if err != nil {
|
||||
return valuer.UUID{}, errors.Wrapf(err, errors.TypeInvalidInput, aio11ymappingtypes.ErrCodeMappingInvalidInput, "mapper id is not a valid uuid")
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package aio11ypricingrule
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types/aio11ypricingruletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type Module interface {
|
||||
List(ctx context.Context, orgID valuer.UUID, offset, limit int) ([]*aio11ypricingruletypes.PricingRule, int, error)
|
||||
Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*aio11ypricingruletypes.PricingRule, error)
|
||||
Create(ctx context.Context, orgID valuer.UUID, createdBy string, req *aio11ypricingruletypes.PostablePricingRule) (*aio11ypricingruletypes.PricingRule, error)
|
||||
Update(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, req *aio11ypricingruletypes.UpdatablePricingRule) (*aio11ypricingruletypes.PricingRule, error)
|
||||
Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
||||
}
|
||||
|
||||
// Handler defines the HTTP handler interface for pricing rule endpoints.
|
||||
type Handler interface {
|
||||
List(rw http.ResponseWriter, r *http.Request)
|
||||
Get(rw http.ResponseWriter, r *http.Request)
|
||||
Create(rw http.ResponseWriter, r *http.Request)
|
||||
Update(rw http.ResponseWriter, r *http.Request)
|
||||
Delete(rw http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
package implaio11ypricingrule
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"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/aio11ypricingrule"
|
||||
"github.com/SigNoz/signoz/pkg/types/aio11ypricingruletypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
const maxLimit = 100
|
||||
|
||||
type handler struct {
|
||||
module aio11ypricingrule.Module
|
||||
providerSettings factory.ProviderSettings
|
||||
}
|
||||
|
||||
func NewHandler(module aio11ypricingrule.Module, providerSettings factory.ProviderSettings) aio11ypricingrule.Handler {
|
||||
return &handler{module: module, providerSettings: providerSettings}
|
||||
}
|
||||
|
||||
// List handles GET /api/v1/ai-o11y/pricing/rules.
|
||||
func (h *handler) List(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
var q aio11ypricingruletypes.ListPricingRulesQuery
|
||||
if err := binding.Query.BindQuery(r.URL.Query(), &q); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
if q.Limit <= 0 {
|
||||
q.Limit = 20
|
||||
} else if q.Limit > maxLimit {
|
||||
q.Limit = maxLimit
|
||||
}
|
||||
if q.Offset < 0 {
|
||||
render.Error(rw, errors.Newf(errors.TypeInvalidInput, aio11ypricingruletypes.ErrCodePricingRuleInvalidInput, "offset must be a non-negative integer"))
|
||||
return
|
||||
}
|
||||
|
||||
rules, total, err := h.module.List(ctx, orgID, q.Offset, q.Limit)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
items := make([]*aio11ypricingruletypes.GettablePricingRule, len(rules))
|
||||
for i, r := range rules {
|
||||
items[i] = aio11ypricingruletypes.NewGettablePricingRule(r)
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, &aio11ypricingruletypes.ListPricingRulesResponse{
|
||||
Items: items,
|
||||
Total: total,
|
||||
Offset: q.Offset,
|
||||
Limit: q.Limit,
|
||||
})
|
||||
}
|
||||
|
||||
// Get handles GET /api/v1/ai-o11y/pricing/rules/{id}.
|
||||
func (h *handler) Get(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := ruleIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
rule, err := h.module.Get(ctx, orgID, id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, aio11ypricingruletypes.NewGettablePricingRule(rule))
|
||||
}
|
||||
|
||||
// Create handles POST /api/v1/ai-o11y/pricing/rules.
|
||||
func (h *handler) Create(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(aio11ypricingruletypes.PostablePricingRule)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
rule, err := h.module.Create(ctx, orgID, claims.Email, req)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusCreated, aio11ypricingruletypes.NewGettablePricingRule(rule))
|
||||
}
|
||||
|
||||
// Update handles PUT /api/v1/ai-o11y/pricing/rules/{id}
|
||||
func (h *handler) Update(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := ruleIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(aio11ypricingruletypes.UpdatablePricingRule)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
rule, err := h.module.Update(ctx, orgID, id, claims.Email, req)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, aio11ypricingruletypes.NewGettablePricingRule(rule))
|
||||
}
|
||||
|
||||
// Delete handles DELETE /api/v1/ai-o11y/pricing/rules/{id}
|
||||
func (h *handler) Delete(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := ruleIDFromPath(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.module.Delete(ctx, orgID, id); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
// ruleIDFromPath extracts and validates the {id} path variable.
|
||||
func ruleIDFromPath(r *http.Request) (valuer.UUID, error) {
|
||||
raw := mux.Vars(r)["id"]
|
||||
if raw == "" {
|
||||
return valuer.UUID{}, errors.Newf(errors.TypeInvalidInput, aio11ypricingruletypes.ErrCodePricingRuleInvalidInput, "id is missing from the path")
|
||||
}
|
||||
id, err := valuer.NewUUID(raw)
|
||||
if err != nil {
|
||||
return valuer.UUID{}, errors.Wrapf(err, errors.TypeInvalidInput, aio11ypricingruletypes.ErrCodePricingRuleInvalidInput, "id is not a valid uuid")
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/global"
|
||||
"github.com/SigNoz/signoz/pkg/global/signozglobal"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/modules/aio11ypricingrule"
|
||||
"github.com/SigNoz/signoz/pkg/modules/aio11ymapping"
|
||||
"github.com/SigNoz/signoz/pkg/modules/apdex"
|
||||
"github.com/SigNoz/signoz/pkg/modules/apdex/implapdex"
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration"
|
||||
@@ -43,27 +43,27 @@ import (
|
||||
)
|
||||
|
||||
type Handlers struct {
|
||||
SavedView savedview.Handler
|
||||
Apdex apdex.Handler
|
||||
Dashboard dashboard.Handler
|
||||
QuickFilter quickfilter.Handler
|
||||
TraceFunnel tracefunnel.Handler
|
||||
RawDataExport rawdataexport.Handler
|
||||
SpanPercentile spanpercentile.Handler
|
||||
Services services.Handler
|
||||
MetricsExplorer metricsexplorer.Handler
|
||||
Global global.Handler
|
||||
FlaggerHandler flagger.Handler
|
||||
GatewayHandler gateway.Handler
|
||||
Fields fields.Handler
|
||||
AuthzHandler authz.Handler
|
||||
ZeusHandler zeus.Handler
|
||||
QuerierHandler querier.Handler
|
||||
ServiceAccountHandler serviceaccount.Handler
|
||||
RegistryHandler factory.Handler
|
||||
CloudIntegrationHandler cloudintegration.Handler
|
||||
RuleStateHistory rulestatehistory.Handler
|
||||
AIO11yPricingRuleHandler aio11ypricingrule.Handler
|
||||
SavedView savedview.Handler
|
||||
Apdex apdex.Handler
|
||||
Dashboard dashboard.Handler
|
||||
QuickFilter quickfilter.Handler
|
||||
TraceFunnel tracefunnel.Handler
|
||||
RawDataExport rawdataexport.Handler
|
||||
SpanPercentile spanpercentile.Handler
|
||||
Services services.Handler
|
||||
MetricsExplorer metricsexplorer.Handler
|
||||
Global global.Handler
|
||||
FlaggerHandler flagger.Handler
|
||||
GatewayHandler gateway.Handler
|
||||
Fields fields.Handler
|
||||
AuthzHandler authz.Handler
|
||||
ZeusHandler zeus.Handler
|
||||
QuerierHandler querier.Handler
|
||||
ServiceAccountHandler serviceaccount.Handler
|
||||
RegistryHandler factory.Handler
|
||||
CloudIntegrationHandler cloudintegration.Handler
|
||||
RuleStateHistory rulestatehistory.Handler
|
||||
AIO11yMappingHandler aio11ymapping.Handler
|
||||
}
|
||||
|
||||
func NewHandlers(
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/global"
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/instrumentation"
|
||||
"github.com/SigNoz/signoz/pkg/modules/aio11ypricingrule"
|
||||
"github.com/SigNoz/signoz/pkg/modules/aio11ymapping"
|
||||
"github.com/SigNoz/signoz/pkg/modules/authdomain"
|
||||
"github.com/SigNoz/signoz/pkg/modules/cloudintegration"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
@@ -70,7 +70,7 @@ func NewOpenAPI(ctx context.Context, instrumentation instrumentation.Instrumenta
|
||||
struct{ factory.Handler }{},
|
||||
struct{ cloudintegration.Handler }{},
|
||||
struct{ rulestatehistory.Handler }{},
|
||||
struct{ aio11ypricingrule.Handler }{},
|
||||
struct{ aio11ymapping.Handler }{},
|
||||
).New(ctx, instrumentation.ToProviderSettings(), apiserver.Config{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -3,6 +3,8 @@ package signoz
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager/nfmanager"
|
||||
"github.com/SigNoz/signoz/pkg/auditor"
|
||||
"github.com/SigNoz/signoz/pkg/auditor/noopauditor"
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager/nfmanager/rulebasednotification"
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
||||
"github.com/SigNoz/signoz/pkg/analytics"
|
||||
@@ -10,8 +12,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/analytics/segmentanalytics"
|
||||
"github.com/SigNoz/signoz/pkg/apiserver"
|
||||
"github.com/SigNoz/signoz/pkg/apiserver/signozapiserver"
|
||||
"github.com/SigNoz/signoz/pkg/auditor"
|
||||
"github.com/SigNoz/signoz/pkg/auditor/noopauditor"
|
||||
"github.com/SigNoz/signoz/pkg/authz"
|
||||
"github.com/SigNoz/signoz/pkg/cache"
|
||||
"github.com/SigNoz/signoz/pkg/cache/memorycache"
|
||||
@@ -288,7 +288,7 @@ func NewAPIServerProviderFactories(orgGetter organization.Getter, authz authz.Au
|
||||
handlers.RegistryHandler,
|
||||
handlers.CloudIntegrationHandler,
|
||||
handlers.RuleStateHistory,
|
||||
handlers.AIO11yPricingRuleHandler,
|
||||
handlers.AIO11yMappingHandler,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
11
pkg/types/aio11ymappingtypes/errors.go
Normal file
11
pkg/types/aio11ymappingtypes/errors.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package aio11ymappingtypes
|
||||
|
||||
import "github.com/SigNoz/signoz/pkg/errors"
|
||||
|
||||
var (
|
||||
ErrCodeMappingGroupNotFound = errors.MustNewCode("mapping_group_not_found")
|
||||
ErrCodeMappingGroupAlreadyExists = errors.MustNewCode("mapping_group_already_exists")
|
||||
ErrCodeMapperNotFound = errors.MustNewCode("mapper_not_found")
|
||||
ErrCodeMapperAlreadyExists = errors.MustNewCode("mapper_already_exists")
|
||||
ErrCodeMappingInvalidInput = errors.MustNewCode("mapping_invalid_input")
|
||||
)
|
||||
147
pkg/types/aio11ymappingtypes/group.go
Normal file
147
pkg/types/aio11ymappingtypes/group.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package aio11ymappingtypes
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type GroupCategory string
|
||||
|
||||
const (
|
||||
GroupCategoryLLM GroupCategory = "llm"
|
||||
GroupCategoryTool GroupCategory = "tool"
|
||||
GroupCategoryAgent GroupCategory = "agent"
|
||||
)
|
||||
|
||||
func (GroupCategory) Enum() []any {
|
||||
return []any{GroupCategoryLLM, GroupCategoryTool, GroupCategoryAgent}
|
||||
}
|
||||
|
||||
// Condition is the trigger condition for a mapping group.
|
||||
// A group runs when any of the listed attribute/resource key patterns match.
|
||||
// It implements driver.Valuer and sql.Scanner for JSON text column storage.
|
||||
type Condition struct {
|
||||
Attributes []string `json:"attributes"`
|
||||
Resource []string `json:"resource"`
|
||||
}
|
||||
|
||||
func (c Condition) Value() (driver.Value, error) {
|
||||
b, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func (c *Condition) Scan(src any) error {
|
||||
var raw []byte
|
||||
switch v := src.(type) {
|
||||
case string:
|
||||
raw = []byte(v)
|
||||
case []byte:
|
||||
raw = v
|
||||
case nil:
|
||||
*c = Condition{}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("aio11ymappingtypes: cannot scan %T into Condition", src)
|
||||
}
|
||||
return json.Unmarshal(raw, c)
|
||||
}
|
||||
|
||||
// MappingGroup is the domain model for a span attribute mapping group.
|
||||
// It has no serialisation concerns — use GettableMappingGroup for HTTP responses.
|
||||
type MappingGroup struct {
|
||||
types.TimeAuditable
|
||||
types.UserAuditable
|
||||
|
||||
ID string
|
||||
OrgID valuer.UUID
|
||||
Name string
|
||||
Category GroupCategory
|
||||
Condition Condition
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// NewMappingGroupFromStorable converts a StorableMappingGroup to a MappingGroup.
|
||||
func NewMappingGroupFromStorable(s *StorableMappingGroup) *MappingGroup {
|
||||
return &MappingGroup{
|
||||
TimeAuditable: s.TimeAuditable,
|
||||
UserAuditable: s.UserAuditable,
|
||||
ID: s.ID.StringValue(),
|
||||
OrgID: s.OrgID,
|
||||
Name: s.Name,
|
||||
Category: s.Category,
|
||||
Condition: s.Condition,
|
||||
Enabled: s.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
// NewMappingGroupsFromStorable converts a slice of StorableMappingGroup to a slice of MappingGroup.
|
||||
func NewMappingGroupsFromStorable(ss []*StorableMappingGroup) []*MappingGroup {
|
||||
groups := make([]*MappingGroup, len(ss))
|
||||
for i, s := range ss {
|
||||
groups[i] = NewMappingGroupFromStorable(s)
|
||||
}
|
||||
return groups
|
||||
}
|
||||
|
||||
// GettableMappingGroup is the HTTP response representation of a mapping group.
|
||||
type GettableMappingGroup struct {
|
||||
ID string `json:"id" required:"true"`
|
||||
Name string `json:"name" required:"true"`
|
||||
Category GroupCategory `json:"category" required:"true"`
|
||||
Condition Condition `json:"condition" required:"true"`
|
||||
Enabled bool `json:"enabled" required:"true"`
|
||||
CreatedAt time.Time `json:"created_at" required:"true"`
|
||||
UpdatedAt time.Time `json:"updated_at" required:"true"`
|
||||
CreatedBy string `json:"created_by" required:"true"`
|
||||
UpdatedBy string `json:"updated_by" required:"true"`
|
||||
}
|
||||
|
||||
// NewGettableMappingGroup converts a domain MappingGroup to a GettableMappingGroup.
|
||||
func NewGettableMappingGroup(g *MappingGroup) *GettableMappingGroup {
|
||||
return &GettableMappingGroup{
|
||||
ID: g.ID,
|
||||
Name: g.Name,
|
||||
Category: g.Category,
|
||||
Condition: g.Condition,
|
||||
Enabled: g.Enabled,
|
||||
CreatedAt: g.CreatedAt,
|
||||
UpdatedAt: g.UpdatedAt,
|
||||
CreatedBy: g.CreatedBy,
|
||||
UpdatedBy: g.UpdatedBy,
|
||||
}
|
||||
}
|
||||
|
||||
// PostableMappingGroup is the HTTP request body for creating a mapping group.
|
||||
type PostableMappingGroup struct {
|
||||
Name string `json:"name" required:"true"`
|
||||
Category GroupCategory `json:"category" required:"true"`
|
||||
Condition Condition `json:"condition" required:"true"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
// UpdatableMappingGroup is the HTTP request body for updating a mapping group.
|
||||
// All fields are optional; only non-nil fields are applied.
|
||||
type UpdatableMappingGroup struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Condition *Condition `json:"condition,omitempty"`
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
// ListMappingGroupsQuery holds optional filter parameters for listing mapping groups.
|
||||
type ListMappingGroupsQuery struct {
|
||||
Category *GroupCategory `query:"category"`
|
||||
Enabled *bool `query:"enabled"`
|
||||
}
|
||||
|
||||
// ListMappingGroupsResponse is the response for listing mapping groups.
|
||||
type ListMappingGroupsResponse struct {
|
||||
Items []*GettableMappingGroup `json:"items" required:"true" nullable:"true"`
|
||||
}
|
||||
183
pkg/types/aio11ymappingtypes/mapper.go
Normal file
183
pkg/types/aio11ymappingtypes/mapper.go
Normal file
@@ -0,0 +1,183 @@
|
||||
package aio11ymappingtypes
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
// FieldContext is where the target attribute is written.
|
||||
type FieldContext string
|
||||
|
||||
const (
|
||||
FieldContextSpanAttribute FieldContext = "span_attribute"
|
||||
FieldContextResource FieldContext = "resource"
|
||||
)
|
||||
|
||||
func (FieldContext) Enum() []any {
|
||||
return []any{FieldContextSpanAttribute, FieldContextResource}
|
||||
}
|
||||
|
||||
// MapperOperation determines whether the source attribute is moved (deleted) or copied.
|
||||
type MapperOperation string
|
||||
|
||||
const (
|
||||
MapperOperationMove MapperOperation = "move"
|
||||
MapperOperationCopy MapperOperation = "copy"
|
||||
)
|
||||
|
||||
func (MapperOperation) Enum() []any {
|
||||
return []any{MapperOperationMove, MapperOperationCopy}
|
||||
}
|
||||
|
||||
// SourceContext indicates whether the source key is read from span attributes or resource attributes.
|
||||
type SourceContext string
|
||||
|
||||
const (
|
||||
SourceContextAttribute SourceContext = "attribute"
|
||||
SourceContextResource SourceContext = "resource"
|
||||
)
|
||||
|
||||
func (SourceContext) Enum() []any {
|
||||
return []any{SourceContextAttribute, SourceContextResource}
|
||||
}
|
||||
|
||||
// MapperSource describes one candidate source for a target attribute.
|
||||
type MapperSource struct {
|
||||
// Key is the span/resource attribute key to read from.
|
||||
Key string `json:"key"`
|
||||
// Context indicates whether to read from span attributes or resource attributes.
|
||||
Context SourceContext `json:"context"`
|
||||
// Operation determines whether to move or copy the source value.
|
||||
Operation MapperOperation `json:"operation"`
|
||||
// Priority controls the evaluation order; lower value = higher priority.
|
||||
Priority int `json:"priority"`
|
||||
}
|
||||
|
||||
// MapperConfig holds the mapping logic for a single target attribute.
|
||||
// It implements driver.Valuer and sql.Scanner for JSON text column storage.
|
||||
type MapperConfig struct {
|
||||
Sources []MapperSource `json:"sources"`
|
||||
}
|
||||
|
||||
func (m MapperConfig) Value() (driver.Value, error) {
|
||||
b, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func (m *MapperConfig) Scan(src any) error {
|
||||
var raw []byte
|
||||
switch v := src.(type) {
|
||||
case string:
|
||||
raw = []byte(v)
|
||||
case []byte:
|
||||
raw = v
|
||||
case nil:
|
||||
*m = MapperConfig{}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("aio11ymappingtypes: cannot scan %T into MapperConfig", src)
|
||||
}
|
||||
return json.Unmarshal(raw, m)
|
||||
}
|
||||
|
||||
// Mapper is the domain model for a span attribute mapper.
|
||||
type Mapper struct {
|
||||
types.TimeAuditable
|
||||
types.UserAuditable
|
||||
|
||||
ID string
|
||||
OrgID valuer.UUID
|
||||
GroupID valuer.UUID
|
||||
Name string
|
||||
FieldContext FieldContext
|
||||
Config MapperConfig
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// NewMapperFromStorable converts a StorableMapper to a Mapper.
|
||||
func NewMapperFromStorable(s *StorableMapper) *Mapper {
|
||||
return &Mapper{
|
||||
TimeAuditable: s.TimeAuditable,
|
||||
UserAuditable: s.UserAuditable,
|
||||
ID: s.ID.StringValue(),
|
||||
OrgID: s.OrgID,
|
||||
GroupID: s.GroupID,
|
||||
Name: s.Name,
|
||||
FieldContext: s.FieldContext,
|
||||
Config: s.Config,
|
||||
Enabled: s.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
// NewMappersFromStorable converts a slice of StorableMapper to a slice of Mapper.
|
||||
func NewMappersFromStorable(ss []*StorableMapper) []*Mapper {
|
||||
mappers := make([]*Mapper, len(ss))
|
||||
for i, s := range ss {
|
||||
mappers[i] = NewMapperFromStorable(s)
|
||||
}
|
||||
return mappers
|
||||
}
|
||||
|
||||
// GettableMapper is the HTTP response representation of a mapper.
|
||||
type GettableMapper struct {
|
||||
ID string `json:"id" required:"true"`
|
||||
GroupID string `json:"group_id" required:"true"`
|
||||
Name string `json:"name" required:"true"`
|
||||
FieldContext FieldContext `json:"field_context" required:"true"`
|
||||
Config MapperConfig `json:"config" required:"true"`
|
||||
Enabled bool `json:"enabled" required:"true"`
|
||||
CreatedAt time.Time `json:"created_at" required:"true"`
|
||||
UpdatedAt time.Time `json:"updated_at" required:"true"`
|
||||
CreatedBy string `json:"created_by" required:"true"`
|
||||
UpdatedBy string `json:"updated_by" required:"true"`
|
||||
}
|
||||
|
||||
// NewGettableMapper converts a domain Mapper to a GettableMapper.
|
||||
func NewGettableMapper(m *Mapper) *GettableMapper {
|
||||
return &GettableMapper{
|
||||
ID: m.ID,
|
||||
GroupID: m.GroupID.StringValue(),
|
||||
Name: m.Name,
|
||||
FieldContext: m.FieldContext,
|
||||
Config: m.Config,
|
||||
Enabled: m.Enabled,
|
||||
CreatedAt: m.CreatedAt,
|
||||
UpdatedAt: m.UpdatedAt,
|
||||
CreatedBy: m.CreatedBy,
|
||||
UpdatedBy: m.UpdatedBy,
|
||||
}
|
||||
}
|
||||
|
||||
// PostableMapper is the HTTP request body for creating a mapper.
|
||||
type PostableMapper struct {
|
||||
Name string `json:"name" required:"true"`
|
||||
FieldContext FieldContext `json:"field_context" required:"true"`
|
||||
Config MapperConfig `json:"config" required:"true"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
// UpdatableMapper is the HTTP request body for updating a mapper.
|
||||
// All fields are optional; only non-nil fields are applied.
|
||||
type UpdatableMapper struct {
|
||||
FieldContext *FieldContext `json:"field_context,omitempty"`
|
||||
Config *MapperConfig `json:"config,omitempty"`
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
// ListMappersQuery holds optional filter parameters for listing mappers in a group.
|
||||
type ListMappersQuery struct {
|
||||
Enabled *bool `query:"enabled"`
|
||||
}
|
||||
|
||||
// ListMappersResponse is the response for listing mappers within a group.
|
||||
type ListMappersResponse struct {
|
||||
Items []*GettableMapper `json:"items" required:"true" nullable:"true"`
|
||||
}
|
||||
38
pkg/types/aio11ymappingtypes/storable.go
Normal file
38
pkg/types/aio11ymappingtypes/storable.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package aio11ymappingtypes
|
||||
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
// StorableMappingGroup is the bun/DB representation of a span attribute mapping group.
|
||||
type StorableMappingGroup struct {
|
||||
bun.BaseModel `bun:"table:span_attribute_mapping_group,alias:span_attribute_mapping_group"`
|
||||
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
types.UserAuditable
|
||||
|
||||
OrgID valuer.UUID `bun:"org_id,type:text,notnull"`
|
||||
Name string `bun:"name,type:text,notnull"`
|
||||
Category GroupCategory `bun:"category,type:text,notnull"`
|
||||
Condition Condition `bun:"condition,type:text,notnull"`
|
||||
Enabled bool `bun:"enabled,notnull,default:true"`
|
||||
}
|
||||
|
||||
// StorableMapper is the bun/DB representation of a span attribute mapper.
|
||||
type StorableMapper struct {
|
||||
bun.BaseModel `bun:"table:span_mapping_attribute,alias:span_mapping_attribute"`
|
||||
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
types.UserAuditable
|
||||
|
||||
OrgID valuer.UUID `bun:"org_id,type:text,notnull"`
|
||||
GroupID valuer.UUID `bun:"group_id,type:text,notnull"`
|
||||
Name string `bun:"name,type:text,notnull"`
|
||||
FieldContext FieldContext `bun:"field_context,type:text,notnull"`
|
||||
Config MapperConfig `bun:"config,type:text,notnull"`
|
||||
Enabled bool `bun:"enabled,notnull,default:true"`
|
||||
}
|
||||
23
pkg/types/aio11ymappingtypes/store.go
Normal file
23
pkg/types/aio11ymappingtypes/store.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package aio11ymappingtypes
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
// Group operations
|
||||
ListGroups(ctx context.Context, orgID valuer.UUID, q *ListMappingGroupsQuery) ([]*StorableMappingGroup, error)
|
||||
GetGroup(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*StorableMappingGroup, error)
|
||||
CreateGroup(ctx context.Context, group *StorableMappingGroup) error
|
||||
UpdateGroup(ctx context.Context, group *StorableMappingGroup) error
|
||||
DeleteGroup(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
||||
|
||||
// Mapper operations
|
||||
ListMappers(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, q *ListMappersQuery) ([]*StorableMapper, error)
|
||||
GetMapper(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, id valuer.UUID) (*StorableMapper, error)
|
||||
CreateMapper(ctx context.Context, mapper *StorableMapper) error
|
||||
UpdateMapper(ctx context.Context, mapper *StorableMapper) error
|
||||
DeleteMapper(ctx context.Context, orgID valuer.UUID, groupID valuer.UUID, id valuer.UUID) error
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package aio11ypricingruletypes
|
||||
|
||||
import "github.com/SigNoz/signoz/pkg/errors"
|
||||
|
||||
var (
|
||||
ErrCodePricingRuleNotFound = errors.MustNewCode("pricing_rule_not_found")
|
||||
ErrCodePricingRuleAlreadyExists = errors.MustNewCode("pricing_rule_already_exists")
|
||||
ErrCodePricingRuleInvalidInput = errors.MustNewCode("pricing_rule_invalid_input")
|
||||
)
|
||||
@@ -1,91 +0,0 @@
|
||||
package aio11ypricingruletypes
|
||||
|
||||
import "time"
|
||||
|
||||
// GettablePricingRule is the HTTP response representation of a pricing rule.
|
||||
type GettablePricingRule struct {
|
||||
ID string `json:"id" required:"true"`
|
||||
Model string `json:"model_name" required:"true"`
|
||||
ModelPattern []string `json:"model_pattern" required:"true"`
|
||||
Unit Unit `json:"unit" required:"true"`
|
||||
CacheMode CacheMode `json:"cache_mode" required:"true"`
|
||||
CostInput float64 `json:"cost_input" required:"true"`
|
||||
CostOutput float64 `json:"cost_output" required:"true"`
|
||||
CostCacheRead float64 `json:"cost_cache_read" required:"true"`
|
||||
CostCacheWrite float64 `json:"cost_cache_write" required:"true"`
|
||||
IsOverride bool `json:"is_override" required:"true"`
|
||||
SyncedAt *time.Time `json:"synced_at,omitempty"`
|
||||
Enabled bool `json:"enabled" required:"true"`
|
||||
CreatedAt time.Time `json:"created_at" required:"true"`
|
||||
UpdatedAt time.Time `json:"updated_at" required:"true"`
|
||||
CreatedBy string `json:"created_by" required:"true"`
|
||||
UpdatedBy string `json:"updated_by" required:"true"`
|
||||
}
|
||||
|
||||
// NewGettablePricingRule converts a domain PricingRule to a GettablePricingRule.
|
||||
func NewGettablePricingRule(r *PricingRule) *GettablePricingRule {
|
||||
pattern := make([]string, len(r.ModelPattern))
|
||||
copy(pattern, r.ModelPattern)
|
||||
|
||||
return &GettablePricingRule{
|
||||
ID: r.ID,
|
||||
Model: r.Model,
|
||||
ModelPattern: pattern,
|
||||
Unit: r.Unit,
|
||||
CacheMode: r.CacheMode,
|
||||
CostInput: r.CostInput,
|
||||
CostOutput: r.CostOutput,
|
||||
CostCacheRead: r.CostCacheRead,
|
||||
CostCacheWrite: r.CostCacheWrite,
|
||||
IsOverride: r.IsOverride,
|
||||
SyncedAt: r.SyncedAt,
|
||||
Enabled: r.Enabled,
|
||||
CreatedAt: r.CreatedAt,
|
||||
UpdatedAt: r.UpdatedAt,
|
||||
CreatedBy: r.CreatedBy,
|
||||
UpdatedBy: r.UpdatedBy,
|
||||
}
|
||||
}
|
||||
|
||||
// PostablePricingRule is the HTTP request body for creating a pricing rule.
|
||||
// All fields are required.
|
||||
type PostablePricingRule struct {
|
||||
Model string `json:"model_name" required:"true"`
|
||||
ModelPattern []string `json:"model_pattern" required:"true"`
|
||||
Unit Unit `json:"unit" required:"true"`
|
||||
CacheMode CacheMode `json:"cache_mode" required:"true"`
|
||||
CostInput float64 `json:"cost_input" required:"true"`
|
||||
CostOutput float64 `json:"cost_output" required:"true"`
|
||||
CostCacheRead float64 `json:"cost_cache_read" required:"true"`
|
||||
CostCacheWrite float64 `json:"cost_cache_write" required:"true"`
|
||||
Enabled bool `json:"enabled" required:"true"`
|
||||
}
|
||||
|
||||
// UpdatablePricingRule is the HTTP request body for updating a pricing rule.
|
||||
// All fields are optional; only non-nil fields are applied.
|
||||
type UpdatablePricingRule struct {
|
||||
Model *string `json:"model_name,omitempty"`
|
||||
ModelPattern []string `json:"model_pattern,omitempty"`
|
||||
Unit *Unit `json:"unit,omitempty"`
|
||||
CacheMode *CacheMode `json:"cache_mode,omitempty"`
|
||||
CostInput *float64 `json:"cost_input,omitempty"`
|
||||
CostOutput *float64 `json:"cost_output,omitempty"`
|
||||
CostCacheRead *float64 `json:"cost_cache_read,omitempty"`
|
||||
CostCacheWrite *float64 `json:"cost_cache_write,omitempty"`
|
||||
IsOverride *bool `json:"is_override,omitempty"`
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
// ListPricingRulesQuery holds the pagination parameters for listing pricing rules.
|
||||
type ListPricingRulesQuery struct {
|
||||
Offset int `query:"offset" json:"offset"`
|
||||
Limit int `query:"limit" json:"limit"`
|
||||
}
|
||||
|
||||
// ListPricingRulesResponse is the paginated response for listing pricing rules.
|
||||
type ListPricingRulesResponse struct {
|
||||
Items []*GettablePricingRule `json:"items" required:"true" nullable:"true"`
|
||||
Total int `json:"total" required:"true"`
|
||||
Offset int `json:"offset" required:"true"`
|
||||
Limit int `json:"limit" required:"true"`
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package aio11ypricingruletypes
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type Unit string
|
||||
|
||||
const (
|
||||
UnitPerMillionTokens Unit = "per_million_tokens"
|
||||
)
|
||||
|
||||
func (Unit) Enum() []any {
|
||||
return []any{UnitPerMillionTokens}
|
||||
}
|
||||
|
||||
type CacheMode string
|
||||
|
||||
const (
|
||||
// CacheModeSubtract: cached tokens are inside input_tokens (OpenAI-style).
|
||||
CacheModeSubtract CacheMode = "subtract"
|
||||
// CacheModeAdditive: cached tokens are reported separately (Anthropic-style).
|
||||
CacheModeAdditive CacheMode = "additive"
|
||||
// CacheModeUnknown: provider behaviour is unknown; falls back to subtract.
|
||||
CacheModeUnknown CacheMode = "unknown"
|
||||
)
|
||||
|
||||
func (CacheMode) Enum() []any {
|
||||
return []any{CacheModeSubtract, CacheModeAdditive, CacheModeUnknown}
|
||||
}
|
||||
|
||||
// PricingRule is the domain model for an LLM pricing rule.
|
||||
// It has no serialisation concerns — use GettablePricingRule for HTTP responses.
|
||||
type PricingRule struct {
|
||||
types.TimeAuditable
|
||||
types.UserAuditable
|
||||
|
||||
ID string
|
||||
OrgID valuer.UUID
|
||||
Model string
|
||||
ModelPattern []string
|
||||
Unit Unit
|
||||
CacheMode CacheMode
|
||||
CostInput float64
|
||||
CostOutput float64
|
||||
CostCacheRead float64
|
||||
CostCacheWrite float64
|
||||
// IsOverride marks that cost fields were manually edited.
|
||||
// When true the sync job skips this rule.
|
||||
IsOverride bool
|
||||
SyncedAt *time.Time
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// NewPricingRuleFromStorable converts a StorablePricingRule to a PricingRule.
|
||||
func NewPricingRuleFromStorable(s *StorablePricingRule) *PricingRule {
|
||||
pattern := make([]string, len(s.ModelPattern))
|
||||
copy(pattern, s.ModelPattern)
|
||||
|
||||
return &PricingRule{
|
||||
TimeAuditable: s.TimeAuditable,
|
||||
UserAuditable: s.UserAuditable,
|
||||
ID: s.ID.StringValue(),
|
||||
OrgID: s.OrgID,
|
||||
Model: s.Model,
|
||||
ModelPattern: pattern,
|
||||
Unit: s.Unit,
|
||||
CacheMode: s.CacheMode,
|
||||
CostInput: s.CostInput,
|
||||
CostOutput: s.CostOutput,
|
||||
CostCacheRead: s.CostCacheRead,
|
||||
CostCacheWrite: s.CostCacheWrite,
|
||||
IsOverride: s.IsOverride,
|
||||
SyncedAt: s.SyncedAt,
|
||||
Enabled: s.Enabled,
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package aio11ypricingruletypes
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
// StringSlice is a []string that is stored as a JSON text column.
|
||||
// It is compatible with both SQLite and PostgreSQL.
|
||||
type StringSlice []string
|
||||
|
||||
func (s StringSlice) Value() (driver.Value, error) {
|
||||
if s == nil {
|
||||
return "[]", nil
|
||||
}
|
||||
b, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func (s *StringSlice) Scan(src any) error {
|
||||
var raw []byte
|
||||
switch v := src.(type) {
|
||||
case string:
|
||||
raw = []byte(v)
|
||||
case []byte:
|
||||
raw = v
|
||||
case nil:
|
||||
*s = nil
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("aio11ypricingruletypes: cannot scan %T into StringSlice", src)
|
||||
}
|
||||
return json.Unmarshal(raw, s)
|
||||
}
|
||||
|
||||
// StorablePricingRule is the bun/DB representation of an LLM pricing rule.
|
||||
type StorablePricingRule struct {
|
||||
bun.BaseModel `bun:"table:llm_pricing_rules,alias:llm_pricing_rules"`
|
||||
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
types.UserAuditable
|
||||
|
||||
OrgID valuer.UUID `bun:"org_id,type:text,notnull"`
|
||||
Model string `bun:"model,type:text,notnull"`
|
||||
ModelPattern StringSlice `bun:"model_pattern,type:text,notnull"`
|
||||
Unit Unit `bun:"unit,type:text,notnull"`
|
||||
CacheMode CacheMode `bun:"cache_mode,type:text,notnull"`
|
||||
CostInput float64 `bun:"cost_input,notnull"`
|
||||
CostOutput float64 `bun:"cost_output,notnull"`
|
||||
CostCacheRead float64 `bun:"cost_cache_read,notnull"`
|
||||
CostCacheWrite float64 `bun:"cost_cache_write,notnull"`
|
||||
// IsOverride marks that cost fields were manually edited.
|
||||
// When true the sync job skips this rule.
|
||||
IsOverride bool `bun:"is_override,notnull,default:false"`
|
||||
// SourceConfig holds the last upstream pricing snapshot; used to revert
|
||||
// when IsOverride is cleared.
|
||||
SourceConfig string `bun:"source_config,type:text,notnull,default:'{}'"`
|
||||
SyncedAt *time.Time `bun:"synced_at"`
|
||||
Enabled bool `bun:"enabled,notnull,default:true"`
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package aio11ypricingruletypes
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
List(ctx context.Context, orgID valuer.UUID, offset, limit int) ([]*StorablePricingRule, int, error)
|
||||
|
||||
Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*StorablePricingRule, error)
|
||||
|
||||
Create(ctx context.Context, rule *StorablePricingRule) error
|
||||
|
||||
Update(ctx context.Context, rule *StorablePricingRule) error
|
||||
|
||||
Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
||||
}
|
||||
Reference in New Issue
Block a user