-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherror_template.go
More file actions
125 lines (111 loc) · 3.24 KB
/
error_template.go
File metadata and controls
125 lines (111 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package errors
// ErrorTemplate defines a reusable error blueprint that includes metadata
// and custom key-value fields. It is designed for creating structured errors
// with consistent attributes such as severity and HTTP status code.
type ErrorTemplate struct {
// metadata contains the error's metadata (message, severity, status code, etc.).
metadata
// fields holds the error's custom key-value pairs.
fields map[string]any
}
// Template returns a new ErrorTemplate initialized with the given message.
// It can be extended with additional attributes and reused to create
// multiple error instances.
func Template(msg string) *ErrorTemplate {
return &ErrorTemplate{
metadata: metadata{
message: msg,
},
}
}
// Error returns the error message from the template.
func (et *ErrorTemplate) Error() string {
return et.message
}
// toError converts the ErrorTemplate to an Error instance.
func (et *ErrorTemplate) toError() *Error {
return &Error{
metadata: et.metadata,
fields: cloneMap(et.fields),
}
}
// Wrap wraps an existing error with the ErrorTemplate's metadata and fields.
// It supports wrapping both ErrorTemplate and Error types,
// preserving their fields and stack trace.
func (et *ErrorTemplate) Wrap(err error) *Error {
switch x := err.(type) {
case *ErrorTemplate:
return &Error{
metadata: et.metadata,
fields: cloneMap(et.fields),
pureWrapper: true,
err: err,
stack: DefaultCallerFrames(3),
}
case *Error:
res := Error{
metadata: et.metadata,
fields: cloneMap(et.fields),
pureWrapper: true,
err: err,
}
if x.stack != nil {
res.stack = x.stack
} else {
res.stack = DefaultCallerFrames(3)
}
if len(x.fields) > 0 {
if res.fields == nil {
res.fields = make(map[string]interface{}, len(x.fields))
}
for k, v := range x.fields {
res.fields[k] = v
}
}
return &res
}
return &Error{
metadata: et.metadata,
pureWrapper: true,
err: err,
fields: cloneMap(et.fields),
stack: DefaultCallerFrames(3),
}
}
// New creates a new Error instance using the template's metadata and fields.
// A new stack trace is captured at the point of the call.
func (et *ErrorTemplate) New() *Error {
return &Error{
metadata: et.metadata,
fields: cloneMap(et.fields),
stack: CallerFramesFunc(1),
}
}
// Set adds a custom key-value pair to the template's fields.
func (et *ErrorTemplate) Set(key string, value any) *ErrorTemplate {
if et.fields == nil {
et.fields = make(map[string]any)
}
et.fields[key] = value
return et
}
// Code sets an application-specific error code on the template.
func (et *ErrorTemplate) Code(code string) *ErrorTemplate {
et.code = code
return et
}
// Severity sets the severity level for the error template.
func (et *ErrorTemplate) Severity(severity SeverityLevel) *ErrorTemplate {
et.severity = severity
return et
}
// StatusCode sets the HTTP status code associated with the error.
func (et *ErrorTemplate) StatusCode(statusCode int) *ErrorTemplate {
et.statusCode = statusCode
return et
}
// Protected marks the error as protected, indicating it should not be exposed externally.
func (et *ErrorTemplate) Protected(protected bool) *ErrorTemplate {
et.protected = protected
return et
}