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 15package config 16 17import ( 18 "errors" 19 "strings" 20) 21 22// typeAndNameSeparator is the separator that is used between type and name in type/name composite keys. 23const typeAndNameSeparator = "/" 24 25// identifiable is an interface that all components configurations MUST embed. 26type identifiable interface { 27 // ID returns the ID of the component that this configuration belongs to. 28 ID() ComponentID 29 // SetIDName updates the name part of the ID for the component that this configuration belongs to. 30 SetIDName(idName string) 31} 32 33// ComponentID represents the identity for a component. It combines two values: 34// * type - the Type of the component. 35// * name - the name of that component. 36// The component ComponentID (combination type + name) is unique for a given component.Kind. 37type ComponentID struct { 38 typeVal Type `mapstructure:"-"` 39 nameVal string `mapstructure:"-"` 40} 41 42// NewID returns a new ComponentID with the given Type and empty name. 43func NewID(typeVal Type) ComponentID { 44 return ComponentID{typeVal: typeVal} 45} 46 47// NewIDWithName returns a new ComponentID with the given Type and name. 48func NewIDWithName(typeVal Type, nameVal string) ComponentID { 49 return ComponentID{typeVal: typeVal, nameVal: nameVal} 50} 51 52// NewIDFromString decodes a string in type[/name] format into ComponentID. 53// The type and name components will have spaces trimmed, the "type" part must be present, 54// the forward slash and "name" are optional. 55// The returned ComponentID will be invalid if err is not-nil. 56func NewIDFromString(idStr string) (ComponentID, error) { 57 items := strings.SplitN(idStr, typeAndNameSeparator, 2) 58 59 id := ComponentID{} 60 if len(items) >= 1 { 61 id.typeVal = Type(strings.TrimSpace(items[0])) 62 } 63 64 if len(items) == 0 || id.typeVal == "" { 65 return id, errors.New("idStr must have non empty type") 66 } 67 68 if len(items) > 1 { 69 // "name" part is present. 70 id.nameVal = strings.TrimSpace(items[1]) 71 if id.nameVal == "" { 72 return id, errors.New("name part must be specified after " + typeAndNameSeparator + " in type/name key") 73 } 74 } 75 76 return id, nil 77} 78 79// Type returns the type of the component. 80func (id ComponentID) Type() Type { 81 return id.typeVal 82} 83 84// Name returns the custom name of the component. 85func (id ComponentID) Name() string { 86 return id.nameVal 87} 88 89// String returns the ComponentID string representation as "type[/name]" format. 90func (id ComponentID) String() string { 91 if id.nameVal == "" { 92 return string(id.typeVal) 93 } 94 95 return string(id.typeVal) + typeAndNameSeparator + id.nameVal 96} 97