mirror of
https://github.com/hanzoai/insights-go.git
synced 2026-09-30 22:46:12 +00:00
Rename Go package from posthog to insights across all 80+ files. Consumers now import as `insights "github.com/hanzoai/insights-go"` and use insights.Client, insights.Config, insights.Capture, etc. - Rename posthog.go -> insights.go, posthog_test.go -> insights_test.go - Update package declaration from posthog to insights in all .go files - Update SDKName from posthog-go to insights-go - Update DefaultEndpoint from app.posthog.com to insights.hanzo.ai - Update all FieldError/ConfigError type strings - Update User-Agent headers, log prefixes, comments, and docs - Update JSON test fixtures to match new SDK name - Update CLI, examples, extras, and sdk_compliance_adapter - Fix pre-existing go vet warnings (non-constant format strings)
80 lines
2.4 KiB
Go
80 lines
2.4 KiB
Go
package insights
|
||
|
||
import (
|
||
"fmt"
|
||
"path/filepath"
|
||
"runtime"
|
||
"strings"
|
||
)
|
||
|
||
// InAppDecider reports whether a stack frame should be considered “in-app”
|
||
// (i.e., part of the calling application’s own code) as opposed to external
|
||
// dependencies, standard library, or tooling internals. The UI can use this
|
||
// signal to visually emphasize frames that are likely actionable.
|
||
type InAppDecider func(frame runtime.Frame) bool
|
||
|
||
// SimpleInAppDecider a naive implementation of InAppDecider which checks the file paths.
|
||
// It's good enough for 90% of the cases.
|
||
func SimpleInAppDecider(frame runtime.Frame) bool {
|
||
f := frame.File
|
||
sep := string(filepath.Separator)
|
||
|
||
if strings.Contains(f, "pkg/mod/golang.org/toolchain") ||
|
||
strings.Contains(f, fmt.Sprintf("%[1]svendor%[1]s", sep)) ||
|
||
strings.Contains(f, fmt.Sprintf("%[1]spkg%[1]smod%[1]s", sep)) {
|
||
return false
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
// StackTraceExtractor produces a stack trace for the current goroutine to
|
||
// enrich captured exceptions with call-site context.
|
||
type StackTraceExtractor interface {
|
||
// GetStackTrace returns an Insights-compatible stack trace.
|
||
//
|
||
// The skip parameter controls how many leading frames to omit before
|
||
// recording. Use it to drop extractor/logging internals and start at the
|
||
// application call site. For example, a skip of 3–5 is typically enough to
|
||
// hide wrapper layers when called from a slog handler.
|
||
GetStackTrace(skip int) *ExceptionStacktrace
|
||
}
|
||
|
||
// DefaultStackTraceExtractor is provided by default as a sane / simple implementation
|
||
// of a StackTraceExtractor. It should be enough for most use cases, however, you're free to
|
||
// create your own implementation if you require more flexibility.
|
||
type DefaultStackTraceExtractor struct {
|
||
InAppDecider InAppDecider
|
||
}
|
||
|
||
func (d DefaultStackTraceExtractor) GetStackTrace(skip int) *ExceptionStacktrace {
|
||
pcs := make([]uintptr, 64)
|
||
stackCallCount := runtime.Callers(skip, pcs)
|
||
frames := runtime.CallersFrames(pcs[:stackCallCount])
|
||
|
||
traces := make([]StackFrame, 0, stackCallCount)
|
||
for {
|
||
frame, hasMore := frames.Next()
|
||
if frame == *new(runtime.Frame) {
|
||
break
|
||
}
|
||
|
||
traces = append(traces, StackFrame{
|
||
Filename: frame.File,
|
||
LineNo: frame.Line,
|
||
Function: frame.Function,
|
||
InApp: d.InAppDecider(frame),
|
||
Synthetic: false,
|
||
Platform: "go",
|
||
})
|
||
if !hasMore {
|
||
break
|
||
}
|
||
}
|
||
|
||
return &ExceptionStacktrace{
|
||
Type: "raw",
|
||
Frames: traces,
|
||
}
|
||
}
|