1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2024-12-04 09:43:23 +02:00

OT resource detector (#939)

* first

* all included

* constant

* res keys

* env detector

* Update sdk/detect/env.go

Co-authored-by: Anthony Mirabella <a9@aneurysm9.com>

* new test cases and strings operation to handle labels

* solved conflict

* typo

* corrected comments

* deleted env var handling

* push again

* rerun

* restructuring

* new way to aggregate errors

* all in resources package and verbose comments

* solved merge conflicts

* included new error types

* improved error handling

* updated changelog.md

* updated changelog

* updated changelog.md

* updated changelog

* Update CHANGELOG.md

Co-authored-by: Anthony Mirabella <a9@aneurysm9.com>
Co-authored-by: Liz Fong-Jones <lizf@honeycomb.io>
Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
This commit is contained in:
YANYZP 2020-07-20 11:43:51 -04:00 committed by GitHub
parent b2b23e15e5
commit 99c299877d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 239 additions and 3 deletions

View File

@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Added
- Define a general Resources Detector Interface and allow resources to be detected from environment variables. (#939)
- Github action to generate protobuf Go bindings locally in `internal/opentelemetry-proto-gen`. (#938)
- OTLP .proto files from `open-telemetry/opentelemetry-proto` imported as a git submodule under `internal/opentelemetry-proto`.
References to `github.com/open-telemetry/opentelemetry-proto` changed to `go.opentelemetry.io/otel/internal/opentelemetry-proto-gen`. (#942)

67
sdk/resource/auto.go Normal file
View File

@ -0,0 +1,67 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package resource
import (
"context"
"errors"
"fmt"
)
var (
// ErrMissingResource is returned by a detector when source information
// is unavailable for a Resource.
ErrMissingResource = errors.New("missing resource")
// ErrPartialResource is returned by a detector when complete source
// information for a Resource is unavailable or the source information
// contains invalid values that are omitted from the returned Resource.
ErrPartialResource = errors.New("partial resource")
)
// Detector detects OpenTelemetry resource information
type Detector interface {
// Detect returns an initialized Resource based on gathered information.
// If source information to construct a Resource is inaccessible, an
// uninitialized Resource is returned with an appropriately wrapped
// ErrMissingResource error is returned. If the source information to
// construct a Resource contains invalid values, a Resource is returned
// with the valid parts of the source information used for
// initialization along with an appropriately wrapped ErrPartialResource
// error.
Detect(ctx context.Context) (*Resource, error)
}
// Detect calls all input detectors sequentially and merges each result with the previous one.
// It returns the merged error too.
func Detect(ctx context.Context, detectors ...Detector) (*Resource, error) {
var autoDetectedRes *Resource
var errInfo []string
for _, detector := range detectors {
res, err := detector.Detect(ctx)
if err != nil {
errInfo = append(errInfo, err.Error())
if !errors.Is(err, ErrPartialResource) {
continue
}
}
autoDetectedRes = Merge(autoDetectedRes, res)
}
var aggregatedError error
if len(errInfo) > 0 {
aggregatedError = fmt.Errorf("detecting resources: %s", errInfo)
}
return autoDetectedRes, aggregatedError
}

28
sdk/resource/doc.go Normal file
View File

@ -0,0 +1,28 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package resource provides detecting and representing resources.
//
// The fundamental struct is a Resource which holds identifying information
// about the entities for which telemetry is exported.
//
// To automatically construct Resources from an environment a Detector
// interface is defined. Implementations of this interface can be passed to
// the Detect function to generate a Resource from the merged information.
//
// To load a user defined Resource from the environment variable
// OTEL_RESOURCE_LABELS the FromEnv Detector can be used. It will interpret
// the value as a list of comma delimited key/value pairs
// (e.g. `<key1>=<value1>,<key2>=<value2>,...`).
package resource

69
sdk/resource/env.go Normal file
View File

@ -0,0 +1,69 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package resource
import (
"context"
"fmt"
"os"
"strings"
"go.opentelemetry.io/otel/api/kv"
)
// envVar is the environment variable name OpenTelemetry Resource information can be assigned to.
const envVar = "OTEL_RESOURCE_LABELS"
var (
//errMissingValue is returned when a resource value is missing.
errMissingValue = fmt.Errorf("%w: missing value", ErrPartialResource)
)
// FromEnv is a detector that implements the Detector and collects resources
// from environment
type FromEnv struct{}
// compile time assertion that FromEnv implements Detector interface
var _ Detector = (*FromEnv)(nil)
// Detect collects resources from environment
func (d *FromEnv) Detect(context.Context) (*Resource, error) {
labels := strings.TrimSpace(os.Getenv(envVar))
if labels == "" {
return Empty(), ErrMissingResource
}
return constructOTResources(labels)
}
func constructOTResources(s string) (*Resource, error) {
pairs := strings.Split(s, ",")
labels := []kv.KeyValue{}
var invalid []string
for _, p := range pairs {
field := strings.SplitN(p, "=", 2)
if len(field) != 2 {
invalid = append(invalid, p)
continue
}
k, v := strings.TrimSpace(field[0]), strings.TrimSpace(field[1])
labels = append(labels, kv.String(k, v))
}
var err error
if len(invalid) > 0 {
err = fmt.Errorf("%w: %v", errMissingValue, invalid)
}
return New(labels...), err
}

73
sdk/resource/env_test.go Normal file
View File

@ -0,0 +1,73 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package resource
import (
"context"
"fmt"
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/api/kv"
)
func TestDetectOnePair(t *testing.T) {
os.Setenv(envVar, "key=value")
detector := &FromEnv{}
res, err := detector.Detect(context.Background())
require.NoError(t, err)
assert.Equal(t, New(kv.String("key", "value")), res)
}
func TestDetectMultiPairs(t *testing.T) {
os.Setenv("x", "1")
os.Setenv(envVar, "key=value, k = v , a= x, a=z")
detector := &FromEnv{}
res, err := detector.Detect(context.Background())
require.NoError(t, err)
assert.Equal(t, res, New(
kv.String("key", "value"),
kv.String("k", "v"),
kv.String("a", "x"),
kv.String("a", "z"),
))
}
func TestEmpty(t *testing.T) {
os.Setenv(envVar, "")
detector := &FromEnv{}
res, err := detector.Detect(context.Background())
require.Error(t, err)
assert.Equal(t, err, ErrMissingResource)
assert.Equal(t, Empty(), res)
}
func TestMissingKeyError(t *testing.T) {
os.Setenv(envVar, "key=value,key")
detector := &FromEnv{}
res, err := detector.Detect(context.Background())
assert.Error(t, err)
assert.Equal(t, err, fmt.Errorf("%w: %v", errMissingValue, "[key]"))
assert.Equal(t, res, New(
kv.String("key", "value"),
))
}

View File

@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Package resource provides functionality for resource, which capture
// identifying information about the entities for which signals are exported.
package resource
import (
@ -34,7 +32,7 @@ type Resource struct {
var emptyResource Resource
// Key creates a resource from a set of attributes. If there are
// New creates a resource from a set of attributes. If there are
// duplicate keys present in the list of attributes, then the last
// value found for the key is preserved.
func New(kvs ...kv.KeyValue) *Resource {