blob: b6965293f7e4350ec5d30d45304e6eae5b48f40e [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
17// Package adaptercore provides the utility for olt devices, flows and statistics
18package adaptercore
19
20import (
21 "encoding/json"
22 "fmt"
23 "github.com/opencord/voltha-lib-go/v3/pkg/log"
24 "strings"
25)
26
27const (
28 defaultLogAndReturnLevel = log.DebugLevel
29)
30
31func copy(src log.Fields) log.Fields {
32 dst := make(log.Fields)
33 for k, v := range src {
34 dst[k] = v
35 }
36 return dst
37}
38
39func merge(one, two log.Fields) log.Fields {
40 dst := make(log.Fields)
41 for k, v := range one {
42 dst[k] = v
43 }
44 for k, v := range two {
45 dst[k] = v
46 }
47 return dst
48}
49
50// LoggableError defined functions that can be used to log an object
51type LoggableError interface {
52 error
53 Log() error
54 LogAt(int) error
55}
56
57// ErrAdapter represents a basic adapter error that combines an name, field set
58// and wrapped error
59type ErrAdapter struct {
60 name string
61 fields log.Fields
62 wrapped error
63}
64
65// NewErrAdapter constructs a new error with the given values
66func NewErrAdapter(name string, fields log.Fields, wrapped error) LoggableError {
67 return &ErrAdapter{
68 name: name,
69 fields: copy(fields),
70 wrapped: wrapped,
71 }
72}
73
74// Name returns the error name
75func (e *ErrAdapter) Name() string {
76 return e.name
77}
78
79// Fields returns the fields associated with the error
80func (e *ErrAdapter) Fields() log.Fields {
81 return e.fields
82}
83
84// Unwrap returns the wrapped or nested error
85func (e *ErrAdapter) Unwrap() error {
86 return e.wrapped
87}
88
89// Error returns a string representation of the error
90func (e *ErrAdapter) Error() string {
91 var buf strings.Builder
92 buf.WriteString(e.name)
93 if len(e.fields) > 0 {
94 if val, err := json.Marshal(e.fields); err == nil {
95 buf.WriteString(": [")
96 buf.WriteString(string(val))
97 buf.WriteString("]")
98 }
99 }
100 if e.wrapped != nil {
101 buf.WriteString(": ")
102 buf.WriteString(e.wrapped.Error())
103 }
104 return buf.String()
105}
106
107// Log logs the error at the default level for log and return
108func (e *ErrAdapter) Log() error {
109 return e.LogAt(defaultLogAndReturnLevel)
110}
111
112// LogAt logs the error at the specified level and then returns the error
113func (e *ErrAdapter) LogAt(level int) error {
114 logger := log.Debugw
115 switch level {
116 case log.InfoLevel:
117 logger = log.Infow
118 case log.WarnLevel:
119 logger = log.Warnw
120 case log.ErrorLevel:
121 logger = log.Errorw
122 case log.FatalLevel:
123 logger = log.Fatalw
124 }
125 local := e.fields
126 if e.wrapped != nil {
127 local = merge(e.fields, log.Fields{"wrapped": e.wrapped})
128 }
129 logger(e.name, local)
130 return e
131}
132
133// ErrInvalidValue represents an error condition with given value is not able to
134// be processed
135type ErrInvalidValue struct {
136 ErrAdapter
137}
138
139// NewErrInvalidValue constructs a new error based on the given values
140func NewErrInvalidValue(fields log.Fields, wrapped error) LoggableError {
141 return &ErrInvalidValue{
142 ErrAdapter{
143 name: "invalid-value",
144 fields: copy(fields),
145 wrapped: wrapped,
146 },
147 }
148}
149
150// Log logs the error at the default level for log and return
151func (e *ErrInvalidValue) Log() error {
152 _ = e.ErrAdapter.Log()
153 return e
154}
155
156// LogAt logs the error at the specified level and then returns the error
157func (e *ErrInvalidValue) LogAt(level int) error {
158 _ = e.ErrAdapter.LogAt(level)
159 return e
160}
161
162// ErrNotFound represents an error condition when a value can not be located
163// given a field set of criteria
164type ErrNotFound struct {
165 ErrAdapter
166}
167
168// NewErrNotFound constructs a new error based on the given values
169func NewErrNotFound(target string, fields log.Fields, wrapped error) LoggableError {
170 return &ErrNotFound{
171 ErrAdapter{
172 name: "not-found",
173 fields: merge(fields, log.Fields{"target": target}),
174 wrapped: wrapped,
175 },
176 }
177}
178
179// Log logs the error at the default level for log and return
180func (e *ErrNotFound) Log() error {
181 _ = e.ErrAdapter.Log()
182 return e
183}
184
185// LogAt logs the error at the specified level and then returns the error
186func (e *ErrNotFound) LogAt(level int) error {
187 _ = e.ErrAdapter.LogAt(level)
188 return e
189}
190
191// ErrPersistence representation an error condition when a persistence operation
192// did not succeed
193type ErrPersistence struct {
194 ErrAdapter
195}
196
197// NewErrPersistence constructs a new error based on the given values
198func NewErrPersistence(operation, entityType string, ID uint32, fields log.Fields, wrapped error) LoggableError {
199 return &ErrPersistence{
200 ErrAdapter{
201 name: "unable-to-persist",
202 fields: merge(fields, log.Fields{
203 "operation": operation,
204 "entity-type": entityType,
205 "id": fmt.Sprintf("0x%x", ID)}),
206 wrapped: wrapped,
207 },
208 }
209}
210
211// Log logs the error at the default level for log and return
212func (e *ErrPersistence) Log() error {
213 _ = e.ErrAdapter.Log()
214 return e
215}
216
217// LogAt logs the error at the specified level and then returns the error
218func (e *ErrPersistence) LogAt(level int) error {
219 _ = e.ErrAdapter.LogAt(level)
220 return e
221}
222
223// ErrCommunication representation an error condition when an interprocess
224// message communication fails
225type ErrCommunication struct {
226 ErrAdapter
227}
228
229// NewErrCommunication constructs a new error based on the given values
230func NewErrCommunication(operation string, fields log.Fields, wrapped error) LoggableError {
231 return &ErrCommunication{
232 ErrAdapter{
233 name: "failed-communication",
234 fields: merge(fields, log.Fields{
235 "operation": operation}),
236 wrapped: wrapped,
237 },
238 }
239}
240
241// Log logs the error at the default level for log and return
242func (e *ErrCommunication) Log() error {
243 _ = e.ErrAdapter.Log()
244 return e
245}
246
247// LogAt logs the error at the specified level and then returns the error
248func (e *ErrCommunication) LogAt(level int) error {
249 _ = e.ErrAdapter.LogAt(level)
250 return e
251}
252
253// ErrFlowOp represents an error condition when a flow operation to a device did
254// not succeed
255type ErrFlowOp struct {
256 ErrAdapter
257}
258
259// NewErrFlowOp constructs a new error based on the given values
260func NewErrFlowOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
261 return &ErrPersistence{
262 ErrAdapter{
263 name: "unable-to-perform-flow-operation",
264 fields: merge(fields, log.Fields{
265 "operation": operation,
266 "id": fmt.Sprintf("0x%x", ID)}),
267 wrapped: wrapped,
268 },
269 }
270}
271
272// Log logs the error at the default level for log and return
273func (e *ErrFlowOp) Log() error {
274 _ = e.ErrAdapter.Log()
275 return e
276}
277
278// LogAt logs the error at the specified level and then returns the error
279func (e *ErrFlowOp) LogAt(level int) error {
280 _ = e.ErrAdapter.LogAt(level)
281 return e
282}
283
284// ErrTimeout represents an error condition when the deadline for performing an
285// operation has been exceeded
286type ErrTimeout struct {
287 ErrAdapter
288}
289
290// NewErrTimeout constructs a new error based on the given values
291func NewErrTimeout(operation string, fields log.Fields, wrapped error) LoggableError {
292 return &ErrTimeout{
293 ErrAdapter{
294 name: "operation-timed-out",
295 fields: merge(fields, log.Fields{"operation": operation}),
296 wrapped: wrapped,
297 },
298 }
299}
300
301// Log logs the error at the default level for log and return
302func (e *ErrTimeout) Log() error {
303 _ = e.ErrAdapter.Log()
304 return e
305}
306
307// LogAt logs the error at the specified level and then returns the error
308func (e *ErrTimeout) LogAt(level int) error {
309 _ = e.ErrAdapter.LogAt(level)
310 return e
311}
312
313var (
314 // ErrNotImplemented error returned when an unimplemented method is
315 // invoked
316 ErrNotImplemented = NewErrAdapter("not-implemented", nil, nil)
317
318 // ErrInvalidPortRange error returned when a given port is not in the
319 // valid range
320 ErrInvalidPortRange = NewErrAdapter("invalid-port-range", nil, nil)
321
322 // ErrStateTransition error returned when a state transition is fails
323 ErrStateTransition = NewErrAdapter("state-transition", nil, nil)
324
325 // ErrResourceManagerInstantiating error returned when an unexpected
326 // condition occcurs while instantiating the resource manager
327 ErrResourceManagerInstantiating = NewErrAdapter("resoure-manager-instantiating", nil, nil)
328)