Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an otelcol.processor.resourcedetection component #5764

Merged
merged 16 commits into from
Jan 23, 2024
Merged
Next Next commit
Add a otelcol.processor.resourcedetection component
ptodev committed Jan 23, 2024

Verified

This commit was signed with the committer’s verified signature.
ptodev Paulin Todev
commit 7db6642811f6b533ecc249d2637c339d7c2c43ab
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"`
ptodev marked this conversation as resolved.
Show resolved Hide resolved

// 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