Files
notarius/internal/framework/pipeline/diagnostics.go

125 lines
4.4 KiB
Go

package pipeline
import (
"fmt"
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
frameworkdiagnostics "gitea.maximumdirect.net/eric/notarius/internal/framework/diagnostics"
)
func terminalDiagnosticGroups(terminal producerAttemptTerminal, origin contracts.DiagnosticOrigin, chunk *source.Chunk) ([]contracts.DiagnosticGroup, error) {
return promoteCheckpointDiagnostics(terminalCheckpointDiagnostics(terminal), origin, chunk)
}
func terminalCheckpointDiagnostics(terminal producerAttemptTerminal) []CheckpointDiagnostic {
diagnostics := make([]CheckpointDiagnostic, 0, len(terminal.Diagnostics))
for _, diagnostic := range terminal.Diagnostics {
diagnostics = append(diagnostics, CheckpointDiagnostic{Diagnostic: diagnostic})
}
for _, record := range terminal.Validation.Diagnostics() {
diagnostics = append(diagnostics, CheckpointDiagnostic{Diagnostic: record.diagnostic, ValidatorKey: record.validatorName})
}
if terminal.Action == producerTerminalIncompleteAccepted {
for _, record := range incompleteValidationDiagnostics(terminal.Validation) {
diagnostics = append(diagnostics, CheckpointDiagnostic{Diagnostic: record.diagnostic, ValidatorKey: record.validatorName})
}
}
return cloneCheckpointDiagnostics(diagnostics)
}
func promoteCheckpointDiagnostics(diagnostics []CheckpointDiagnostic, origin contracts.DiagnosticOrigin, chunk *source.Chunk) ([]contracts.DiagnosticGroup, error) {
groups := make([]contracts.DiagnosticGroup, 0, len(diagnostics))
for _, record := range diagnostics {
validatorOrigin := origin
validatorOrigin.ValidatorKey = record.ValidatorKey
promoted, err := promoteProducerDiagnostics([]contracts.ProducerDiagnostic{record.Diagnostic}, validatorOrigin, chunk)
if err != nil {
return nil, fmt.Errorf("checkpoint diagnostic: %w", err)
}
groups = append(groups, promoted...)
}
return groups, nil
}
func cloneCheckpointDiagnostics(diagnostics []CheckpointDiagnostic) []CheckpointDiagnostic {
if len(diagnostics) == 0 {
return nil
}
cloned := make([]CheckpointDiagnostic, len(diagnostics))
for index, diagnostic := range diagnostics {
cloned[index] = CheckpointDiagnostic{
Diagnostic: contracts.CloneProducerDiagnostics([]contracts.ProducerDiagnostic{diagnostic.Diagnostic})[0],
ValidatorKey: diagnostic.ValidatorKey,
}
}
return cloned
}
func promoteProducerDiagnostics(diagnostics []contracts.ProducerDiagnostic, origin contracts.DiagnosticOrigin, chunk *source.Chunk) ([]contracts.DiagnosticGroup, error) {
if err := contracts.ValidateProducerDiagnostics(diagnostics); err != nil {
return nil, err
}
if len(diagnostics) == 0 {
return nil, nil
}
groups := make([]contracts.DiagnosticGroup, len(diagnostics))
for index, diagnostic := range diagnostics {
group := contracts.DiagnosticGroup{
Disposition: diagnostic.Disposition,
Category: diagnostic.Category,
ReasonCode: diagnostic.ReasonCode,
Origin: origin,
OccurrenceCount: diagnostic.OccurrenceCount,
Samples: cloneDiagnosticSamples(diagnostic.Samples, chunk),
OmittedSampleCount: diagnostic.OmittedSampleCount,
}
if err := group.Validate(); err != nil {
return nil, err
}
groups[index] = group
}
return groups, nil
}
func cloneDiagnosticSamples(samples []contracts.DiagnosticSample, chunk *source.Chunk) []contracts.DiagnosticSample {
if len(samples) == 0 {
return nil
}
cloned := make([]contracts.DiagnosticSample, len(samples))
for index, sample := range samples {
if chunk != nil {
chunkIndex := chunk.Index
sample.ChunkID = chunk.ID
sample.ChunkIndex = &chunkIndex
} else if sample.ChunkIndex != nil {
chunkIndex := *sample.ChunkIndex
sample.ChunkIndex = &chunkIndex
}
cloned[index] = sample
}
return cloned
}
func appendDiagnosticGroups(output *RunOutput, groups []contracts.DiagnosticGroup) {
if output == nil || len(groups) == 0 {
return
}
cloned := contracts.CloneDiagnosticCollection(contracts.DiagnosticCollection{Groups: groups}).Groups
output.diagnosticGroups = append(output.diagnosticGroups, cloned...)
}
func finalizeDiagnostics(output *RunOutput) error {
if output == nil {
return nil
}
aggregator := frameworkdiagnostics.Aggregator{}
for _, group := range output.diagnosticGroups {
if err := aggregator.Add(group); err != nil {
return err
}
}
output.Diagnostics = aggregator.Collection()
return nil
}