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...) }