1 // Copyright 2018, OpenCensus Authors
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 // Package resource provides functionality for resource, which capture
16 // identifying information about the entities for which signals are exported.
29 // Environment variables used by FromEnv to decode a resource.
31 EnvVarType = "OC_RESOURCE_TYPE"
32 EnvVarLabels = "OC_RESOURCE_LABELS"
35 // Resource describes an entity about which identifying information and metadata is exposed.
36 // For example, a type "k8s.io/container" may hold labels describing the pod name and namespace.
37 type Resource struct {
39 Labels map[string]string
42 // EncodeLabels encodes a labels map to a string as provided via the OC_RESOURCE_LABELS environment variable.
43 func EncodeLabels(labels map[string]string) string {
44 sortedKeys := make([]string, 0, len(labels))
45 for k := range labels {
46 sortedKeys = append(sortedKeys, k)
48 sort.Strings(sortedKeys)
51 for i, k := range sortedKeys {
55 s += k + "=" + strconv.Quote(labels[k])
60 var labelRegex = regexp.MustCompile(`^\s*([[:ascii:]]{1,256}?)=("[[:ascii:]]{0,256}?")\s*,`)
62 // DecodeLabels decodes a serialized label map as used in the OC_RESOURCE_LABELS variable.
63 // A list of labels of the form `<key1>="<value1>",<key2>="<value2>",...` is accepted.
64 // Domain names and paths are accepted as label keys.
65 // Most users will want to use FromEnv instead.
66 func DecodeLabels(s string) (map[string]string, error) {
67 m := map[string]string{}
68 // Ensure a trailing comma, which allows us to keep the regex simpler
69 s = strings.TrimRight(strings.TrimSpace(s), ",") + ","
72 match := labelRegex.FindStringSubmatch(s)
74 return nil, fmt.Errorf("invalid label formatting, remainder: %s", s)
81 if v, err = strconv.Unquote(v); err != nil {
82 return nil, fmt.Errorf("invalid label formatting, remainder: %s, err: %s", s, err)
92 // FromEnv is a detector that loads resource information from the OC_RESOURCE_TYPE
93 // and OC_RESOURCE_labelS environment variables.
94 func FromEnv(context.Context) (*Resource, error) {
96 Type: strings.TrimSpace(os.Getenv(EnvVarType)),
98 labels := strings.TrimSpace(os.Getenv(EnvVarLabels))
103 if res.Labels, err = DecodeLabels(labels); err != nil {
109 var _ Detector = FromEnv
111 // merge resource information from b into a. In case of a collision, a takes precedence.
112 func merge(a, b *Resource) *Resource {
121 Labels: map[string]string{},
126 for k, v := range b.Labels {
129 // Labels from resource a overwrite labels from resource b.
130 for k, v := range a.Labels {
136 // Detector attempts to detect resource information.
137 // If the detector cannot find resource information, the returned resource is nil but no
138 // error is returned.
139 // An error is only returned on unexpected failures.
140 type Detector func(context.Context) (*Resource, error)
142 // MultiDetector returns a Detector that calls all input detectors in order and
143 // merges each result with the previous one. In case a type of label key is already set,
144 // the first set value is takes precedence.
145 // It returns on the first error that a sub-detector encounters.
146 func MultiDetector(detectors ...Detector) Detector {
147 return func(ctx context.Context) (*Resource, error) {
148 return detectAll(ctx, detectors...)
152 // detectall calls all input detectors sequentially an merges each result with the previous one.
153 // It returns on the first error that a sub-detector encounters.
154 func detectAll(ctx context.Context, detectors ...Detector) (*Resource, error) {
156 for _, d := range detectors {