Files
PandeyandGitHub 472f898a5b refactor(ledger): extract domain primitives and centralize tracking (#113)
## Summary

- Extract \`DistinctID\`, \`Event\`, and \`Properties\` value objects
from \`internal/ledger\` into \`internal/domain\` so they can be reused
without coupling callers to ledger orchestration. Move the analytics
serializer to \`api/v1alpha1\` as \`Casting.TrackableProperties()\`.
Tighten \`Ledger.Track\` to take \`domain.Event\` and
\`domain.Properties\`.
- Add \`cmd/foundryctl/root.go\` with shared
\`rootLogger\`/\`rootTracker\` initialized via \`PersistentPreRunE\`,
plus \`recoverRunE\` — a wrapper that converts panics to \`TypeFatal\`
errors and centralizes log + ledger tracking of success/failure for
every command. Each \`runX\` collapses to \`(domain.Properties, error)\`
with no in-function tracking.
- Add \`WithStacktrace\` on \`*base\` errors so the recovered panic
stack flows through the existing \`LogAttr\` machinery.
2026-05-04 23:36:04 +05:30

46 lines
1.0 KiB
Go

package errors
import (
"fmt"
"runtime"
"strings"
)
// stacktrace holds a snapshot of program counters.
type stacktrace []uintptr
// newStackTrace captures a stack trace, skipping 3 frames to record the
// snapshot at the origin of the error:
// 1. runtime.Callers
// 2. newStackTrace
// 3. the constructor (New, Newf, Wrapf, Wrap)
//
// Inspired by https://github.com/thanos-io/thanos/blob/main/pkg/errors/stacktrace.go
func newStackTrace() stacktrace {
const depth = 16
pc := make([]uintptr, depth)
n := runtime.Callers(3, pc)
return stacktrace(pc[:n:n])
}
// String formats the stacktrace as function/file/line pairs.
func (s stacktrace) String() string {
var buf strings.Builder
frames := runtime.CallersFrames(s)
for {
frame, more := frames.Next()
fmt.Fprintf(&buf, "%s\n\t%s:%d\n", frame.Function, frame.File, frame.Line)
if !more {
break
}
}
return buf.String()
}
// rawStacktrace holds a pre-formatted stacktrace string.
type rawStacktrace string
func (r rawStacktrace) String() string {
return string(r)
}