blob: 33ef71ef42d741577bf61c66b7bdbf11ac078f1c [file] [log] [blame]
David K. Bainbridge794735f2020-02-11 21:01:37 -08001/*
2 * Copyright 2020-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Thomas Lee S94109f12020-03-03 16:39:29 +053017//Package olterrors implements functions to manipulate OLT errors
18package olterrors
David K. Bainbridge794735f2020-02-11 21:01:37 -080019
20import (
21 "encoding/json"
22 "fmt"
23 "github.com/opencord/voltha-lib-go/v3/pkg/log"
24 "strings"
25)
26
27const (
28 defaultLogAndReturnLevel = log.DebugLevel
29)
30
31func copy(src log.Fields) log.Fields {
32 dst := make(log.Fields)
33 for k, v := range src {
34 dst[k] = v
35 }
36 return dst
37}
38
39func merge(one, two log.Fields) log.Fields {
40 dst := make(log.Fields)
41 for k, v := range one {
42 dst[k] = v
43 }
44 for k, v := range two {
45 dst[k] = v
46 }
47 return dst
48}
49
50// LoggableError defined functions that can be used to log an object
51type LoggableError interface {
52 error
53 Log() error
Rohan Agrawal02f784d2020-02-14 09:34:02 +000054 LogAt(log.LogLevel) error
David K. Bainbridge794735f2020-02-11 21:01:37 -080055}
56
57// ErrAdapter represents a basic adapter error that combines an name, field set
58// and wrapped error
59type ErrAdapter struct {
60 name string
61 fields log.Fields
62 wrapped error
63}
64
65// NewErrAdapter constructs a new error with the given values
66func NewErrAdapter(name string, fields log.Fields, wrapped error) LoggableError {
67 return &ErrAdapter{
68 name: name,
69 fields: copy(fields),
70 wrapped: wrapped,
71 }
72}
73
74// Name returns the error name
75func (e *ErrAdapter) Name() string {
76 return e.name
77}
78
79// Fields returns the fields associated with the error
80func (e *ErrAdapter) Fields() log.Fields {
81 return e.fields
82}
83
84// Unwrap returns the wrapped or nested error
85func (e *ErrAdapter) Unwrap() error {
86 return e.wrapped
87}
88
89// Error returns a string representation of the error
90func (e *ErrAdapter) Error() string {
91 var buf strings.Builder
92 buf.WriteString(e.name)
93 if len(e.fields) > 0 {
94 if val, err := json.Marshal(e.fields); err == nil {
95 buf.WriteString(": [")
96 buf.WriteString(string(val))
97 buf.WriteString("]")
98 }
99 }
100 if e.wrapped != nil {
101 buf.WriteString(": ")
102 buf.WriteString(e.wrapped.Error())
103 }
104 return buf.String()
105}
106
107// Log logs the error at the default level for log and return
108func (e *ErrAdapter) Log() error {
109 return e.LogAt(defaultLogAndReturnLevel)
110}
111
112// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000113func (e *ErrAdapter) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800114 logger := log.Debugw
115 switch level {
116 case log.InfoLevel:
117 logger = log.Infow
118 case log.WarnLevel:
119 logger = log.Warnw
120 case log.ErrorLevel:
121 logger = log.Errorw
122 case log.FatalLevel:
123 logger = log.Fatalw
124 }
125 local := e.fields
126 if e.wrapped != nil {
127 local = merge(e.fields, log.Fields{"wrapped": e.wrapped})
128 }
129 logger(e.name, local)
130 return e
131}
132
133// ErrInvalidValue represents an error condition with given value is not able to
134// be processed
135type ErrInvalidValue struct {
136 ErrAdapter
137}
138
139// NewErrInvalidValue constructs a new error based on the given values
140func NewErrInvalidValue(fields log.Fields, wrapped error) LoggableError {
141 return &ErrInvalidValue{
142 ErrAdapter{
143 name: "invalid-value",
144 fields: copy(fields),
145 wrapped: wrapped,
146 },
147 }
148}
149
150// Log logs the error at the default level for log and return
151func (e *ErrInvalidValue) Log() error {
152 _ = e.ErrAdapter.Log()
153 return e
154}
155
156// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000157func (e *ErrInvalidValue) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800158 _ = e.ErrAdapter.LogAt(level)
159 return e
160}
161
162// ErrNotFound represents an error condition when a value can not be located
163// given a field set of criteria
164type ErrNotFound struct {
165 ErrAdapter
166}
167
168// NewErrNotFound constructs a new error based on the given values
169func NewErrNotFound(target string, fields log.Fields, wrapped error) LoggableError {
170 return &ErrNotFound{
171 ErrAdapter{
172 name: "not-found",
173 fields: merge(fields, log.Fields{"target": target}),
174 wrapped: wrapped,
175 },
176 }
177}
178
179// Log logs the error at the default level for log and return
180func (e *ErrNotFound) Log() error {
181 _ = e.ErrAdapter.Log()
182 return e
183}
184
185// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000186func (e *ErrNotFound) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800187 _ = e.ErrAdapter.LogAt(level)
188 return e
189}
190
191// ErrPersistence representation an error condition when a persistence operation
192// did not succeed
193type ErrPersistence struct {
194 ErrAdapter
195}
196
197// NewErrPersistence constructs a new error based on the given values
198func NewErrPersistence(operation, entityType string, ID uint32, fields log.Fields, wrapped error) LoggableError {
199 return &ErrPersistence{
200 ErrAdapter{
201 name: "unable-to-persist",
202 fields: merge(fields, log.Fields{
203 "operation": operation,
204 "entity-type": entityType,
205 "id": fmt.Sprintf("0x%x", ID)}),
206 wrapped: wrapped,
207 },
208 }
209}
210
211// Log logs the error at the default level for log and return
212func (e *ErrPersistence) Log() error {
213 _ = e.ErrAdapter.Log()
214 return e
215}
216
217// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000218func (e *ErrPersistence) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800219 _ = e.ErrAdapter.LogAt(level)
220 return e
221}
222
223// ErrCommunication representation an error condition when an interprocess
224// message communication fails
225type ErrCommunication struct {
226 ErrAdapter
227}
228
229// NewErrCommunication constructs a new error based on the given values
230func NewErrCommunication(operation string, fields log.Fields, wrapped error) LoggableError {
231 return &ErrCommunication{
232 ErrAdapter{
233 name: "failed-communication",
234 fields: merge(fields, log.Fields{
235 "operation": operation}),
236 wrapped: wrapped,
237 },
238 }
239}
240
241// Log logs the error at the default level for log and return
242func (e *ErrCommunication) Log() error {
243 _ = e.ErrAdapter.Log()
244 return e
245}
246
247// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000248func (e *ErrCommunication) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800249 _ = e.ErrAdapter.LogAt(level)
250 return e
251}
252
253// ErrFlowOp represents an error condition when a flow operation to a device did
254// not succeed
255type ErrFlowOp struct {
256 ErrAdapter
257}
258
259// NewErrFlowOp constructs a new error based on the given values
260func NewErrFlowOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
261 return &ErrPersistence{
262 ErrAdapter{
263 name: "unable-to-perform-flow-operation",
264 fields: merge(fields, log.Fields{
265 "operation": operation,
266 "id": fmt.Sprintf("0x%x", ID)}),
267 wrapped: wrapped,
268 },
269 }
270}
271
272// Log logs the error at the default level for log and return
273func (e *ErrFlowOp) Log() error {
274 _ = e.ErrAdapter.Log()
275 return e
276}
277
278// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000279func (e *ErrFlowOp) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800280 _ = e.ErrAdapter.LogAt(level)
281 return e
282}
283
Andrea Campanellac63bba92020-03-10 17:01:04 +0100284// ErrGroupOp represents an error condition when a group operation to a device did
285// not succeed
286type ErrGroupOp struct {
287 ErrAdapter
288}
289
290// NewErrGroupOp constructs a new error based on the given values
291func NewErrGroupOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
292 return &ErrPersistence{
293 ErrAdapter{
294 name: "unable-to-perform-group-operation",
295 fields: merge(fields, log.Fields{
296 "operation": operation,
297 "id": fmt.Sprintf("0x%x", ID)}),
298 wrapped: wrapped,
299 },
300 }
301}
302
303// Log logs the error at the default level for log and return
304func (e *ErrGroupOp) Log() error {
305 _ = e.ErrAdapter.Log()
306 return e
307}
308
309// LogAt logs the error at the specified level and then returns the error
310func (e *ErrGroupOp) LogAt(level log.LogLevel) error {
311 _ = e.ErrAdapter.LogAt(level)
312 return e
313}
314
David K. Bainbridge794735f2020-02-11 21:01:37 -0800315// ErrTimeout represents an error condition when the deadline for performing an
316// operation has been exceeded
317type ErrTimeout struct {
318 ErrAdapter
319}
320
321// NewErrTimeout constructs a new error based on the given values
322func NewErrTimeout(operation string, fields log.Fields, wrapped error) LoggableError {
323 return &ErrTimeout{
324 ErrAdapter{
325 name: "operation-timed-out",
326 fields: merge(fields, log.Fields{"operation": operation}),
327 wrapped: wrapped,
328 },
329 }
330}
331
332// Log logs the error at the default level for log and return
333func (e *ErrTimeout) Log() error {
334 _ = e.ErrAdapter.Log()
335 return e
336}
337
338// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000339func (e *ErrTimeout) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800340 _ = e.ErrAdapter.LogAt(level)
341 return e
342}
343
344var (
345 // ErrNotImplemented error returned when an unimplemented method is
346 // invoked
347 ErrNotImplemented = NewErrAdapter("not-implemented", nil, nil)
348
349 // ErrInvalidPortRange error returned when a given port is not in the
350 // valid range
351 ErrInvalidPortRange = NewErrAdapter("invalid-port-range", nil, nil)
352
353 // ErrStateTransition error returned when a state transition is fails
354 ErrStateTransition = NewErrAdapter("state-transition", nil, nil)
355
356 // ErrResourceManagerInstantiating error returned when an unexpected
357 // condition occcurs while instantiating the resource manager
358 ErrResourceManagerInstantiating = NewErrAdapter("resoure-manager-instantiating", nil, nil)
359)