codes.go

  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}