diff --git a/README.md b/README.md index 9c17eb06..b3c3c569 100644 --- a/README.md +++ b/README.md @@ -260,7 +260,9 @@ To enable [Grafana Cloud Application Observability](https://grafana.com/docs/gra 2. Click on **Enable metrics generation** to enable the usage of Application Observability. 3. Interact with the QuickPizza app to generate traffic. After a few minutes, the QuickPizza components will be automatically discovered and displayed in the UI. -![Application Observability](./docs/images/grafana-cloud-application-application-observability-quickpizza.png) +![Application Observability](./docs/images/grafana-cloud-application-observability.png) + +![Application Observability - Public API Service](./docs/images/grafana-cloud-application-observability-public-api-svc.png) To enable [Grafana Cloud Frontend Observability](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/): diff --git a/alloy/cloud.alloy b/alloy/cloud.alloy index 13bba198..5586e7a2 100644 --- a/alloy/cloud.alloy +++ b/alloy/cloud.alloy @@ -81,37 +81,140 @@ pyroscope.scrape "application_containers" { // Traces otelcol.receiver.otlp "default" { - grpc { - endpoint = "0.0.0.0:4317" + // https://grafana.com/docs/alloy/latest/reference/components/otelcol.receiver.otlp/ + + // configures the default grpc endpoint "0.0.0.0:4317" + grpc { } + // configures the default http/protobuf endpoint "0.0.0.0:4318" + http { } + + output { + metrics = [otelcol.processor.resourcedetection.default.input] + logs = [otelcol.processor.resourcedetection.default.input] + traces = [otelcol.processor.resourcedetection.default.input] } - - http { - endpoint = "0.0.0.0:4318" +} + +otelcol.processor.resourcedetection "default" { + // https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.resourcedetection/ + detectors = ["env", "system"] // add "gcp", "ec2", "ecs", "elastic_beanstalk", "eks", "lambda", "azure", "aks", "consul", "heroku" if you want to use cloud resource detection + + system { + hostname_sources = ["os"] } - + + output { + metrics = [otelcol.processor.transform.drop_unneeded_resource_attributes.input] + logs = [otelcol.processor.transform.drop_unneeded_resource_attributes.input] + traces = [otelcol.processor.transform.drop_unneeded_resource_attributes.input] + } +} + +otelcol.processor.transform "drop_unneeded_resource_attributes" { + // https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.transform/ + error_mode = "ignore" + + trace_statements { + context = "resource" + statements = [ + "delete_key(attributes, \"k8s.pod.start_time\")", + "delete_key(attributes, \"os.description\")", + "delete_key(attributes, \"os.type\")", + "delete_key(attributes, \"process.command_args\")", + "delete_key(attributes, \"process.executable.path\")", + "delete_key(attributes, \"process.pid\")", + "delete_key(attributes, \"process.runtime.description\")", + "delete_key(attributes, \"process.runtime.name\")", + "delete_key(attributes, \"process.runtime.version\")", + ] + } + + metric_statements { + context = "resource" + statements = [ + "delete_key(attributes, \"k8s.pod.start_time\")", + "delete_key(attributes, \"os.description\")", + "delete_key(attributes, \"os.type\")", + "delete_key(attributes, \"process.command_args\")", + "delete_key(attributes, \"process.executable.path\")", + "delete_key(attributes, \"process.pid\")", + "delete_key(attributes, \"process.runtime.description\")", + "delete_key(attributes, \"process.runtime.name\")", + "delete_key(attributes, \"process.runtime.version\")", + ] + } + + log_statements { + context = "resource" + statements = [ + "delete_key(attributes, \"k8s.pod.start_time\")", + "delete_key(attributes, \"os.description\")", + "delete_key(attributes, \"os.type\")", + "delete_key(attributes, \"process.command_args\")", + "delete_key(attributes, \"process.executable.path\")", + "delete_key(attributes, \"process.pid\")", + "delete_key(attributes, \"process.runtime.description\")", + "delete_key(attributes, \"process.runtime.name\")", + "delete_key(attributes, \"process.runtime.version\")", + ] + } + output { + metrics = [otelcol.processor.transform.add_resource_attributes_as_metric_attributes.input] + logs = [otelcol.processor.batch.default.input] traces = [ - otelcol.processor.batch.default.input, - otelcol.connector.host_info.default.input, + otelcol.processor.batch.default.input, + otelcol.connector.host_info.default.input, ] } } - + otelcol.connector.host_info "default" { + // https://grafana.com/docs/alloy/latest/reference/components/otelcol.connector.host_info/ host_identifiers = ["container.name", "container.id", "service.name"] - metrics_flush_interval = "10s" - + output { - metrics = [otelcol.exporter.prometheus.otlp_metrics.input] + metrics = [otelcol.processor.batch.default.input] } } -otelcol.exporter.prometheus "otlp_metrics" { - forward_to = [ - grafana_cloud.stack.receivers.metrics, - ] + +otelcol.processor.transform "add_resource_attributes_as_metric_attributes" { + // https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.transform/ + error_mode = "ignore" + + metric_statements { + context = "datapoint" + statements = [ + "set(attributes[\"deployment.environment\"], resource.attributes[\"deployment.environment\"])", + "set(attributes[\"service.version\"], resource.attributes[\"service.version\"])", + ] + } + + output { + metrics = [otelcol.processor.batch.default.input] + } } + otelcol.processor.batch "default" { + // https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.batch/ output { - traces = [grafana_cloud.stack.receivers.traces] + metrics = [otelcol.exporter.otlphttp.otlpEndpoint.input] + logs = [otelcol.exporter.otlphttp.otlpEndpoint.input] + traces = [otelcol.exporter.otlphttp.otlpEndpoint.input] + } +} + +otelcol.auth.basic "otlpEndpoint" { + // Grafana Cloud Instance ID. + username = grafana_cloud.stack.receivers.info["id"] + password = env("GRAFANA_CLOUD_TOKEN") +} + +otelcol.exporter.otlphttp "otlpEndpoint" { + client { + // FR: gcom API to return the Grafana Cloud OTLP endpoint + endpoint = "https://otlp-gateway-"+ grafana_cloud.stack.receivers.info["regionSlug"] + ".grafana.net/otlp" + // https://github.com/grafana/beyla/blob/069049182455db603f3bda6865e7de13e45e038f/pkg/export/otel/common.go#L22 + auth = otelcol.auth.basic.otlpEndpoint.handler } } \ No newline at end of file diff --git a/docs/images/grafana-cloud-application-application-observability-quickpizza.png b/docs/images/grafana-cloud-application-application-observability-quickpizza.png deleted file mode 100644 index 2e54c4b3..00000000 Binary files a/docs/images/grafana-cloud-application-application-observability-quickpizza.png and /dev/null differ diff --git a/docs/images/grafana-cloud-application-observability-public-api-svc.png b/docs/images/grafana-cloud-application-observability-public-api-svc.png new file mode 100644 index 00000000..47ca7d56 Binary files /dev/null and b/docs/images/grafana-cloud-application-observability-public-api-svc.png differ diff --git a/docs/images/grafana-cloud-application-observability.png b/docs/images/grafana-cloud-application-observability.png new file mode 100644 index 00000000..4d5d3f4d Binary files /dev/null and b/docs/images/grafana-cloud-application-observability.png differ diff --git a/kubernetes/README.md b/kubernetes/README.md index 478cabca..7e733736 100644 --- a/kubernetes/README.md +++ b/kubernetes/README.md @@ -72,8 +72,8 @@ You should now be able to access the application on port `3333` in the IP addres To collect telemetry data, use one of the following setups: -- Use [`kubernetes/cloud-stack`](./cloud-stack/) to send telemetry data to Grafana Cloud with a cloud access policy. -- Use [`kubernetes/cloud-otlp`](./cloud-otlp/) to send telemetry data to Grafana Cloud via the OTLP endpoint. +- Use [`kubernetes/cloud`](./cloud/) to send telemetry data to Grafana Cloud. +- Use [`kubernetes/cloud-testing`](./cloud-testing/) to implement your custom setup. Before deployment: diff --git a/kubernetes/cloud-k8s-monitoring/config/config.alloy b/kubernetes/cloud-k8s-monitoring/config/config.alloy deleted file mode 100644 index fce03cab..00000000 --- a/kubernetes/cloud-k8s-monitoring/config/config.alloy +++ /dev/null @@ -1,163 +0,0 @@ -// Traces -otelcol.receiver.otlp "default" { - grpc { - endpoint = "0.0.0.0:4317" - } - - http { - endpoint = "0.0.0.0:4318" - } - - output { - traces = [otelcol.processor.batch.default.input] - } -} - -otelcol.processor.batch "default" { - output { - metrics = [] - logs = [] - traces = [ - grafana_cloud.stack.receivers.traces, - ] - } -} - -// Metrics: kube-state-metrics -// TODO: install kube-state-metrics in your minikube cluster: -discovery.kubernetes "kube_state_metrics" { - role = "pod" - selectors { - role = "pod" - label = "app.kubernetes.io/name=kube-state-metrics" - } - namespaces { - names = ["kube-system", "monitoring"] - } -} - -discovery.relabel "kube_state_metrics" { - rule { - source_labels = ["__meta_kubernetes_pod_container_port_name"] - regex = "http" - action = "keep" - } - // rule { - // source_labels = ["__meta_kubernetes_pod_container_port_name"] - // regex = "http-metrics" - // action = "keep" - // } - rule { - target_label = "service" - replacement = "quickpizza" - } - rule { - target_label = "service_namespace" - replacement = "quickpizza" - } - rule { - target_label = "cluster" - replacement = "minikube" - } - rule { - target_label = "job" - replacement = "kube-state-metrics" - } - rule { - target_label = "instance" - source_labels = [ - "__meta_kubernetes_pod_name", - ] - } - rule { - target_label = "namespace" - source_labels = [ - "__meta_kubernetes_pod_namespace", - ] - } - rule { - source_labels = ["__meta_kubernetes_pod_annotation_prometheus_io_scrape"] - regex = "true" - action = "keep" - } - targets = discovery.kubernetes.kube_state_metrics.targets -} -prometheus.scrape "kube_state_metrics" { - scrape_interval = "10s" - forward_to = [grafana_cloud.stack.receivers.metrics] - targets = discovery.relabel.kube_state_metrics.output -} - - -discovery.kubernetes "application_pods" { - selectors { - label = "app.k8s.io/name=quickpizza" - role = "pod" - } - role = "pod" - namespaces { - own_namespace = true - } -} - -discovery.relabel "application_pods" { - rule { - target_label = "instance" - source_labels = [ - "__meta_kubernetes_pod_name", - ] - } - rule { - target_label = "service_namespace" - source_labels = [ - // quickpizza - "__meta_kubernetes_pod_label_app_k8s_io_name", - ] - } - rule { - target_label = "service_name" - source_labels = [ - "__meta_kubernetes_pod_label_app_kubernetes_io_instance", - ] - } - rule { - target_label = "cluster" - replacement = "minikube" - } - targets = discovery.kubernetes.application_pods.targets -} - -// Metrics: application pods -prometheus.scrape "application_pods" { - scrape_interval = "10s" - forward_to = [grafana_cloud.stack.receivers.metrics] - targets = discovery.relabel.application_pods.output -} - -// Logs: application pods -loki.source.kubernetes "application_pods" { - forward_to = [grafana_cloud.stack.receivers.logs] - targets = discovery.relabel.application_pods.output -} - - -// TODO: not working -pyroscope.receive_http "default" { - forward_to = [grafana_cloud.stack.receivers.profiles] - http { - listen_address = "127.0.0.1" - listen_port = 9999 - } -} - -import.git "grafana_cloud" { - repository = "https://github.com/grafana/alloy-modules.git" - revision = "main" - path = "modules/cloud/grafana/cloud/module.alloy" - pull_frequency = "0s" -} - -grafana_cloud.stack "receivers" { - stack_name = env("GRAFANA_CLOUD_STACK") - token = env("GRAFANA_CLOUD_TOKEN") -} \ No newline at end of file diff --git a/kubernetes/cloud-k8s-monitoring/kustomization.yaml b/kubernetes/cloud-k8s-monitoring/kustomization.yaml deleted file mode 100644 index 7faf2d47..00000000 --- a/kubernetes/cloud-k8s-monitoring/kustomization.yaml +++ /dev/null @@ -1,34 +0,0 @@ - -# This environment is intended to test Grafana Kubernetes Monitoring integration. -resources: - - ../base/quickpizza - - ../base/alloy - -# To use a custom image (e.g., locally built), uncomment `newName` and `newTag` below. -# Example: docker build -t local-quickpizza:latest . && minikube image load local-quickpizza:latest -images: - - name: ghcr.io/grafana/quickpizza-local - # newName: local-quickpizza - # newTag: latest -# Note: Do not commit changes to newName/newTag values (leave commented). TODO: consider Kustomize's env var substitution - -# For telemetry functionality, change the following lines to match your configuration. -secretGenerator: - - name: grafana-alloy-credentials - envs: - - .env - -# You can use the following generator to add additional environment variables to all QuickPizza pods. -configMapGenerator: - - name: quickpizza-env - envs: - # load FARO variables - - .env - literals: - # Enable tracing - - QUICKPIZZA_OTLP_ENDPOINT=http://grafana-alloy:4318 - # TODO: pyroscope not working - - QUICKPIZZA_PYROSCOPE_ENDPOINT=http://grafana-alloy:9999 - - name: alloy-config - files: - - ./config/config.alloy \ No newline at end of file diff --git a/kubernetes/cloud-otlp/.env.local b/kubernetes/cloud-otlp/.env.local deleted file mode 100644 index 7ca704dc..00000000 --- a/kubernetes/cloud-otlp/.env.local +++ /dev/null @@ -1,15 +0,0 @@ -# TODO: create .env file in this folder - - -# The name of your Grafana Cloud Stack, which can be found in the Grafana Cloud portal. -GRAFANA_CLOUD_STACK=your-cloud-stack -# An Access Policy Token that includes the following scopes for the selected Grafana Cloud Stack: `stacks:read`, `metrics:write`, `logs:write`, `traces:write`, and `profiles:write`. -GRAFANA_CLOUD_TOKEN=your-cloud-token - -## Grafana Cloud OTLP Endpoint -GRAFANA_CLOUD_OTLP_ENDPOINT= - -# The Grafana Cloud OTLP endpoint for your stack, which can be found in the Grafana Cloud portal. -GRAFANA_CLOUD_INSTANCE_ID= - - diff --git a/kubernetes/cloud-otlp/config/config.alloy b/kubernetes/cloud-otlp/config/config.alloy deleted file mode 100644 index e7cb098c..00000000 --- a/kubernetes/cloud-otlp/config/config.alloy +++ /dev/null @@ -1,199 +0,0 @@ -// Based on demo-plugin alloy config -// https://github.com/grafana/demo-plugin/blob/main/deployment/quickpizza/grafana-alloy-config.yaml - -import.git "grafana_cloud" { - repository = "https://github.com/grafana/alloy-modules.git" - revision = "main" - path = "modules/cloud/grafana/cloud/module.alloy" - pull_frequency = "0s" -} -grafana_cloud.stack "receivers" { - stack_name = env("GRAFANA_CLOUD_STACK") - token = env("GRAFANA_CLOUD_TOKEN") -} - - -// Metrics -discovery.kubernetes "application_pods" { - selectors { - label = "app.k8s.io/name=quickpizza" - role = "pod" - } - role = "pod" - namespaces { - own_namespace = true - } -} -prometheus.scrape "default" { - forward_to = [ - grafana_cloud.stack.receivers.metrics, - ] - targets = discovery.relabel.relabel_targets.output -} - -discovery.relabel "relabel_targets" { - rule { - target_label = "job" - source_labels = [ - "__meta_kubernetes_pod_label_app_kubernetes_io_component", - ] - } - rule { - target_label = "service_name" - source_labels = [ - "__meta_kubernetes_pod_label_app_kubernetes_io_component", - ] - } - rule { - target_label = "instance" - source_labels = [ - "__meta_kubernetes_pod_name", - ] - } - targets = discovery.kubernetes.application_pods.targets -} - -pyroscope.scrape "scrape_profiles" { - forward_to = [ - grafana_cloud.stack.receivers.profiles, - ] - targets = discovery.relabel.relabel_targets.output -} - -otelcol.receiver.otlp "default" { - // https://grafana.com/docs/alloy/latest/reference/components/otelcol.receiver.otlp/ - - // configures the default grpc endpoint "0.0.0.0:4317" - grpc { } - // configures the default http/protobuf endpoint "0.0.0.0:4318" - http { } - - output { - metrics = [otelcol.processor.resourcedetection.default.input] - logs = [otelcol.processor.resourcedetection.default.input] - traces = [otelcol.processor.resourcedetection.default.input] - } -} - -otelcol.processor.resourcedetection "default" { - // https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.resourcedetection/ - detectors = ["env", "system"] // add "gcp", "ec2", "ecs", "elastic_beanstalk", "eks", "lambda", "azure", "aks", "consul", "heroku" if you want to use cloud resource detection - - system { - hostname_sources = ["os"] - } - - output { - metrics = [otelcol.processor.transform.drop_unneeded_resource_attributes.input] - logs = [otelcol.processor.transform.drop_unneeded_resource_attributes.input] - traces = [otelcol.processor.transform.drop_unneeded_resource_attributes.input] - } -} - -otelcol.processor.transform "drop_unneeded_resource_attributes" { - // https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.transform/ - error_mode = "ignore" - - trace_statements { - context = "resource" - statements = [ - "delete_key(attributes, \"k8s.pod.start_time\")", - "delete_key(attributes, \"os.description\")", - "delete_key(attributes, \"os.type\")", - "delete_key(attributes, \"process.command_args\")", - "delete_key(attributes, \"process.executable.path\")", - "delete_key(attributes, \"process.pid\")", - "delete_key(attributes, \"process.runtime.description\")", - "delete_key(attributes, \"process.runtime.name\")", - "delete_key(attributes, \"process.runtime.version\")", - ] - } - - metric_statements { - context = "resource" - statements = [ - "delete_key(attributes, \"k8s.pod.start_time\")", - "delete_key(attributes, \"os.description\")", - "delete_key(attributes, \"os.type\")", - "delete_key(attributes, \"process.command_args\")", - "delete_key(attributes, \"process.executable.path\")", - "delete_key(attributes, \"process.pid\")", - "delete_key(attributes, \"process.runtime.description\")", - "delete_key(attributes, \"process.runtime.name\")", - "delete_key(attributes, \"process.runtime.version\")", - ] - } - - log_statements { - context = "resource" - statements = [ - "delete_key(attributes, \"k8s.pod.start_time\")", - "delete_key(attributes, \"os.description\")", - "delete_key(attributes, \"os.type\")", - "delete_key(attributes, \"process.command_args\")", - "delete_key(attributes, \"process.executable.path\")", - "delete_key(attributes, \"process.pid\")", - "delete_key(attributes, \"process.runtime.description\")", - "delete_key(attributes, \"process.runtime.name\")", - "delete_key(attributes, \"process.runtime.version\")", - ] - } - - output { - metrics = [otelcol.processor.transform.add_resource_attributes_as_metric_attributes.input] - logs = [otelcol.processor.batch.default.input] - traces = [ - otelcol.processor.batch.default.input, - otelcol.connector.host_info.default.input, - ] - } -} - -otelcol.connector.host_info "default" { - // https://grafana.com/docs/alloy/latest/reference/components/otelcol.connector.host_info/ - host_identifiers = ["host.name"] - - output { - metrics = [otelcol.processor.batch.default.input] - } -} - -otelcol.processor.transform "add_resource_attributes_as_metric_attributes" { - // https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.transform/ - error_mode = "ignore" - - metric_statements { - context = "datapoint" - statements = [ - "set(attributes[\"deployment.environment\"], resource.attributes[\"deployment.environment\"])", - "set(attributes[\"service.version\"], resource.attributes[\"service.version\"])", - ] - } - - output { - metrics = [otelcol.processor.batch.default.input] - } -} - -otelcol.processor.batch "default" { - // https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.batch/ - output { - metrics = [otelcol.exporter.otlphttp.grafana_cloud.input] - logs = [otelcol.exporter.otlphttp.grafana_cloud.input] - traces = [otelcol.exporter.otlphttp.grafana_cloud.input] - } -} - -otelcol.auth.basic "grafana_cloud" { - // TODO: Fix info["htInstanceId"] not working, and need to pass GRAFANA_CLOUD_INSTANCE_ID. - //username = grafana_cloud.stack.receivers.info["htInstanceId"] - username = env("GRAFANA_CLOUD_INSTANCE_ID") - password = env("GRAFANA_CLOUD_TOKEN") -} - -otelcol.exporter.otlphttp "grafana_cloud" { - client { - endpoint = env("GRAFANA_CLOUD_OTLP_ENDPOINT") - auth = otelcol.auth.basic.grafana_cloud.handler - } -} diff --git a/kubernetes/cloud-stack/.env.local b/kubernetes/cloud-testing/.env.local similarity index 100% rename from kubernetes/cloud-stack/.env.local rename to kubernetes/cloud-testing/.env.local diff --git a/kubernetes/cloud-stack/config/config.alloy b/kubernetes/cloud-testing/config/config.alloy similarity index 100% rename from kubernetes/cloud-stack/config/config.alloy rename to kubernetes/cloud-testing/config/config.alloy diff --git a/kubernetes/cloud-stack/kustomization.yaml b/kubernetes/cloud-testing/kustomization.yaml similarity index 100% rename from kubernetes/cloud-stack/kustomization.yaml rename to kubernetes/cloud-testing/kustomization.yaml diff --git a/kubernetes/cloud-k8s-monitoring/.env.local b/kubernetes/cloud/.env.local similarity index 67% rename from kubernetes/cloud-k8s-monitoring/.env.local rename to kubernetes/cloud/.env.local index f6fee442..167e3f8a 100644 --- a/kubernetes/cloud-k8s-monitoring/.env.local +++ b/kubernetes/cloud/.env.local @@ -1,13 +1,23 @@ # TODO: create .env file in this folder +## Alloy Configuration + # The name of your Grafana Cloud Stack, which can be found in the Grafana Cloud portal. GRAFANA_CLOUD_STACK=your-cloud-stack # An Access Policy Token that includes the following scopes for the selected Grafana Cloud Stack: # `stacks:read`, `metrics:write`, `logs:write`, `traces:write`, and `profiles:write`. -# `metrics:read`, `fleet-management:read` GRAFANA_CLOUD_TOKEN=your-cloud-token +## QuickPizza Configuration + +# FRONTEND OBSERVABILITY URL +# QUICKPIZZA_CONF_FARO_URL= + +# FRONTEND OBSERVABILITY APPLICATION NAME +# QUICKPIZZA_CONF_FARO_APP_NAME= + + diff --git a/alloy/cloud.otlp.alloy b/kubernetes/cloud/config/config.alloy similarity index 73% rename from alloy/cloud.otlp.alloy rename to kubernetes/cloud/config/config.alloy index 6177338f..0e583bd7 100644 --- a/alloy/cloud.otlp.alloy +++ b/kubernetes/cloud/config/config.alloy @@ -1,81 +1,85 @@ - import.git "grafana_cloud" { repository = "https://github.com/grafana/alloy-modules.git" revision = "main" path = "modules/cloud/grafana/cloud/module.alloy" pull_frequency = "0s" } - grafana_cloud.stack "receivers" { stack_name = env("GRAFANA_CLOUD_STACK") token = env("GRAFANA_CLOUD_TOKEN") } -// discover containers running QuickPizza -discovery.docker "application_containers" { - host = "unix:///var/run/docker.sock" - filter { - name = "label" - values = ["service.type=application"] +// Metrics +discovery.kubernetes "application_pods" { + selectors { + label = "app.k8s.io/name=quickpizza" + role = "pod" + } + role = "pod" + namespaces { + own_namespace = true } } -// set expected labels -discovery.relabel "application_containers" { +discovery.relabel "application_pods" { + // See https://grafana.com/docs/grafana-cloud/monitor-applications/application-observability/setup/resource-attributes/ rule { target_label = "job" + separator = "/" source_labels = [ - "__meta_docker_container_name", + "__meta_kubernetes_pod_label_app_k8s_io_name", + "__meta_kubernetes_pod_label_app_kubernetes_io_instance", ] - regex = "/(.*)" - replacement = "quickpizza/${1}" } rule { target_label = "instance" source_labels = [ - "__meta_docker_container_name", + "__meta_kubernetes_pod_name", ] - regex = "/(.*)" - replacement = "${1}" } rule { target_label = "service_namespace" - replacement = "quickpizza" + source_labels = [ + // quickpizza + "__meta_kubernetes_pod_label_app_k8s_io_name", + ] } // the `namespace` label is for visualizing Profiles in Application Observability rule { target_label = "namespace" - replacement = "quickpizza" + source_labels = [ + // quickpizza + "__meta_kubernetes_pod_label_app_k8s_io_name", + ] } rule { target_label = "service_name" source_labels = [ - "__meta_docker_container_name", + "__meta_kubernetes_pod_label_app_kubernetes_io_instance", ] - regex = "/(.*)" - replacement = "${1}" } - targets = discovery.docker.application_containers.targets + targets = discovery.kubernetes.application_pods.targets } -// Metrics -prometheus.scrape "application_containers" { + +// Metrics: application pods +prometheus.scrape "application_pods" { scrape_interval = "10s" - targets = discovery.relabel.application_containers.output forward_to = [grafana_cloud.stack.receivers.metrics] + targets = discovery.relabel.application_pods.output } -// Logs -loki.source.docker "application_containers" { - host = "unix:///var/run/docker.sock" - targets = discovery.relabel.application_containers.output + +// Logs: application pods +loki.source.kubernetes "application_pods" { forward_to = [grafana_cloud.stack.receivers.logs] + targets = discovery.relabel.application_pods.output } // Profiling Pull Mode -pyroscope.scrape "application_containers" { +pyroscope.scrape "application_pods" { // https://grafana.com/docs/pyroscope/latest/configure-client/grafana-alloy/go_pull/ scrape_interval = "30s" - targets = discovery.relabel.application_containers.output + targets = discovery.relabel.application_pods.output forward_to = [grafana_cloud.stack.receivers.profiles] } @@ -171,7 +175,7 @@ otelcol.processor.transform "drop_unneeded_resource_attributes" { otelcol.connector.host_info "default" { // https://grafana.com/docs/alloy/latest/reference/components/otelcol.connector.host_info/ - host_identifiers = ["container.name", "container.id", "service.name"] + host_identifiers = ["host.name"] output { metrics = [otelcol.processor.batch.default.input] @@ -198,22 +202,23 @@ otelcol.processor.transform "add_resource_attributes_as_metric_attributes" { otelcol.processor.batch "default" { // https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.batch/ output { - metrics = [otelcol.exporter.otlphttp.grafana_cloud.input] - logs = [otelcol.exporter.otlphttp.grafana_cloud.input] - traces = [otelcol.exporter.otlphttp.grafana_cloud.input] + metrics = [otelcol.exporter.otlphttp.otlpEndpoint.input] + logs = [otelcol.exporter.otlphttp.otlpEndpoint.input] + traces = [otelcol.exporter.otlphttp.otlpEndpoint.input] } } -otelcol.auth.basic "grafana_cloud" { - // TODO: Fix info["htInstanceId"] not working, and need to pass GRAFANA_CLOUD_INSTANCE_ID. - //username = grafana_cloud.stack.receivers.info["htInstanceId"] - username = env("GRAFANA_CLOUD_INSTANCE_ID") +otelcol.auth.basic "otlpEndpoint" { + // Grafana Cloud Instance ID. + username = grafana_cloud.stack.receivers.info["id"] password = env("GRAFANA_CLOUD_TOKEN") } -otelcol.exporter.otlphttp "grafana_cloud" { +otelcol.exporter.otlphttp "otlpEndpoint" { client { - endpoint = env("GRAFANA_CLOUD_OTLP_ENDPOINT") - auth = otelcol.auth.basic.grafana_cloud.handler + // FR: gcom API to return the Grafana Cloud OTLP endpoint + endpoint = "https://otlp-gateway-"+ grafana_cloud.stack.receivers.info["regionSlug"] + ".grafana.net/otlp" + // https://github.com/grafana/beyla/blob/069049182455db603f3bda6865e7de13e45e038f/pkg/export/otel/common.go#L22 + auth = otelcol.auth.basic.otlpEndpoint.handler } } \ No newline at end of file diff --git a/kubernetes/cloud-otlp/kustomization.yaml b/kubernetes/cloud/kustomization.yaml similarity index 88% rename from kubernetes/cloud-otlp/kustomization.yaml rename to kubernetes/cloud/kustomization.yaml index a8c5398f..b2795591 100644 --- a/kubernetes/cloud-otlp/kustomization.yaml +++ b/kubernetes/cloud/kustomization.yaml @@ -8,20 +8,20 @@ images: - name: ghcr.io/grafana/quickpizza-local # newName: local-quickpizza # newTag: latest -# Note: Do not commit changes to newName/newTag values (leave commented). TODO: consider Kustomize's env var substitution +# Note: Do not commit changes to newName/newTag values (leave commented). TODO: consider Kustomize's env var substitution # For telemetry functionality, change the following lines to match your configuration. secretGenerator: - name: grafana-alloy-credentials envs: - - .env + - .env # You can use the following generator to add additional environment variables to all QuickPizza pods. configMapGenerator: - name: quickpizza-env envs: - # load FARO variables - - .env + # load FARO variables + - .env literals: # Enable tracing - QUICKPIZZA_OTLP_ENDPOINT=http://grafana-alloy:4318