ariadne/internal/domain/errorrecord/event.go
2026-07-24 05:45:04 +09:00

96 lines
2.8 KiB
Go

package errorrecord
import (
"errors"
"fmt"
"strings"
"time"
"git.toki-labs.com/toki/ariadne/internal/domain/organization"
"github.com/google/uuid"
)
const SchemaVersionV1 = "ariadne.error-event.v1"
// Event is Ariadne's normalized domain representation of an incoming error.
// OrganizationID, ProjectID and IngestionSourceID are resolved from
// authenticated ingestion credentials and are intentionally not part of the
// external error-event payload.
type Event struct {
SchemaVersion string
EventID string
OrganizationID organization.ID
ProjectID string
IngestionSourceID string
OccurredAt time.Time
Source Source
Error ErrorDetail
Runtime *Runtime
Fingerprint string
Labels map[string]string
}
type Source struct {
System string
Service string
Environment string
Component string
}
type ErrorDetail struct {
Type string
Code string
Message string
StackTrace string
Cause string
}
type Runtime struct {
Host string
Process string
Version string
CommitSHA string
}
func (event Event) Validate() error {
var validationErrors []error
if event.SchemaVersion != SchemaVersionV1 {
validationErrors = append(validationErrors, fmt.Errorf("unsupported schema version %q", event.SchemaVersion))
}
if strings.TrimSpace(event.EventID) == "" {
validationErrors = append(validationErrors, errors.New("event id is required"))
}
if err := event.OrganizationID.Validate(); err != nil {
validationErrors = append(validationErrors, fmt.Errorf("organization id: %w", err))
}
if _, err := uuid.Parse(event.ProjectID); err != nil {
validationErrors = append(validationErrors, fmt.Errorf("project id: %w", err))
}
if _, err := uuid.Parse(event.IngestionSourceID); err != nil {
validationErrors = append(
validationErrors,
fmt.Errorf("ingestion source id: %w", err),
)
}
if event.OccurredAt.IsZero() {
validationErrors = append(validationErrors, errors.New("occurred at is required"))
}
if strings.TrimSpace(event.Source.System) == "" {
validationErrors = append(validationErrors, errors.New("source system is required"))
}
if strings.TrimSpace(event.Source.Service) == "" {
validationErrors = append(validationErrors, errors.New("source service is required"))
}
if strings.TrimSpace(event.Source.Environment) == "" {
validationErrors = append(validationErrors, errors.New("source environment is required"))
}
if strings.TrimSpace(event.Error.Type) == "" {
validationErrors = append(validationErrors, errors.New("error type is required"))
}
if strings.TrimSpace(event.Error.Message) == "" {
validationErrors = append(validationErrors, errors.New("error message is required"))
}
return errors.Join(validationErrors...)
}