blob: 53c4d619c62a303d2e56e6dd7b1c92008b40202f [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 (
Girish Kumara1ea2aa2020-08-19 18:14:22 +000021 "context"
David K. Bainbridge794735f2020-02-11 21:01:37 -080022 "encoding/json"
23 "fmt"
David K. Bainbridge794735f2020-02-11 21:01:37 -080024 "strings"
khenaidoo106c61a2021-08-11 18:05:46 -040025
26 "github.com/opencord/voltha-lib-go/v7/pkg/log"
David K. Bainbridge794735f2020-02-11 21:01:37 -080027)
28
29const (
Shrey Baid19b563a2020-04-03 18:41:12 +053030 defaultLogAndReturnLevel = log.ErrorLevel
David K. Bainbridge794735f2020-02-11 21:01:37 -080031)
32
33func copy(src log.Fields) log.Fields {
34 dst := make(log.Fields)
35 for k, v := range src {
36 dst[k] = v
37 }
38 return dst
39}
40
41func merge(one, two log.Fields) log.Fields {
42 dst := make(log.Fields)
43 for k, v := range one {
44 dst[k] = v
45 }
46 for k, v := range two {
47 dst[k] = v
48 }
49 return dst
50}
51
52// LoggableError defined functions that can be used to log an object
53type LoggableError interface {
54 error
55 Log() error
Rohan Agrawal02f784d2020-02-14 09:34:02 +000056 LogAt(log.LogLevel) error
David K. Bainbridge794735f2020-02-11 21:01:37 -080057}
58
Elia Battiston2aaf4342022-02-07 15:16:38 +010059// WrappedError can be used to extract the wrapped errors of structs that include ErrAdapter
60type WrappedError interface {
61 Unwrap() error
62}
63
David K. Bainbridge794735f2020-02-11 21:01:37 -080064// ErrAdapter represents a basic adapter error that combines an name, field set
65// and wrapped error
66type ErrAdapter struct {
67 name string
68 fields log.Fields
69 wrapped error
70}
71
72// NewErrAdapter constructs a new error with the given values
73func NewErrAdapter(name string, fields log.Fields, wrapped error) LoggableError {
74 return &ErrAdapter{
75 name: name,
76 fields: copy(fields),
77 wrapped: wrapped,
78 }
79}
80
81// Name returns the error name
82func (e *ErrAdapter) Name() string {
83 return e.name
84}
85
86// Fields returns the fields associated with the error
87func (e *ErrAdapter) Fields() log.Fields {
88 return e.fields
89}
90
91// Unwrap returns the wrapped or nested error
92func (e *ErrAdapter) Unwrap() error {
93 return e.wrapped
94}
95
96// Error returns a string representation of the error
97func (e *ErrAdapter) Error() string {
Girish Kumar935f7af2020-08-18 11:59:42 +000098 ctx := context.Background()
David K. Bainbridge794735f2020-02-11 21:01:37 -080099 var buf strings.Builder
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200100 _, er := buf.WriteString(e.name)
101 if er != nil {
Girish Kumar935f7af2020-08-18 11:59:42 +0000102 logger.Error(ctx, er)
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200103 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800104 if len(e.fields) > 0 {
105 if val, err := json.Marshal(e.fields); err == nil {
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200106 _, er = buf.WriteString(fmt.Sprintf(": [%s]", string(val)))
107 if er != nil {
Girish Kumar935f7af2020-08-18 11:59:42 +0000108 logger.Error(ctx, er)
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200109 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800110 }
111 }
112 if e.wrapped != nil {
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200113 _, er = buf.WriteString(fmt.Sprintf(": %s", e.wrapped.Error()))
114 if er != nil {
Girish Kumar935f7af2020-08-18 11:59:42 +0000115 logger.Error(ctx, er)
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200116 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800117 }
118 return buf.String()
119}
120
121// Log logs the error at the default level for log and return
122func (e *ErrAdapter) Log() error {
123 return e.LogAt(defaultLogAndReturnLevel)
124}
125
126// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000127func (e *ErrAdapter) LogAt(level log.LogLevel) error {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000128 loggerFunc := logger.Debugw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800129 switch level {
130 case log.InfoLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000131 loggerFunc = logger.Infow
David K. Bainbridge794735f2020-02-11 21:01:37 -0800132 case log.WarnLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000133 loggerFunc = logger.Warnw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800134 case log.ErrorLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000135 loggerFunc = logger.Errorw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800136 case log.FatalLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000137 loggerFunc = logger.Fatalw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800138 }
139 local := e.fields
140 if e.wrapped != nil {
141 local = merge(e.fields, log.Fields{"wrapped": e.wrapped})
142 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000143 loggerFunc(context.Background(), e.name, local)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800144 return e
145}
146
147// ErrInvalidValue represents an error condition with given value is not able to
148// be processed
149type ErrInvalidValue struct {
150 ErrAdapter
151}
152
153// NewErrInvalidValue constructs a new error based on the given values
154func NewErrInvalidValue(fields log.Fields, wrapped error) LoggableError {
155 return &ErrInvalidValue{
156 ErrAdapter{
157 name: "invalid-value",
158 fields: copy(fields),
159 wrapped: wrapped,
160 },
161 }
162}
163
164// Log logs the error at the default level for log and return
165func (e *ErrInvalidValue) Log() error {
166 _ = e.ErrAdapter.Log()
167 return e
168}
169
170// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000171func (e *ErrInvalidValue) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800172 _ = e.ErrAdapter.LogAt(level)
173 return e
174}
175
176// ErrNotFound represents an error condition when a value can not be located
177// given a field set of criteria
178type ErrNotFound struct {
179 ErrAdapter
180}
181
182// NewErrNotFound constructs a new error based on the given values
183func NewErrNotFound(target string, fields log.Fields, wrapped error) LoggableError {
184 return &ErrNotFound{
185 ErrAdapter{
186 name: "not-found",
187 fields: merge(fields, log.Fields{"target": target}),
188 wrapped: wrapped,
189 },
190 }
191}
192
193// Log logs the error at the default level for log and return
194func (e *ErrNotFound) Log() error {
195 _ = e.ErrAdapter.Log()
196 return e
197}
198
199// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000200func (e *ErrNotFound) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800201 _ = e.ErrAdapter.LogAt(level)
202 return e
203}
204
205// ErrPersistence representation an error condition when a persistence operation
206// did not succeed
207type ErrPersistence struct {
208 ErrAdapter
209}
210
211// NewErrPersistence constructs a new error based on the given values
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700212func NewErrPersistence(operation, entityType string, ID uint64, fields log.Fields, wrapped error) LoggableError {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800213 return &ErrPersistence{
214 ErrAdapter{
215 name: "unable-to-persist",
216 fields: merge(fields, log.Fields{
217 "operation": operation,
218 "entity-type": entityType,
219 "id": fmt.Sprintf("0x%x", ID)}),
220 wrapped: wrapped,
221 },
222 }
223}
224
225// Log logs the error at the default level for log and return
226func (e *ErrPersistence) Log() error {
227 _ = e.ErrAdapter.Log()
228 return e
229}
230
231// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000232func (e *ErrPersistence) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800233 _ = e.ErrAdapter.LogAt(level)
234 return e
235}
236
237// ErrCommunication representation an error condition when an interprocess
238// message communication fails
239type ErrCommunication struct {
240 ErrAdapter
241}
242
243// NewErrCommunication constructs a new error based on the given values
244func NewErrCommunication(operation string, fields log.Fields, wrapped error) LoggableError {
245 return &ErrCommunication{
246 ErrAdapter{
247 name: "failed-communication",
248 fields: merge(fields, log.Fields{
249 "operation": operation}),
250 wrapped: wrapped,
251 },
252 }
253}
254
255// Log logs the error at the default level for log and return
256func (e *ErrCommunication) Log() error {
257 _ = e.ErrAdapter.Log()
258 return e
259}
260
261// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000262func (e *ErrCommunication) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800263 _ = e.ErrAdapter.LogAt(level)
264 return e
265}
266
267// ErrFlowOp represents an error condition when a flow operation to a device did
268// not succeed
269type ErrFlowOp struct {
270 ErrAdapter
271}
272
273// NewErrFlowOp constructs a new error based on the given values
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700274func NewErrFlowOp(operation string, ID uint64, fields log.Fields, wrapped error) LoggableError {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800275 return &ErrPersistence{
276 ErrAdapter{
277 name: "unable-to-perform-flow-operation",
278 fields: merge(fields, log.Fields{
279 "operation": operation,
280 "id": fmt.Sprintf("0x%x", ID)}),
281 wrapped: wrapped,
282 },
283 }
284}
285
286// Log logs the error at the default level for log and return
287func (e *ErrFlowOp) Log() error {
288 _ = e.ErrAdapter.Log()
289 return e
290}
291
292// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000293func (e *ErrFlowOp) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800294 _ = e.ErrAdapter.LogAt(level)
295 return e
296}
297
Andrea Campanellac63bba92020-03-10 17:01:04 +0100298// ErrGroupOp represents an error condition when a group operation to a device did
299// not succeed
300type ErrGroupOp struct {
301 ErrAdapter
302}
303
304// NewErrGroupOp constructs a new error based on the given values
305func NewErrGroupOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
306 return &ErrPersistence{
307 ErrAdapter{
308 name: "unable-to-perform-group-operation",
309 fields: merge(fields, log.Fields{
310 "operation": operation,
311 "id": fmt.Sprintf("0x%x", ID)}),
312 wrapped: wrapped,
313 },
314 }
315}
316
317// Log logs the error at the default level for log and return
318func (e *ErrGroupOp) Log() error {
319 _ = e.ErrAdapter.Log()
320 return e
321}
322
323// LogAt logs the error at the specified level and then returns the error
324func (e *ErrGroupOp) LogAt(level log.LogLevel) error {
325 _ = e.ErrAdapter.LogAt(level)
326 return e
327}
328
David K. Bainbridge794735f2020-02-11 21:01:37 -0800329// ErrTimeout represents an error condition when the deadline for performing an
330// operation has been exceeded
331type ErrTimeout struct {
332 ErrAdapter
333}
334
335// NewErrTimeout constructs a new error based on the given values
336func NewErrTimeout(operation string, fields log.Fields, wrapped error) LoggableError {
337 return &ErrTimeout{
338 ErrAdapter{
339 name: "operation-timed-out",
340 fields: merge(fields, log.Fields{"operation": operation}),
341 wrapped: wrapped,
342 },
343 }
344}
345
346// Log logs the error at the default level for log and return
347func (e *ErrTimeout) Log() error {
348 _ = e.ErrAdapter.Log()
349 return e
350}
351
352// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000353func (e *ErrTimeout) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800354 _ = e.ErrAdapter.LogAt(level)
355 return e
356}
357
358var (
359 // ErrNotImplemented error returned when an unimplemented method is
360 // invoked
361 ErrNotImplemented = NewErrAdapter("not-implemented", nil, nil)
362
363 // ErrInvalidPortRange error returned when a given port is not in the
364 // valid range
365 ErrInvalidPortRange = NewErrAdapter("invalid-port-range", nil, nil)
366
367 // ErrStateTransition error returned when a state transition is fails
368 ErrStateTransition = NewErrAdapter("state-transition", nil, nil)
369
370 // ErrResourceManagerInstantiating error returned when an unexpected
371 // condition occcurs while instantiating the resource manager
372 ErrResourceManagerInstantiating = NewErrAdapter("resoure-manager-instantiating", nil, nil)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700373
374 // ErrFlowManagerInstantiating error returned when an unexpected
375 // condition occcurs while instantiating the flow manager
376 ErrFlowManagerInstantiating = NewErrAdapter("flow-manager-instantiating", nil, nil)
377
378 // ErrGroupManagerInstantiating error returned when an unexpected
379 // condition occcurs while instantiating the group manager
380 ErrGroupManagerInstantiating = NewErrAdapter("group-manager-instantiating", nil, nil)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800381)