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

[AppSignals] Implement translation for appsignals on native k8s #1012

Merged
merged 7 commits into from
Jan 19, 2024

Conversation

JayPolanco
Copy link
Contributor

Description of the issue

Native kubernetes(k8s) requires a different configuration for appsignals. This PR handles the translation for when the agent is on a native k8s cluster

Description of changes

  • Modifies the awsemf exporter translator and yaml
  • Modifies awsxray exporter translator to append HostedIn.K8s.Cluster when on native k8s instead of HostedIn.EKS.Cluster
  • Modifies awsappsignals processor translator to configure the resolver as a K8s resolver when on native
  • Modifies pipeline translator to omit the resourcedetection processor if on native k8s as it will not be used as well as there not existing a k8s detector for it.

License

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Tests

Unit tested. Tested on native kubernetes cluster using minikube. Translated yaml for both native k8s and EKS attached below:

Note: ContainerInsights was disabled to remove clutter when viewing translated yaml

Native k8s:

exporters:
    awsemf/app_signals:
        certificate_file_path: ""
        detailed_metrics: false
        dimension_rollup_option: NoDimensionRollup
        disable_metric_extraction: false
        eks_fargate_container_insights_enabled: false
        endpoint: ""
        enhanced_container_insights: false
        imds_retries: 0
        local_mode: false
        log_group_name: /aws/appsignals/k8s
        log_retention: 0
        log_stream_name: ""
        max_retries: 2
        metric_declarations:
            - dimensions:
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - Operation
                  - Service
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - Service
              label_matchers:
                - label_names:
                    - aws.span.kind
                  regex: ^(SERVER|LOCAL_ROOT)$
                  separator: ;
              metric_name_selectors:
                - Latency
                - Fault
                - Error
            - dimensions:
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - K8s.RemoteNamespace
                  - Operation
                  - RemoteOperation
                  - RemoteService
                  - RemoteTarget
                  - Service
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - K8s.RemoteNamespace
                  - Operation
                  - RemoteOperation
                  - RemoteService
                  - Service
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - Operation
                  - RemoteOperation
                  - RemoteService
                  - RemoteTarget
                  - Service
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - Operation
                  - RemoteOperation
                  - RemoteService
                  - Service
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - K8s.RemoteNamespace
                  - RemoteService
                  - Service
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - RemoteService
                  - Service
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - K8s.RemoteNamespace
                  - RemoteOperation
                  - RemoteService
                  - RemoteTarget
                  - Service
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - K8s.RemoteNamespace
                  - RemoteOperation
                  - RemoteService
                  - Service
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - RemoteOperation
                  - RemoteService
                  - RemoteTarget
                  - Service
                - - HostedIn.K8s.Cluster
                  - HostedIn.K8s.Namespace
                  - RemoteOperation
                  - RemoteService
                  - Service
                - - RemoteService
              label_matchers:
                - label_names:
                    - aws.span.kind
                  regex: ^(CLIENT|PRODUCER|CONSUMER)$
                  separator: ;
              metric_name_selectors:
                - Latency
                - Fault
                - Error
        metric_descriptors: []
        middleware: agenthealth/logs
        namespace: AppSignals
        no_verify_ssl: false
        num_workers: 8
        output_destination: cloudwatch
        parse_json_encoded_attr_values: []
        profile: ""
        proxy_address: ""
        region: ""
        request_timeout_seconds: 30
        resource_arn: ""
        resource_to_telemetry_conversion:
            enabled: false
        retain_initial_value_of_delta_metric: false
        role_arn: ""
        shared_credentials_file: []
        version: "1"
    awsxray/app_signals:
        aws_log_groups: []
        certificate_file_path: ""
        endpoint: ""
        imds_retries: 1
        index_all_attributes: false
        indexed_attributes:
            - aws.local.service
            - aws.local.operation
            - aws.remote.service
            - aws.remote.operation
            - HostedIn.K8s.Namespace
            - K8s.RemoteNamespace
            - aws.remote.target
            - HostedIn.Environment
            - HostedIn.K8s.Cluster
        local_mode: false
        max_retries: 2
        middleware: agenthealth/traces
        no_verify_ssl: false
        num_workers: 8
        profile: ""
        proxy_address: ""
        region: us-west-2
        request_timeout_seconds: 30
        resource_arn: ""
        role_arn: ""
        shared_credentials_file: []
        telemetry:
            enabled: true
            include_metadata: true
extensions:
    agenthealth/logs:
        is_usage_data_enabled: true
        stats:
            operations:
                - PutLogEvents
    agenthealth/traces:
        is_usage_data_enabled: true
        stats:
            operations:
                - PutTraceSegments
    awsproxy/app_signals:
        aws_endpoint: ""
        endpoint: 0.0.0.0:2000
        local_mode: false
        proxy_address: ""
        region: ""
        role_arn: ""
processors:
    awsappsignals:
        resolvers:
            - name: cwak8s
              platform: k8s
        rules: []
receivers:
    otlp/app_signals:
        protocols:
            grpc:
                auth: null
                endpoint: 0.0.0.0:4315
                include_metadata: false
                keepalive: null
                max_concurrent_streams: 0
                max_recv_msg_size_mib: 0
                read_buffer_size: 524288
                tls: null
                transport: tcp
                write_buffer_size: 0
            http:
                auth: null
                cors: null
                endpoint: 0.0.0.0:4316
                include_metadata: false
                logs_url_path: /v1/logs
                max_request_body_size: 0
                metrics_url_path: /v1/metrics
                response_headers: {}
                tls: null
                traces_url_path: /v1/traces
service:
    extensions:
        - awsproxy/app_signals
        - agenthealth/traces
        - agenthealth/logs
    pipelines:
        metrics/app_signals:
            exporters:
                - awsemf/app_signals
            processors:
                - awsappsignals
            receivers:
                - otlp/app_signals
        traces/app_signals:
            exporters:
                - awsxray/app_signals
            processors:
                - awsappsignals
            receivers:
                - otlp/app_signals
    telemetry:
        logs:
            development: false
            disable_caller: false
            disable_stacktrace: false
            encoding: console
            error_output_paths: []
            initial_fields: {}
            level: info
            output_paths: []
            sampling:
                enabled: true
                initial: 2
                thereafter: 500
                tick: 10s
        metrics:
            address: ""
            level: None
            readers: []
        resource: {}
        traces:
            processors: []
            propagators: []

EKS (No changes made, this snippet is just for confirmation):

exporters:
    awsemf/app_signals:
        certificate_file_path: ""
        detailed_metrics: false
        dimension_rollup_option: NoDimensionRollup
        disable_metric_extraction: false
        eks_fargate_container_insights_enabled: false
        endpoint: ""
        enhanced_container_insights: false
        imds_retries: 0
        local_mode: false
        log_group_name: /aws/appsignals/eks
        log_retention: 0
        log_stream_name: ""
        max_retries: 2
        metric_declarations:
            - dimensions:
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - Operation
                  - Service
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - Service
              label_matchers:
                - label_names:
                    - aws.span.kind
                  regex: ^(SERVER|LOCAL_ROOT)$
                  separator: ;
              metric_name_selectors:
                - Latency
                - Fault
                - Error
            - dimensions:
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - K8s.RemoteNamespace
                  - Operation
                  - RemoteOperation
                  - RemoteService
                  - RemoteTarget
                  - Service
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - K8s.RemoteNamespace
                  - Operation
                  - RemoteOperation
                  - RemoteService
                  - Service
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - Operation
                  - RemoteOperation
                  - RemoteService
                  - RemoteTarget
                  - Service
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - Operation
                  - RemoteOperation
                  - RemoteService
                  - Service
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - K8s.RemoteNamespace
                  - RemoteService
                  - Service
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - RemoteService
                  - Service
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - K8s.RemoteNamespace
                  - RemoteOperation
                  - RemoteService
                  - RemoteTarget
                  - Service
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - K8s.RemoteNamespace
                  - RemoteOperation
                  - RemoteService
                  - Service
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - RemoteOperation
                  - RemoteService
                  - RemoteTarget
                  - Service
                - - HostedIn.EKS.Cluster
                  - HostedIn.K8s.Namespace
                  - RemoteOperation
                  - RemoteService
                  - Service
                - - RemoteService
              label_matchers:
                - label_names:
                    - aws.span.kind
                  regex: ^(CLIENT|PRODUCER|CONSUMER)$
                  separator: ;
              metric_name_selectors:
                - Latency
                - Fault
                - Error
        metric_descriptors: []
        middleware: agenthealth/logs
        namespace: AppSignals
        no_verify_ssl: false
        num_workers: 8
        output_destination: cloudwatch
        parse_json_encoded_attr_values: []
        profile: ""
        proxy_address: ""
        region: ""
        request_timeout_seconds: 30
        resource_arn: ""
        resource_to_telemetry_conversion:
            enabled: false
        retain_initial_value_of_delta_metric: false
        role_arn: ""
        shared_credentials_file: []
        version: "1"
    awsxray/app_signals:
        aws_log_groups: []
        certificate_file_path: ""
        endpoint: ""
        imds_retries: 1
        index_all_attributes: false
        indexed_attributes:
            - aws.local.service
            - aws.local.operation
            - aws.remote.service
            - aws.remote.operation
            - HostedIn.K8s.Namespace
            - K8s.RemoteNamespace
            - aws.remote.target
            - HostedIn.Environment
            - HostedIn.EKS.Cluster
        local_mode: false
        max_retries: 2
        middleware: agenthealth/traces
        no_verify_ssl: false
        num_workers: 8
        profile: ""
        proxy_address: ""
        region: us-west-2
        request_timeout_seconds: 30
        resource_arn: ""
        role_arn: ""
        shared_credentials_file: []
        telemetry:
            enabled: true
            include_metadata: true
extensions:
    agenthealth/logs:
        is_usage_data_enabled: true
        stats:
            operations:
                - PutLogEvents
    agenthealth/traces:
        is_usage_data_enabled: true
        stats:
            operations:
                - PutTraceSegments
    awsproxy/app_signals:
        aws_endpoint: ""
        endpoint: 0.0.0.0:2000
        local_mode: false
        proxy_address: ""
        region: ""
        role_arn: ""
processors:
    awsappsignals:
        resolvers:
            - name: pulse
              platform: eks
        rules: []
    resourcedetection:
        aks:
            resource_attributes:
                cloud.platform:
                    enabled: true
                cloud.provider:
                    enabled: true
        attributes: []
        auth: null
        azure:
            resource_attributes:
                azure.resourcegroup.name:
                    enabled: true
                azure.vm.name:
                    enabled: true
                azure.vm.scaleset.name:
                    enabled: true
                azure.vm.size:
                    enabled: true
                cloud.account.id:
                    enabled: true
                cloud.platform:
                    enabled: true
                cloud.provider:
                    enabled: true
                cloud.region:
                    enabled: true
                host.id:
                    enabled: true
                host.name:
                    enabled: true
        compression: ""
        consul:
            address: ""
            datacenter: ""
            meta: {}
            namespace: ""
            resource_attributes:
                azure.resourcegroup.name:
                    enabled: true
                azure.vm.name:
                    enabled: true
                azure.vm.scaleset.name:
                    enabled: true
                azure.vm.size:
                    enabled: true
                cloud.account.id:
                    enabled: true
                cloud.platform:
                    enabled: true
                cloud.provider:
                    enabled: true
                cloud.region:
                    enabled: true
                host.id:
                    enabled: true
                host.name:
                    enabled: true
            token: '[REDACTED]'
            token_file: ""
        detectors:
            - eks
            - env
            - ec2
        disable_keep_alives: false
        docker:
            resource_attributes:
                host.name:
                    enabled: true
                os.type:
                    enabled: true
        ec2:
            resource_attributes:
                cloud.account.id:
                    enabled: true
                cloud.availability_zone:
                    enabled: true
                cloud.platform:
                    enabled: true
                cloud.provider:
                    enabled: true
                cloud.region:
                    enabled: true
                host.id:
                    enabled: true
                host.image.id:
                    enabled: true
                host.name:
                    enabled: true
                host.type:
                    enabled: true
            tags:
                - ^kubernetes.io/cluster/.*$
        ecs:
            resource_attributes:
                aws.ecs.cluster.arn:
                    enabled: true
                aws.ecs.launchtype:
                    enabled: true
                aws.ecs.task.arn:
                    enabled: true
                aws.ecs.task.family:
                    enabled: true
                aws.ecs.task.revision:
                    enabled: true
                aws.log.group.arns:
                    enabled: true
                aws.log.group.names:
                    enabled: true
                aws.log.stream.arns:
                    enabled: true
                aws.log.stream.names:
                    enabled: true
                cloud.account.id:
                    enabled: true
                cloud.availability_zone:
                    enabled: true
                cloud.platform:
                    enabled: true
                cloud.provider:
                    enabled: true
                cloud.region:
                    enabled: true
        eks:
            resource_attributes:
                cloud.platform:
                    enabled: true
                cloud.provider:
                    enabled: true
        elasticbeanstalk:
            resource_attributes:
                cloud.platform:
                    enabled: true
                cloud.provider:
                    enabled: true
                deployment.environment:
                    enabled: true
                service.instance.id:
                    enabled: true
                service.version:
                    enabled: true
        endpoint: ""
        gcp:
            resource_attributes:
                cloud.account.id:
                    enabled: true
                cloud.availability_zone:
                    enabled: true
                cloud.platform:
                    enabled: true
                cloud.provider:
                    enabled: true
                cloud.region:
                    enabled: true
                faas.id:
                    enabled: true
                faas.instance:
                    enabled: true
                faas.name:
                    enabled: true
                faas.version:
                    enabled: true
                gcp.cloud_run.job.execution:
                    enabled: true
                gcp.cloud_run.job.task_index:
                    enabled: true
                gcp.gce.instance.hostname:
                    enabled: false
                gcp.gce.instance.name:
                    enabled: false
                host.id:
                    enabled: true
                host.name:
                    enabled: true
                host.type:
                    enabled: true
                k8s.cluster.name:
                    enabled: true
        headers: {}
        heroku:
            resource_attributes:
                cloud.provider:
                    enabled: true
                heroku.app.id:
                    enabled: true
                heroku.dyno.id:
                    enabled: true
                heroku.release.commit:
                    enabled: true
                heroku.release.creation_timestamp:
                    enabled: true
                service.instance.id:
                    enabled: true
                service.name:
                    enabled: true
                service.version:
                    enabled: true
        idle_conn_timeout: 1m30s
        k8snode:
            auth_type: serviceAccount
            context: ""
            node_from_env_var: ""
            resource_attributes:
                k8s.node.name:
                    enabled: true
                k8s.node.uid:
                    enabled: true
        lambda:
            resource_attributes:
                aws.log.group.names:
                    enabled: true
                aws.log.stream.names:
                    enabled: true
                cloud.platform:
                    enabled: true
                cloud.provider:
                    enabled: true
                cloud.region:
                    enabled: true
                faas.instance:
                    enabled: true
                faas.max_memory:
                    enabled: true
                faas.name:
                    enabled: true
                faas.version:
                    enabled: true
        max_conns_per_host: null
        max_idle_conns: 100
        max_idle_conns_per_host: null
        openshift:
            address: ""
            resource_attributes:
                cloud.platform:
                    enabled: true
                cloud.provider:
                    enabled: true
                cloud.region:
                    enabled: true
                k8s.cluster.name:
                    enabled: true
            tls:
                ca_file: ""
                ca_pem: '[REDACTED]'
                cert_file: ""
                cert_pem: '[REDACTED]'
                insecure: false
                insecure_skip_verify: false
                key_file: ""
                key_pem: '[REDACTED]'
                max_version: ""
                min_version: ""
                reload_interval: 0s
                server_name_override: ""
            token: ""
        override: true
        read_buffer_size: 0
        system:
            hostname_sources: []
            resource_attributes:
                host.arch:
                    enabled: false
                host.cpu.cache.l2.size:
                    enabled: false
                host.cpu.family:
                    enabled: false
                host.cpu.model.id:
                    enabled: false
                host.cpu.model.name:
                    enabled: false
                host.cpu.stepping:
                    enabled: false
                host.cpu.vendor.id:
                    enabled: false
                host.id:
                    enabled: false
                host.name:
                    enabled: true
                os.description:
                    enabled: false
                os.type:
                    enabled: true
        timeout: 2s
        write_buffer_size: 0
receivers:
    otlp/app_signals:
        protocols:
            grpc:
                auth: null
                endpoint: 0.0.0.0:4315
                include_metadata: false
                keepalive: null
                max_concurrent_streams: 0
                max_recv_msg_size_mib: 0
                read_buffer_size: 524288
                tls: null
                transport: tcp
                write_buffer_size: 0
            http:
                auth: null
                cors: null
                endpoint: 0.0.0.0:4316
                include_metadata: false
                logs_url_path: /v1/logs
                max_request_body_size: 0
                metrics_url_path: /v1/metrics
                response_headers: {}
                tls: null
                traces_url_path: /v1/traces
service:
    extensions:
        - awsproxy/app_signals
        - agenthealth/traces
        - agenthealth/logs
    pipelines:
        metrics/app_signals:
            exporters:
                - awsemf/app_signals
            processors:
                - resourcedetection
                - awsappsignals
            receivers:
                - otlp/app_signals
        traces/app_signals:
            exporters:
                - awsxray/app_signals
            processors:
                - resourcedetection
                - awsappsignals
            receivers:
                - otlp/app_signals
    telemetry:
        logs:
            development: false
            disable_caller: false
            disable_stacktrace: false
            encoding: console
            error_output_paths: []
            initial_fields: {}
            level: info
            output_paths: []
            sampling:
                enabled: true
                initial: 2
                thereafter: 500
                tick: 10s
        metrics:
            address: ""
            level: None
            readers: []
        resource: {}
        traces:
            processors: []
            propagators: []

Requirements

Before commit the code, please do the following steps.

  1. Run make fmt and make fmt-sh
  2. Run make lint

@codecov-commenter
Copy link

codecov-commenter commented Jan 18, 2024

Codecov Report

Attention: 42 lines in your changes are missing coverage. Please review.

Comparison is base (96d4763) 57.58% compared to head (09ebe1a) 63.30%.
Report is 475 commits behind head on main.

Files Patch % Lines
cfg/aws/credentials.go 0.00% 22 Missing ⚠️
cfg/aws/shared_config.go 62.50% 15 Missing ⚠️
cfg/envconfig/envconfig.go 50.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1012      +/-   ##
==========================================
+ Coverage   57.58%   63.30%   +5.72%     
==========================================
  Files         370      361       -9     
  Lines       17548    18199     +651     
==========================================
+ Hits        10105    11521    +1416     
+ Misses       6848     6083     -765     
  Partials      595      595              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines +70 to +81
isEks, err := common.IsEKS()
if err != nil {
return nil, err
}

if isEks {
cfg.Resolvers = []appsignalsconfig.Resolver{
appsignalsconfig.NewEKSResolver(hostedIn),
}
} else {
cfg.Resolvers = []appsignalsconfig.Resolver{
appsignalsconfig.NewK8sResolver(hostedIn),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this code snippet used in a bunch of places ? can it be moved to a common util package ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic within the if else blocks are all different. The common code would be lines 70 to 73, but that can't be exported because we would still need to return if an error occurs.

@JayPolanco JayPolanco merged commit d292a28 into aws:main Jan 19, 2024
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants