{{ define "alloy.config.profilesPprof" }}
{{- if .Values.profiles.pprof.enabled }}
// Profiles: pprof
discovery.kubernetes "pprof_pods" {
  role = "pod"
  selectors {
    role = "pod"
    field = "spec.nodeName=" + sys.env("HOSTNAME")
  }
{{- if .Values.profiles.pprof.namespaces }}
  namespaces {
    names = {{ .Values.profiles.pprof.namespaces | toJson }}
  }
{{- end }}
}

discovery.relabel "pprof_pods" {
  targets = discovery.kubernetes.pprof_pods.targets
  rule {
    source_labels = ["__meta_kubernetes_pod_phase"]
    regex         = "Pending|Succeeded|Failed|Completed"
    action        = "drop"
  }

  rule {
    regex  = "__meta_kubernetes_pod_label_(.+)"
    action = "labelmap"
  }
  rule {
    source_labels = ["__meta_kubernetes_namespace"]
    target_label  = "namespace"
  }
{{- if .Values.profiles.pprof.excludeNamespaces }}
  rule {
    source_labels = ["namespace"]
    regex = "{{ .Values.profiles.pprof.excludeNamespaces | join "|" }}"
    action = "drop"
  }
{{- end }}

  rule {
    source_labels = ["__meta_kubernetes_pod_name"]
    target_label  = "pod"
  }

  rule {
    source_labels = ["__meta_kubernetes_pod_container_name"]
    target_label  = "container"
  }
{{- if .Values.profiles.pprof.extraRelabelingRules }}
{{ .Values.profiles.pprof.extraRelabelingRules | indent 2 }}
{{- end }}
}

{{- $profileTypes := .Values.profiles.pprof.types }}
{{- $allProfileTypes := list "memory" "block" "goroutine" "mutex" "cpu" "fgprof" "godeltaprof_memory"  "godeltaprof_mutex"  "godeltaprof_block" }}
{{ range $currentType := $allProfileTypes }}
{{- if has $currentType $.Values.profiles.pprof.types }}
  {{- $scrapeAnnotation := include "pod_annotation" (printf "%s/%s.%s" $.Values.profiles.annotations.prefix $currentType $.Values.profiles.pprof.annotations.enable) }}
  {{- $portNameAnnotation := include "pod_annotation" (printf "%s/%s.%s" $.Values.profiles.annotations.prefix $currentType $.Values.profiles.pprof.annotations.portName) }}
  {{- $portNumberAnnotation := include "pod_annotation" (printf "%s/%s.%s" $.Values.profiles.annotations.prefix $currentType $.Values.profiles.pprof.annotations.portNumber) }}
  {{- $schemeAnnotation := include "pod_annotation" (printf "%s/%s.%s" $.Values.profiles.annotations.prefix $currentType $.Values.profiles.pprof.annotations.scheme) }}
  {{- $pathAnnotation := include "pod_annotation" (printf "%s/%s.%s" $.Values.profiles.annotations.prefix $currentType $.Values.profiles.pprof.annotations.path) }}
  {{- $containerAnnotation := include "pod_annotation" (printf "%s/%s.%s" $.Values.profiles.annotations.prefix $currentType $.Values.profiles.pprof.annotations.container) }}
discovery.relabel "pprof_pods_{{ $currentType }}" {
  targets = discovery.relabel.pprof_pods.output

  // Keep only pods with the scrape annotation set
  rule {
    source_labels = [{{ $scrapeAnnotation | quote }}]
    regex         = "true"
    action        = "keep"
  }

  // Rules to choose the right container
  rule {
    source_labels = ["container"]
    target_label = "__tmp_container"
  }
  rule {
    source_labels = ["{{ $containerAnnotation }}"]
    regex = "(.+)"
    target_label = "__tmp_container"
  }
  rule {
    source_labels = ["container"]
    action = "keepequal"
    target_label = "__tmp_container"
  }
  rule {
    action = "labeldrop"
    regex = "__tmp_container"
  }

  // Rules to choose the right port by name
  // The discovery generates a target for each declared container port of the pod.
  // If the portName annotation has value, keep only the target where the port name matches the one of the annotation.
  rule {
    source_labels = ["__meta_kubernetes_pod_container_port_name"]
    target_label = "__tmp_port"
  }
  rule {
    source_labels = ["{{ $portNameAnnotation }}"]
    regex = "(.+)"
    target_label = "__tmp_port"
  }
  rule {
    source_labels = ["__meta_kubernetes_pod_container_port_name"]
    action = "keepequal"
    target_label = "__tmp_port"
  }
  rule {
    action = "labeldrop"
    regex = "__tmp_port"
  }

  // If the portNumber annotation has a value, override the target address to use it, regardless whether it is
  // one of the declared ports on that Pod.
  rule {
    source_labels = ["{{ $portNumberAnnotation }}", "__meta_kubernetes_pod_ip"]
    regex = "(\\d+);(([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4})"
    replacement = "[$2]:$1" // IPv6
    target_label = "__address__"
  }
  rule {
    source_labels = ["{{ $portNumberAnnotation }}", "__meta_kubernetes_pod_ip"]
    regex = "(\\d+);((([0-9]+?)(\\.|$)){4})" // IPv4, takes priority over IPv6 when both exists
    replacement = "$2:$1"
    target_label = "__address__"
  }

  rule {
    source_labels = [{{ $schemeAnnotation | quote }}]
    regex         = "(https?)"
    target_label  = "__scheme__"
  }
  rule {
    source_labels = [{{ $pathAnnotation | quote }}]
    regex         = "(.+)"
    target_label  = "__profile_path__"
  }
}

pyroscope.scrape "pyroscope_scrape_{{ $currentType }}" {
  targets = discovery.relabel.pprof_pods_{{ $currentType }}.output

  bearer_token_file = "/var/run/secrets/kubernetes.io/serviceaccount/token"
  profiling_config {
    {{- $currentType := . -}}
    {{- range $allProfileTypes }}
    profile.{{if eq . "cpu"}}process_cpu{{else}}{{.}}{{end}} {
      enabled = {{if eq . $currentType}}true{{else}}false{{end}}
    }
    {{- end }}
  }

  scrape_interval = {{ $.Values.profiles.pprof.scrapeInterval | quote }}
  scrape_timeout = {{ $.Values.profiles.pprof.scrapeTimeout | quote }}

  forward_to = [pyroscope.write.profiles_service.receiver]
}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
