blob: bafc721286d4655aeb573476ed1f6752eeb096ee [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
59// ErrAdapter represents a basic adapter error that combines an name, field set
60// and wrapped error
61type ErrAdapter struct {
62 name string
63 fields log.Fields
64 wrapped error
65}
66
67// NewErrAdapter constructs a new error with the given values
68func NewErrAdapter(name string, fields log.Fields, wrapped error) LoggableError {
69 return &ErrAdapter{
70 name: name,
71 fields: copy(fields),
72 wrapped: wrapped,
73 }
74}
75
76// Name returns the error name
77func (e *ErrAdapter) Name() string {
78 return e.name
79}
80
81// Fields returns the fields associated with the error
82func (e *ErrAdapter) Fields() log.Fields {
83 return e.fields
84}
85
86// Unwrap returns the wrapped or nested error
87func (e *ErrAdapter) Unwrap() error {
88 return e.wrapped
89}
90
91// Error returns a string representation of the error
92func (e *ErrAdapter) Error() string {
Girish Kumar935f7af2020-08-18 11:59:42 +000093 ctx := context.Background()
David K. Bainbridge794735f2020-02-11 21:01:37 -080094 var buf strings.Builder
Andrey Pozolotinff797a92020-08-14 01:54:57 +020095 _, er := buf.WriteString(e.name)
96 if er != nil {
Girish Kumar935f7af2020-08-18 11:59:42 +000097 logger.Error(ctx, er)
Andrey Pozolotinff797a92020-08-14 01:54:57 +020098 }
David K. Bainbridge794735f2020-02-11 21:01:37 -080099 if len(e.fields) > 0 {
100 if val, err := json.Marshal(e.fields); err == nil {
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200101 _, er = buf.WriteString(fmt.Sprintf(": [%s]", string(val)))
102 if er != nil {
Girish Kumar935f7af2020-08-18 11:59:42 +0000103 logger.Error(ctx, er)
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200104 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800105 }
106 }
107 if e.wrapped != nil {
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200108 _, er = buf.WriteString(fmt.Sprintf(": %s", e.wrapped.Error()))
109 if er != nil {
Girish Kumar935f7af2020-08-18 11:59:42 +0000110 logger.Error(ctx, er)
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200111 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800112 }
113 return buf.String()
114}
115
116// Log logs the error at the default level for log and return
117func (e *ErrAdapter) Log() error {
118 return e.LogAt(defaultLogAndReturnLevel)
119}
120
121// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000122func (e *ErrAdapter) LogAt(level log.LogLevel) error {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000123 loggerFunc := logger.Debugw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800124 switch level {
125 case log.InfoLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000126 loggerFunc = logger.Infow
David K. Bainbridge794735f2020-02-11 21:01:37 -0800127 case log.WarnLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000128 loggerFunc = logger.Warnw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800129 case log.ErrorLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000130 loggerFunc = logger.Errorw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800131 case log.FatalLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000132 loggerFunc = logger.Fatalw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800133 }
134 local := e.fields
135 if e.wrapped != nil {
136 local = merge(e.fields, log.Fields{"wrapped": e.wrapped})
137 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000138 loggerFunc(context.Background(), e.name, local)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800139 return e
140}
141
142// ErrInvalidValue represents an error condition with given value is not able to
143// be processed
144type ErrInvalidValue struct {
145 ErrAdapter
146}
147
148// NewErrInvalidValue constructs a new error based on the given values
149func NewErrInvalidValue(fields log.Fields, wrapped error) LoggableError {
150 return &ErrInvalidValue{
151 ErrAdapter{
152 name: "invalid-value",
153 fields: copy(fields),
154 wrapped: wrapped,
155 },
156 }
157}
158
159// Log logs the error at the default level for log and return
160func (e *ErrInvalidValue) Log() error {
161 _ = e.ErrAdapter.Log()
162 return e
163}
164
165// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000166func (e *ErrInvalidValue) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800167 _ = e.ErrAdapter.LogAt(level)
168 return e
169}
170
171// ErrNotFound represents an error condition when a value can not be located
172// given a field set of criteria
173type ErrNotFound struct {
174 ErrAdapter
175}
176
177// NewErrNotFound constructs a new error based on the given values
178func NewErrNotFound(target string, fields log.Fields, wrapped error) LoggableError {
179 return &ErrNotFound{
180 ErrAdapter{
181 name: "not-found",
182 fields: merge(fields, log.Fields{"target": target}),
183 wrapped: wrapped,
184 },
185 }
186}
187
188// Log logs the error at the default level for log and return
189func (e *ErrNotFound) Log() error {
190 _ = e.ErrAdapter.Log()
191 return e
192}
193
194// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000195func (e *ErrNotFound) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800196 _ = e.ErrAdapter.LogAt(level)
197 return e
198}
199
200// ErrPersistence representation an error condition when a persistence operation
201// did not succeed
202type ErrPersistence struct {
203 ErrAdapter
204}
205
206// NewErrPersistence constructs a new error based on the given values
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700207func NewErrPersistence(operation, entityType string, ID uint64, fields log.Fields, wrapped error) LoggableError {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800208 return &ErrPersistence{
209 ErrAdapter{
210 name: "unable-to-persist",
211 fields: merge(fields, log.Fields{
212 "operation": operation,
213 "entity-type": entityType,
214 "id": fmt.Sprintf("0x%x", ID)}),
215 wrapped: wrapped,
216 },
217 }
218}
219
220// Log logs the error at the default level for log and return
221func (e *ErrPersistence) Log() error {
222 _ = e.ErrAdapter.Log()
223 return e
224}
225
226// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000227func (e *ErrPersistence) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800228 _ = e.ErrAdapter.LogAt(level)
229 return e
230}
231
232// ErrCommunication representation an error condition when an interprocess
233// message communication fails
234type ErrCommunication struct {
235 ErrAdapter
236}
237
238// NewErrCommunication constructs a new error based on the given values
239func NewErrCommunication(operation string, fields log.Fields, wrapped error) LoggableError {
240 return &ErrCommunication{
241 ErrAdapter{
242 name: "failed-communication",
243 fields: merge(fields, log.Fields{
244 "operation": operation}),
245 wrapped: wrapped,
246 },
247 }
248}
249
250// Log logs the error at the default level for log and return
251func (e *ErrCommunication) Log() error {
252 _ = e.ErrAdapter.Log()
253 return e
254}
255
256// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000257func (e *ErrCommunication) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800258 _ = e.ErrAdapter.LogAt(level)
259 return e
260}
261
262// ErrFlowOp represents an error condition when a flow operation to a device did
263// not succeed
264type ErrFlowOp struct {
265 ErrAdapter
266}
267
268// NewErrFlowOp constructs a new error based on the given values
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700269func NewErrFlowOp(operation string, ID uint64, fields log.Fields, wrapped error) LoggableError {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800270 return &ErrPersistence{
271 ErrAdapter{
272 name: "unable-to-perform-flow-operation",
273 fields: merge(fields, log.Fields{
274 "operation": operation,
275 "id": fmt.Sprintf("0x%x", ID)}),
276 wrapped: wrapped,
277 },
278 }
279}
280
281// Log logs the error at the default level for log and return
282func (e *ErrFlowOp) Log() error {
283 _ = e.ErrAdapter.Log()
284 return e
285}
286
287// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000288func (e *ErrFlowOp) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800289 _ = e.ErrAdapter.LogAt(level)
290 return e
291}
292
Andrea Campanellac63bba92020-03-10 17:01:04 +0100293// ErrGroupOp represents an error condition when a group operation to a device did
294// not succeed
295type ErrGroupOp struct {
296 ErrAdapter
297}
298
299// NewErrGroupOp constructs a new error based on the given values
300func NewErrGroupOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
301 return &ErrPersistence{
302 ErrAdapter{
303 name: "unable-to-perform-group-operation",
304 fields: merge(fields, log.Fields{
305 "operation": operation,
306 "id": fmt.Sprintf("0x%x", ID)}),
307 wrapped: wrapped,
308 },
309 }
310}
311
312// Log logs the error at the default level for log and return
313func (e *ErrGroupOp) Log() error {
314 _ = e.ErrAdapter.Log()
315 return e
316}
317
318// LogAt logs the error at the specified level and then returns the error
319func (e *ErrGroupOp) LogAt(level log.LogLevel) error {
320 _ = e.ErrAdapter.LogAt(level)
321 return e
322}
323
David K. Bainbridge794735f2020-02-11 21:01:37 -0800324// ErrTimeout represents an error condition when the deadline for performing an
325// operation has been exceeded
326type ErrTimeout struct {
327 ErrAdapter
328}
329
330// NewErrTimeout constructs a new error based on the given values
331func NewErrTimeout(operation string, fields log.Fields, wrapped error) LoggableError {
332 return &ErrTimeout{
333 ErrAdapter{
334 name: "operation-timed-out",
335 fields: merge(fields, log.Fields{"operation": operation}),
336 wrapped: wrapped,
337 },
338 }
339}
340
341// Log logs the error at the default level for log and return
342func (e *ErrTimeout) Log() error {
343 _ = e.ErrAdapter.Log()
344 return e
345}
346
347// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000348func (e *ErrTimeout) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800349 _ = e.ErrAdapter.LogAt(level)
350 return e
351}
352
353var (
354 // ErrNotImplemented error returned when an unimplemented method is
355 // invoked
356 ErrNotImplemented = NewErrAdapter("not-implemented", nil, nil)
357
358 // ErrInvalidPortRange error returned when a given port is not in the
359 // valid range
360 ErrInvalidPortRange = NewErrAdapter("invalid-port-range", nil, nil)
361
362 // ErrStateTransition error returned when a state transition is fails
363 ErrStateTransition = NewErrAdapter("state-transition", nil, nil)
364
365 // ErrResourceManagerInstantiating error returned when an unexpected
366 // condition occcurs while instantiating the resource manager
367 ErrResourceManagerInstantiating = NewErrAdapter("resoure-manager-instantiating", nil, nil)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700368
369 // ErrFlowManagerInstantiating error returned when an unexpected
370 // condition occcurs while instantiating the flow manager
371 ErrFlowManagerInstantiating = NewErrAdapter("flow-manager-instantiating", nil, nil)
372
373 // ErrGroupManagerInstantiating error returned when an unexpected
374 // condition occcurs while instantiating the group manager
375 ErrGroupManagerInstantiating = NewErrAdapter("group-manager-instantiating", nil, nil)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800376)