# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: otel
spec:
  image: otel/opentelemetry-collector-contrib:0.112.0
  config: |
    receivers:
      # receive OTLP spans from Beyla
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    connectors:
      # convert spans into a calls metric
      spanmetrics/servicegraph:
        histogram:
          disable: true
        dimensions:
          - name: server.address
          - name: client.address
        exclude_dimensions:
          - 'status.code'
          - 'span.kind'
          - 'span.name'
          - 'service.name'
          - 'rpc.method'
          - 'rpc.system'
          - 'rpc.grpc.status_code'
          - 'server.port'
    processors:
      # filter down to only non-local http server spans
      filter/serveronly:
        error_mode: ignore
        traces:
          span:
            - attributes["http.request.method"] == nil and attributes["rpc.method"] == nil
            - kind.string != "Server"
            - attributes["server.address"] == "127.0.0.1"
      # detect gke resource attributes
      resourcedetection:
        detectors: [env, gcp]
        timeout: 2s
        override: false
      # Move server and client address from metric attributes to resource attributes so we can
      # use it to get k8s.pod.name for the server and client pods
      groupbyattrs:
        keys:
          - server.address
          - client.address
      # Metrics are generated from server spans only, so k8s.pod.name already contains the server pod
      transform/k8spodname_to_server:
        metric_statements:
          - context: resource
            statements:
            - set(attributes["server"], attributes["k8s.pod.name"])
            - delete_key(attributes, "k8s.pod.name")
            # Put the client address into k8s.pod.ip for k8sattributes processor to detect the client pod name
            - set(attributes["k8s.pod.ip"], attributes["client.address"])
      # Add k8s.pod.name
      k8sattributes:
        extract:
          metadata:
            - k8s.pod.name
        pod_association:
          - sources:
            - from: resource_attribute
              name: k8s.pod.ip
      # Moves annotated k8s.pod.name to client.address
      transform/k8spodname_to_client:
        metric_statements:
          - context: resource
            statements:
            - set(attributes["client"], attributes["k8s.pod.name"])
            - delete_key(attributes, "k8s.pod.name")
            - delete_key(attributes, "k8s.pod.ip")
      transform/servicegraphconventions:
        metric_statements:
          - context: datapoint
            statements:
              # GMP metrics are expected to be double
              - set(value_double, Double(value_int))
          # Rename metric to match the servicegraphconnector's output
          # https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/connector/servicegraphconnector#how-it-works
          - context: metric
            statements:
              - set(name, "traces_service_graph_request") where name == "traces.span.metrics.calls"
      resource/podinstance:
        attributes:
          - key: pod
            from_attribute: k8s.pod.name
            action: upsert
          - key: service.instance.id
            from_attribute: k8s.pod.uid
            action: upsert
    exporters:
      googlemanagedprometheus:
        metric:
          resource_filters:
            - regex: 'pod'
            - regex: client
            - regex: server
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [filter/serveronly]
          exporters: [spanmetrics/servicegraph]
        metrics:
          receivers: [spanmetrics/servicegraph]
          processors:
          - groupbyattrs
          - transform/k8spodname_to_server
          - k8sattributes
          - transform/k8spodname_to_client
          - transform/servicegraphconventions
          - resourcedetection
          exporters: [googlemanagedprometheus]
