mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-30 09:38:26 -05:00
Bumps [github.com/olekukonko/tablewriter](https://github.com/olekukonko/tablewriter) from 0.0.5 to 1.0.6. - [Commits](https://github.com/olekukonko/tablewriter/compare/v0.0.5...v1.0.6) --- updated-dependencies: - dependency-name: github.com/olekukonko/tablewriter dependency-version: 1.0.6 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
154 lines
4.1 KiB
Go
154 lines
4.1 KiB
Go
// Package errors provides utility functions for error handling, including stack
|
||
// trace capture and function name extraction.
|
||
package errors
|
||
|
||
import (
|
||
"database/sql"
|
||
"fmt"
|
||
"reflect"
|
||
"runtime"
|
||
"strings"
|
||
)
|
||
|
||
// captureStack captures a stack trace with the configured depth.
|
||
// Skip=0 captures the current call site; skips captureStack and its caller (+2 frames); thread-safe via stackPool.
|
||
func captureStack(skip int) []uintptr {
|
||
buf := stackPool.Get().([]uintptr)
|
||
buf = buf[:cap(buf)]
|
||
|
||
// +2 to skip captureStack and the immediate caller
|
||
n := runtime.Callers(skip+2, buf)
|
||
if n == 0 {
|
||
stackPool.Put(buf)
|
||
return nil
|
||
}
|
||
|
||
// Create a new slice to return, avoiding direct use of pooled memory
|
||
stack := make([]uintptr, n)
|
||
copy(stack, buf[:n])
|
||
stackPool.Put(buf)
|
||
|
||
return stack
|
||
}
|
||
|
||
// min returns the smaller of two integers.
|
||
// Simple helper for limiting stack trace size or other comparisons.
|
||
func min(a, b int) int {
|
||
if a < b {
|
||
return a
|
||
}
|
||
return b
|
||
}
|
||
|
||
// clearMap removes all entries from a map.
|
||
// Helper function to reset map contents without reallocating.
|
||
func clearMap(m map[string]interface{}) {
|
||
for k := range m {
|
||
delete(m, k)
|
||
}
|
||
}
|
||
|
||
// sqlNull detects if a value represents a SQL NULL type.
|
||
// Returns true for nil or invalid sql.Null* types (e.g., NullString, NullInt64); false otherwise.
|
||
func sqlNull(v interface{}) bool {
|
||
if v == nil {
|
||
return true
|
||
}
|
||
|
||
switch val := v.(type) {
|
||
case sql.NullString:
|
||
return !val.Valid
|
||
case sql.NullTime:
|
||
return !val.Valid
|
||
case sql.NullInt64:
|
||
return !val.Valid
|
||
case sql.NullBool:
|
||
return !val.Valid
|
||
case sql.NullFloat64:
|
||
return !val.Valid
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
// getFuncName extracts the function name from an interface, typically a function or method.
|
||
// Returns "unknown" if the input is nil or invalid; trims leading dots from runtime name.
|
||
func getFuncName(fn interface{}) string {
|
||
if fn == nil {
|
||
return "unknown"
|
||
}
|
||
fullName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
|
||
return strings.TrimPrefix(fullName, ".")
|
||
}
|
||
|
||
// isInternalFrame determines if a stack frame is considered "internal".
|
||
// Returns true for frames from runtime, reflect, or this package’s subdirectories if FilterInternal is true.
|
||
func isInternalFrame(frame runtime.Frame) bool {
|
||
if strings.HasPrefix(frame.Function, "runtime.") || strings.HasPrefix(frame.Function, "reflect.") {
|
||
return true
|
||
}
|
||
|
||
suffixes := []string{
|
||
"errors",
|
||
"utils",
|
||
"helper",
|
||
"retry",
|
||
"multi",
|
||
}
|
||
|
||
file := frame.File
|
||
for _, v := range suffixes {
|
||
if strings.Contains(file, fmt.Sprintf("github.com/olekukonko/errors/%s", v)) {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// FormatError returns a formatted string representation of an error.
|
||
// Includes message, name, context, stack trace, and cause for *Error types; just message for others; "<nil>" if nil.
|
||
func FormatError(err error) string {
|
||
if err == nil {
|
||
return "<nil>"
|
||
}
|
||
var sb strings.Builder
|
||
if e, ok := err.(*Error); ok {
|
||
sb.WriteString(fmt.Sprintf("Error: %s\n", e.Error()))
|
||
if e.name != "" {
|
||
sb.WriteString(fmt.Sprintf("Name: %s\n", e.name))
|
||
}
|
||
if ctx := e.Context(); len(ctx) > 0 {
|
||
sb.WriteString("Context:\n")
|
||
for k, v := range ctx {
|
||
sb.WriteString(fmt.Sprintf("\t%s: %v\n", k, v))
|
||
}
|
||
}
|
||
if stack := e.Stack(); len(stack) > 0 {
|
||
sb.WriteString("Stack Trace:\n")
|
||
for _, frame := range stack {
|
||
sb.WriteString(fmt.Sprintf("\t%s\n", frame))
|
||
}
|
||
}
|
||
if e.cause != nil {
|
||
sb.WriteString(fmt.Sprintf("Caused by: %s\n", FormatError(e.cause)))
|
||
}
|
||
} else {
|
||
sb.WriteString(fmt.Sprintf("Error: %s\n", err.Error()))
|
||
}
|
||
return sb.String()
|
||
}
|
||
|
||
// Caller returns the file, line, and function name of the caller at the specified skip level.
|
||
// Skip=0 returns the caller of this function, 1 returns its caller, etc.; returns "unknown" if no caller found.
|
||
func Caller(skip int) (file string, line int, function string) {
|
||
configMu.RLock()
|
||
defer configMu.RUnlock()
|
||
var pcs [1]uintptr
|
||
n := runtime.Callers(skip+2, pcs[:]) // +2 skips Caller and its immediate caller
|
||
if n == 0 {
|
||
return "", 0, "unknown"
|
||
}
|
||
frame, _ := runtime.CallersFrames(pcs[:n]).Next()
|
||
return frame.File, frame.Line, frame.Function
|
||
}
|