opentelemetry-collector/component/componentstatus/instance.go

92 lines
2.5 KiB
Go

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package componentstatus // import "go.opentelemetry.io/collector/component/componentstatus"
import (
"slices"
"sort"
"strings"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pipeline"
)
// pipelineDelim is the delimiter for internal representation of pipeline
// component IDs.
const pipelineDelim = byte(0x20)
// InstanceID uniquely identifies a component instance
//
// TODO: consider moving this struct to a new package/module like `extension/statuswatcher`
// https://github.com/open-telemetry/opentelemetry-collector/issues/10764
type InstanceID struct {
componentID component.ID
kind component.Kind
pipelineIDs string // IDs encoded as a string so InstanceID is Comparable.
}
// NewInstanceID returns an ID that uniquely identifies a component.
func NewInstanceID(componentID component.ID, kind component.Kind, pipelineIDs ...pipeline.ID) *InstanceID {
instanceID := &InstanceID{
componentID: componentID,
kind: kind,
}
instanceID.addPipelines(pipelineIDs)
return instanceID
}
// ComponentID returns the ComponentID associated with this instance.
func (id *InstanceID) ComponentID() component.ID {
return id.componentID
}
// Kind returns the component Kind associated with this instance.
func (id *InstanceID) Kind() component.Kind {
return id.kind
}
// AllPipelineIDs calls f for each pipeline this instance is associated with. If
// f returns false it will stop iteration.
func (id *InstanceID) AllPipelineIDs(f func(pipeline.ID) bool) {
var bs []byte
for _, b := range []byte(id.pipelineIDs) {
if b != pipelineDelim {
bs = append(bs, b)
continue
}
pipelineID := pipeline.ID{}
err := pipelineID.UnmarshalText(bs)
bs = bs[:0]
if err != nil {
continue
}
if !f(pipelineID) {
break
}
}
}
// WithPipelines returns a new InstanceID updated to include the given
// pipelineIDs.
func (id *InstanceID) WithPipelines(pipelineIDs ...pipeline.ID) *InstanceID {
instanceID := &InstanceID{
componentID: id.componentID,
kind: id.kind,
pipelineIDs: id.pipelineIDs,
}
instanceID.addPipelines(pipelineIDs)
return instanceID
}
func (id *InstanceID) addPipelines(pipelineIDs []pipeline.ID) {
delim := string(pipelineDelim)
strIDs := strings.Split(id.pipelineIDs, delim)
for _, pID := range pipelineIDs {
strIDs = append(strIDs, pID.String())
}
sort.Strings(strIDs)
strIDs = slices.Compact(strIDs)
id.pipelineIDs = strings.Join(strIDs, delim) + delim
}