blob: 8555cf1c7e61e7794c9bb56277533c39afcd5f50 [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"
24 "github.com/opencord/voltha-lib-go/v3/pkg/log"
25 "strings"
26)
27
28const (
Shrey Baid19b563a2020-04-03 18:41:12 +053029 defaultLogAndReturnLevel = log.ErrorLevel
David K. Bainbridge794735f2020-02-11 21:01:37 -080030)
31
32func copy(src log.Fields) log.Fields {
33 dst := make(log.Fields)
34 for k, v := range src {
35 dst[k] = v
36 }
37 return dst
38}
39
40func merge(one, two log.Fields) log.Fields {
41 dst := make(log.Fields)
42 for k, v := range one {
43 dst[k] = v
44 }
45 for k, v := range two {
46 dst[k] = v
47 }
48 return dst
49}
50
51// LoggableError defined functions that can be used to log an object
52type LoggableError interface {
53 error
54 Log() error
Rohan Agrawal02f784d2020-02-14 09:34:02 +000055 LogAt(log.LogLevel) error
David K. Bainbridge794735f2020-02-11 21:01:37 -080056}
57
58// ErrAdapter represents a basic adapter error that combines an name, field set
59// and wrapped error
60type ErrAdapter struct {
61 name string
62 fields log.Fields
63 wrapped error
64}
65
66// NewErrAdapter constructs a new error with the given values
67func NewErrAdapter(name string, fields log.Fields, wrapped error) LoggableError {
68 return &ErrAdapter{
69 name: name,
70 fields: copy(fields),
71 wrapped: wrapped,
72 }
73}
74
75// Name returns the error name
76func (e *ErrAdapter) Name() string {
77 return e.name
78}
79
80// Fields returns the fields associated with the error
81func (e *ErrAdapter) Fields() log.Fields {
82 return e.fields
83}
84
85// Unwrap returns the wrapped or nested error
86func (e *ErrAdapter) Unwrap() error {
87 return e.wrapped
88}
89
90// Error returns a string representation of the error
91func (e *ErrAdapter) Error() string {
92 var buf strings.Builder
Andrey Pozolotinff797a92020-08-14 01:54:57 +020093 _, er := buf.WriteString(e.name)
94 if er != nil {
95 log.Error(er)
96 }
David K. Bainbridge794735f2020-02-11 21:01:37 -080097 if len(e.fields) > 0 {
98 if val, err := json.Marshal(e.fields); err == nil {
Andrey Pozolotinff797a92020-08-14 01:54:57 +020099 _, er = buf.WriteString(fmt.Sprintf(": [%s]", string(val)))
100 if er != nil {
101 log.Error(er)
102 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800103 }
104 }
105 if e.wrapped != nil {
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200106 _, er = buf.WriteString(fmt.Sprintf(": %s", e.wrapped.Error()))
107 if er != nil {
108 log.Error(er)
109 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800110 }
111 return buf.String()
112}
113
114// Log logs the error at the default level for log and return
115func (e *ErrAdapter) Log() error {
116 return e.LogAt(defaultLogAndReturnLevel)
117}
118
119// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000120func (e *ErrAdapter) LogAt(level log.LogLevel) error {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000121 loggerFunc := logger.Debugw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800122 switch level {
123 case log.InfoLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000124 loggerFunc = logger.Infow
David K. Bainbridge794735f2020-02-11 21:01:37 -0800125 case log.WarnLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000126 loggerFunc = logger.Warnw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800127 case log.ErrorLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000128 loggerFunc = logger.Errorw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800129 case log.FatalLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000130 loggerFunc = logger.Fatalw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800131 }
132 local := e.fields
133 if e.wrapped != nil {
134 local = merge(e.fields, log.Fields{"wrapped": e.wrapped})
135 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000136 loggerFunc(context.Background(), e.name, local)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800137 return e
138}
139
140// ErrInvalidValue represents an error condition with given value is not able to
141// be processed
142type ErrInvalidValue struct {
143 ErrAdapter
144}
145
146// NewErrInvalidValue constructs a new error based on the given values
147func NewErrInvalidValue(fields log.Fields, wrapped error) LoggableError {
148 return &ErrInvalidValue{
149 ErrAdapter{
150 name: "invalid-value",
151 fields: copy(fields),
152 wrapped: wrapped,
153 },
154 }
155}
156
157// Log logs the error at the default level for log and return
158func (e *ErrInvalidValue) Log() error {
159 _ = e.ErrAdapter.Log()
160 return e
161}
162
163// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000164func (e *ErrInvalidValue) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800165 _ = e.ErrAdapter.LogAt(level)
166 return e
167}
168
169// ErrNotFound represents an error condition when a value can not be located
170// given a field set of criteria
171type ErrNotFound struct {
172 ErrAdapter
173}
174
175// NewErrNotFound constructs a new error based on the given values
176func NewErrNotFound(target string, fields log.Fields, wrapped error) LoggableError {
177 return &ErrNotFound{
178 ErrAdapter{
179 name: "not-found",
180 fields: merge(fields, log.Fields{"target": target}),
181 wrapped: wrapped,
182 },
183 }
184}
185
186// Log logs the error at the default level for log and return
187func (e *ErrNotFound) Log() error {
188 _ = e.ErrAdapter.Log()
189 return e
190}
191
192// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000193func (e *ErrNotFound) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800194 _ = e.ErrAdapter.LogAt(level)
195 return e
196}
197
198// ErrPersistence representation an error condition when a persistence operation
199// did not succeed
200type ErrPersistence struct {
201 ErrAdapter
202}
203
204// NewErrPersistence constructs a new error based on the given values
205func NewErrPersistence(operation, entityType string, ID uint32, fields log.Fields, wrapped error) LoggableError {
206 return &ErrPersistence{
207 ErrAdapter{
208 name: "unable-to-persist",
209 fields: merge(fields, log.Fields{
210 "operation": operation,
211 "entity-type": entityType,
212 "id": fmt.Sprintf("0x%x", ID)}),
213 wrapped: wrapped,
214 },
215 }
216}
217
218// Log logs the error at the default level for log and return
219func (e *ErrPersistence) Log() error {
220 _ = e.ErrAdapter.Log()
221 return e
222}
223
224// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000225func (e *ErrPersistence) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800226 _ = e.ErrAdapter.LogAt(level)
227 return e
228}
229
230// ErrCommunication representation an error condition when an interprocess
231// message communication fails
232type ErrCommunication struct {
233 ErrAdapter
234}
235
236// NewErrCommunication constructs a new error based on the given values
237func NewErrCommunication(operation string, fields log.Fields, wrapped error) LoggableError {
238 return &ErrCommunication{
239 ErrAdapter{
240 name: "failed-communication",
241 fields: merge(fields, log.Fields{
242 "operation": operation}),
243 wrapped: wrapped,
244 },
245 }
246}
247
248// Log logs the error at the default level for log and return
249func (e *ErrCommunication) Log() error {
250 _ = e.ErrAdapter.Log()
251 return e
252}
253
254// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000255func (e *ErrCommunication) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800256 _ = e.ErrAdapter.LogAt(level)
257 return e
258}
259
260// ErrFlowOp represents an error condition when a flow operation to a device did
261// not succeed
262type ErrFlowOp struct {
263 ErrAdapter
264}
265
266// NewErrFlowOp constructs a new error based on the given values
267func NewErrFlowOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
268 return &ErrPersistence{
269 ErrAdapter{
270 name: "unable-to-perform-flow-operation",
271 fields: merge(fields, log.Fields{
272 "operation": operation,
273 "id": fmt.Sprintf("0x%x", ID)}),
274 wrapped: wrapped,
275 },
276 }
277}
278
279// Log logs the error at the default level for log and return
280func (e *ErrFlowOp) Log() error {
281 _ = e.ErrAdapter.Log()
282 return e
283}
284
285// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000286func (e *ErrFlowOp) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800287 _ = e.ErrAdapter.LogAt(level)
288 return e
289}
290
Andrea Campanellac63bba92020-03-10 17:01:04 +0100291// ErrGroupOp represents an error condition when a group operation to a device did
292// not succeed
293type ErrGroupOp struct {
294 ErrAdapter
295}
296
297// NewErrGroupOp constructs a new error based on the given values
298func NewErrGroupOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
299 return &ErrPersistence{
300 ErrAdapter{
301 name: "unable-to-perform-group-operation",
302 fields: merge(fields, log.Fields{
303 "operation": operation,
304 "id": fmt.Sprintf("0x%x", ID)}),
305 wrapped: wrapped,
306 },
307 }
308}
309
310// Log logs the error at the default level for log and return
311func (e *ErrGroupOp) Log() error {
312 _ = e.ErrAdapter.Log()
313 return e
314}
315
316// LogAt logs the error at the specified level and then returns the error
317func (e *ErrGroupOp) LogAt(level log.LogLevel) error {
318 _ = e.ErrAdapter.LogAt(level)
319 return e
320}
321
David K. Bainbridge794735f2020-02-11 21:01:37 -0800322// ErrTimeout represents an error condition when the deadline for performing an
323// operation has been exceeded
324type ErrTimeout struct {
325 ErrAdapter
326}
327
328// NewErrTimeout constructs a new error based on the given values
329func NewErrTimeout(operation string, fields log.Fields, wrapped error) LoggableError {
330 return &ErrTimeout{
331 ErrAdapter{
332 name: "operation-timed-out",
333 fields: merge(fields, log.Fields{"operation": operation}),
334 wrapped: wrapped,
335 },
336 }
337}
338
339// Log logs the error at the default level for log and return
340func (e *ErrTimeout) Log() error {
341 _ = e.ErrAdapter.Log()
342 return e
343}
344
345// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000346func (e *ErrTimeout) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800347 _ = e.ErrAdapter.LogAt(level)
348 return e
349}
350
351var (
352 // ErrNotImplemented error returned when an unimplemented method is
353 // invoked
354 ErrNotImplemented = NewErrAdapter("not-implemented", nil, nil)
355
356 // ErrInvalidPortRange error returned when a given port is not in the
357 // valid range
358 ErrInvalidPortRange = NewErrAdapter("invalid-port-range", nil, nil)
359
360 // ErrStateTransition error returned when a state transition is fails
361 ErrStateTransition = NewErrAdapter("state-transition", nil, nil)
362
363 // ErrResourceManagerInstantiating error returned when an unexpected
364 // condition occcurs while instantiating the resource manager
365 ErrResourceManagerInstantiating = NewErrAdapter("resoure-manager-instantiating", nil, nil)
366)