1// Copyright The OpenTelemetry Authors
2// SPDX-License-Identifier: Apache-2.0
3
4package codes // import "go.opentelemetry.io/otel/codes"
5
6import (
7 "encoding/json"
8 "errors"
9 "fmt"
10 "strconv"
11)
12
13const (
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.
36type Code uint32
37
38var codeToStr = map[Code]string{
39 Unset: "Unset",
40 Error: "Error",
41 Ok: "Ok",
42}
43
44var strToCode = map[string]Code{
45 `"Unset"`: Unset,
46 `"Error"`: Error,
47 `"Ok"`: Ok,
48}
49
50// String returns the Code as a string.
51func (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
59func (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 interface{}
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.
97func (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 []byte(fmt.Sprintf("%q", str)), nil
106}