6c92f85d10
Bring the Nexus/Praxis/Hexis integration in line with MAVEN_ECOSYSTEM_ARCHITECTURE.md: - Praxis over HTTP: drop the in-process praxis.db open (praxisstore/ praxistools) and call praxisd's /api/v1/tools/* API via a new praxisClient. Honors the "no component reads another's DB" invariant (AC#12). PraxisConfig.DBPath -> URL. - Hexis confirmation gate: mutating capabilities (ReadOnly=false) now park a bound pendingHexis confirmation and require a spoken "да" before executing; read-only run immediately (AC#7, no auto attention->action). - Capability safety: >1 verb match is ambiguous -> ask instead of firing the first; ambiguous Nexus resolution asks for clarification (AC#2). - Correlation IDs on Hexis execute, recorded in the cross-service trace. - Bug: importance arrives as JSON float64 over HTTP, not int. - Tests: confirm-gate, decline, read-only, and ambiguity paths. Build: vendor/ bakes in the hexis client (replace-directed at a sibling repo outside the Docker context); Dockerfile builds from vendor and no longer `go mod download`s the unreachable replace paths. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
package cron
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// DefaultLogger is used by Cron if none is specified.
|
|
var DefaultLogger Logger = PrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))
|
|
|
|
// DiscardLogger can be used by callers to discard all log messages.
|
|
var DiscardLogger Logger = PrintfLogger(log.New(ioutil.Discard, "", 0))
|
|
|
|
// Logger is the interface used in this package for logging, so that any backend
|
|
// can be plugged in. It is a subset of the github.com/go-logr/logr interface.
|
|
type Logger interface {
|
|
// Info logs routine messages about cron's operation.
|
|
Info(msg string, keysAndValues ...interface{})
|
|
// Error logs an error condition.
|
|
Error(err error, msg string, keysAndValues ...interface{})
|
|
}
|
|
|
|
// PrintfLogger wraps a Printf-based logger (such as the standard library "log")
|
|
// into an implementation of the Logger interface which logs errors only.
|
|
func PrintfLogger(l interface{ Printf(string, ...interface{}) }) Logger {
|
|
return printfLogger{l, false}
|
|
}
|
|
|
|
// VerbosePrintfLogger wraps a Printf-based logger (such as the standard library
|
|
// "log") into an implementation of the Logger interface which logs everything.
|
|
func VerbosePrintfLogger(l interface{ Printf(string, ...interface{}) }) Logger {
|
|
return printfLogger{l, true}
|
|
}
|
|
|
|
type printfLogger struct {
|
|
logger interface{ Printf(string, ...interface{}) }
|
|
logInfo bool
|
|
}
|
|
|
|
func (pl printfLogger) Info(msg string, keysAndValues ...interface{}) {
|
|
if pl.logInfo {
|
|
keysAndValues = formatTimes(keysAndValues)
|
|
pl.logger.Printf(
|
|
formatString(len(keysAndValues)),
|
|
append([]interface{}{msg}, keysAndValues...)...)
|
|
}
|
|
}
|
|
|
|
func (pl printfLogger) Error(err error, msg string, keysAndValues ...interface{}) {
|
|
keysAndValues = formatTimes(keysAndValues)
|
|
pl.logger.Printf(
|
|
formatString(len(keysAndValues)+2),
|
|
append([]interface{}{msg, "error", err}, keysAndValues...)...)
|
|
}
|
|
|
|
// formatString returns a logfmt-like format string for the number of
|
|
// key/values.
|
|
func formatString(numKeysAndValues int) string {
|
|
var sb strings.Builder
|
|
sb.WriteString("%s")
|
|
if numKeysAndValues > 0 {
|
|
sb.WriteString(", ")
|
|
}
|
|
for i := 0; i < numKeysAndValues/2; i++ {
|
|
if i > 0 {
|
|
sb.WriteString(", ")
|
|
}
|
|
sb.WriteString("%v=%v")
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
// formatTimes formats any time.Time values as RFC3339.
|
|
func formatTimes(keysAndValues []interface{}) []interface{} {
|
|
var formattedArgs []interface{}
|
|
for _, arg := range keysAndValues {
|
|
if t, ok := arg.(time.Time); ok {
|
|
arg = t.Format(time.RFC3339)
|
|
}
|
|
formattedArgs = append(formattedArgs, arg)
|
|
}
|
|
return formattedArgs
|
|
}
|