Skip to content

Commit

Permalink
Add a otelcol.processor.resourcedetection component
Browse files Browse the repository at this point in the history
  • Loading branch information
ptodev committed Nov 14, 2023
1 parent 65d35ec commit a6191b2
Show file tree
Hide file tree
Showing 21 changed files with 2,120 additions and 0 deletions.
25 changes: 25 additions & 0 deletions component/otelcol/config_k8s.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package otelcol

import "fmt"

// KubernetesAPIConfig contains options relevant to connecting to the K8s API
type KubernetesAPIConfig struct {
// How to authenticate to the K8s API server. This can be one of `none`
// (for no auth), `serviceAccount` (to use the standard service account
// token provided to the agent pod), or `kubeConfig` to use credentials
// from `~/.kube/config`.
AuthType string `river:"auth_type,attr,optional"`

// When using auth_type `kubeConfig`, override the current context.
Context string `river:"context,attr,optional"`
}

// Validate returns an error if the config is invalid.
func (c *KubernetesAPIConfig) Validate() error {
switch c.AuthType {
case "none", "serviceAccount", "kubeConfig", "tls":
return nil
default:
return fmt.Errorf("invalid auth_type %q", c.AuthType)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ec2

import rac "github.com/grafana/agent/component/otelcol/processor/resourcedetection/internal/resource_attribute_config"

// Config defines user-specified configurations unique to the EC2 detector
type Config struct {
// Tags is a list of regex's to match ec2 instance tag keys that users want
// to add as resource attributes to processed data
Tags []string `river:"tags,attr,optional"`
ResourceAttributes ResourceAttributesConfig `river:"resource_attributes,block"`
}

func (args *Config) Convert() map[string]interface{} {
var tags []string
if args.Tags != nil {
tags = append([]string{}, args.Tags...)
}

return map[string]interface{}{
"tags": tags,
"resource_attributes": args.ResourceAttributes.Convert(),
}
}

// ResourceAttributesConfig provides config for resourcedetectionprocessor/ec2 resource attributes.
type ResourceAttributesConfig struct {
CloudAccountID *rac.ResourceAttributeConfig `river:"cloud.account.id,block,optional"`
CloudAvailabilityZone *rac.ResourceAttributeConfig `river:"cloud.availability_zone,block,optional"`
CloudPlatform *rac.ResourceAttributeConfig `river:"cloud.platform,block,optional"`
CloudProvider *rac.ResourceAttributeConfig `river:"cloud.provider,block,optional"`
CloudRegion *rac.ResourceAttributeConfig `river:"cloud.region,block,optional"`
HostID *rac.ResourceAttributeConfig `river:"host.id,block,optional"`
HostImageID *rac.ResourceAttributeConfig `river:"host.image.id,block,optional"`
HostName *rac.ResourceAttributeConfig `river:"host.name,block,optional"`
HostType *rac.ResourceAttributeConfig `river:"host.type,block,optional"`
}

func (r *ResourceAttributesConfig) Convert() map[string]interface{} {
return map[string]interface{}{
"cloud.account.id": r.CloudAccountID.Convert(),
"cloud.availability_zone": r.CloudAvailabilityZone.Convert(),
"cloud.platform": r.CloudPlatform.Convert(),
"cloud.provider": r.CloudProvider.Convert(),
"cloud.region": r.CloudRegion.Convert(),
"host.id": r.HostID.Convert(),
"host.image.id": r.HostImageID.Convert(),
"host.name": r.HostName.Convert(),
"host.type": r.HostType.Convert(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ecs

import rac "github.com/grafana/agent/component/otelcol/processor/resourcedetection/internal/resource_attribute_config"

type Config struct {
ResourceAttributes ResourceAttributesConfig `river:"resource_attributes,block"`
}

func (args *Config) Convert() map[string]interface{} {
return map[string]interface{}{
"resource_attributes": args.ResourceAttributes.Convert(),
}
}

// ResourceAttributesConfig provides config for resourcedetectionprocessor/ecs resource attributes.
type ResourceAttributesConfig struct {
AwsEcsClusterArn *rac.ResourceAttributeConfig `river:"aws.ecs.cluster.arn,block,optional"`
AwsEcsLaunchtype *rac.ResourceAttributeConfig `river:"aws.ecs.launchtype,block,optional"`
AwsEcsTaskArn *rac.ResourceAttributeConfig `river:"aws.ecs.task.arn,block,optional"`
AwsEcsTaskFamily *rac.ResourceAttributeConfig `river:"aws.ecs.task.family,block,optional"`
AwsEcsTaskRevision *rac.ResourceAttributeConfig `river:"aws.ecs.task.revision,block,optional"`
AwsLogGroupArns *rac.ResourceAttributeConfig `river:"aws.log.group.arns,block,optional"`
AwsLogGroupNames *rac.ResourceAttributeConfig `river:"aws.log.group.names,block,optional"`
AwsLogStreamArns *rac.ResourceAttributeConfig `river:"aws.log.stream.arns,block,optional"`
AwsLogStreamNames *rac.ResourceAttributeConfig `river:"aws.log.stream.names,block,optional"`
CloudAccountID *rac.ResourceAttributeConfig `river:"cloud.account.id,block,optional"`
CloudAvailabilityZone *rac.ResourceAttributeConfig `river:"cloud.availability_zone,block,optional"`
CloudPlatform *rac.ResourceAttributeConfig `river:"cloud.platform,block,optional"`
CloudProvider *rac.ResourceAttributeConfig `river:"cloud.provider,block,optional"`
CloudRegion *rac.ResourceAttributeConfig `river:"cloud.region,block,optional"`
}

func (r *ResourceAttributesConfig) Convert() map[string]interface{} {
return map[string]interface{}{
"aws.ecs.cluster.arn": r.AwsEcsClusterArn.Convert(),
"aws.ecs.launchtype": r.AwsEcsLaunchtype.Convert(),
"aws.ecs.task.arn": r.AwsEcsTaskArn.Convert(),
"aws.ecs.task.family": r.AwsEcsTaskFamily.Convert(),
"aws.ecs.task.revision": r.AwsEcsTaskRevision.Convert(),
"aws.log.group.arns": r.AwsLogGroupArns.Convert(),
"aws.log.group.names": r.AwsLogGroupNames.Convert(),
"aws.log.stream.arns": r.AwsLogStreamArns.Convert(),
"aws.log.stream.names": r.AwsLogStreamNames.Convert(),
"cloud.account.id": r.CloudAccountID.Convert(),
"cloud.availability_zone": r.CloudAvailabilityZone.Convert(),
"cloud.platform": r.CloudPlatform.Convert(),
"cloud.provider": r.CloudProvider.Convert(),
"cloud.region": r.CloudRegion.Convert(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package eks

import rac "github.com/grafana/agent/component/otelcol/processor/resourcedetection/internal/resource_attribute_config"

type Config struct {
ResourceAttributes ResourceAttributesConfig `river:"resource_attributes,block"`
}

func (args *Config) Convert() map[string]interface{} {
return map[string]interface{}{
"resource_attributes": args.ResourceAttributes.Convert(),
}
}

// ResourceAttributesConfig provides config for resourcedetectionprocessor/eks resource attributes.
type ResourceAttributesConfig struct {
CloudPlatform *rac.ResourceAttributeConfig `river:"cloud.platform,block,optional"`
CloudProvider *rac.ResourceAttributeConfig `river:"cloud.provider,block,optional"`
}

func (r *ResourceAttributesConfig) Convert() map[string]interface{} {
return map[string]interface{}{
"cloud.platform": r.CloudPlatform.Convert(),
"cloud.provider": r.CloudProvider.Convert(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package elasticbeanstalk

import rac "github.com/grafana/agent/component/otelcol/processor/resourcedetection/internal/resource_attribute_config"

type Config struct {
ResourceAttributes ResourceAttributesConfig `river:"resource_attributes,block"`
}

func (args *Config) Convert() map[string]interface{} {
return map[string]interface{}{
"resource_attributes": args.ResourceAttributes.Convert(),
}
}

// ResourceAttributesConfig provides config for resourcedetectionprocessor/elastic_beanstalk resource attributes.
type ResourceAttributesConfig struct {
CloudPlatform *rac.ResourceAttributeConfig `river:"cloud.platform,block,optional"`
CloudProvider *rac.ResourceAttributeConfig `river:"cloud.provider,block,optional"`
DeploymentEnvironment *rac.ResourceAttributeConfig `river:"deployment.environment,block,optional"`
ServiceInstanceID *rac.ResourceAttributeConfig `river:"service.instance.id,block,optional"`
ServiceVersion *rac.ResourceAttributeConfig `river:"service.version,block,optional"`
}

func (r *ResourceAttributesConfig) Convert() map[string]interface{} {
return map[string]interface{}{
"cloud.platform": r.CloudPlatform.Convert(),
"cloud.provider": r.CloudProvider.Convert(),
"deployment.environment": r.DeploymentEnvironment.Convert(),
"service.instance.id": r.ServiceInstanceID.Convert(),
"service.version": r.ServiceVersion.Convert(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package lambda

import rac "github.com/grafana/agent/component/otelcol/processor/resourcedetection/internal/resource_attribute_config"

type Config struct {
ResourceAttributes ResourceAttributesConfig `river:"resource_attributes,block"`
}

func (args *Config) Convert() map[string]interface{} {
return map[string]interface{}{
"resource_attributes": args.ResourceAttributes.Convert(),
}
}

// ResourceAttributesConfig provides config for resourcedetectionprocessor/lambda resource attributes.
type ResourceAttributesConfig struct {
AwsLogGroupNames *rac.ResourceAttributeConfig `river:"aws.log.group.names,block,optional"`
AwsLogStreamNames *rac.ResourceAttributeConfig `river:"aws.log.stream.names,block,optional"`
CloudPlatform *rac.ResourceAttributeConfig `river:"cloud.platform,block,optional"`
CloudProvider *rac.ResourceAttributeConfig `river:"cloud.provider,block,optional"`
CloudRegion *rac.ResourceAttributeConfig `river:"cloud.region,block,optional"`
FaasInstance *rac.ResourceAttributeConfig `river:"faas.instance,block,optional"`
FaasMaxMemory *rac.ResourceAttributeConfig `river:"faas.max_memory,block,optional"`
FaasName *rac.ResourceAttributeConfig `river:"faas.name,block,optional"`
FaasVersion *rac.ResourceAttributeConfig `river:"faas.version,block,optional"`
}

func (r *ResourceAttributesConfig) Convert() map[string]interface{} {
return map[string]interface{}{
"aws.log.group.names": r.AwsLogGroupNames.Convert(),
"aws.log.stream.names": r.AwsLogStreamNames.Convert(),
"cloud.platform": r.CloudPlatform.Convert(),
"cloud.provider": r.CloudProvider.Convert(),
"cloud.region": r.CloudRegion.Convert(),
"faas.instance": r.FaasInstance.Convert(),
"faas.max_memory": r.FaasMaxMemory.Convert(),
"faas.name": r.FaasName.Convert(),
"faas.version": r.FaasVersion.Convert(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package aks

import rac "github.com/grafana/agent/component/otelcol/processor/resourcedetection/internal/resource_attribute_config"

type Config struct {
ResourceAttributes ResourceAttributesConfig `river:"resource_attributes,block"`
}

func (args *Config) Convert() map[string]interface{} {
return map[string]interface{}{
"resource_attributes": args.ResourceAttributes.Convert(),
}
}

// ResourceAttributesConfig provides config for resourcedetectionprocessor/aks resource attributes.
type ResourceAttributesConfig struct {
CloudPlatform *rac.ResourceAttributeConfig `river:"cloud.platform,block,optional"`
CloudProvider *rac.ResourceAttributeConfig `river:"cloud.provider,block,optional"`
}

func (r *ResourceAttributesConfig) Convert() map[string]interface{} {
return map[string]interface{}{
"cloud.platform": r.CloudPlatform.Convert(),
"cloud.provider": r.CloudProvider.Convert(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package azure

import rac "github.com/grafana/agent/component/otelcol/processor/resourcedetection/internal/resource_attribute_config"

type Config struct {
ResourceAttributes ResourceAttributesConfig `river:"resource_attributes,block"`
}

func (args *Config) Convert() map[string]interface{} {
return map[string]interface{}{
"resource_attributes": args.ResourceAttributes.Convert(),
}
}

// ResourceAttributesConfig provides config for resourcedetectionprocessor/azure resource attributes.
type ResourceAttributesConfig struct {
AzureResourcegroupName *rac.ResourceAttributeConfig `river:"azure.resourcegroup.name,block,optional"`
AzureVMName *rac.ResourceAttributeConfig `river:"azure.vm.name,block,optional"`
AzureVMScalesetName *rac.ResourceAttributeConfig `river:"azure.vm.scaleset.name,block,optional"`
AzureVMSize *rac.ResourceAttributeConfig `river:"azure.vm.size,block,optional"`
CloudAccountID *rac.ResourceAttributeConfig `river:"cloud.account.id,block,optional"`
CloudPlatform *rac.ResourceAttributeConfig `river:"cloud.platform,block,optional"`
CloudProvider *rac.ResourceAttributeConfig `river:"cloud.provider,block,optional"`
CloudRegion *rac.ResourceAttributeConfig `river:"cloud.region,block,optional"`
HostID *rac.ResourceAttributeConfig `river:"host.id,block,optional"`
HostName *rac.ResourceAttributeConfig `river:"host.name,block,optional"`
}

func (r *ResourceAttributesConfig) Convert() map[string]interface{} {
return map[string]interface{}{
"azure.resourcegroup.name": r.AzureResourcegroupName.Convert(),
"azure.vm.name": r.AzureVMName.Convert(),
"azure.vm.scaleset.name": r.AzureVMScalesetName.Convert(),
"azure.vm.size": r.AzureVMSize.Convert(),
"cloud.account.id": r.CloudAccountID.Convert(),
"cloud.platform": r.CloudPlatform.Convert(),
"cloud.provider": r.CloudProvider.Convert(),
"cloud.region": r.CloudRegion.Convert(),
"host.id": r.HostID.Convert(),
"host.name": r.HostName.Convert(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package consul

import (
rac "github.com/grafana/agent/component/otelcol/processor/resourcedetection/internal/resource_attribute_config"
"github.com/grafana/river/rivertypes"
"go.opentelemetry.io/collector/config/configopaque"
)

// The struct requires no user-specified fields by default as consul agent's default
// configuration will be provided to the API client.
// See `consul.go#NewDetector` for more information.
type Config struct {
// Address is the address of the Consul server
Address string `river:"address,attr,optional"`

// Datacenter to use. If not provided, the default agent datacenter is used.
Datacenter string `river:"datacenter,attr,optional"`

// Token is used to provide a per-request ACL token which overrides the
// agent's default (empty) token. Token is only required if
// [Consul's ACL System](https://www.consul.io/docs/security/acl/acl-system)
// is enabled.
Token rivertypes.Secret `river:"token,attr,optional"`

// TokenFile is not necessary in River because users can use the local.file
// Flow component instead.
//
// TokenFile string `river:"token_file"`

// Namespace is the name of the namespace to send along for the request
// when no other Namespace is present in the QueryOptions
Namespace string `river:"namespace,attr,optional"`

// Allowlist of [Consul Metadata](https://www.consul.io/docs/agent/options#node_meta)
// keys to use as resource attributes.
MetaLabels []string `river:"meta,attr,optional"`

// ResourceAttributes configuration for Consul detector
ResourceAttributes ResourceAttributesConfig `river:"resource_attributes,block"`
}

func (args *Config) Convert() map[string]interface{} {
//TODO(ptodev): Change the OTel Collector's "meta" param to be a slice instead of a map.
var metaLabels map[string]string
if args.MetaLabels != nil {
metaLabels = make(map[string]string, len(args.MetaLabels))
for _, label := range args.MetaLabels {
metaLabels[label] = ""
}
}

return map[string]interface{}{
"address": args.Address,
"datacenter": args.Datacenter,
"token": configopaque.String(args.Token),
"namespace": args.Namespace,
"meta": metaLabels,
"resource_attributes": args.ResourceAttributes.Convert(),
}
}

// ResourceAttributesConfig provides config for resourcedetectionprocessor/consul resource attributes.
type ResourceAttributesConfig struct {
AzureResourcegroupName *rac.ResourceAttributeConfig `river:"azure.resourcegroup.name,block,optional"`
AzureVMName *rac.ResourceAttributeConfig `river:"azure.vm.name,block,optional"`
AzureVMScalesetName *rac.ResourceAttributeConfig `river:"azure.vm.scaleset.name,block,optional"`
AzureVMSize *rac.ResourceAttributeConfig `river:"azure.vm.size,block,optional"`
CloudAccountID *rac.ResourceAttributeConfig `river:"cloud.account.id,block,optional"`
CloudPlatform *rac.ResourceAttributeConfig `river:"cloud.platform,block,optional"`
CloudProvider *rac.ResourceAttributeConfig `river:"cloud.provider,block,optional"`
CloudRegion *rac.ResourceAttributeConfig `river:"cloud.region,block,optional"`
HostID *rac.ResourceAttributeConfig `river:"host.id,block,optional"`
HostName *rac.ResourceAttributeConfig `river:"host.name,block,optional"`
}

func (r *ResourceAttributesConfig) Convert() map[string]interface{} {
return map[string]interface{}{
"azure.resourcegroup.name": r.AzureResourcegroupName.Convert(),
"azure.vm.name": r.AzureVMName.Convert(),
"azure.vm.scaleset.name": r.AzureVMScalesetName.Convert(),
"azure.vm.size": r.AzureVMSize.Convert(),
"cloud.account.id": r.CloudAccountID.Convert(),
"cloud.platform": r.CloudPlatform.Convert(),
"cloud.provider": r.CloudProvider.Convert(),
"cloud.region": r.CloudRegion.Convert(),
"host.id": r.HostID.Convert(),
"host.name": r.HostName.Convert(),
}
}
Loading

0 comments on commit a6191b2

Please sign in to comment.