auto.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright The OpenTelemetry Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package resource // import "go.opentelemetry.io/otel/sdk/resource"
  15. import (
  16. "context"
  17. "errors"
  18. "fmt"
  19. "strings"
  20. )
  21. var (
  22. // ErrPartialResource is returned by a detector when complete source
  23. // information for a Resource is unavailable or the source information
  24. // contains invalid values that are omitted from the returned Resource.
  25. ErrPartialResource = errors.New("partial resource")
  26. )
  27. // Detector detects OpenTelemetry resource information.
  28. type Detector interface {
  29. // DO NOT CHANGE: any modification will not be backwards compatible and
  30. // must never be done outside of a new major release.
  31. // Detect returns an initialized Resource based on gathered information.
  32. // If the source information to construct a Resource contains invalid
  33. // values, a Resource is returned with the valid parts of the source
  34. // information used for initialization along with an appropriately
  35. // wrapped ErrPartialResource error.
  36. Detect(ctx context.Context) (*Resource, error)
  37. // DO NOT CHANGE: any modification will not be backwards compatible and
  38. // must never be done outside of a new major release.
  39. }
  40. // Detect calls all input detectors sequentially and merges each result with the previous one.
  41. // It returns the merged error too.
  42. func Detect(ctx context.Context, detectors ...Detector) (*Resource, error) {
  43. r := new(Resource)
  44. return r, detect(ctx, r, detectors)
  45. }
  46. // detect runs all detectors using ctx and merges the result into res. This
  47. // assumes res is allocated and not nil, it will panic otherwise.
  48. func detect(ctx context.Context, res *Resource, detectors []Detector) error {
  49. var (
  50. r *Resource
  51. errs detectErrs
  52. err error
  53. )
  54. for _, detector := range detectors {
  55. if detector == nil {
  56. continue
  57. }
  58. r, err = detector.Detect(ctx)
  59. if err != nil {
  60. errs = append(errs, err)
  61. if !errors.Is(err, ErrPartialResource) {
  62. continue
  63. }
  64. }
  65. r, err = Merge(res, r)
  66. if err != nil {
  67. errs = append(errs, err)
  68. }
  69. *res = *r
  70. }
  71. if len(errs) == 0 {
  72. return nil
  73. }
  74. return errs
  75. }
  76. type detectErrs []error
  77. func (e detectErrs) Error() string {
  78. errStr := make([]string, len(e))
  79. for i, err := range e {
  80. errStr[i] = fmt.Sprintf("* %s", err)
  81. }
  82. format := "%d errors occurred detecting resource:\n\t%s"
  83. return fmt.Sprintf(format, len(e), strings.Join(errStr, "\n\t"))
  84. }
  85. func (e detectErrs) Unwrap() error {
  86. switch len(e) {
  87. case 0:
  88. return nil
  89. case 1:
  90. return e[0]
  91. }
  92. return e[1:]
  93. }
  94. func (e detectErrs) Is(target error) bool {
  95. return len(e) != 0 && errors.Is(e[0], target)
  96. }