blob: 59eaed96ec0598dff2ec26cf8ce886c6f7366cbb [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
93 buf.WriteString(e.name)
94 if len(e.fields) > 0 {
95 if val, err := json.Marshal(e.fields); err == nil {
96 buf.WriteString(": [")
97 buf.WriteString(string(val))
98 buf.WriteString("]")
99 }
100 }
101 if e.wrapped != nil {
102 buf.WriteString(": ")
103 buf.WriteString(e.wrapped.Error())
104 }
105 return buf.String()
106}
107
108// Log logs the error at the default level for log and return
109func (e *ErrAdapter) Log() error {
110 return e.LogAt(defaultLogAndReturnLevel)
111}
112
113// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000114func (e *ErrAdapter) LogAt(level log.LogLevel) error {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000115 loggerFunc := logger.Debugw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800116 switch level {
117 case log.InfoLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000118 loggerFunc = logger.Infow
David K. Bainbridge794735f2020-02-11 21:01:37 -0800119 case log.WarnLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000120 loggerFunc = logger.Warnw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800121 case log.ErrorLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000122 loggerFunc = logger.Errorw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800123 case log.FatalLevel:
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000124 loggerFunc = logger.Fatalw
David K. Bainbridge794735f2020-02-11 21:01:37 -0800125 }
126 local := e.fields
127 if e.wrapped != nil {
128 local = merge(e.fields, log.Fields{"wrapped": e.wrapped})
129 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000130 loggerFunc(context.Background(), e.name, local)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800131 return e
132}
133
134// ErrInvalidValue represents an error condition with given value is not able to
135// be processed
136type ErrInvalidValue struct {
137 ErrAdapter
138}
139
140// NewErrInvalidValue constructs a new error based on the given values
141func NewErrInvalidValue(fields log.Fields, wrapped error) LoggableError {
142 return &ErrInvalidValue{
143 ErrAdapter{
144 name: "invalid-value",
145 fields: copy(fields),
146 wrapped: wrapped,
147 },
148 }
149}
150
151// Log logs the error at the default level for log and return
152func (e *ErrInvalidValue) Log() error {
153 _ = e.ErrAdapter.Log()
154 return e
155}
156
157// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000158func (e *ErrInvalidValue) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800159 _ = e.ErrAdapter.LogAt(level)
160 return e
161}
162
163// ErrNotFound represents an error condition when a value can not be located
164// given a field set of criteria
165type ErrNotFound struct {
166 ErrAdapter
167}
168
169// NewErrNotFound constructs a new error based on the given values
170func NewErrNotFound(target string, fields log.Fields, wrapped error) LoggableError {
171 return &ErrNotFound{
172 ErrAdapter{
173 name: "not-found",
174 fields: merge(fields, log.Fields{"target": target}),
175 wrapped: wrapped,
176 },
177 }
178}
179
180// Log logs the error at the default level for log and return
181func (e *ErrNotFound) Log() error {
182 _ = e.ErrAdapter.Log()
183 return e
184}
185
186// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000187func (e *ErrNotFound) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800188 _ = e.ErrAdapter.LogAt(level)
189 return e
190}
191
192// ErrPersistence representation an error condition when a persistence operation
193// did not succeed
194type ErrPersistence struct {
195 ErrAdapter
196}
197
198// NewErrPersistence constructs a new error based on the given values
199func NewErrPersistence(operation, entityType string, ID uint32, fields log.Fields, wrapped error) LoggableError {
200 return &ErrPersistence{
201 ErrAdapter{
202 name: "unable-to-persist",
203 fields: merge(fields, log.Fields{
204 "operation": operation,
205 "entity-type": entityType,
206 "id": fmt.Sprintf("0x%x", ID)}),
207 wrapped: wrapped,
208 },
209 }
210}
211
212// Log logs the error at the default level for log and return
213func (e *ErrPersistence) Log() error {
214 _ = e.ErrAdapter.Log()
215 return e
216}
217
218// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000219func (e *ErrPersistence) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800220 _ = e.ErrAdapter.LogAt(level)
221 return e
222}
223
224// ErrCommunication representation an error condition when an interprocess
225// message communication fails
226type ErrCommunication struct {
227 ErrAdapter
228}
229
230// NewErrCommunication constructs a new error based on the given values
231func NewErrCommunication(operation string, fields log.Fields, wrapped error) LoggableError {
232 return &ErrCommunication{
233 ErrAdapter{
234 name: "failed-communication",
235 fields: merge(fields, log.Fields{
236 "operation": operation}),
237 wrapped: wrapped,
238 },
239 }
240}
241
242// Log logs the error at the default level for log and return
243func (e *ErrCommunication) Log() error {
244 _ = e.ErrAdapter.Log()
245 return e
246}
247
248// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000249func (e *ErrCommunication) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800250 _ = e.ErrAdapter.LogAt(level)
251 return e
252}
253
254// ErrFlowOp represents an error condition when a flow operation to a device did
255// not succeed
256type ErrFlowOp struct {
257 ErrAdapter
258}
259
260// NewErrFlowOp constructs a new error based on the given values
261func NewErrFlowOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
262 return &ErrPersistence{
263 ErrAdapter{
264 name: "unable-to-perform-flow-operation",
265 fields: merge(fields, log.Fields{
266 "operation": operation,
267 "id": fmt.Sprintf("0x%x", ID)}),
268 wrapped: wrapped,
269 },
270 }
271}
272
273// Log logs the error at the default level for log and return
274func (e *ErrFlowOp) Log() error {
275 _ = e.ErrAdapter.Log()
276 return e
277}
278
279// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000280func (e *ErrFlowOp) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800281 _ = e.ErrAdapter.LogAt(level)
282 return e
283}
284
Andrea Campanellac63bba92020-03-10 17:01:04 +0100285// ErrGroupOp represents an error condition when a group operation to a device did
286// not succeed
287type ErrGroupOp struct {
288 ErrAdapter
289}
290
291// NewErrGroupOp constructs a new error based on the given values
292func NewErrGroupOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
293 return &ErrPersistence{
294 ErrAdapter{
295 name: "unable-to-perform-group-operation",
296 fields: merge(fields, log.Fields{
297 "operation": operation,
298 "id": fmt.Sprintf("0x%x", ID)}),
299 wrapped: wrapped,
300 },
301 }
302}
303
304// Log logs the error at the default level for log and return
305func (e *ErrGroupOp) Log() error {
306 _ = e.ErrAdapter.Log()
307 return e
308}
309
310// LogAt logs the error at the specified level and then returns the error
311func (e *ErrGroupOp) LogAt(level log.LogLevel) error {
312 _ = e.ErrAdapter.LogAt(level)
313 return e
314}
315
David K. Bainbridge794735f2020-02-11 21:01:37 -0800316// ErrTimeout represents an error condition when the deadline for performing an
317// operation has been exceeded
318type ErrTimeout struct {
319 ErrAdapter
320}
321
322// NewErrTimeout constructs a new error based on the given values
323func NewErrTimeout(operation string, fields log.Fields, wrapped error) LoggableError {
324 return &ErrTimeout{
325 ErrAdapter{
326 name: "operation-timed-out",
327 fields: merge(fields, log.Fields{"operation": operation}),
328 wrapped: wrapped,
329 },
330 }
331}
332
333// Log logs the error at the default level for log and return
334func (e *ErrTimeout) Log() error {
335 _ = e.ErrAdapter.Log()
336 return e
337}
338
339// LogAt logs the error at the specified level and then returns the error
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000340func (e *ErrTimeout) LogAt(level log.LogLevel) error {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800341 _ = e.ErrAdapter.LogAt(level)
342 return e
343}
344
345var (
346 // ErrNotImplemented error returned when an unimplemented method is
347 // invoked
348 ErrNotImplemented = NewErrAdapter("not-implemented", nil, nil)
349
350 // ErrInvalidPortRange error returned when a given port is not in the
351 // valid range
352 ErrInvalidPortRange = NewErrAdapter("invalid-port-range", nil, nil)
353
354 // ErrStateTransition error returned when a state transition is fails
355 ErrStateTransition = NewErrAdapter("state-transition", nil, nil)
356
357 // ErrResourceManagerInstantiating error returned when an unexpected
358 // condition occcurs while instantiating the resource manager
359 ErrResourceManagerInstantiating = NewErrAdapter("resoure-manager-instantiating", nil, nil)
360)