1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
3 4 package codes // import "go.opentelemetry.io/otel/codes"
5 6 import (
7 "encoding/json"
8 "errors"
9 "fmt"
10 "strconv"
11 )
12 13 const (
14 // Unset is the default status code.
15 Unset Code = 0
16 17 // Error indicates the operation contains an error.
18 //
19 // NOTE: The error code in OTLP is 2.
20 // The value of this enum is only relevant to the internals
21 // of the Go SDK.
22 Error Code = 1
23 24 // Ok indicates operation has been validated by an Application developers
25 // or Operator to have completed successfully, or contain no error.
26 //
27 // NOTE: The Ok code in OTLP is 1.
28 // The value of this enum is only relevant to the internals
29 // of the Go SDK.
30 Ok Code = 2
31 32 maxCode = 3
33 )
34 35 // Code is an 32-bit representation of a status state.
36 type Code uint32
37 38 var codeToStr = map[Code]string{
39 Unset: "Unset",
40 Error: "Error",
41 Ok: "Ok",
42 }
43 44 var strToCode = map[string]Code{
45 `"Unset"`: Unset,
46 `"Error"`: Error,
47 `"Ok"`: Ok,
48 }
49 50 // String returns the Code as a string.
51 func (c Code) String() string {
52 return codeToStr[c]
53 }
54 55 // UnmarshalJSON unmarshals b into the Code.
56 //
57 // This is based on the functionality in the gRPC codes package:
58 // https://github.com/grpc/grpc-go/blob/bb64fee312b46ebee26be43364a7a966033521b1/codes/codes.go#L218-L244
59 func (c *Code) UnmarshalJSON(b []byte) error {
60 // From json.Unmarshaler: By convention, to approximate the behavior of
61 // Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
62 // a no-op.
63 if string(b) == "null" {
64 return nil
65 }
66 if c == nil {
67 return errors.New("nil receiver passed to UnmarshalJSON")
68 }
69 70 var x any
71 if err := json.Unmarshal(b, &x); err != nil {
72 return err
73 }
74 switch x.(type) {
75 case string:
76 if jc, ok := strToCode[string(b)]; ok {
77 *c = jc
78 return nil
79 }
80 return fmt.Errorf("invalid code: %q", string(b))
81 case float64:
82 if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
83 if ci >= maxCode {
84 return fmt.Errorf("invalid code: %q", ci)
85 }
86 87 *c = Code(ci) // nolint: gosec // Bit size of 32 check above.
88 return nil
89 }
90 return fmt.Errorf("invalid code: %q", string(b))
91 default:
92 return fmt.Errorf("invalid code: %q", string(b))
93 }
94 }
95 96 // MarshalJSON returns c as the JSON encoding of c.
97 func (c *Code) MarshalJSON() ([]byte, error) {
98 if c == nil {
99 return []byte("null"), nil
100 }
101 str, ok := codeToStr[*c]
102 if !ok {
103 return nil, fmt.Errorf("invalid code: %d", *c)
104 }
105 return fmt.Appendf(nil, "%q", str), nil
106 }
107