blob: 4aa2373da39247877006c5033dc5eae89eabcebf [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"
Girish Gowdra4c3d4602021-07-22 16:33:37 -070024 "github.com/opencord/voltha-lib-go/v6/pkg/log"
David K. Bainbridge794735f2020-02-11 21:01:37 -080025 "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 {
Girish Kumar935f7af2020-08-18 11:59:42 +000092 ctx := context.Background()
David K. Bainbridge794735f2020-02-11 21:01:37 -080093 var buf strings.Builder
Andrey Pozolotinff797a92020-08-14 01:54:57 +020094 _, er := buf.WriteString(e.name)
95 if er != nil {
Girish Kumar935f7af2020-08-18 11:59:42 +000096 logger.Error(ctx, er)
Andrey Pozolotinff797a92020-08-14 01:54:57 +020097 }
David K. Bainbridge794735f2020-02-11 21:01:37 -080098 if len(e.fields) > 0 {
99 if val, err := json.Marshal(e.fields); err == nil {
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200100 _, er = buf.WriteString(fmt.Sprintf(": [%s]", string(val)))
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 }
105 }
106 if e.wrapped != nil {
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200107 _, er = buf.WriteString(fmt.Sprintf(": %s", e.wrapped.Error()))
108 if er != nil {
Girish Kumar935f7af2020-08-18 11:59:42 +0000109 logger.Error(ctx, er)
Andrey Pozolotinff797a92020-08-14 01:54:57 +0200110 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800111 }
112 return buf.String()
113}
114
115// Log logs the error at the default level for log and return
116func (e *ErrAdapter) Log() error {
117 return e.LogAt(defaultLogAndReturnLevel)
118}
119
120// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000121func (e *ErrAdapter) LogAt(level log.LogLevel) error {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000122 loggerFunc := logger.Debugw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800123 switch level {
124 case log.InfoLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000125 loggerFunc = logger.Infow
David K. Bainbridge794735f2020-02-11 21:01:37 -0800126 case log.WarnLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000127 loggerFunc = logger.Warnw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800128 case log.ErrorLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000129 loggerFunc = logger.Errorw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800130 case log.FatalLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000131 loggerFunc = logger.Fatalw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800132 }
133 local := e.fields
134 if e.wrapped != nil {
135 local = merge(e.fields, log.Fields{"wrapped": e.wrapped})
136 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000137 loggerFunc(context.Background(), e.name, local)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800138 return e
139}
140
141// ErrInvalidValue represents an error condition with given value is not able to
142// be processed
143type ErrInvalidValue struct {
144 ErrAdapter
145}
146
147// NewErrInvalidValue constructs a new error based on the given values
148func NewErrInvalidValue(fields log.Fields, wrapped error) LoggableError {
149 return &ErrInvalidValue{
150 ErrAdapter{
151 name: "invalid-value",
152 fields: copy(fields),
153 wrapped: wrapped,
154 },
155 }
156}
157
158// Log logs the error at the default level for log and return
159func (e *ErrInvalidValue) Log() error {
160 _ = e.ErrAdapter.Log()
161 return e
162}
163
164// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000165func (e *ErrInvalidValue) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800166 _ = e.ErrAdapter.LogAt(level)
167 return e
168}
169
170// ErrNotFound represents an error condition when a value can not be located
171// given a field set of criteria
172type ErrNotFound struct {
173 ErrAdapter
174}
175
176// NewErrNotFound constructs a new error based on the given values
177func NewErrNotFound(target string, fields log.Fields, wrapped error) LoggableError {
178 return &ErrNotFound{
179 ErrAdapter{
180 name: "not-found",
181 fields: merge(fields, log.Fields{"target": target}),
182 wrapped: wrapped,
183 },
184 }
185}
186
187// Log logs the error at the default level for log and return
188func (e *ErrNotFound) Log() error {
189 _ = e.ErrAdapter.Log()
190 return e
191}
192
193// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000194func (e *ErrNotFound) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800195 _ = e.ErrAdapter.LogAt(level)
196 return e
197}
198
199// ErrPersistence representation an error condition when a persistence operation
200// did not succeed
201type ErrPersistence struct {
202 ErrAdapter
203}
204
205// NewErrPersistence constructs a new error based on the given values
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700206func NewErrPersistence(operation, entityType string, ID uint64, fields log.Fields, wrapped error) LoggableError {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800207 return &ErrPersistence{
208 ErrAdapter{
209 name: "unable-to-persist",
210 fields: merge(fields, log.Fields{
211 "operation": operation,
212 "entity-type": entityType,
213 "id": fmt.Sprintf("0x%x", ID)}),
214 wrapped: wrapped,
215 },
216 }
217}
218
219// Log logs the error at the default level for log and return
220func (e *ErrPersistence) Log() error {
221 _ = e.ErrAdapter.Log()
222 return e
223}
224
225// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000226func (e *ErrPersistence) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800227 _ = e.ErrAdapter.LogAt(level)
228 return e
229}
230
231// ErrCommunication representation an error condition when an interprocess
232// message communication fails
233type ErrCommunication struct {
234 ErrAdapter
235}
236
237// NewErrCommunication constructs a new error based on the given values
238func NewErrCommunication(operation string, fields log.Fields, wrapped error) LoggableError {
239 return &ErrCommunication{
240 ErrAdapter{
241 name: "failed-communication",
242 fields: merge(fields, log.Fields{
243 "operation": operation}),
244 wrapped: wrapped,
245 },
246 }
247}
248
249// Log logs the error at the default level for log and return
250func (e *ErrCommunication) Log() error {
251 _ = e.ErrAdapter.Log()
252 return e
253}
254
255// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000256func (e *ErrCommunication) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800257 _ = e.ErrAdapter.LogAt(level)
258 return e
259}
260
261// ErrFlowOp represents an error condition when a flow operation to a device did
262// not succeed
263type ErrFlowOp struct {
264 ErrAdapter
265}
266
267// NewErrFlowOp constructs a new error based on the given values
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700268func NewErrFlowOp(operation string, ID uint64, fields log.Fields, wrapped error) LoggableError {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800269 return &ErrPersistence{
270 ErrAdapter{
271 name: "unable-to-perform-flow-operation",
272 fields: merge(fields, log.Fields{
273 "operation": operation,
274 "id": fmt.Sprintf("0x%x", ID)}),
275 wrapped: wrapped,
276 },
277 }
278}
279
280// Log logs the error at the default level for log and return
281func (e *ErrFlowOp) Log() error {
282 _ = e.ErrAdapter.Log()
283 return e
284}
285
286// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000287func (e *ErrFlowOp) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800288 _ = e.ErrAdapter.LogAt(level)
289 return e
290}
291
Andrea Campanellac63bba92020-03-10 17:01:04 +0100292// ErrGroupOp represents an error condition when a group operation to a device did
293// not succeed
294type ErrGroupOp struct {
295 ErrAdapter
296}
297
298// NewErrGroupOp constructs a new error based on the given values
299func NewErrGroupOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
300 return &ErrPersistence{
301 ErrAdapter{
302 name: "unable-to-perform-group-operation",
303 fields: merge(fields, log.Fields{
304 "operation": operation,
305 "id": fmt.Sprintf("0x%x", ID)}),
306 wrapped: wrapped,
307 },
308 }
309}
310
311// Log logs the error at the default level for log and return
312func (e *ErrGroupOp) Log() error {
313 _ = e.ErrAdapter.Log()
314 return e
315}
316
317// LogAt logs the error at the specified level and then returns the error
318func (e *ErrGroupOp) LogAt(level log.LogLevel) error {
319 _ = e.ErrAdapter.LogAt(level)
320 return e
321}
322
David K. Bainbridge794735f2020-02-11 21:01:37 -0800323// ErrTimeout represents an error condition when the deadline for performing an
324// operation has been exceeded
325type ErrTimeout struct {
326 ErrAdapter
327}
328
329// NewErrTimeout constructs a new error based on the given values
330func NewErrTimeout(operation string, fields log.Fields, wrapped error) LoggableError {
331 return &ErrTimeout{
332 ErrAdapter{
333 name: "operation-timed-out",
334 fields: merge(fields, log.Fields{"operation": operation}),
335 wrapped: wrapped,
336 },
337 }
338}
339
340// Log logs the error at the default level for log and return
341func (e *ErrTimeout) Log() error {
342 _ = e.ErrAdapter.Log()
343 return e
344}
345
346// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000347func (e *ErrTimeout) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800348 _ = e.ErrAdapter.LogAt(level)
349 return e
350}
351
352var (
353 // ErrNotImplemented error returned when an unimplemented method is
354 // invoked
355 ErrNotImplemented = NewErrAdapter("not-implemented", nil, nil)
356
357 // ErrInvalidPortRange error returned when a given port is not in the
358 // valid range
359 ErrInvalidPortRange = NewErrAdapter("invalid-port-range", nil, nil)
360
361 // ErrStateTransition error returned when a state transition is fails
362 ErrStateTransition = NewErrAdapter("state-transition", nil, nil)
363
364 // ErrResourceManagerInstantiating error returned when an unexpected
365 // condition occcurs while instantiating the resource manager
366 ErrResourceManagerInstantiating = NewErrAdapter("resoure-manager-instantiating", nil, nil)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700367
368 // ErrFlowManagerInstantiating error returned when an unexpected
369 // condition occcurs while instantiating the flow manager
370 ErrFlowManagerInstantiating = NewErrAdapter("flow-manager-instantiating", nil, nil)
371
372 // ErrGroupManagerInstantiating error returned when an unexpected
373 // condition occcurs while instantiating the group manager
374 ErrGroupManagerInstantiating = NewErrAdapter("group-manager-instantiating", nil, nil)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800375)