diff --git a/.gitignore b/.gitignore
index ff7161e57..ed34f7842 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ node_modules
 
 # draw.io temp files
 .$*.bkp
-.$*.dtmp
\ No newline at end of file
+.$*.dtmp
+venv
\ No newline at end of file
diff --git a/metrics-collector/.ceignore b/metrics-collector/.ceignore
new file mode 100644
index 000000000..a5ed506b1
--- /dev/null
+++ b/metrics-collector/.ceignore
@@ -0,0 +1,2 @@
+images/
+setup/
\ No newline at end of file
diff --git a/metrics-collector/Dockerfile b/metrics-collector/Dockerfile
index 111dd9481..83a2322c6 100644
--- a/metrics-collector/Dockerfile
+++ b/metrics-collector/Dockerfile
@@ -1,11 +1,51 @@
-FROM quay.io/projectquay/golang:1.23 AS build-env
+# Stage 1: Build Go binary
+FROM quay.io/projectquay/golang:1.25 AS go-builder
 WORKDIR /go/src/app
-COPY . .
-
+COPY go.mod go.sum ./
 RUN go mod download
-RUN CGO_ENABLED=0 go build -o /go/bin/app main.go
+COPY main.go ./
+RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app main.go
+
+# Stage 2: Download and extract Prometheus
+FROM busybox:1.36-glibc AS prometheus-downloader
+ARG PROMETHEUS_VERSION=3.10.0
+ARG TARGETARCH=amd64
+
+WORKDIR /tmp
+RUN wget https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.linux-${TARGETARCH}.tar.gz && \
+    tar xzf prometheus-${PROMETHEUS_VERSION}.linux-${TARGETARCH}.tar.gz && \
+    mv prometheus-${PROMETHEUS_VERSION}.linux-${TARGETARCH}/prometheus /prometheus
+
+# Stage 3: Get CA certificates
+FROM alpine:latest AS certs
+RUN apk --no-cache add ca-certificates
+
+# Stage 4: Runtime image
+FROM busybox:1.36-glibc
+
+# Copy CA certificates for TLS verification
+COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
+
+# Copy Go binary
+COPY --from=go-builder /go/src/app/app /app
+
+# Copy Prometheus binary
+COPY --from=prometheus-downloader /prometheus /bin/prometheus
+
+# Copy configuration and scripts
+COPY prometheus.yml.template /etc/prometheus/prometheus.yml.template
+COPY start.sh /start.sh
+RUN chmod +x /start.sh
+
+# Create necessary directories with proper permissions
+RUN mkdir -p /tmp/agent-data && \
+    mkdir -p /etc/secrets && \
+    chmod 777 /tmp/agent-data
+
+# Set SSL certificate path environment variable
+ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
+
+# Use non-root user
+USER 1000:1000
 
-# Copy the exe into a smaller base image
-FROM gcr.io/distroless/static-debian12
-COPY --from=build-env /go/bin/app /
-CMD ["/app"]
+ENTRYPOINT ["/start.sh"]
diff --git a/metrics-collector/README.md b/metrics-collector/README.md
index 9abb6844a..02b3cd47d 100644
--- a/metrics-collector/README.md
+++ b/metrics-collector/README.md
@@ -1,59 +1,132 @@
 # IBM Cloud Code Engine - Metrics Collector
 
-Code Engine job that demonstrates how to collect resource metrics (CPU, memory and disk usage) of running Code Engine apps, jobs, and builds
+Code Engine job that demonstrates how to collect resource metrics (CPU, memory and disk usage) of running Code Engine apps, jobs, and builds. Those metrics can either be render 
+
+in **IBM Cloud Monitoring** (see [instructions](#Send-metrics-to-IBM-Cloud-Monitoring))
+
+![](./images/monitoring-dashboard-ce-component-resources.png)
+
+or in **IBM Cloud Logs** (see [instructions](#ibm-cloud-logs-setup))
 
 ![Dashboard overview](./images/icl-dashboard-overview.png)
 
-## Installation
 
-### Capture metrics every n seconds
+## Send metrics to IBM Cloud Monitoring
 
-* Create Code Engine job template
-```
-$ ibmcloud ce job create \
-    --name metrics-collector \
-    --src . \
-    --mode daemon \
-    --cpu 0.25 \
-    --memory 0.5G \
-    --wait
-```
+### How It Works
 
-* Submit a daemon job that collects metrics in an endless loop. The daemon job queries the Metrics API every 30 seconds
-```
-$ ibmcloud ce jobrun submit \
-    --job metrics-collector \
-    --env INTERVAL=30 
+![](./images/metrics-collector.overview.png)
+
+1. The metrics collector exposes Prometheus metrics on `localhost:9100/metrics`
+2. The embedded Prometheus agent scrapes these metrics every 30 seconds
+3. The agent also discovers and scrapes pods with the `codeengine.cloud.ibm.com/userMetricsScrape: 'true'` annotation
+4. All metrics are forwarded to IBM Cloud Monitoring via remote write
+5. If either the collector or Prometheus agent crashes, the container exits with a non-zero code to trigger a restart
+
+### Setup Instructions
+
+**Step 1:** You need an IBM Cloud Monitoring instance
+```bash
+REGION=<yourMonitoringInstanceRegion>
+MONITORING_INSTANCE_NAME="<yourMonitoringInstanceName>"
+MONITORING_INSTANCE_GUID=$(ibmcloud resource service-instance "$MONITORING_INSTANCE_NAME" -o JSON|jq -r '.[0].guid')
+echo "MONITORING_INSTANCE_GUID: '$MONITORING_INSTANCE_GUID'"
 ```
+**Step 2:** The collector must run in a Code Engine project
+```bash
+# Create new Code Engine project 
+ibmcloud ce project create --name <yourCodeEngineProjectName>
 
+# Select an existing Code Engine project
+ibmcloud ce project select --name <yourProjectName>
+```
 
-### Capture metrics every n minutes
+**Step 3:** Create a secret with your IBM Cloud Monitoring API token
+```bash
+# Obtain the Monitoring API token of the IBM Cloud Monitoring instance
+# using the IAM access token of the current IBM CLI Session
+MONITORING_INSTANCE_MONITORING_API_KEY=$(curl --silent -X GET https://$REGION.monitoring.cloud.ibm.com/api/token -H "Authorization: $(ibmcloud iam oauth-tokens --output JSON|jq -r '.iam_token')" -H "IBMInstanceID: $MONITORING_INSTANCE_GUID" -H "content-type: application/json"|jq -r '.token.key')
 
-* Create Code Engine job template
+# Create a Code Engine secret that stores the Monitoring API Key
+ibmcloud ce secret create \
+    --name monitoring-apikey \
+    --from-literal monitoring-apikey=$MONITORING_INSTANCE_MONITORING_API_KEY
 ```
-$ ibmcloud ce job create \
+
+**Step 4:** Create your metrics-collector job with the required configuration
+```bash
+ibmcloud ce job create \
     --name metrics-collector \
-    --src . \
-    --mode task \
+    --src "." \
+    --mode daemon \
     --cpu 0.25 \
     --memory 0.5G \
-    --wait
+    --service-account reader \
+    --build-size xlarge \
+    --env INTERVAL=30 \
+    --env METRICS_ENABLED=true \
+    --env METRICS_REMOTE_WRITE_FQDN=ingest.prws.private.${REGION}.monitoring.cloud.ibm.com \
+    --env CE_PROJECT_NAME="$(ibmcloud ce proj current --output json|jq -r '.name')" \
+    --mount-secret /etc/secrets=monitoring-apikey
 ```
 
-* Submit a Code Engine cron subscription that triggers the metrics collector every minute to query the Metrics API
+**Step 5:** Submit a daemon job run**
+```bash
+ibmcloud ce jobrun submit \
+    --job metrics-collector
 ```
-$ ibmcloud ce subscription cron create \
-    --name collect-metrics-every-minute \
-    --destination-type job \
-    --destination metrics-collector \
-    --schedule '*/1 * * * *'
+
+**Step 6:** Import the "IBM Cloud Code Engine - Component Resource Overview" dashboard
+```bash
+# Load the most recent dashboard configuration
+CE_MONITORING_DASHBOARD=$(curl -sL https://raw.githubusercontent.com/IBM/CodeEngine/main/metrics-collector/setup/ibm-cloud-monitoring/code-engine-component-resource-overview.json)
+
+# Import the dashboard
+curl -X POST https://$REGION.monitoring.cloud.ibm.com/api/v3/dashboards \
+      -H "Authorization: $(ibmcloud iam oauth-tokens --output JSON|jq -r '.iam_token')" \
+      -H "IBMInstanceID: $MONITORING_INSTANCE_GUID" \
+      -H "Content-Type: application/json" \
+      -d "{\"dashboard\": $CE_MONITORING_DASHBOARD}"
+
 ```
 
-## Configuration
+**Note:** A more elaborated approach to manage custom Cloud Monitoring dashboards can be found [here](setup/ibm-cloud-monitoring/README.md)
+
 
-Per default the metrics collector collects memory and CPU statistics, like `usage`, `current` and `configured`. 
+#### Exposed Metrics
 
-One can use the environment variable `COLLECT_DISKUSAGE=true` to also collect the amount of disk space that is used. Please note, the metrics collector can only calculate the overall file size stored in the pods filesystem which includes files that are part of the container image, the epheremal storage as well as mounted COS buckets. Hence, this metric cannot be used to calculate the ephemeral storage usage. 
+The following Prometheus metrics are exposed as gauges:
+
+Container Metrics:
+- **`ibm_codeengine_instance_cpu_usage_millicores`**: Current CPU usage in millicores
+- **`ibm_codeengine_instance_cpu_limit_millicores`**: Configured CPU limit in millicores
+- **`ibm_codeengine_instance_memory_usage_bytes`**: Current memory usage in bytes
+- **`ibm_codeengine_instance_memory_limit_bytes`**: Configured memory limit in bytes
+- **`ibm_codeengine_instance_ephemeral_storage_usage_bytes`**: Current ephemeral storage usage in bytes (if `COLLECT_DISKUSAGE=true`)
+
+The following 3 metrics are used to monitor the collector itself:
+- **`ibm_codeengine_collector_collection_duration_seconds`**: Time taken to collect metrics in seconds (if `METRICS_INTERNAL_STATS=true`)
+- **`ibm_codeengine_collector_last_collection_timestamp_seconds`**: Unix timestamp of last successful collection (if `METRICS_INTERNAL_STATS=true`)
+- **`ibm_codeengine_collector_collection_errors_total`**: Total number of collection errors (counter) (if `METRICS_INTERNAL_STATS=true`)
+
+#### Metric Labels
+
+All container metrics include the following labels:
+- `ibm_codeengine_instance_name`: Name of the pod instance
+- `ibm_codeengine_component_type`: Type of component (`app`, `job`, or `build`)
+- `ibm_codeengine_component_name`: Name of the Code Engine component
+
+#### Example Metrics Output
+
+```prometheus
+# HELP ibm_codeengine_instance_cpu_usage_millicores Current CPU usage in millicores
+# TYPE ibm_codeengine_instance_cpu_usage_millicores gauge
+ibm_codeengine_instance_cpu_usage_millicores{ibm_codeengine_instance_name="myapp-00001-deployment-abc123",ibm_codeengine_component_type="app",ibm_codeengine_component_name="myapp"} 250
+
+# HELP ibm_codeengine_instance_memory_usage_bytes Current memory usage in bytes
+# TYPE ibm_codeengine_instance_memory_usage_bytes gauge
+ibm_codeengine_instance_memory_usage_bytes{ibm_codeengine_instance_name="myapp-00001-deployment-abc123",ibm_codeengine_component_type="app",ibm_codeengine_component_name="myapp"} 134217728
+```
 
 ## IBM Cloud Logs setup
 
@@ -71,7 +144,7 @@ Follow the steps below to create a custom dashboard in your IBM Cloud Logs insta
 
 ![New dashboard](./images/icl-dashboard-new.png)
 
-* In the "Import" modal, select the file [./setup/dashboard-code_engine_resource_consumption_metrics.json](./setup/dashboard-code_engine_resource_consumption_metrics.json) located in this repository, and click "Import"
+* In the "Import" modal, select the file [./setup/ibm-cloud-logs/dashboard-code_engine_resource_consumption_metrics.json](./setup/ibm-cloud-logs/dashboard-code_engine_resource_consumption_metrics.json) located in this repository, and click "Import"
 
 ![Import modal](./images/icl-dashboard-import.png)
 
@@ -117,8 +190,6 @@ app:"codeengine" AND message.metric:"instance-resources"
 
 * In the top-right corner, select `1-line` as view mode
 
-![View](./images/icl-logs-view-mode.png)
-
 * In the graph title it says "**Count** all grouped by **Severity**". Click on `Severity` and select `message.component_name` instead. Furthermore, select `Max` as aggregation metric and choose `message.memory.usage` as aggregation field
 
 ![Graph](./images/icl-logs-view-graph.png)
@@ -132,54 +203,16 @@ app:"codeengine" AND message.metric:"instance-resources"
 ![Logs overview](./images/icl-logs-view-overview.png)
 
 
-## IBM Log Analysis setup (deprecated)
-
-### Log lines
-
-Along with a human readable message, like `Captured metrics of app instance 'load-generator-00001-deployment-677d5b7754-ktcf6': 3m vCPU, 109 MB memory, 50 MB ephemeral storage`, each log line passes specific resource utilization details in a structured way allowing to apply advanced filters on them.
-
-E.g.
-- `cpu.usage:>80`: Filter for all log lines that noticed a CPU utilization of 80% or higher
-- `memory.current:>1000`: Filter for all log lines that noticed an instance that used 1GB or higher of memory
-- `component_type:app`: Filter only for app instances. Possible values are `app`, `job`, and `build`
-- `component_name:<app-name>`: Filter for all instances of a specific app, job, or build
-- `name:<instance-name>`: Filter for a specific instance
-
-![IBM Cloud Logs](./images/ibm-cloud-logs--loglines.png)
-
-### Log graphs
-
-Best is to create IBM Cloud Logs Board, in order to visualize the CPU and Memory usage per Code Engine component.
-
-1. In your log instance navigate to Boards
-1. Give it a proper name, enter `metric:instance-resources` as query and submit by clicking `Add Graph`
-![New Board](./images/new-board.png)
-1. Now the graph shows the overall amount of logs captured for the specified query per time interval
-![Count of metrics log lines ](./images/count-of-metrics-lines.png)
-1. Click on the filter icon above the graph and put in `metric:instance-resources AND component_name:<app-name>`
-1. Switch the metric of the Graph to `Maximums`
-1. Below the graph Add a new plot`cpu.usage` as field and choose `ANY` as field values
-![Configure Graph plots](./images/configure-plots.png)
-1. Add another plot for the field `memory.usage` and values `ANY`
-1. Finally delete the plot `metrics:instance-resources` and adjust the plot colors to your likings
-![Resource Usage graph](./images/resource-usage-graph.png)
-1. The usage graph above renders the utilization in % of the CPU and Memory
-
-#### Add CPU utilization
-1. Duplicate the graph, change its name to CPU and replace its plots with `cpu.configured` and `cpu.current`.
-- The resulting graph will render the actual CPU usage compared to the configured limit. The the unit is milli vCPUs (1000 -> 1 vCPU).
-![](./images/cpu-utilization.png)
-
-
-#### Add memory utilization
-1. Duplicate the graph, change its name to Memory and replace its plots with `memory.configured` and `memory.current`.
-1. The resulting graph will render the actual memory usage compared to the configured limit. The the unit is MB (1000 -> 1 GB).
-![](./images/memory-utilization.png)
-
+### Troubleshooting & Configuration
 
+If the container fails to start with `METRICS_ENABLED=true`, check the logs for:
+- Missing `/etc/secrets/monitoring-apikey` file
+- Missing or wrong `METRICS_REMOTE_WRITE_FQDN` environment variable
 
-#### Add disk utilization
-1. Duplicate the graph or create a new one, change its name to "Disk usage" and replace its plots with `disk_usage.current`.
-1. The resulting graph will render the actual disk usage. While this does not allow to identify the usage of disk space compared with the configured ephemeral storage limit, this graph gives an impression on whether the disk usage is growing over time. The the unit is MB (1000 -> 1 GB).
-![](./images/disk-utilization.png)
+#### Environment Variables
 
+- **`INTERVAL`** (default: `30`): Collection interval in seconds (minimum 30 seconds). Controls how frequently metrics are collected from the Kubernetes API endpoint in daemon mode.
+- **`COLLECT_DISKUSAGE`** (default: `false`): Set to `true` to collect disk space usage. Note: The metrics collector calculates the overall file size stored in the pod's filesystem, which includes files from the container image, ephemeral storage, and mounted COS buckets. This metric cannot be used to calculate ephemeral storage usage alone.
+- **`METRICS_ENABLED`** (default: `false`): Set to `true` to enable the HTTP metrics server. When disabled, the collector still runs and logs metrics to stdout but does not expose the HTTP endpoint.
+- **`METRICS_REMOTE_WRITE_FQDN`**: IBM Cloud Monitoring ingestion endpoint FQDN (required when `METRICS_ENABLED=true`)
+- **`METRICS_PORT`** (default: `9100`): HTTP server port for the Prometheus metrics endpoint. Only used when `METRICS_ENABLED=true` in daemon mode.
diff --git a/metrics-collector/docs/metrics-collector.drawio b/metrics-collector/docs/metrics-collector.drawio
new file mode 100644
index 000000000..8c61e9815
--- /dev/null
+++ b/metrics-collector/docs/metrics-collector.drawio
@@ -0,0 +1,199 @@
+<mxfile host="Electron" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/25.0.2 Chrome/128.0.6613.186 Electron/32.2.5 Safari/537.36" version="25.0.2">
+  <diagram name="Page-1" id="5yxw62Nhsevp5IbapNpR">
+    <mxGraphModel dx="1656" dy="1067" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+      <root>
+        <mxCell id="0" />
+        <mxCell id="1" parent="0" />
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-4" value="" style="container=1;collapsible=0;expand=0;recursiveResize=0;html=1;whiteSpace=wrap;strokeWidth=1" vertex="1" parent="1">
+          <mxGeometry x="40" y="500" width="1070" height="380" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-5" value="IBM Cloud" style="shape=rect;fillColor=none;aspect=fixed;resizable=0;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;strokeColor=none;part=1;spacingLeft=5;fontSize=14;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-4">
+          <mxGeometry width="48" height="48" relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-6" value="" style="fillColor=#1192E8;shape=mxgraph.ibm_cloud.ibm-cloud;strokeColor=none;dashed=0;outlineConnect=0;html=1;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;part=1;movable=0;resizable=0;rotatable=0;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-5">
+          <mxGeometry width="24" height="24" relative="1" as="geometry">
+            <mxPoint x="12" y="12" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-7" value="" style="shape=rect;fillColor=#1192E8;aspect=fixed;resizable=0;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;strokeColor=none;part=1;spacingLeft=5;fontSize=14;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-4">
+          <mxGeometry width="4" height="48" relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-12" value="" style="container=1;collapsible=0;expand=0;recursiveResize=0;html=1;whiteSpace=wrap;strokeColor=#1192E8;fillColor=none;strokeWidth=1" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-4">
+          <mxGeometry x="840" y="60" width="200" height="300" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-13" value="Monitoring instance" style="shape=rect;fillColor=none;aspect=fixed;resizable=0;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;strokeColor=none;part=1;spacingLeft=5;fontSize=14;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-12">
+          <mxGeometry width="48" height="48" relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-14" value="" style="fillColor=#1192E8;shape=mxgraph.ibm_cloud.cloud-services;strokeColor=none;dashed=0;outlineConnect=0;html=1;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;part=1;movable=0;resizable=0;rotatable=0;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-13">
+          <mxGeometry width="24" height="24" relative="1" as="geometry">
+            <mxPoint x="12" y="12" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-15" value="" style="shape=rect;fillColor=#1192E8;aspect=fixed;resizable=0;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;strokeColor=none;part=1;spacingLeft=5;fontSize=14;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-12">
+          <mxGeometry width="4" height="48" relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-24" value="Remote-Write endpoint" style="shape=rect;fillColor=#009D9A;aspect=fixed;resizable=0;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;strokeColor=none;fontSize=14;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-12">
+          <mxGeometry x="76" y="87" width="48" height="48" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-25" value="" style="fillColor=#ffffff;strokeColor=none;dashed=0;outlineConnect=0;html=1;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;part=1;movable=0;resizable=0;rotatable=0;shape=mxgraph.ibm_cloud.cloud--monitoring" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-24">
+          <mxGeometry width="24" height="24" relative="1" as="geometry">
+            <mxPoint x="12" y="12" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <object label="Monitoring API Key" release="v3.0.1" generation="2.0" id="cDDFkdkcNhUbpnDVuA-s-41">
+          <mxCell style="shape=image;aspect=fixed;image=data:image/svg+xml,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNDhweCIgaGVpZ2h0PSI0OHB4IiB2aWV3Qm94PSIwIDAgNDggNDgiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+Y3JlZGVudGlhbHM8L3RpdGxlPgogICAgPGcgaWQ9IlYyLUljb25zIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0iSUJNLS8tQ2xvdWQtLy1TZWN1cml0eSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ2NiwgLTE0KSI+CiAgICAgICAgICAgIDxnIGlkPSJjcmVkZW50aWFscyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDY2LCAxNCkiPgogICAgICAgICAgICAgICAgPHJlY3QgaWQ9IlJlY3RhbmdsZSIgZmlsbD0iI0ZBNEQ1NiIgeD0iMCIgeT0iMCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48L3JlY3Q+CiAgICAgICAgICAgICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiwgMTIpIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIsMTYuNSBDMTMuNjU2ODU0MiwxNi41IDE1LDE1LjE1Njg1NDIgMTUsMTMuNSBDMTUsMTEuODQzMTQ1OCAxMy42NTY4NTQyLDEwLjUgMTIsMTAuNSBDMTAuMzQzMTQ1OCwxMC41IDksMTEuODQzMTQ1OCA5LDEzLjUgQzksMTUuMTU2ODU0MiAxMC4zNDMxNDU4LDE2LjUgMTIsMTYuNSBaIE0xMiwxMiBDMTIuODI4NDI3MSwxMiAxMy41LDEyLjY3MTU3MjkgMTMuNSwxMy41IEMxMy41LDE0LjMyODQyNzEgMTIuODI4NDI3MSwxNSAxMiwxNSBDMTEuMTcxNTcyOSwxNSAxMC41LDE0LjMyODQyNzEgMTAuNSwxMy41IEMxMC41LDEyLjY3MTU3MjkgMTEuMTcxNTcyOSwxMiAxMiwxMiBaIiBpZD0iU2hhcGUiIGZpbGw9IiNGRkZGRkYiIGZpbGwtcnVsZT0ibm9uemVybyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxyZWN0IGlkPSJSZWN0YW5nbGUiIGZpbGw9IiNGRkZGRkYiIGZpbGwtcnVsZT0ibm9uemVybyIgeD0iMTAuNSIgeT0iNC41IiB3aWR0aD0iMyIgaGVpZ2h0PSIxLjUiPjwvcmVjdD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTgsMS41IEw0LjUsMS41IEM1LjE3MTkxNTYxLDEuNTAwODI2ODQgNC41MDA4MjY4NCwyLjE3MTkxNTYxIDQuNSwzIEw0LjUsMjEgQzQuNTAwOTUwNiwyMS44MjgwMzMxIDUuMTcxOTY2OTUsMjIuNDk5MDQ5NCA0LjUsMjIuNSBMMTgsMjIuNSBDMTguODI3OTY0NiwyMi40OTg4ODQ1IDE5LjQ5ODg4NDUsMjEuODI3OTY0NiAxOS41LDIxIEwxOS41LDMgQzE5LjQ5OTA0OTQsMi4xNzE5NjY5NSAxOC44MjgwMzMxLDEuNTAwOTUwNiAxOCwxLjUgTDE4LDEuNSBaIE0xNSwyMSBMOSwyMSBMOSwxOS41IEM5LDE5LjA4NTc4NjQgOS4zMzU3ODY0NCwxOC43NSA5Ljc1LDE4Ljc1IEwxNC4yNSwxOC43NSBDMTQuNjY0MjEzNiwxOC43NSAxNSwxOS4wODU3ODY0IDE1LDE5LjUgTDE1LDIxIFogTTE2LjUsMjEgTDE2LjUsMTkuNSBDMTYuNSwxOC4yNTczNTkzIDE1LjQ5MjY0MDcsMTcuMjUgMTQuMjUsMTcuMjUgTDkuNzUsMTcuMjUgQzguNTA3MzU5MzEsMTcuMjUgNy41LDE4LjI1NzM1OTMgNy41LDE5LjUgTDcuNSwyMSBMNiwyMSBMNiwzIEwxOCwzIEwxOCwyMSBMMTYuNSwyMSBaIiBpZD0iU2hhcGUiIGZpbGw9IiNGRkZGRkYiIGZpbGwtcnVsZT0ibm9uemVybyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxyZWN0IGlkPSJfVHJhbnNwYXJlbnRfUmVjdGFuZ2xlXyIgeD0iMCIgeT0iMCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48L3JlY3Q+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==;fontFamily=IBM Plex Sans;fontSize=14;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;spacingTop=-7;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-12">
+            <mxGeometry x="76" y="200" width="48" height="48" as="geometry" />
+          </mxCell>
+        </object>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-16" value="" style="container=1;collapsible=0;expand=0;recursiveResize=0;html=1;whiteSpace=wrap;strokeColor=#1192E8;fillColor=none;strokeWidth=1" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-4">
+          <mxGeometry x="40" y="60" width="780" height="300" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-17" value="Code Engine project" style="shape=rect;fillColor=none;aspect=fixed;resizable=0;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;strokeColor=none;part=1;spacingLeft=5;fontSize=14;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-16">
+          <mxGeometry width="48" height="48" relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-18" value="" style="fillColor=#1192E8;shape=mxgraph.ibm_cloud.cloud-services;strokeColor=none;dashed=0;outlineConnect=0;html=1;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;part=1;movable=0;resizable=0;rotatable=0;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-17">
+          <mxGeometry width="24" height="24" relative="1" as="geometry">
+            <mxPoint x="12" y="12" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-19" value="" style="shape=rect;fillColor=#1192E8;aspect=fixed;resizable=0;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;strokeColor=none;part=1;spacingLeft=5;fontSize=14;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-16">
+          <mxGeometry width="4" height="48" relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-1" value="" style="container=1;collapsible=0;expand=0;recursiveResize=0;html=1;whiteSpace=wrap;strokeColor=#A56EFF;fillColor=none;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-16">
+          <mxGeometry x="279" y="40" width="331" height="240" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-2" value="metrics-collector (daemon job)" style="shape=rect;fillColor=#A56EFF;aspect=fixed;resizable=0;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;strokeColor=none;part=1;spacingLeft=5;fontSize=14;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-1">
+          <mxGeometry width="48" height="48" relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-3" value="" style="fillColor=#ffffff;shape=mxgraph.ibm_cloud.application;strokeColor=none;dashed=0;outlineConnect=0;html=1;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;part=1;movable=0;resizable=0;rotatable=0;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-2">
+          <mxGeometry width="24" height="24" relative="1" as="geometry">
+            <mxPoint x="12" y="12" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <object label="project‑metrics‑endpoint" release="v3.0.1" generation="2.0" id="cDDFkdkcNhUbpnDVuA-s-22">
+          <mxCell style="shape=image;verticalLabelPosition=bottom;verticalAlign=top;imageAspect=0;aspect=fixed;image=data:image/svg+xml,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCA0OCA0OCIgaGVpZ2h0PSI0OHB4IiB3aWR0aD0iNDhweCI+JiN4YTsgICAgPHRpdGxlPkFQSSAxPC90aXRsZT4mI3hhOyAgICA8ZyBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlPSJub25lIiBpZD0iVjItSWNvbnMiPiYjeGE7ICAgICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNTAsIC04MikiIGlkPSJJQk0vQ2xvdWQvQWN0b3JzIj4mI3hhOyAgICAgICAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDUwLCA4MikiIGlkPSJBUEktMSI+JiN4YTsgICAgICAgICAgICAgICAgPHJlY3Qgcng9IjI0IiBoZWlnaHQ9IjQ4IiB3aWR0aD0iNDgiIHk9IjAiIHg9IjAiIGZpbGw9IiNBNTZFRkYiIGlkPSJSZWN0YW5nbGUtQ29weS02Ii8+JiN4YTsgICAgICAgICAgICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTIsIDEyKSIgaWQ9ImFwaSgyKSI+JiN4YTsgICAgICAgICAgICAgICAgICAgIDxwYXRoIGZpbGwtcnVsZT0ibm9uemVybyIgZmlsbD0iI0ZGRkZGRiIgaWQ9IlNoYXBlIiBkPSJNMTkuNSwxNi41IEMxOC45NzAzMDU4LDE2LjUwMjU4ODQgMTguNDUxNDc0MiwxNi42NTA0NTU0IDE4LDE2LjkyNzUgTDE1LjY4MjUsMTQuNjAyNSBDMTYuNzg3Njk2NiwxMy4wNDM1MDI4IDE2Ljc4NzY5NjYsMTAuOTU2NDk3MiAxNS42ODI1LDkuMzk3NSBMMTgsNy4wNzI1IEMxOC40NTE0NzQyLDcuMzQ5NTQ0NjMgMTguOTcwMzA1OCw3LjQ5NzQxMTYyIDE5LjUsNy41IEMyMS4xNTY4NTQyLDcuNSAyMi41LDYuMTU2ODU0MjUgMjIuNSw0LjUgQzIyLjUsMi44NDMxNDU3NSAyMS4xNTY4NTQyLDEuNSAxOS41LDEuNSBDMTcuODQzMTQ1OCwxLjUgMTYuNSwyLjg0MzE0NTc1IDE2LjUsNC41IEMxNi41MDI1ODg0LDUuMDI5Njk0MjQgMTYuNjUwNDU1NCw1LjU0ODUyNTc5IDE2LjkyNzUsNiBMMTQuNjAyNSw4LjMxNzUgQzEzLjA0MzUwMjgsNy4yMTIzMDMzNyAxMC45NTY0OTcyLDcuMjEyMzAzMzcgOS4zOTc1LDguMzE3NSBMNy4wNzI1LDYgQzcuMzQ5NTQ0NjMsNS41NDg1MjU3OSA3LjQ5NzQxMTYyLDUuMDI5Njk0MjQgNy41LDQuNSBDNy41LDIuODQzMTQ1NzUgNi4xNTY4NTQyNSwxLjUgNC41LDEuNSBDMi44NDMxNDU3NSwxLjUgMS41LDIuODQzMTQ1NzUgMS41LDQuNSBDMS41LDYuMTU2ODU0MjUgMi44NDMxNDU3NSw3LjUgNC41LDcuNSBDNS4wMjk2OTQyNCw3LjQ5NzQxMTYyIDUuNTQ4NTI1NzksNy4zNDk1NDQ2MyA2LDcuMDcyNSBMOC4zMTc1LDkuMzk3NSBDNy4yMTIzMDMzNywxMC45NTY0OTcyIDcuMjEyMzAzMzcsMTMuMDQzNTAyOCA4LjMxNzUsMTQuNjAyNSBMNiwxNi45Mjc1IEM1LjU0ODUyNTc5LDE2LjY1MDQ1NTQgNS4wMjk2OTQyNCwxNi41MDI1ODg0IDQuNSwxNi41IEMyLjg0MzE0NTc1LDE2LjUgMS41LDE3Ljg0MzE0NTggMS41LDE5LjUgQzEuNSwyMS4xNTY4NTQyIDIuODQzMTQ1NzUsMjIuNSA0LjUsMjIuNSBDNi4xNTY4NTQyNSwyMi41IDcuNSwyMS4xNTY4NTQyIDcuNSwxOS41IEM3LjQ5NzQxMTYyLDE4Ljk3MDMwNTggNy4zNDk1NDQ2MywxOC40NTE0NzQyIDcuMDcyNSwxOCBMOS4zOTc1LDE1LjY4MjUgQzEwLjk1NjQ5NzIsMTYuNzg3Njk2NiAxMy4wNDM1MDI4LDE2Ljc4NzY5NjYgMTQuNjAyNSwxNS42ODI1IEwxNi45Mjc1LDE4IEMxNi42NTA0NTU0LDE4LjQ1MTQ3NDIgMTYuNTAyNTg4NCwxOC45NzAzMDU4IDE2LjUsMTkuNSBDMTYuNSwyMS4xNTY4NTQyIDE3Ljg0MzE0NTgsMjIuNSAxOS41LDIyLjUgQzIxLjE1Njg1NDIsMjIuNSAyMi41LDIxLjE1Njg1NDIgMjIuNSwxOS41IEMyMi41LDE3Ljg0MzE0NTggMjEuMTU2ODU0MiwxNi41IDE5LjUsMTYuNSBMMTkuNSwxNi41IFogTTE5LjUsMyBDMjAuMzI4NDI3MSwzIDIxLDMuNjcxNTcyODggMjEsNC41IEMyMSw1LjMyODQyNzEyIDIwLjMyODQyNzEsNiAxOS41LDYgQzE4LjY3MTU3MjksNiAxOCw1LjMyODQyNzEyIDE4LDQuNSBDMTgsMy42NzE1NzI4OCAxOC42NzE1NzI5LDMgMTkuNSwzIFogTTMsNC41IEMzLDMuNjcxNTcyODggMy42NzE1NzI4OCwzIDQuNSwzIEM1LjMyODQyNzEyLDMgNiwzLjY3MTU3Mjg4IDYsNC41IEM2LDUuMzI4NDI3MTIgNS4zMjg0MjcxMiw2IDQuNSw2IEM0LjEwMjE3NTI3LDYgMy43MjA2NDQ0LDUuODQxOTY0NzQgMy40MzkzMzk4Myw1LjU2MDY2MDE3IEMzLjE1ODAzNTI2LDUuMjc5MzU1NiAzLDQuODk3ODI0NzMgMyw0LjUgWiBNNC41LDIxIEMzLjY3MTU3Mjg4LDIxIDMsMjAuMzI4NDI3MSAzLDE5LjUgQzMsMTguNjcxNTcyOSAzLjY3MTU3Mjg4LDE4IDQuNSwxOCBDNS4zMjg0MjcxMiwxOCA2LDE4LjY3MTU3MjkgNiwxOS41IEM2LDIwLjMyODQyNzEgNS4zMjg0MjcxMiwyMSA0LjUsMjEgWiBNMTIsMTUgQzEwLjM0MzE0NTgsMTUgOSwxMy42NTY4NTQyIDksMTIgQzksMTAuMzQzMTQ1OCAxMC4zNDMxNDU4LDkgMTIsOSBDMTMuNjU2ODU0Miw5IDE1LDEwLjM0MzE0NTggMTUsMTIgQzE1LDEyLjc5NTY0OTUgMTQuNjgzOTI5NSwxMy41NTg3MTEyIDE0LjEyMTMyMDMsMTQuMTIxMzIwMyBDMTMuNTU4NzExMiwxNC42ODM5Mjk1IDEyLjc5NTY0OTUsMTUgMTIsMTUgWiBNMTkuNSwyMSBDMTguNjcxNTcyOSwyMSAxOCwyMC4zMjg0MjcxIDE4LDE5LjUgQzE4LDE4LjY3MTU3MjkgMTguNjcxNTcyOSwxOCAxOS41LDE4IEMyMC4zMjg0MjcxLDE4IDIxLDE4LjY3MTU3MjkgMjEsMTkuNSBDMjEsMjAuMzI4NDI3MSAyMC4zMjg0MjcxLDIxIDE5LjUsMjEgWiIvPiYjeGE7ICAgICAgICAgICAgICAgICAgICA8cmVjdCBoZWlnaHQ9IjI0IiB3aWR0aD0iMjQiIHk9IjAiIHg9IjAiIGlkPSJSZWN0YW5nbGUiLz4mI3hhOyAgICAgICAgICAgICAgICA8L2c+JiN4YTsgICAgICAgICAgICA8L2c+JiN4YTsgICAgICAgIDwvZz4mI3hhOyAgICA8L2c+JiN4YTs8L3N2Zz4=;fontFamily=IBM Plex Sans;fontSize=14;spacingTop=-7;labelPosition=center;align=center;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-1">
+            <mxGeometry x="65" y="162" width="48" height="48" as="geometry" />
+          </mxCell>
+        </object>
+        <object label="prometheus-agent" release="v3.0.1" generation="2.0" id="cDDFkdkcNhUbpnDVuA-s-23">
+          <mxCell style="shape=image;verticalLabelPosition=bottom;verticalAlign=top;imageAspect=0;aspect=fixed;image=data:image/svg+xml,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCA0OCA0OCIgaGVpZ2h0PSI0OHB4IiB3aWR0aD0iNDhweCI+JiN4YTsgICAgPHRpdGxlPkF1dG9tYXRpb24gU2NyaXB0PC90aXRsZT4mI3hhOyAgICA8ZyBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlPSJub25lIiBpZD0iVjItSWNvbnMiPiYjeGE7ICAgICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNTMxLCAtODIpIiBpZD0iSUJNL0Nsb3VkL0FjdG9ycyI+JiN4YTsgICAgICAgICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1MzEsIDgyKSIgaWQ9IkF1dG9tYXRpb24tU2NyaXB0Ij4mI3hhOyAgICAgICAgICAgICAgICA8cmVjdCByeD0iMjQiIGhlaWdodD0iNDgiIHdpZHRoPSI0OCIgeT0iMCIgeD0iMCIgZmlsbD0iI0E1NkVGRiIgaWQ9IlJlY3RhbmdsZS1Db3B5Ii8+JiN4YTsgICAgICAgICAgICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTIsIDEyKSIgaWQ9InNjcmlwdCgyKS1jb3B5Ij4mI3hhOyAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gcG9pbnRzPSIxNC4xMjI1IDE5LjUgMTYuMDU3NSAxNy41NjUgMTUgMTYuNSAxMiAxOS41IDE1IDIyLjUgMTYuMDY1IDIxLjQ0MjUiIGZpbGwtcnVsZT0ibm9uemVybyIgZmlsbD0iI0ZGRkZGRiIgaWQ9IlBhdGgiLz4mI3hhOyAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gcG9pbnRzPSIyMC4zNzc1IDE5LjUgMTguNDQyNSAyMS40MzUgMTkuNSAyMi41IDIyLjUgMTkuNSAxOS41IDE2LjUgMTguNDM1IDE3LjU1NzUiIGZpbGwtcnVsZT0ibm9uemVybyIgZmlsbD0iI0ZGRkZGRiIgaWQ9IlBhdGgiLz4mI3hhOyAgICAgICAgICAgICAgICAgICAgPHBhdGggZmlsbC1ydWxlPSJub256ZXJvIiBmaWxsPSIjRkZGRkZGIiBpZD0iU2hhcGUiIGQ9Ik0xMC41LDIxIEw2LDIxIEw2LDMgTDEyLDMgTDEyLDcuNSBDMTIuMDAyMzg5Miw4LjMyNzQzNTQ3IDEyLjY3MjU2NDUsOC45OTc2MTA4MiAxMy41LDkgTDE4LDkgTDE4LDEzLjUgTDE5LjUsMTMuNSBMMTkuNSw3LjUgQzE5LjUwNTQzNzcsNy4zMDA1MDY3MSAxOS40MjMyMTA4LDcuMTA4NjQzOTYgMTkuMjc1LDYuOTc1IEwxNC4wMjUsMS43MjUgQzEzLjg5MTM4NjIsMS41NzY3NDcwNSAxMy42OTk1MDMsMS40OTQ1MTEzOSAxMy41LDEuNSBMNiwxLjUgQzUuMTcyNTY0NTMsMS41MDIzODkxOCA0LjUwMjM4OTE4LDIuMTcyNTY0NTMgNC41LDMgTDQuNSwyMSBDNC41MDIzODkxOCwyMS44Mjc0MzU1IDUuMTcyNTY0NTMsMjIuNDk3NjEwOCA2LDIyLjUgTDEwLjUsMjIuNSBMMTAuNSwyMSBaIE0xMy41LDMuMyBMMTcuNyw3LjUgTDEzLjUsNy41IEwxMy41LDMuMyBaIi8+JiN4YTsgICAgICAgICAgICAgICAgICAgIDxyZWN0IGhlaWdodD0iMjQiIHdpZHRoPSIyNCIgeT0iMCIgeD0iMCIgaWQ9Il9UcmFuc3BhcmVudF9SZWN0YW5nbGVfIi8+JiN4YTsgICAgICAgICAgICAgICAgPC9nPiYjeGE7ICAgICAgICAgICAgPC9nPiYjeGE7ICAgICAgICA8L2c+JiN4YTsgICAgPC9nPiYjeGE7PC9zdmc+;fontFamily=IBM Plex Sans;fontSize=14;spacingTop=-7;labelPosition=center;align=center;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-1">
+            <mxGeometry x="232" y="59" width="48" height="48" as="geometry" />
+          </mxCell>
+        </object>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-32" value="" style="html=1;labelBackgroundColor=#ffffff;jettySize=auto;orthogonalLoop=1;fontSize=14;rounded=0;jumpStyle=gap;edgeStyle=orthogonalEdgeStyle;startArrow=oval;endArrow=block;strokeWidth=2;startFill=1;endFill=1;sourcePerimeterSpacing=3;targetPerimeterSpacing=3;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0;exitY=0.75;exitDx=0;exitDy=0;" edge="1" parent="cDDFkdkcNhUbpnDVuA-s-1" source="cDDFkdkcNhUbpnDVuA-s-23" target="cDDFkdkcNhUbpnDVuA-s-22">
+          <mxGeometry width="48" height="48" relative="1" as="geometry">
+            <mxPoint x="160" y="258" as="sourcePoint" />
+            <mxPoint x="208" y="210" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="89" y="96" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-37" value="pulls cpu/memory metrics" style="edgeLabel;html=1;align=left;verticalAlign=middle;resizable=0;points=[];fontStyle=2" vertex="1" connectable="0" parent="cDDFkdkcNhUbpnDVuA-s-32">
+          <mxGeometry x="0.1312" y="-3" relative="1" as="geometry">
+            <mxPoint x="-22" y="-9" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <object label="Code Engine &#xa;app instances" generation="2.0" release="v3.0.1" id="cDDFkdkcNhUbpnDVuA-s-20">
+          <mxCell style="shape=image;aspect=fixed;image=data:image/svg+xml,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNDlweCIgaGVpZ2h0PSI0OXB4IiB2aWV3Qm94PSIwIDAgNDkgNDkiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+Q29kZSBFbmdpbmUgdjIgSWNvbjwvdGl0bGU+CiAgICA8ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0idjItNDh4NDgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yNjE4LCAtOTM5KSI+CiAgICAgICAgICAgIDxnIGlkPSJDb2RlLUVuZ2luZS12Mi1JY29uIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNjE4LjUsIDkzOS41MzA0KSI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iS3ViZXJuZXRlcyIgZmlsbD0iIzE5ODAzOCI+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IkZpbGwtNCIgcG9pbnRzPSIwIDQ4IDQ4IDQ4IDQ4IDAgMCAwIj48L3BvbHlnb24+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iaWJtLWNsb3VkLS1jb2RlLWVuZ2luZSgxKSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTEuNSwgMTIuNDY5NikiPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNi41LDE1IEwxNi41LDIwLjk0MjI1IEMxNi41LDIxLjM4ODUgMTYuMTM4NSwyMS43NSAxNS42OTIyNSwyMS43NSBMNi44MDc3NSwyMS43NSBDNi4zNjE1LDIxLjc1IDYsMjEuMzg4NSA2LDIwLjk0MjI1IEw2LDE3LjI1IEwxLjUsMTcuMjUgTDEuNSwxNS43NSBMNiwxNS43NSBMNiwxMi4wNTc3NSBDNiwxMS42MTE1IDYuMzYxNSwxMS4yNSA2LjgwNzc1LDExLjI1IEw5Ljc1LDExLjI1IEw5Ljc1LDEyLjc1IEw3LjUsMTIuNzUgTDcuNSwyMC4yNSBMMTUsMjAuMjUgTDE1LDE1IEwxNi41LDE1IFogTTkuNzUsNiBMMS41LDYgTDEuNSw3LjUgTDkuNzUsNy41IEw5Ljc1LDYgWiBNMjEuNzUsMTIuNzUgQzIyLjE2NDc1LDEyLjc1IDIyLjUsMTIuNDE0NzUgMjIuNSwxMiBMMjIuNSwzIEMyMi41LDIuNTg2IDIyLjE2NDc1LDIuMjUgMjEuNzUsMi4yNSBMMTIuNzUsMi4yNSBDMTIuMzM1MjUsMi4yNSAxMiwyLjU4NiAxMiwzIEwxMiwxMiBDMTIsMTIuNDE0NzUgMTIuMzM1MjUsMTIuNzUgMTIuNzUsMTIuNzUgTDIxLjc1LDEyLjc1IE0xMy41LDMuNzUgTDIxLDMuNzUgTDIxLDExLjI1IEwxMy41LDExLjI1IEwxMy41LDMuNzUgWiIgaWQ9IlNoYXBlIiBmaWxsPSIjRkZGRkZGIiBmaWxsLXJ1bGU9Im5vbnplcm8iPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cmVjdCBpZD0iX3gzQ19UcmFuc3BhcmVudF9SZWN0YW5nbGVfeDNFXyIgeD0iMCIgeT0iMCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48L3JlY3Q+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==;fontSize=14;fontFamily=IBM Plex Sans;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;spacingTop=-7;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-16">
+            <mxGeometry x="40" y="74" width="49" height="49" as="geometry" />
+          </mxCell>
+        </object>
+        <object label="Code Engine job&#xa;instances" generation="2.0" release="v3.0.1" id="cDDFkdkcNhUbpnDVuA-s-21">
+          <mxCell style="shape=image;aspect=fixed;image=data:image/svg+xml,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNDlweCIgaGVpZ2h0PSI0OXB4IiB2aWV3Qm94PSIwIDAgNDkgNDkiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+Q29kZSBFbmdpbmUgdjIgSWNvbjwvdGl0bGU+CiAgICA8ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0idjItNDh4NDgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yNjE4LCAtOTM5KSI+CiAgICAgICAgICAgIDxnIGlkPSJDb2RlLUVuZ2luZS12Mi1JY29uIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNjE4LjUsIDkzOS41MzA0KSI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iS3ViZXJuZXRlcyIgZmlsbD0iIzE5ODAzOCI+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IkZpbGwtNCIgcG9pbnRzPSIwIDQ4IDQ4IDQ4IDQ4IDAgMCAwIj48L3BvbHlnb24+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iaWJtLWNsb3VkLS1jb2RlLWVuZ2luZSgxKSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTEuNSwgMTIuNDY5NikiPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNi41LDE1IEwxNi41LDIwLjk0MjI1IEMxNi41LDIxLjM4ODUgMTYuMTM4NSwyMS43NSAxNS42OTIyNSwyMS43NSBMNi44MDc3NSwyMS43NSBDNi4zNjE1LDIxLjc1IDYsMjEuMzg4NSA2LDIwLjk0MjI1IEw2LDE3LjI1IEwxLjUsMTcuMjUgTDEuNSwxNS43NSBMNiwxNS43NSBMNiwxMi4wNTc3NSBDNiwxMS42MTE1IDYuMzYxNSwxMS4yNSA2LjgwNzc1LDExLjI1IEw5Ljc1LDExLjI1IEw5Ljc1LDEyLjc1IEw3LjUsMTIuNzUgTDcuNSwyMC4yNSBMMTUsMjAuMjUgTDE1LDE1IEwxNi41LDE1IFogTTkuNzUsNiBMMS41LDYgTDEuNSw3LjUgTDkuNzUsNy41IEw5Ljc1LDYgWiBNMjEuNzUsMTIuNzUgQzIyLjE2NDc1LDEyLjc1IDIyLjUsMTIuNDE0NzUgMjIuNSwxMiBMMjIuNSwzIEMyMi41LDIuNTg2IDIyLjE2NDc1LDIuMjUgMjEuNzUsMi4yNSBMMTIuNzUsMi4yNSBDMTIuMzM1MjUsMi4yNSAxMiwyLjU4NiAxMiwzIEwxMiwxMiBDMTIsMTIuNDE0NzUgMTIuMzM1MjUsMTIuNzUgMTIuNzUsMTIuNzUgTDIxLjc1LDEyLjc1IE0xMy41LDMuNzUgTDIxLDMuNzUgTDIxLDExLjI1IEwxMy41LDExLjI1IEwxMy41LDMuNzUgWiIgaWQ9IlNoYXBlIiBmaWxsPSIjRkZGRkZGIiBmaWxsLXJ1bGU9Im5vbnplcm8iPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cmVjdCBpZD0iX3gzQ19UcmFuc3BhcmVudF9SZWN0YW5nbGVfeDNFXyIgeD0iMCIgeT0iMCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48L3JlY3Q+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==;fontSize=14;fontFamily=IBM Plex Sans;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;spacingTop=-7;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-16">
+            <mxGeometry x="40" y="190" width="49" height="49" as="geometry" />
+          </mxCell>
+        </object>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-28" value="" style="html=1;labelBackgroundColor=#ffffff;jettySize=auto;orthogonalLoop=1;fontSize=14;rounded=0;jumpStyle=gap;edgeStyle=orthogonalEdgeStyle;startArrow=oval;endArrow=block;startFill=1;endFill=1;strokeWidth=2;dashed=1;sourcePerimeterSpacing=3;targetPerimeterSpacing=3;entryX=1;entryY=0.75;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="cDDFkdkcNhUbpnDVuA-s-16" source="cDDFkdkcNhUbpnDVuA-s-22" target="cDDFkdkcNhUbpnDVuA-s-20">
+          <mxGeometry width="48" height="48" relative="1" as="geometry">
+            <mxPoint x="390" y="318" as="sourcePoint" />
+            <mxPoint x="438" y="270" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="130" y="226" />
+              <mxPoint x="130" y="110" />
+              <mxPoint x="89" y="110" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-30" value="&lt;span&gt;observes cpu/memory usage&lt;/span&gt;" style="edgeLabel;html=1;align=left;verticalAlign=middle;resizable=0;points=[];fontStyle=2" vertex="1" connectable="0" parent="cDDFkdkcNhUbpnDVuA-s-28">
+          <mxGeometry x="-0.3297" y="-2" relative="1" as="geometry">
+            <mxPoint x="-57" y="-10" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-29" value="" style="html=1;labelBackgroundColor=#ffffff;jettySize=auto;orthogonalLoop=1;fontSize=14;rounded=0;jumpStyle=gap;edgeStyle=orthogonalEdgeStyle;startArrow=oval;endArrow=block;startFill=1;endFill=1;strokeWidth=2;dashed=1;sourcePerimeterSpacing=3;targetPerimeterSpacing=3;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="cDDFkdkcNhUbpnDVuA-s-16" source="cDDFkdkcNhUbpnDVuA-s-22" target="cDDFkdkcNhUbpnDVuA-s-21">
+          <mxGeometry width="48" height="48" relative="1" as="geometry">
+            <mxPoint x="390" y="318" as="sourcePoint" />
+            <mxPoint x="438" y="270" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="341" y="227" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <object label="monitoring-apikey&#xa;(Code Engine secret)" release="v3.0.1" generation="2.0" id="cDDFkdkcNhUbpnDVuA-s-42">
+          <mxCell style="shape=image;aspect=fixed;image=data:image/svg+xml,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNDhweCIgaGVpZ2h0PSI0OHB4IiB2aWV3Qm94PSIwIDAgNDggNDgiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+Y3JlZGVudGlhbHM8L3RpdGxlPgogICAgPGcgaWQ9IlYyLUljb25zIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0iSUJNLS8tQ2xvdWQtLy1TZWN1cml0eSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ2NiwgLTE0KSI+CiAgICAgICAgICAgIDxnIGlkPSJjcmVkZW50aWFscyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDY2LCAxNCkiPgogICAgICAgICAgICAgICAgPHJlY3QgaWQ9IlJlY3RhbmdsZSIgZmlsbD0iI0ZBNEQ1NiIgeD0iMCIgeT0iMCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48L3JlY3Q+CiAgICAgICAgICAgICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiwgMTIpIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIsMTYuNSBDMTMuNjU2ODU0MiwxNi41IDE1LDE1LjE1Njg1NDIgMTUsMTMuNSBDMTUsMTEuODQzMTQ1OCAxMy42NTY4NTQyLDEwLjUgMTIsMTAuNSBDMTAuMzQzMTQ1OCwxMC41IDksMTEuODQzMTQ1OCA5LDEzLjUgQzksMTUuMTU2ODU0MiAxMC4zNDMxNDU4LDE2LjUgMTIsMTYuNSBaIE0xMiwxMiBDMTIuODI4NDI3MSwxMiAxMy41LDEyLjY3MTU3MjkgMTMuNSwxMy41IEMxMy41LDE0LjMyODQyNzEgMTIuODI4NDI3MSwxNSAxMiwxNSBDMTEuMTcxNTcyOSwxNSAxMC41LDE0LjMyODQyNzEgMTAuNSwxMy41IEMxMC41LDEyLjY3MTU3MjkgMTEuMTcxNTcyOSwxMiAxMiwxMiBaIiBpZD0iU2hhcGUiIGZpbGw9IiNGRkZGRkYiIGZpbGwtcnVsZT0ibm9uemVybyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxyZWN0IGlkPSJSZWN0YW5nbGUiIGZpbGw9IiNGRkZGRkYiIGZpbGwtcnVsZT0ibm9uemVybyIgeD0iMTAuNSIgeT0iNC41IiB3aWR0aD0iMyIgaGVpZ2h0PSIxLjUiPjwvcmVjdD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTgsMS41IEw0LjUsMS41IEM1LjE3MTkxNTYxLDEuNTAwODI2ODQgNC41MDA4MjY4NCwyLjE3MTkxNTYxIDQuNSwzIEw0LjUsMjEgQzQuNTAwOTUwNiwyMS44MjgwMzMxIDUuMTcxOTY2OTUsMjIuNDk5MDQ5NCA0LjUsMjIuNSBMMTgsMjIuNSBDMTguODI3OTY0NiwyMi40OTg4ODQ1IDE5LjQ5ODg4NDUsMjEuODI3OTY0NiAxOS41LDIxIEwxOS41LDMgQzE5LjQ5OTA0OTQsMi4xNzE5NjY5NSAxOC44MjgwMzMxLDEuNTAwOTUwNiAxOCwxLjUgTDE4LDEuNSBaIE0xNSwyMSBMOSwyMSBMOSwxOS41IEM5LDE5LjA4NTc4NjQgOS4zMzU3ODY0NCwxOC43NSA5Ljc1LDE4Ljc1IEwxNC4yNSwxOC43NSBDMTQuNjY0MjEzNiwxOC43NSAxNSwxOS4wODU3ODY0IDE1LDE5LjUgTDE1LDIxIFogTTE2LjUsMjEgTDE2LjUsMTkuNSBDMTYuNSwxOC4yNTczNTkzIDE1LjQ5MjY0MDcsMTcuMjUgMTQuMjUsMTcuMjUgTDkuNzUsMTcuMjUgQzguNTA3MzU5MzEsMTcuMjUgNy41LDE4LjI1NzM1OTMgNy41LDE5LjUgTDcuNSwyMSBMNiwyMSBMNiwzIEwxOCwzIEwxOCwyMSBMMTYuNSwyMSBaIiBpZD0iU2hhcGUiIGZpbGw9IiNGRkZGRkYiIGZpbGwtcnVsZT0ibm9uemVybyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxyZWN0IGlkPSJfVHJhbnNwYXJlbnRfUmVjdGFuZ2xlXyIgeD0iMCIgeT0iMCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48L3JlY3Q+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==;fontFamily=IBM Plex Sans;fontSize=14;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;spacingTop=-7;" vertex="1" parent="cDDFkdkcNhUbpnDVuA-s-16">
+            <mxGeometry x="671" y="200" width="48" height="48" as="geometry" />
+          </mxCell>
+        </object>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-44" value="" style="html=1;labelBackgroundColor=#ffffff;jettySize=auto;orthogonalLoop=1;fontSize=14;rounded=0;jumpStyle=gap;edgeStyle=orthogonalEdgeStyle;startArrow=block;endArrow=oval;startFill=1;endFill=1;strokeWidth=2;dashed=1;sourcePerimeterSpacing=3;targetPerimeterSpacing=3;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="cDDFkdkcNhUbpnDVuA-s-16" source="cDDFkdkcNhUbpnDVuA-s-42" target="cDDFkdkcNhUbpnDVuA-s-23">
+          <mxGeometry width="48" height="48" relative="1" as="geometry">
+            <mxPoint x="220" y="-2" as="sourcePoint" />
+            <mxPoint x="268" y="-50" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-51" value="mounts" style="edgeLabel;html=1;align=left;verticalAlign=middle;resizable=0;points=[];fontStyle=2" vertex="1" connectable="0" parent="cDDFkdkcNhUbpnDVuA-s-44">
+          <mxGeometry x="-0.4779" y="-3" relative="1" as="geometry">
+            <mxPoint x="-76" y="-2" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-48" value="" style="html=1;labelBackgroundColor=#ffffff;jettySize=auto;orthogonalLoop=1;fontSize=14;rounded=0;jumpStyle=gap;edgeStyle=orthogonalEdgeStyle;startArrow=oval;endArrow=block;strokeWidth=2;startFill=1;endFill=1;sourcePerimeterSpacing=3;targetPerimeterSpacing=3;entryX=1;entryY=0.25;entryDx=0;entryDy=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;" edge="1" parent="cDDFkdkcNhUbpnDVuA-s-16" source="cDDFkdkcNhUbpnDVuA-s-23" target="cDDFkdkcNhUbpnDVuA-s-20">
+          <mxGeometry width="48" height="48" relative="1" as="geometry">
+            <mxPoint x="510" y="148" as="sourcePoint" />
+            <mxPoint x="558" y="100" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="160" y="111" />
+              <mxPoint x="160" y="86" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-49" value="" style="html=1;labelBackgroundColor=#ffffff;jettySize=auto;orthogonalLoop=1;fontSize=14;rounded=0;jumpStyle=gap;edgeStyle=orthogonalEdgeStyle;startArrow=oval;endArrow=block;strokeWidth=2;startFill=1;endFill=1;sourcePerimeterSpacing=3;targetPerimeterSpacing=3;entryX=1;entryY=0.25;entryDx=0;entryDy=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;" edge="1" parent="cDDFkdkcNhUbpnDVuA-s-16" source="cDDFkdkcNhUbpnDVuA-s-23" target="cDDFkdkcNhUbpnDVuA-s-21">
+          <mxGeometry width="48" height="48" relative="1" as="geometry">
+            <mxPoint x="510" y="148" as="sourcePoint" />
+            <mxPoint x="558" y="100" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="510" y="111" />
+              <mxPoint x="160" y="111" />
+              <mxPoint x="160" y="202" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-50" value="pulls custom metrics" style="edgeLabel;html=1;align=left;verticalAlign=middle;resizable=0;points=[];fontStyle=2" vertex="1" connectable="0" parent="cDDFkdkcNhUbpnDVuA-s-49">
+          <mxGeometry x="0.1554" y="-2" relative="1" as="geometry">
+            <mxPoint x="-45" y="-10" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-38" value="" style="html=1;labelBackgroundColor=#ffffff;jettySize=auto;orthogonalLoop=1;fontSize=14;rounded=0;jumpStyle=gap;edgeStyle=orthogonalEdgeStyle;startArrow=oval;endArrow=block;strokeWidth=2;startFill=1;endFill=1;strokeColor=#198038;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="cDDFkdkcNhUbpnDVuA-s-4" source="cDDFkdkcNhUbpnDVuA-s-23" target="cDDFkdkcNhUbpnDVuA-s-24">
+          <mxGeometry width="48" height="48" relative="1" as="geometry">
+            <mxPoint x="660" y="278" as="sourcePoint" />
+            <mxPoint x="708" y="230" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-47" value="&lt;i&gt;Periodically ingest &lt;br&gt;via&amp;nbsp;&lt;/i&gt;&lt;i&gt;Remote Write mechanism&lt;br&gt;&lt;/i&gt;&lt;i&gt;over HTTPS&lt;/i&gt;" style="edgeLabel;html=1;align=left;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="cDDFkdkcNhUbpnDVuA-s-38">
+          <mxGeometry x="-0.4929" y="3" relative="1" as="geometry">
+            <mxPoint x="-16" y="-22" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-45" value="" style="html=1;labelBackgroundColor=#ffffff;jettySize=auto;orthogonalLoop=1;fontSize=14;rounded=0;jumpStyle=gap;edgeStyle=orthogonalEdgeStyle;startArrow=block;endArrow=oval;startFill=1;endFill=1;strokeWidth=2;dashed=1;sourcePerimeterSpacing=3;targetPerimeterSpacing=3;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" target="cDDFkdkcNhUbpnDVuA-s-41">
+          <mxGeometry width="48" height="48" relative="1" as="geometry">
+            <mxPoint x="800" y="784" as="sourcePoint" />
+            <mxPoint x="348" y="510" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="cDDFkdkcNhUbpnDVuA-s-52" value="copied" style="edgeLabel;html=1;align=left;verticalAlign=middle;resizable=0;points=[];fontStyle=2" vertex="1" connectable="0" parent="cDDFkdkcNhUbpnDVuA-s-45">
+          <mxGeometry x="-0.5089" relative="1" as="geometry">
+            <mxPoint x="-20" y="-10" as="offset" />
+          </mxGeometry>
+        </mxCell>
+      </root>
+    </mxGraphModel>
+  </diagram>
+</mxfile>
diff --git a/metrics-collector/go.mod b/metrics-collector/go.mod
index b816d4e37..e358afe92 100644
--- a/metrics-collector/go.mod
+++ b/metrics-collector/go.mod
@@ -1,6 +1,6 @@
 module metrics-collector
 
-go 1.23.0
+go 1.25.0
 
 require (
 	k8s.io/api v0.30.1
@@ -31,7 +31,7 @@ require (
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
-	golang.org/x/net v0.38.0 // indirect
+	golang.org/x/net v0.23.0 // indirect
 	golang.org/x/oauth2 v0.27.0 // indirect
 	golang.org/x/sys v0.31.0 // indirect
 	golang.org/x/term v0.30.0 // indirect
@@ -42,7 +42,7 @@ require (
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	k8s.io/klog/v2 v2.120.1 // indirect
-	k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f // indirect
+	k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
 	k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect
 	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
 	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
diff --git a/metrics-collector/go.sum b/metrics-collector/go.sum
index 6f6389a87..f2758c0dc 100644
--- a/metrics-collector/go.sum
+++ b/metrics-collector/go.sum
@@ -14,8 +14,7 @@ github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDsl
 github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
 github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
 github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
-github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
-github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
@@ -28,8 +27,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=
-github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
+github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
+github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -58,10 +57,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
-github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g=
-github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc=
-github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
-github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
+github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
+github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
+github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE=
+github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
@@ -83,8 +82,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
-golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
+golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
+golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
 golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
 golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -133,8 +132,8 @@ k8s.io/client-go v0.30.1 h1:uC/Ir6A3R46wdkgCV3vbLyNOYyCJ8oZnjtJGKfytl/Q=
 k8s.io/client-go v0.30.1/go.mod h1:wrAqLNs2trwiCH/wxxmT/x3hKVH9PuV0GGW0oDoHVqc=
 k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
 k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
-k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f h1:0LQagt0gDpKqvIkAMPaRGcXawNMouPECM1+F9BVxEaM=
-k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f/go.mod h1:S9tOR0FxgyusSNR+MboCuiDpVWkAifZvaYI1Q2ubgro=
+k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
+k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
 k8s.io/kubectl v0.30.1 h1:sHFIRI3oP0FFZmBAVEE8ErjnTyXDPkBcvO88mH9RjuY=
 k8s.io/kubectl v0.30.1/go.mod h1:7j+L0Cc38RYEcx+WH3y44jRBe1Q1jxdGPKkX0h4iDq0=
 k8s.io/metrics v0.30.1 h1:PeA9cP0kxVtaC8Wkzp4sTkr7YSkd9R0UYP6cCHOOY1M=
diff --git a/metrics-collector/images/configure-plots.png b/metrics-collector/images/configure-plots.png
deleted file mode 100644
index ceffd258b..000000000
Binary files a/metrics-collector/images/configure-plots.png and /dev/null differ
diff --git a/metrics-collector/images/count-of-metrics-lines.png b/metrics-collector/images/count-of-metrics-lines.png
deleted file mode 100644
index e274f48b1..000000000
Binary files a/metrics-collector/images/count-of-metrics-lines.png and /dev/null differ
diff --git a/metrics-collector/images/cpu-utilization.png b/metrics-collector/images/cpu-utilization.png
deleted file mode 100644
index 4329d5714..000000000
Binary files a/metrics-collector/images/cpu-utilization.png and /dev/null differ
diff --git a/metrics-collector/images/ibm-cloud-logs--loglines.png b/metrics-collector/images/ibm-cloud-logs--loglines.png
deleted file mode 100644
index e865c935c..000000000
Binary files a/metrics-collector/images/ibm-cloud-logs--loglines.png and /dev/null differ
diff --git a/metrics-collector/images/memory-utilization.png b/metrics-collector/images/memory-utilization.png
deleted file mode 100644
index d1b533810..000000000
Binary files a/metrics-collector/images/memory-utilization.png and /dev/null differ
diff --git a/metrics-collector/images/metrics-collector.overview.png b/metrics-collector/images/metrics-collector.overview.png
new file mode 100644
index 000000000..89535b90c
Binary files /dev/null and b/metrics-collector/images/metrics-collector.overview.png differ
diff --git a/metrics-collector/images/monitoring-dashboard-ce-component-resources.png b/metrics-collector/images/monitoring-dashboard-ce-component-resources.png
new file mode 100644
index 000000000..c6b2a282f
Binary files /dev/null and b/metrics-collector/images/monitoring-dashboard-ce-component-resources.png differ
diff --git a/metrics-collector/images/new-board.png b/metrics-collector/images/new-board.png
deleted file mode 100644
index b95e182e5..000000000
Binary files a/metrics-collector/images/new-board.png and /dev/null differ
diff --git a/metrics-collector/images/resource-usage-graph.png b/metrics-collector/images/resource-usage-graph.png
deleted file mode 100644
index 47eb80be4..000000000
Binary files a/metrics-collector/images/resource-usage-graph.png and /dev/null differ
diff --git a/metrics-collector/main.go b/metrics-collector/main.go
index 63a2ba867..2bb5c1db8 100644
--- a/metrics-collector/main.go
+++ b/metrics-collector/main.go
@@ -5,10 +5,14 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"net/http"
 	"os"
+	"os/signal"
 	"strconv"
 	"strings"
 	"sync"
+	"sync/atomic"
+	"syscall"
 	"time"
 
 	v1 "k8s.io/api/core/v1"
@@ -23,13 +27,180 @@ import (
 	metricsv "k8s.io/metrics/pkg/client/clientset/versioned"
 )
 
-func main() {
+// MetricsCache holds the latest collected metrics in a thread-safe manner
+type MetricsCache struct {
+	mu              sync.RWMutex
+	metrics         []InstanceResourceStats
+	namespace       string
+	lastUpdate      time.Time
+	collectionCount int64
+	errorCount      int64
+}
+
+// CollectorStats tracks collector performance metrics
+type CollectorStats struct {
+	lastCollectionDuration atomic.Int64 // in milliseconds
+	lastCollectionTime     atomic.Int64 // unix timestamp
+	totalErrors            atomic.Int64
+}
+
+var (
+	metricsCache   = &MetricsCache{}
+	collectorStats = &CollectorStats{}
+)
+
+// setupHTTPHandlers configures the HTTP routes
+func setupHTTPHandlers() http.Handler {
+	mux := http.NewServeMux()
+	mux.HandleFunc("/metrics", metricsHandler)
+	return mux
+}
+
+// metricsHandler serves Prometheus-formatted metrics
+func metricsHandler(w http.ResponseWriter, r *http.Request) {
+	if r.Method != http.MethodGet {
+		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+		return
+	}
+
+	metricsCache.mu.RLock()
+	metrics := metricsCache.metrics
+	namespace := metricsCache.namespace
+	lastUpdate := metricsCache.lastUpdate
+	metricsCache.mu.RUnlock()
+
+	// Set content type for Prometheus
+	w.Header().Set("Content-Type", "text/plain; version=0.0.4; charset=utf-8")
+
+	// Write Prometheus metrics
+	output := formatPrometheusMetrics(metrics, namespace, lastUpdate)
+	w.Write([]byte(output))
+}
+
+// formatPrometheusMetrics converts metrics to Prometheus text format
+func formatPrometheusMetrics(metrics []InstanceResourceStats, namespace string, lastUpdate time.Time) string {
+	var sb strings.Builder
+
+	// Helper function to escape label values
+	escapeLabelValue := func(s string) string {
+		s = strings.ReplaceAll(s, "\\", "\\\\")
+		s = strings.ReplaceAll(s, "\"", "\\\"")
+		s = strings.ReplaceAll(s, "\n", "\\n")
+		return s
+	}
+
+	// Write container CPU usage metrics
+	sb.WriteString("# HELP ibm_codeengine_instance_cpu_usage_millicores Current CPU usage in millicores\n")
+	sb.WriteString("# TYPE ibm_codeengine_instance_cpu_usage_millicores gauge\n")
+	for _, m := range metrics {
+		labels := fmt.Sprintf("ibm_codeengine_instance_name=\"%s\",ibm_codeengine_component_type=\"%s\",ibm_codeengine_component_name=\"%s\"",
+			escapeLabelValue(m.Name),
+			escapeLabelValue(m.ComponentType),
+			escapeLabelValue(m.ComponentName))
+		sb.WriteString(fmt.Sprintf("ibm_codeengine_instance_cpu_usage_millicores{%s} %d\n", labels, m.Cpu.Current))
+	}
+	sb.WriteString("\n")
+
+	// Write container CPU limit metrics
+	sb.WriteString("# HELP ibm_codeengine_instance_cpu_limit_millicores Configured CPU limit in millicores\n")
+	sb.WriteString("# TYPE ibm_codeengine_instance_cpu_limit_millicores gauge\n")
+	for _, m := range metrics {
+		if m.Cpu.Configured > 0 {
+			labels := fmt.Sprintf("ibm_codeengine_instance_name=\"%s\",ibm_codeengine_component_type=\"%s\",ibm_codeengine_component_name=\"%s\"",
+				escapeLabelValue(m.Name),
+				escapeLabelValue(m.ComponentType),
+				escapeLabelValue(m.ComponentName))
+			sb.WriteString(fmt.Sprintf("ibm_codeengine_instance_cpu_limit_millicores{%s} %d\n", labels, m.Cpu.Configured))
+		}
+	}
+	sb.WriteString("\n")
+
+	// Write container memory usage metrics
+	sb.WriteString("# HELP ibm_codeengine_instance_memory_usage_bytes Current memory usage in bytes\n")
+	sb.WriteString("# TYPE ibm_codeengine_instance_memory_usage_bytes gauge\n")
+	for _, m := range metrics {
+		labels := fmt.Sprintf("ibm_codeengine_instance_name=\"%s\",ibm_codeengine_component_type=\"%s\",ibm_codeengine_component_name=\"%s\"",
+			escapeLabelValue(m.Name),
+			escapeLabelValue(m.ComponentType),
+			escapeLabelValue(m.ComponentName))
+		// Convert MB to bytes
+		sb.WriteString(fmt.Sprintf("ibm_codeengine_instance_memory_usage_bytes{%s} %d\n", labels, m.Memory.Current*1000*1000))
+	}
+	sb.WriteString("\n")
+
+	// Write container memory limit metrics
+	sb.WriteString("# HELP ibm_codeengine_instance_memory_limit_bytes Configured memory limit in bytes\n")
+	sb.WriteString("# TYPE ibm_codeengine_instance_memory_limit_bytes gauge\n")
+	for _, m := range metrics {
+		if m.Memory.Configured > 0 {
+			labels := fmt.Sprintf("ibm_codeengine_instance_name=\"%s\",ibm_codeengine_component_type=\"%s\",ibm_codeengine_component_name=\"%s\"",
+				escapeLabelValue(m.Name),
+				escapeLabelValue(m.ComponentType),
+				escapeLabelValue(m.ComponentName))
+			// Convert MB to bytes
+			sb.WriteString(fmt.Sprintf("ibm_codeengine_instance_memory_limit_bytes{%s} %d\n", labels, m.Memory.Configured*1000*1000))
+		}
+	}
+	sb.WriteString("\n")
+
+	// Write container ephemeral storage usage metrics (if available)
+	hasStorageMetrics := false
+	for _, m := range metrics {
+		if m.DiskUsage.Current > 0 {
+			hasStorageMetrics = true
+			break
+		}
+	}
+
+	if hasStorageMetrics {
+		sb.WriteString("# HELP ibm_codeengine_instance_ephemeral_storage_usage_bytes Current ephemeral storage usage in bytes\n")
+		sb.WriteString("# TYPE ibm_codeengine_instance_ephemeral_storage_usage_bytes gauge\n")
+		for _, m := range metrics {
+			if m.DiskUsage.Current > 0 {
+				labels := fmt.Sprintf("ibm_codeengine_instance_name=\"%s\",ibm_codeengine_component_type=\"%s\",ibm_codeengine_component_name=\"%s\"",
+					escapeLabelValue(m.Name),
+					escapeLabelValue(m.ComponentType),
+					escapeLabelValue(m.ComponentName))
+				// Convert MB to bytes
+				sb.WriteString(fmt.Sprintf("ibm_codeengine_instance_ephemeral_storage_usage_bytes{%s} %d\n", labels, m.DiskUsage.Current*1000*1000))
+			}
+		}
+		sb.WriteString("\n")
+	}
+
+	if os.Getenv("METRICS_INTERNAL_STATS") == "true" {
+		// Write collector self-monitoring metrics
+		sb.WriteString("# HELP codeengine_collector_collection_duration_seconds Time taken to collect metrics in seconds\n")
+		sb.WriteString("# TYPE codeengine_collector_collection_duration_seconds gauge\n")
+		durationMs := collectorStats.lastCollectionDuration.Load()
+		sb.WriteString(fmt.Sprintf("codeengine_collector_collection_duration_seconds %.3f\n", float64(durationMs)/1000.0))
+		sb.WriteString("\n")
+
+		sb.WriteString("# HELP codeengine_collector_last_collection_timestamp_seconds Unix timestamp of last successful collection\n")
+		sb.WriteString("# TYPE codeengine_collector_last_collection_timestamp_seconds gauge\n")
+		lastCollectionTime := collectorStats.lastCollectionTime.Load()
+		sb.WriteString(fmt.Sprintf("codeengine_collector_last_collection_timestamp_seconds %d\n", lastCollectionTime))
+		sb.WriteString("\n")
+
+		sb.WriteString("# HELP codeengine_collector_collection_errors_total Total number of collection errors\n")
+		sb.WriteString("# TYPE codeengine_collector_collection_errors_total counter\n")
+		totalErrors := collectorStats.totalErrors.Load()
+		sb.WriteString(fmt.Sprintf("codeengine_collector_collection_errors_total %d\n", totalErrors))
+		sb.WriteString("\n")
+	}
+
+	return sb.String()
+}
 
+func main() {
 	jobMode := os.Getenv("JOB_MODE")
 
 	// In task mode, collect the resource metrics once
 	if jobMode == "task" {
-		collectInstanceMetrics()
+		if err := collectInstanceMetrics(metricsCache); err != nil {
+			fmt.Printf("Error collecting metrics: %v\n", err)
+			os.Exit(1)
+		}
 		return
 	}
 
@@ -42,11 +213,105 @@ func main() {
 		}
 	}
 
-	// In daemon mode, collect resource metrics in an endless loop
-	for {
-		collectInstanceMetrics()
-		time.Sleep(time.Duration(sleepDuration) * time.Second)
+	// Check if HTTP metrics server should be enabled
+	metricsEnabled := os.Getenv("METRICS_ENABLED") == "true"
+
+	// Get metrics port configuration
+	metricsPort := "9100"
+	if port := os.Getenv("METRICS_PORT"); port != "" {
+		metricsPort = port
+	}
+
+	// Create context for graceful shutdown
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel()
+
+	// Setup signal handling for graceful shutdown
+	sigChan := make(chan os.Signal, 1)
+	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
+
+	// Start HTTP server only if METRICS_ENABLED=true
+	var server *http.Server
+	var serverErrors chan error
+
+	if metricsEnabled {
+		server = &http.Server{
+			Addr:    ":" + metricsPort,
+			Handler: setupHTTPHandlers(),
+		}
+
+		// Start HTTP server in a goroutine
+		serverErrors = make(chan error, 1)
+		go func() {
+			fmt.Printf("Starting HTTP metrics server on port %s\n", metricsPort)
+			if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+				serverErrors <- fmt.Errorf("HTTP server error: %w", err)
+			}
+		}()
+	} else {
+		fmt.Println("HTTP metrics server disabled (METRICS_ENABLED not set to 'true')")
+	}
+
+	// Start metrics collection loop in a goroutine
+	collectionDone := make(chan struct{})
+	go func() {
+		defer close(collectionDone)
+		ticker := time.NewTicker(time.Duration(sleepDuration) * time.Second)
+		defer ticker.Stop()
+
+		// Collect metrics immediately on startup
+		if err := collectInstanceMetrics(metricsCache); err != nil {
+			fmt.Printf("Error collecting metrics: %v\n", err)
+			collectorStats.totalErrors.Add(1)
+		}
+
+		for {
+			select {
+			case <-ctx.Done():
+				fmt.Println("Stopping metrics collection...")
+				return
+			case <-ticker.C:
+				if err := collectInstanceMetrics(metricsCache); err != nil {
+					fmt.Printf("Error collecting metrics: %v\n", err)
+					collectorStats.totalErrors.Add(1)
+				}
+			}
+		}
+	}()
+
+	// Wait for shutdown signal or server error
+	if metricsEnabled {
+		select {
+		case sig := <-sigChan:
+			fmt.Printf("\nReceived signal %v, initiating graceful shutdown...\n", sig)
+		case err := <-serverErrors:
+			fmt.Printf("Server error: %v\n", err)
+		}
+	} else {
+		// If server is not running, just wait for signal
+		sig := <-sigChan
+		fmt.Printf("\nReceived signal %v, initiating graceful shutdown...\n", sig)
+	}
+
+	// Cancel context to stop metrics collection
+	cancel()
+
+	// Shutdown HTTP server with timeout (only if it was started)
+	if metricsEnabled && server != nil {
+		shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
+		defer shutdownCancel()
+
+		if err := server.Shutdown(shutdownCtx); err != nil {
+			fmt.Printf("HTTP server shutdown error: %v\n", err)
+		} else {
+			fmt.Println("HTTP server stopped gracefully")
+		}
 	}
+
+	// Wait for metrics collection to finish
+	<-collectionDone
+	fmt.Println("Metrics collection stopped")
+	fmt.Println("Shutdown complete")
 }
 
 type ComponentType int64
@@ -88,28 +353,129 @@ type InstanceResourceStats struct {
 	Message       string        `json:"message"`
 }
 
+// buildPodMap creates a map of pod names to pod objects for O(1) lookup
+func buildPodMap(pods *[]v1.Pod) map[string]*v1.Pod {
+	podMap := make(map[string]*v1.Pod, len(*pods))
+	for i := range *pods {
+		podMap[(*pods)[i].Name] = &(*pods)[i]
+	}
+	return podMap
+}
+
+// extractComponentMetadata extracts component type, name, and parent from pod metric labels
+func extractComponentMetadata(podMetric *v1beta1.PodMetrics) (componentType ComponentType, componentName, parent string) {
+	componentType = determineComponentType(podMetric)
+
+	switch componentType {
+	case Job:
+		if jobName, ok := podMetric.ObjectMeta.Labels["codeengine.cloud.ibm.com/job-definition-name"]; ok {
+			componentName = jobName
+		} else if jobRunName, ok := podMetric.ObjectMeta.Labels["codeengine.cloud.ibm.com/job-run"]; ok {
+			componentName = jobRunName
+		} else {
+			componentName = "standalone"
+		}
+		parent = podMetric.ObjectMeta.Labels["codeengine.cloud.ibm.com/job-run"]
+	case App:
+		componentName = podMetric.ObjectMeta.Labels["serving.knative.dev/service"]
+		parent = podMetric.ObjectMeta.Labels["serving.knative.dev/revision"]
+	case Build:
+		if buildName, ok := podMetric.ObjectMeta.Labels["build.shipwright.io/name"]; ok {
+			componentName = buildName
+		} else if buildRunName, ok := podMetric.ObjectMeta.Labels["buildrun.shipwright.io/name"]; ok {
+			componentName = buildRunName
+		} else {
+			componentName = "standalone"
+		}
+		parent = podMetric.ObjectMeta.Labels["buildrun.shipwright.io/name"]
+	default:
+		componentName = "unknown"
+	}
+
+	return
+}
+
+// processMetric processes a single pod metric and outputs the JSON log line
+func processMetric(
+	podMetric *v1beta1.PodMetrics,
+	podMap map[string]*v1.Pod,
+	clientset *kubernetes.Clientset,
+	namespace string,
+	config *rest.Config,
+) *InstanceResourceStats {
+	// Extract component metadata
+	componentType, componentName, parent := extractComponentMetadata(podMetric)
+
+	// Determine the actual CPU and memory usage
+	cpuCurrent := podMetric.Containers[0].Usage.Cpu().ToDec().AsApproximateFloat64() * 1000
+	memoryCurrent := podMetric.Containers[0].Usage.Memory().ToDec().AsApproximateFloat64() / 1000 / 1000
+
+	stats := InstanceResourceStats{
+		Metric:        "instance-resources",
+		Name:          podMetric.Name,
+		Parent:        parent,
+		ComponentType: componentType.String(),
+		ComponentName: componentName,
+		Cpu: ResourceStats{
+			Current: int64(cpuCurrent),
+		},
+		Memory: ResourceStats{
+			Current: int64(memoryCurrent),
+		},
+	}
+
+	// Gather the configured resource limits and calculate the usage (in percent)
+	pod := podMap[podMetric.Name]
+	if pod != nil {
+		userContainerName := getUserContainerName(componentType, pod)
+
+		// determine the actual disk usage
+		storageCurrent := obtainDiskUsage(clientset, namespace, podMetric.Name, userContainerName, config)
+		stats.DiskUsage.Current = int64(storageCurrent)
+
+		// extract memory and cpu limits
+		cpu, memory := getCpuAndMemoryLimits(userContainerName, pod)
+
+		cpuLimit := cpu.ToDec().AsApproximateFloat64() * 1000
+		stats.Cpu.Configured = int64(cpuLimit)
+		stats.Cpu.Usage = int64((cpuCurrent / cpuLimit) * 100)
+
+		memoryLimit := memory.ToDec().AsApproximateFloat64() / 1000 / 1000
+		stats.Memory.Configured = int64(memoryLimit)
+		stats.Memory.Usage = int64(memoryCurrent / memoryLimit * 100)
+	}
+
+	// Compose the log line message
+	stats.Message = "Captured metrics of " + stats.ComponentType + " instance '" + stats.Name + "': " + fmt.Sprintf("%d", stats.Cpu.Current) + "m vCPU, " + fmt.Sprintf("%d", stats.Memory.Current) + " MB memory, " + fmt.Sprintf("%d", stats.DiskUsage.Current) + " MB disk usage"
+
+	// Write the stringified JSON struct and make use of IBM Cloud Logs built-in parsing mechanism,
+	// which allows to annotate log lines by providing a JSON object instead of a simple string
+	fmt.Println(ToJSONString(&stats))
+
+	return &stats
+}
+
 // Helper function that retrieves all pods and all pod metrics
 // this function creates a structured log line for each pod for which the kube metrics api provides a metric
-func collectInstanceMetrics() {
-
+func collectInstanceMetrics(cache *MetricsCache) error {
 	startTime := time.Now()
 	fmt.Println("Start to capture pod metrics ...")
 
 	config, err := rest.InClusterConfig()
 	if err != nil {
-		panic(err.Error())
+		return fmt.Errorf("failed to get cluster config: %w", err)
 	}
 
 	// obtain the kube namespace related to this Code Engine project
 	nsBytes, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
 	if err != nil {
-		panic(err.Error())
+		return fmt.Errorf("failed to read namespace: %w", err)
 	}
 	namespace := string(nsBytes)
 
 	coreClientset, err := kubernetes.NewForConfig(config)
 	if err != nil {
-		panic(err.Error())
+		return fmt.Errorf("failed to create clientset: %w", err)
 	}
 
 	// fetches all pods
@@ -118,96 +484,53 @@ func collectInstanceMetrics() {
 	// fetch all pod metrics
 	podMetrics := getAllPodMetrics(namespace, config)
 
+	// Build pod map for O(1) lookup
+	podMap := buildPodMap(pods)
+
+	// Collect metrics into a slice
+	var collectedMetrics []InstanceResourceStats
+	var metricsMu sync.Mutex
+
+	// Use semaphore to limit concurrent goroutines
+	const maxConcurrency = 20
+	sem := make(chan struct{}, maxConcurrency)
 	var wg sync.WaitGroup
 
 	for _, metric := range *podMetrics {
 		wg.Add(1)
+		sem <- struct{}{} // Acquire semaphore
 
 		go func(podMetric *v1beta1.PodMetrics) {
 			defer wg.Done()
+			defer func() { <-sem }() // Release semaphore
 
-			// Determine the component type (either app, job, build or unknown)
-			componentType := determineComponentType(podMetric)
-
-			// Determine the component name
-			var componentName string
-			var parent string
-			switch componentType {
-			case Job:
-				if val, ok := podMetric.ObjectMeta.Labels["codeengine.cloud.ibm.com/job-definition-name"]; ok {
-					componentName = val
-				} else {
-					componentName = "standalone"
-				}
-				parent = podMetric.ObjectMeta.Labels["codeengine.cloud.ibm.com/job-run"]
-			case App:
-				componentName = podMetric.ObjectMeta.Labels["serving.knative.dev/service"]
-				parent = podMetric.ObjectMeta.Labels["serving.knative.dev/revision"]
-			case Build:
-				if val, ok := podMetric.ObjectMeta.Labels["build.shipwright.io/name"]; ok {
-					componentName = val
-				} else {
-					componentName = "standalone"
-				}
-
-				parent = podMetric.ObjectMeta.Labels["buildrun.shipwright.io/name"]
-			default:
-				componentName = "unknown"
-			}
-
-			// Determine the actual CPU and memory usage
-			cpuCurrent := podMetric.Containers[0].Usage.Cpu().ToDec().AsApproximateFloat64() * 1000
-			memoryCurrent := podMetric.Containers[0].Usage.Memory().ToDec().AsApproximateFloat64() / 1000 / 1000
-
-			stats := InstanceResourceStats{
-				Metric:        "instance-resources",
-				Name:          podMetric.Name,
-				Parent:        parent,
-				ComponentType: componentType.String(),
-				ComponentName: componentName,
-				Cpu: ResourceStats{
-					Current: int64(cpuCurrent),
-				},
-				Memory: ResourceStats{
-					Current: int64(memoryCurrent),
-				},
-			}
-
-			// Gather the configured resource limits and calculate the usage (in percent)
-			pod := getPod(podMetric.Name, pods)
-			if pod != nil {
-
-				userContainerName := getUserContainerName(componentType, pod)
-
-				// determine the actual disk usage
-				storageCurrent := obtainDiskUsage(coreClientset, namespace, podMetric.Name, userContainerName, config)
-				stats.DiskUsage.Current = int64(storageCurrent)
-
-				// extract memory and cpu limits
-				cpu, memory := getCpuAndMemoryLimits(userContainerName, pod)
-
-				cpuLimit := cpu.ToDec().AsApproximateFloat64() * 1000
-				stats.Cpu.Configured = int64(cpuLimit)
-				stats.Cpu.Usage = int64((cpuCurrent / cpuLimit) * 100)
-
-				memoryLimit := memory.ToDec().AsApproximateFloat64() / 1000 / 1000
-				stats.Memory.Configured = int64(memoryLimit)
-				stats.Memory.Usage = int64(memoryCurrent / memoryLimit * 100)
+			stats := processMetric(podMetric, podMap, coreClientset, namespace, config)
+			if stats != nil {
+				metricsMu.Lock()
+				collectedMetrics = append(collectedMetrics, *stats)
+				metricsMu.Unlock()
 			}
-
-			// Compose the log line message
-			stats.Message = "Captured metrics of " + stats.ComponentType + " instance '" + stats.Name + "': " + fmt.Sprintf("%d", stats.Cpu.Current) + "m vCPU, " + fmt.Sprintf("%d", stats.Memory.Current) + " MB memory, " + fmt.Sprintf("%d", stats.DiskUsage.Current) + " MB disk usage"
-
-			// Write the stringified JSON struct and make use of IBM Cloud Logs built-in parsing mechanism,
-			// which allows to annotate log lines by providing a JSON object instead of a simple string
-			fmt.Println(ToJSONString(&stats))
-
 		}(&metric)
 	}
 
 	wg.Wait()
 
-	fmt.Println("Captured pod metrics in " + strconv.FormatInt(time.Since(startTime).Milliseconds(), 10) + " ms")
+	duration := time.Since(startTime)
+	fmt.Println("Captured pod metrics in " + strconv.FormatInt(duration.Milliseconds(), 10) + " ms")
+
+	// Update cache with collected metrics
+	cache.mu.Lock()
+	cache.metrics = collectedMetrics
+	cache.namespace = namespace
+	cache.lastUpdate = time.Now()
+	cache.collectionCount++
+	cache.mu.Unlock()
+
+	// Update collector statistics
+	collectorStats.lastCollectionDuration.Store(duration.Milliseconds())
+	collectorStats.lastCollectionTime.Store(time.Now().Unix())
+
+	return nil
 }
 
 // Helper function to determine the component type
@@ -224,16 +547,6 @@ func determineComponentType(podMetric *v1beta1.PodMetrics) ComponentType {
 	return Unknown
 }
 
-// Helper function to obtain a pod by its name from a slice of pods
-func getPod(name string, pods *[]v1.Pod) *v1.Pod {
-	for _, pod := range *pods {
-		if pod.Name == name {
-			return &pod
-		}
-	}
-	return nil
-}
-
 // Helper function to retrieve all pods from the Kube API
 func getAllPods(coreClientset *kubernetes.Clientset, namespace string, config *rest.Config) *[]v1.Pod {
 
@@ -374,10 +687,17 @@ func getUserContainerName(componentType ComponentType, pod *v1.Pod) string {
 		return "user-container"
 	}
 
-	if componentType == Job || componentType == Build {
+	if componentType == Job {
 		return pod.Spec.Containers[0].Name
 	}
 
+	// builds are using two containers:
+	// a quite small 'step-source-default'
+	// and the 'step-build-and-push' which does the heavy lifting
+	if componentType == Build && len(pod.Spec.Containers) > 1 {
+		return pod.Spec.Containers[1].Name
+	}
+
 	// for kube-native deployments, we pick the first container
 	return pod.Spec.Containers[0].Name
 }
diff --git a/metrics-collector/prometheus.yml.template b/metrics-collector/prometheus.yml.template
new file mode 100644
index 000000000..b2e515f8f
--- /dev/null
+++ b/metrics-collector/prometheus.yml.template
@@ -0,0 +1,101 @@
+global:
+  scrape_interval: 30s
+  external_labels:
+    ibm_codeengine_project_name: '${CE_PROJECT_NAME}'
+
+scrape_configs:
+  - job_name: 'codeengine-metrics-project'
+    static_configs:
+      - targets: ['localhost:9100']
+    relabel_configs:
+      # Add project name label
+      - source_labels: [job]
+        action: replace
+        regex: (.+)
+        replacement: '${CE_PROJECT_NAME}'
+        target_label: ibm_codeengine_project_name
+
+  - job_name: 'codeengine-metrics-user'
+    fallback_scrape_protocol: PrometheusText0.0.4
+    kubernetes_sd_configs:
+    - api_server: 'https://172.21.0.1'
+      role: pod
+      namespaces:
+        names:
+          - ${CE_SUBDOMAIN}
+      tls_config:
+        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
+      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+    relabel_configs:
+    # only scrape when annotation codeengine.cloud.ibm.com/userMetricsScrape: 'true' is set
+    - source_labels: [__meta_kubernetes_pod_annotation_codeengine_cloud_ibm_com_userMetricsScrape]
+      action: keep
+      regex: true
+    - source_labels: [__meta_kubernetes_pod_annotation_codeengine_cloud_ibm_com_userMetricsPath]
+      action: replace
+      target_label: __metrics_path__
+      regex: (.+)
+    - source_labels: [__address__, __meta_kubernetes_pod_annotation_codeengine_cloud_ibm_com_userMetricsPort]
+      action: replace
+      regex: (.+):(?:\d+);(\d+)
+      replacement: ${1}:${2}
+      target_label: __address__
+    - action: labelmap
+      regex: __meta_kubernetes_pod_label_(.+)
+    # rename important meta data labels
+    - source_labels: [__meta_kubernetes_namespace]
+      action: replace
+      target_label: ibm_codeengine_namespace
+    - action: replace
+      replacement: '${CE_PROJECT_NAME}'
+      target_label: ibm_codeengine_project_name
+    - source_labels: [__meta_kubernetes_pod_name]
+      action: replace
+      target_label: ibm_codeengine_instance_name
+    - source_labels: [__meta_kubernetes_pod_label_serving_knative_dev_service]
+      action: replace
+      target_label: ibm_codeengine_component_name
+    - source_labels: [__meta_kubernetes_pod_label_serving_knative_dev_configuration]
+      action: replace
+      regex: (.+)
+      replacement: app
+      target_label: ibm_codeengine_component_type
+    - source_labels: [__meta_kubernetes_pod_label_serving_knative_dev_revision]
+      action: replace
+      target_label: ibm_codeengine_subcomponent_name
+    - source_labels: [__meta_kubernetes_pod_label_serving_knative_dev_revisionUID]
+      action: replace
+      regex: (.+)
+      replacement: app_revision
+      target_label: ibm_codeengine_subcomponent_type
+    # drop codeengine, istio, and knative labels
+    - action: labeldrop
+      regex: "codeengine_cloud_ibm_com_(.+)"
+    - action: labeldrop
+      regex: "security_istio_io_(.+)"
+    - action: labeldrop
+      regex: "service_istio_io_(.+)"
+    - action: labeldrop
+      regex: "serving_knative_dev_(.+)"
+    # drop default prometheus labels
+    metric_relabel_configs:
+    - action: labeldrop
+      regex: "instance"
+    - action: labeldrop
+      regex: "job"
+    - action: labeldrop
+      regex: "pod_template_hash"
+    - action: labeldrop
+      regex: "app"
+#
+# Define IBM Cloud Monitoring as the remote write target 
+#
+remote_write:
+- url: https://${METRICS_REMOTE_WRITE_FQDN}/prometheus/remote/write
+  authorization:
+    credentials_file: "/etc/secrets/monitoring-apikey"
+  write_relabel_configs:
+    # Dropping scrape metrics (e.g. scrape_duration_seconds)
+    - source_labels: [__name__]
+      regex: 'scrape_duration_seconds|scrape_samples_scraped|scrape_series_added|scrape_samples_post_metric_relabeling'
+      action: drop
\ No newline at end of file
diff --git a/metrics-collector/setup/ibm-cloud-monitoring/README.md b/metrics-collector/setup/ibm-cloud-monitoring/README.md
new file mode 100644
index 000000000..4a4619fc7
--- /dev/null
+++ b/metrics-collector/setup/ibm-cloud-monitoring/README.md
@@ -0,0 +1,243 @@
+# IBM Cloud Monitoring Dashboard Setup
+
+This directory contains tools and dashboards for IBM Cloud Monitoring (Sysdig) integration.
+
+## Files
+
+- **`import_dashboard.py`**: Python script to create or update Sysdig dashboards
+- **`code-engine-component-resource-overview.json`**: Dashboard configuration for Code Engine resource monitoring
+
+## Prerequisites
+
+1. **Python 3.6+** installed on your system
+
+2. **IBM Cloud Account** with:
+   - An IBM Cloud Monitoring (Sysdig) instance
+   - An IBM Cloud IAM API key with access to the Monitoring instance
+   - The Monitoring instance ID (GUID)
+
+3. **Metrics Data**: The dashboard expects metrics from the Code Engine metrics collector to be available in your Sysdig instance
+
+### Getting Your IBM Cloud Credentials
+
+**IBM Cloud IAM API Key:**
+1. Log in to [IBM Cloud Console](https://cloud.ibm.com)
+2. Go to **Manage** > **Access (IAM)** > **API keys**
+3. Click **Create an IBM Cloud API key**
+4. Give it a name and description
+5. Copy and save the API key securely
+
+**Monitoring Instance ID:**
+1. Navigate to your IBM Cloud Monitoring instance
+2. Click on **Overview** or **Settings**
+3. Copy the **Instance ID** (GUID format: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`)
+
+**Region:**
+- Note the region where your Monitoring instance is deployed (e.g., `us-south`, `eu-de`)
+
+## Setup
+
+### Using a Virtual Environment (Recommended)
+
+It's recommended to use a Python virtual environment to isolate dependencies:
+
+```bash
+# Navigate to the setup directory
+cd setup/ibm-cloud-monitoring
+
+# Create a virtual environment
+python3 -m venv venv
+
+# Activate the virtual environment
+# On macOS/Linux:
+source venv/bin/activate
+# On Windows:
+# venv\Scripts\activate
+
+# Install required dependencies
+pip install requests
+
+# You should now see (venv) in your terminal prompt
+```
+
+When you're done, deactivate the virtual environment:
+```bash
+deactivate
+```
+
+### Global Installation (Alternative)
+
+If you prefer to install dependencies globally:
+
+```bash
+pip install requests
+# or
+pip3 install requests
+```
+
+## Usage
+
+### Import or Update Dashboard
+
+```bash
+python import_dashboard.py \
+    --iam-api-key YOUR_IBM_CLOUD_IAM_API_KEY \
+    --instance-id YOUR_MONITORING_INSTANCE_ID \
+    --region us-south \
+    --dashboard code-engine-component-resource-overview.json
+```
+
+### Using Environment Variables
+
+```bash
+export IBM_CLOUD_IAM_API_KEY=YOUR_IBM_CLOUD_IAM_API_KEY
+export SYSDIG_INSTANCE_ID=YOUR_MONITORING_INSTANCE_ID
+export SYSDIG_REGION=us-south
+python import_dashboard.py --dashboard code-engine-component-resource-overview.json
+```
+
+### Supported Regions
+
+- `au-syd` - Australia (Sydney)
+- `br-sao` - Brazil (São Paulo)
+- `ca-tor` - Canada (Toronto)
+- `eu-de` - EU Central (Frankfurt)
+- `eu-es` - EU Spain (Madrid)
+- `eu-gb` - EU GB (London)
+- `jp-osa` - Japan (Osaka)
+- `jp-tok` - Japan (Tokyo)
+- `us-east` - US East (Washington DC)
+- `us-south` - US South (Dallas)
+
+## Dashboard: Code Engine Container Resource Overview
+
+The `code-engine-component-resource-overview.json` dashboard provides comprehensive monitoring of Code Engine resources:
+
+### Panels
+
+1. **CPU Usage vs Limit (per Pod)** - Compares live CPU usage to configured limits
+2. **CPU Utilization % (per App)** - CPU percentage by component
+3. **Memory Usage vs Limit (per Pod)** - Compares memory usage to limits
+4. **Memory Utilization % (per App)** - Memory percentage by component
+5. **CPU Utilization % (per Namespace)** - Namespace-level CPU monitoring
+6. **Memory Utilization % (per Namespace)** - Namespace-level memory monitoring
+7. **CPU Utilization % (per Revision/Parent)** - Revision-level CPU tracking
+8. **Memory Utilization % (per Revision/Parent)** - Revision-level memory tracking
+9. **Top Pods by CPU** - Top 10 CPU consumers
+10. **Top Pods by Memory** - Top 10 memory consumers
+11. **Cluster CPU Utilization (%)** - Global CPU percentage
+12. **Cluster Memory Utilization (%)** - Global memory percentage
+
+### Required Metrics
+
+The dashboard uses the following Prometheus metrics:
+
+- `codeengine_container_cpu_usage_millicores`
+- `codeengine_container_cpu_limit_millicores`
+- `codeengine_container_memory_usage_bytes`
+- `codeengine_container_memory_limit_bytes`
+
+These metrics are exposed by the Code Engine metrics collector when running with `METRICS_ENABLED=true`.
+
+## Script Features
+
+The `import_dashboard.py` script:
+
+- ✅ Creates new dashboards if they don't exist
+- ✅ Updates existing dashboards with the same name
+- ✅ Validates API credentials and region
+- ✅ Provides clear error messages
+- ✅ Displays dashboard URL after creation/update
+
+## Troubleshooting
+
+### Authentication Errors
+
+If you get authentication errors, verify:
+- Your IBM Cloud IAM API key is correct and not expired
+- The IAM API key has permissions to access the Monitoring instance
+- The Monitoring instance ID is correct
+- You're using the correct region where the instance is deployed
+
+### Dashboard Not Showing Data
+
+If the dashboard shows no data:
+- Verify the metrics collector is running with `METRICS_ENABLED=true`
+- Check that metrics are being sent to IBM Cloud Monitoring
+- Ensure the Prometheus remote write configuration is correct
+- Wait a few minutes for data to appear (initial scrape interval)
+
+### Import Errors
+
+If the import fails:
+- Check that the JSON file is valid
+- Ensure you have network connectivity to IBM Cloud
+- Verify the region endpoint is accessible
+
+## Example: Complete Setup with Virtual Environment
+
+```bash
+# 1. Navigate to the setup directory
+cd setup/ibm-cloud-monitoring
+
+# 2. Create and activate virtual environment
+python3 -m venv venv
+source venv/bin/activate  # On Windows: venv\Scripts\activate
+
+# 3. Install dependencies
+pip install requests
+
+# 4. Set environment variables
+export IBM_CLOUD_IAM_API_KEY=your-iam-api-key-here
+export SYSDIG_INSTANCE_ID=your-instance-id-here
+export SYSDIG_REGION=us-south
+
+# 5. Import the dashboard
+python import_dashboard.py --dashboard code-engine-component-resource-overview.json
+
+# Output:
+# Loading dashboard configuration from 'code-engine-component-resource-overview.json'...
+# Obtaining IBM Cloud IAM access token...
+# ✓ IAM access token obtained successfully
+# Checking if dashboard 'IBM Code Engine - Container Resource Overview' exists...
+# Dashboard 'IBM Code Engine - Container Resource Overview' not found. Creating new dashboard...
+# ✓ Dashboard 'IBM Code Engine - Container Resource Overview' created successfully (ID: 12345)!
+#
+# Dashboard URL: https://us-south.monitoring.cloud.ibm.com/#/dashboards/12345
+#
+# ✓ Operation completed successfully!
+
+# 6. Deactivate virtual environment when done
+deactivate
+```
+
+## Example: Quick Run (Without Virtual Environment)
+
+```bash
+# 1. Install dependencies globally
+pip3 install requests
+
+# 2. Run the script
+cd setup/ibm-cloud-monitoring
+python3 import_dashboard.py \
+    --iam-api-key your-iam-api-key-here \
+    --instance-id your-instance-id-here \
+    --region us-south \
+    --dashboard code-engine-component-resource-overview.json
+```
+
+## Customizing Dashboards
+
+To customize the dashboard:
+
+1. Edit `code-engine-component-resource-overview.json`
+2. Modify panel queries, layouts, or add new panels
+3. Run the import script to update the dashboard
+
+The script will detect the existing dashboard by name and update it with your changes.
+
+## Additional Resources
+
+- [IBM Cloud Monitoring Documentation](https://cloud.ibm.com/docs/monitoring)
+- [Sysdig Dashboard API](https://docs.sysdig.com/en/docs/developer-tools/sysdig-rest-api-conventions/)
+- [PromQL Query Language](https://prometheus.io/docs/prometheus/latest/querying/basics/)
\ No newline at end of file
diff --git a/metrics-collector/setup/ibm-cloud-monitoring/code-engine-component-resource-overview.json b/metrics-collector/setup/ibm-cloud-monitoring/code-engine-component-resource-overview.json
new file mode 100644
index 000000000..e7cfd2263
--- /dev/null
+++ b/metrics-collector/setup/ibm-cloud-monitoring/code-engine-component-resource-overview.json
@@ -0,0 +1,1069 @@
+{
+  "name": "IBM Cloud Code Engine - Component Resource Overview",
+  "panels": [
+    {
+      "id": 1,
+      "type": "text",
+      "name": "Dashboard Overview",
+      "description": "",
+      "nullValueDisplayText": null,
+      "links": null,
+      "markdownSource": "Monitor vCPU, and Memory usage across Code Engine components.\n\n**Use the scope filters above to narrow by:**\n- `ibm_codeengine_component_type` (app, job, build)\n- `ibm_codeengine_component_name` (specific app/job/build name)",
+      "transparentBackground": false,
+      "panelTitleVisible": true,
+      "textAutosized": false
+    },
+    {
+      "id": 5,
+      "type": "advancedTimechart",
+      "name": "vCPU Utilization % (by Component)",
+      "description": "vCPU usage as percentage of limit, grouped by ibm_codeengine_component_name",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "(sum by (ibm_codeengine_component_name) (ibm_codeengine_instance_cpu_usage_millicores{$__scope}) / sum by (ibm_codeengine_component_name) (ibm_codeengine_instance_cpu_limit_millicores{$__scope})) * 100",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "CPU %",
+            "timeSeriesDisplayNameTemplate": "{{ibm_codeengine_component_name}}",
+            "type": "lines"
+          },
+          "format": {
+            "unit": "%",
+            "inputFormat": "0-100",
+            "displayFormat": "auto",
+            "decimals": 1,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "connectSolid",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": false,
+            "delta": 1,
+            "timeFormat": "day"
+          }
+        }
+      ],
+      "legendConfiguration": {
+        "enabled": true,
+        "position": "right",
+        "layout": "table",
+        "showCurrent": true,
+        "showMax": true,
+        "showMin": true,
+        "width": null,
+        "height": null
+      },
+      "axesConfiguration": {
+        "bottom": {
+          "enabled": true
+        },
+        "left": {
+          "enabled": true,
+          "displayName": null,
+          "unit": "%",
+          "displayFormat": "auto",
+          "decimals": null,
+          "minValue": 0.0,
+          "maxValue": null,
+          "minInputFormat": "0-100",
+          "maxInputFormat": "0-100",
+          "scale": "linear"
+        },
+        "right": {
+          "enabled": false,
+          "displayName": null,
+          "unit": "%",
+          "displayFormat": "auto",
+          "decimals": null,
+          "minValue": 0.0,
+          "maxValue": null,
+          "minInputFormat": "0-100",
+          "maxInputFormat": "0-100",
+          "scale": "linear"
+        }
+      },
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [
+          {
+            "severity": "high",
+            "value": 80.0,
+            "inputFormat": "0-100",
+            "displayText": ""
+          },
+          {
+            "severity": "ok",
+            "value": 0.0,
+            "inputFormat": "0-100",
+            "displayText": ""
+          }
+        ],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 6,
+      "type": "advancedTimechart",
+      "name": "Memory Utilization % (by Component)",
+      "description": "Memory usage as percentage of limit, grouped by ibm_codeengine_component_name",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "(sum by (ibm_codeengine_component_name) (ibm_codeengine_instance_memory_usage_bytes{$__scope}) / sum by (ibm_codeengine_component_name) (ibm_codeengine_instance_memory_limit_bytes{$__scope})) * 100",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "Memory %",
+            "timeSeriesDisplayNameTemplate": "{{ibm_codeengine_component_name}}",
+            "type": "lines"
+          },
+          "format": {
+            "unit": "%",
+            "inputFormat": "0-100",
+            "displayFormat": "auto",
+            "decimals": 1,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "connectSolid",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": false,
+            "delta": 1,
+            "timeFormat": "day"
+          }
+        }
+      ],
+      "legendConfiguration": {
+        "enabled": true,
+        "position": "right",
+        "layout": "table",
+        "showCurrent": true,
+        "showMax": true,
+        "showMin": true,
+        "width": null,
+        "height": null
+      },
+      "axesConfiguration": {
+        "bottom": {
+          "enabled": true
+        },
+        "left": {
+          "enabled": true,
+          "displayName": null,
+          "unit": "auto",
+          "displayFormat": "auto",
+          "decimals": null,
+          "minValue": 0.0,
+          "maxValue": null,
+          "minInputFormat": "0-100",
+          "maxInputFormat": "0-100",
+          "scale": "linear"
+        },
+        "right": {
+          "enabled": true,
+          "displayName": null,
+          "unit": "auto",
+          "displayFormat": "auto",
+          "decimals": null,
+          "minValue": 0.0,
+          "maxValue": null,
+          "minInputFormat": "1",
+          "maxInputFormat": "1",
+          "scale": "linear"
+        }
+      },
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [
+          {
+            "severity": "high",
+            "value": 80.0,
+            "inputFormat": "0-100",
+            "displayText": ""
+          },
+          {
+            "severity": "ok",
+            "value": 30.0,
+            "inputFormat": "0-100",
+            "displayText": ""
+          }
+        ],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 8,
+      "type": "advancedNumber",
+      "name": "Total vCPU Utilization in %",
+      "description": "Overall vCPU utilization across all instances",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "(sum(ibm_codeengine_instance_cpu_usage_millicores{$__scope}) / sum(ibm_codeengine_instance_cpu_limit_millicores{$__scope})) * 100",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "CPU %",
+            "timeSeriesDisplayNameTemplate": null,
+            "type": "lines"
+          },
+          "format": {
+            "unit": "%",
+            "inputFormat": "0-100",
+            "displayFormat": "auto",
+            "decimals": 1,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "nullGap",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": true,
+            "delta": 1,
+            "timeFormat": "hour"
+          }
+        }
+      ],
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [
+          {
+            "severity": "medium",
+            "value": 90.0,
+            "inputFormat": "0-100",
+            "displayText": ""
+          },
+          {
+            "severity": "ok",
+            "value": 30.0,
+            "inputFormat": "0-100",
+            "displayText": ""
+          },
+          {
+            "severity": "none",
+            "value": 1.0,
+            "inputFormat": "0-100",
+            "displayText": ""
+          }
+        ],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 9,
+      "type": "advancedNumber",
+      "name": "Total Memory Utilization in %",
+      "description": "Overall memory utilization across all instances",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "(sum(ibm_codeengine_instance_memory_usage_bytes{$__scope}) / sum(ibm_codeengine_instance_memory_limit_bytes{$__scope})) * 100",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "Memory %",
+            "timeSeriesDisplayNameTemplate": null,
+            "type": "lines"
+          },
+          "format": {
+            "unit": "%",
+            "inputFormat": "0-100",
+            "displayFormat": "auto",
+            "decimals": 1,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "nullGap",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": true,
+            "delta": 1,
+            "timeFormat": "hour"
+          }
+        }
+      ],
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [
+          {
+            "severity": "medium",
+            "value": 80.0,
+            "inputFormat": "0-100",
+            "displayText": ""
+          },
+          {
+            "severity": "ok",
+            "value": 30.0,
+            "inputFormat": "0-100",
+            "displayText": ""
+          },
+          {
+            "severity": "none",
+            "value": 1.0,
+            "inputFormat": "0-100",
+            "displayText": ""
+          }
+        ],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 11,
+      "type": "advancedNumber",
+      "name": "Total Available vCPUs",
+      "description": "Overall number of available vCPUs across all instances",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "sum(ibm_codeengine_instance_cpu_limit_millicores{$__scope}) / 1000",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "CPU %",
+            "timeSeriesDisplayNameTemplate": null,
+            "type": "lines"
+          },
+          "format": {
+            "unit": "number",
+            "inputFormat": "1",
+            "displayFormat": "auto",
+            "decimals": 1,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "nullGap",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": true,
+            "delta": 1,
+            "timeFormat": "hour"
+          }
+        }
+      ],
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [
+          {
+            "severity": "info",
+            "value": 80.0,
+            "inputFormat": "1",
+            "displayText": ""
+          }
+        ],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 12,
+      "type": "advancedNumber",
+      "name": "Total Available Memory",
+      "description": "Overall amount of available memory across all instances",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "sum(ibm_codeengine_instance_memory_limit_bytes{$__scope})",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "Memory %",
+            "timeSeriesDisplayNameTemplate": null,
+            "type": "lines"
+          },
+          "format": {
+            "unit": "byte",
+            "inputFormat": "B",
+            "displayFormat": "auto",
+            "decimals": 1,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "nullGap",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": true,
+            "delta": 1,
+            "timeFormat": "hour"
+          }
+        }
+      ],
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 13,
+      "type": "advancedNumber",
+      "name": "Total Used vCPUs",
+      "description": "Actual number of vCPUs that are used across all instances",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "sum(ibm_codeengine_instance_cpu_usage_millicores{$__scope}) / 1000",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "CPU %",
+            "timeSeriesDisplayNameTemplate": null,
+            "type": "lines"
+          },
+          "format": {
+            "unit": "number",
+            "inputFormat": "1",
+            "displayFormat": "auto",
+            "decimals": 1,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "nullGap",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": true,
+            "delta": 1,
+            "timeFormat": "hour"
+          }
+        }
+      ],
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [
+          {
+            "severity": "info",
+            "value": 80.0,
+            "inputFormat": "1",
+            "displayText": ""
+          }
+        ],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 14,
+      "type": "advancedNumber",
+      "name": "Total Used Memory",
+      "description": "Actual amount of memory used across all instances",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "sum(ibm_codeengine_instance_memory_usage_bytes{$__scope})",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "Memory %",
+            "timeSeriesDisplayNameTemplate": null,
+            "type": "lines"
+          },
+          "format": {
+            "unit": "byte",
+            "inputFormat": "B",
+            "displayFormat": "auto",
+            "decimals": 1,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "nullGap",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": true,
+            "delta": 1,
+            "timeFormat": "hour"
+          }
+        }
+      ],
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 2,
+      "type": "advancedTimechart",
+      "name": "vCPU Usage (per Instance)",
+      "description": "Current vCPU usage per instance",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "ibm_codeengine_instance_cpu_usage_millicores{$__scope}",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "CPU Usage",
+            "timeSeriesDisplayNameTemplate": "{{ibm_codeengine_component_name}}/{{ibm_codeengine_instance_name}} usage",
+            "type": "lines"
+          },
+          "format": {
+            "unit": "number",
+            "inputFormat": "1",
+            "displayFormat": "auto",
+            "decimals": 0,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "connectSolid",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": false,
+            "delta": 1,
+            "timeFormat": "day"
+          }
+        }
+      ],
+      "legendConfiguration": {
+        "enabled": true,
+        "position": "right",
+        "layout": "table",
+        "showCurrent": true,
+        "showMax": true,
+        "showMin": true,
+        "width": null,
+        "height": null
+      },
+      "axesConfiguration": {
+        "bottom": {
+          "enabled": true
+        },
+        "left": {
+          "enabled": true,
+          "displayName": null,
+          "unit": "auto",
+          "displayFormat": "auto",
+          "decimals": null,
+          "minValue": 0.0,
+          "maxValue": null,
+          "minInputFormat": "0-100",
+          "maxInputFormat": "0-100",
+          "scale": "linear"
+        },
+        "right": {
+          "enabled": true,
+          "displayName": null,
+          "unit": "auto",
+          "displayFormat": "auto",
+          "decimals": null,
+          "minValue": 0.0,
+          "maxValue": null,
+          "minInputFormat": "1",
+          "maxInputFormat": "1",
+          "scale": "linear"
+        }
+      },
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 3,
+      "type": "advancedTimechart",
+      "name": "Memory Usage (per Instance)",
+      "description": "Current memory usage per instance",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "ibm_codeengine_instance_memory_usage_bytes{$__scope}",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "Memory Usage",
+            "timeSeriesDisplayNameTemplate": "{{ibm_codeengine_component_name}}/{{ibm_codeengine_instance_name}} usage",
+            "type": "lines"
+          },
+          "format": {
+            "unit": "byte",
+            "inputFormat": "B",
+            "displayFormat": "auto",
+            "decimals": 0,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "connectSolid",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": false,
+            "delta": 1,
+            "timeFormat": "day"
+          }
+        }
+      ],
+      "legendConfiguration": {
+        "enabled": true,
+        "position": "right",
+        "layout": "table",
+        "showCurrent": true,
+        "showMax": true,
+        "showMin": true,
+        "width": null,
+        "height": null
+      },
+      "axesConfiguration": {
+        "bottom": {
+          "enabled": true
+        },
+        "left": {
+          "enabled": true,
+          "displayName": null,
+          "unit": "auto",
+          "displayFormat": "auto",
+          "decimals": null,
+          "minValue": 0.0,
+          "maxValue": null,
+          "minInputFormat": "B",
+          "maxInputFormat": "B",
+          "scale": "linear"
+        },
+        "right": {
+          "enabled": false,
+          "displayName": null,
+          "unit": "auto",
+          "displayFormat": "auto",
+          "decimals": null,
+          "minValue": 0.0,
+          "maxValue": null,
+          "minInputFormat": "1",
+          "maxInputFormat": "1",
+          "scale": "linear"
+        }
+      },
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 15,
+      "type": "advancedNumber",
+      "name": "Components with Running Instances",
+      "description": "Number of Code Engine components that do have running instances",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "count(count(\n  ibm_codeengine_instance_cpu_limit_millicores{$__scope}\n)by (ibm_codeengine_component_name))",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "CPU %",
+            "timeSeriesDisplayNameTemplate": null,
+            "type": "lines"
+          },
+          "format": {
+            "unit": "number",
+            "inputFormat": "1",
+            "displayFormat": "auto",
+            "decimals": 0,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "nullGap",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": false,
+            "delta": 1,
+            "timeFormat": "hour"
+          }
+        }
+      ],
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    },
+    {
+      "id": 16,
+      "type": "advancedNumber",
+      "name": "Running Instances",
+      "description": "Number of running Code Engine instances",
+      "nullValueDisplayText": null,
+      "links": null,
+      "advancedQueries": [
+        {
+          "query": "sum(count(\n  ibm_codeengine_instance_cpu_limit_millicores{$__scope}\n)by (ibm_codeengine_component_name))",
+          "enabled": true,
+          "displayInfo": {
+            "displayName": "CPU %",
+            "timeSeriesDisplayNameTemplate": null,
+            "type": "lines"
+          },
+          "format": {
+            "unit": "number",
+            "inputFormat": "1",
+            "displayFormat": "auto",
+            "decimals": 0,
+            "yAxis": "auto",
+            "nullValueDisplayMode": "nullGap",
+            "minInterval": null
+          },
+          "compareTo": {
+            "enabled": true,
+            "delta": 1,
+            "timeFormat": "hour"
+          }
+        }
+      ],
+      "numberThresholds": {
+        "useDefaults": null,
+        "values": [
+          {
+            "severity": "info",
+            "value": 80.0,
+            "inputFormat": "1",
+            "displayText": ""
+          }
+        ],
+        "base": {
+          "severity": "none",
+          "displayText": ""
+        }
+      }
+    }
+  ],
+  "scopeExpressionList": [
+    {
+      "operand": "ibm_codeengine_project_name",
+      "operator": "in",
+      "displayName": "",
+      "value": [],
+      "descriptor": {
+        "documentId": "ibm_codeengine_project_name",
+        "id": "ibm_codeengine_project_name",
+        "metricType": "tag",
+        "type": "string",
+        "scale": 0.0,
+        "name": "ibm_codeengine_project_name",
+        "description": "ibm_codeengine_project_name",
+        "namespaces": [
+          "cloudProvider",
+          "host.container",
+          "ecs",
+          "host.fs",
+          "host.file",
+          "host",
+          "kubernetes",
+          "kubernetes.cluster",
+          "kubernetes.daemonSet",
+          "kubernetes.deployment",
+          "kubernetes.job",
+          "kubernetes.namespace",
+          "kubernetes.node",
+          "kubernetes.pod",
+          "kubernetes.replicaSet",
+          "kubernetes.service",
+          "kubernetes.statefulSet",
+          "kubernetes.resourcequota",
+          "kubernetes.hpa",
+          "link",
+          "mesos",
+          "host.net",
+          "host.process",
+          "prometheus",
+          "swarm",
+          "prombeacon"
+        ],
+        "scopes": [],
+        "timeAggregations": [
+          "concat",
+          "distinct",
+          "count"
+        ],
+        "groupAggregations": [
+          "concat",
+          "distinct",
+          "count"
+        ],
+        "aggregationForGroup": "none",
+        "hidden": false,
+        "experimental": false,
+        "deferred": false,
+        "identity": false,
+        "canMonitor": false,
+        "canGroupBy": false,
+        "canFilter": true,
+        "generatedFrom": "com.draios.model.metrics.custom.CustomMetric$Tag",
+        "publicId": "ibm_codeengine_project_name",
+        "heuristic": false,
+        "documentType": "metric",
+        "segment": false,
+        "documentTimestamp": 1772465428162
+      },
+      "variable": true,
+      "isVariable": true
+    },
+    {
+      "operand": "ibm_codeengine_component_type",
+      "operator": "in",
+      "displayName": "",
+      "value": [],
+      "descriptor": {
+        "documentId": "ibm_codeengine_component_type",
+        "id": "ibm_codeengine_component_type",
+        "metricType": "tag",
+        "type": "string",
+        "scale": 0.0,
+        "name": "ibm_codeengine_component_type",
+        "description": "ibm_codeengine_component_type",
+        "namespaces": [
+          "cloudProvider",
+          "host.container",
+          "ecs",
+          "host.fs",
+          "host.file",
+          "host",
+          "kubernetes",
+          "kubernetes.cluster",
+          "kubernetes.daemonSet",
+          "kubernetes.deployment",
+          "kubernetes.job",
+          "kubernetes.namespace",
+          "kubernetes.node",
+          "kubernetes.pod",
+          "kubernetes.replicaSet",
+          "kubernetes.service",
+          "kubernetes.statefulSet",
+          "kubernetes.resourcequota",
+          "kubernetes.hpa",
+          "link",
+          "mesos",
+          "host.net",
+          "host.process",
+          "prometheus",
+          "swarm",
+          "prombeacon"
+        ],
+        "scopes": [],
+        "timeAggregations": [
+          "concat",
+          "distinct",
+          "count"
+        ],
+        "groupAggregations": [
+          "concat",
+          "distinct",
+          "count"
+        ],
+        "aggregationForGroup": "none",
+        "hidden": false,
+        "experimental": false,
+        "deferred": false,
+        "identity": false,
+        "canMonitor": false,
+        "canGroupBy": false,
+        "canFilter": true,
+        "generatedFrom": "com.draios.model.metrics.custom.CustomMetric$Tag",
+        "publicId": "ibm_codeengine_component_type",
+        "heuristic": false,
+        "documentType": "metric",
+        "segment": false,
+        "documentTimestamp": 1772465428162
+      },
+      "variable": true,
+      "isVariable": true
+    },
+    {
+      "operand": "ibm_codeengine_component_name",
+      "operator": "in",
+      "displayName": "",
+      "value": [],
+      "descriptor": {
+        "documentId": "ibm_codeengine_component_name",
+        "id": "ibm_codeengine_component_name",
+        "metricType": "tag",
+        "type": "string",
+        "scale": 0.0,
+        "name": "ibm_codeengine_component_name",
+        "description": "ibm_codeengine_component_name",
+        "namespaces": [
+          "cloudProvider",
+          "host.container",
+          "ecs",
+          "host.fs",
+          "host.file",
+          "host",
+          "kubernetes",
+          "kubernetes.cluster",
+          "kubernetes.daemonSet",
+          "kubernetes.deployment",
+          "kubernetes.job",
+          "kubernetes.namespace",
+          "kubernetes.node",
+          "kubernetes.pod",
+          "kubernetes.replicaSet",
+          "kubernetes.service",
+          "kubernetes.statefulSet",
+          "kubernetes.resourcequota",
+          "kubernetes.hpa",
+          "link",
+          "mesos",
+          "host.net",
+          "host.process",
+          "prometheus",
+          "swarm",
+          "prombeacon"
+        ],
+        "scopes": [],
+        "timeAggregations": [
+          "concat",
+          "distinct",
+          "count"
+        ],
+        "groupAggregations": [
+          "concat",
+          "distinct",
+          "count"
+        ],
+        "aggregationForGroup": "none",
+        "hidden": false,
+        "experimental": false,
+        "deferred": false,
+        "identity": false,
+        "canMonitor": false,
+        "canGroupBy": false,
+        "canFilter": true,
+        "generatedFrom": "com.draios.model.metrics.custom.CustomMetric$Tag",
+        "publicId": "ibm_codeengine_component_name",
+        "heuristic": false,
+        "documentType": "metric",
+        "segment": false,
+        "documentTimestamp": 1772465428162
+      },
+      "variable": true,
+      "isVariable": true
+    }
+  ],
+  "eventDisplaySettings": {
+    "enabled": true,
+    "queryParams": {
+      "severities": [],
+      "alertStatuses": [],
+      "categories": [],
+      "filter": "",
+      "teamScope": false
+    }
+  },
+  "shared": true,
+  "public": false,
+  "description": "Overview of Code Engine instance resource usage: CPU/memory current vs limits, with filtering by ibm_codeengine_component_type and ibm_codeengine_component_name",
+  "layout": [
+    {
+      "panelId": 1,
+      "x": 0,
+      "y": 0,
+      "w": 7,
+      "h": 4
+    },
+    {
+      "panelId": 5,
+      "x": 0,
+      "y": 4,
+      "w": 12,
+      "h": 6
+    },
+    {
+      "panelId": 6,
+      "x": 0,
+      "y": 10,
+      "w": 12,
+      "h": 5
+    },
+    {
+      "panelId": 8,
+      "x": 21,
+      "y": 0,
+      "w": 3,
+      "h": 2
+    },
+    {
+      "panelId": 9,
+      "x": 21,
+      "y": 2,
+      "w": 3,
+      "h": 2
+    },
+    {
+      "panelId": 11,
+      "x": 14,
+      "y": 0,
+      "w": 4,
+      "h": 2
+    },
+    {
+      "panelId": 12,
+      "x": 14,
+      "y": 2,
+      "w": 4,
+      "h": 2
+    },
+    {
+      "panelId": 13,
+      "x": 18,
+      "y": 0,
+      "w": 3,
+      "h": 2
+    },
+    {
+      "panelId": 14,
+      "x": 18,
+      "y": 2,
+      "w": 3,
+      "h": 2
+    },
+    {
+      "panelId": 2,
+      "x": 12,
+      "y": 4,
+      "w": 12,
+      "h": 6
+    },
+    {
+      "panelId": 3,
+      "x": 12,
+      "y": 10,
+      "w": 12,
+      "h": 5
+    },
+    {
+      "panelId": 15,
+      "x": 7,
+      "y": 0,
+      "w": 4,
+      "h": 4
+    },
+    {
+      "panelId": 16,
+      "x": 11,
+      "y": 0,
+      "w": 3,
+      "h": 4
+    }
+  ],
+  "schema": 3
+}
\ No newline at end of file
diff --git a/metrics-collector/setup/ibm-cloud-monitoring/export_dashboard.py b/metrics-collector/setup/ibm-cloud-monitoring/export_dashboard.py
new file mode 100644
index 000000000..983965771
--- /dev/null
+++ b/metrics-collector/setup/ibm-cloud-monitoring/export_dashboard.py
@@ -0,0 +1,379 @@
+#!/usr/bin/env python3
+"""
+IBM Cloud Monitoring Dashboard Export Script
+
+This script exports Sysdig dashboards from IBM Cloud Monitoring using IBM Cloud IAM authentication.
+It uses an IBM Cloud IAM API key to obtain an access token, then retrieves the dashboard via the Sysdig API.
+
+Usage:
+    python export_dashboard.py --iam-api-key <IAM_API_KEY> --instance-id <INSTANCE_ID> --region <REGION> --name <DASHBOARD_NAME>
+
+Environment Variables:
+    IBM_CLOUD_IAM_API_KEY: IBM Cloud IAM API key (alternative to --iam-api-key)
+    SYSDIG_INSTANCE_ID: IBM Cloud Monitoring instance ID (alternative to --instance-id)
+    SYSDIG_REGION: IBM Cloud Monitoring region (alternative to --region)
+
+Example:
+    python export_dashboard.py \\
+        --iam-api-key YOUR_IAM_API_KEY \\
+        --instance-id YOUR_INSTANCE_ID \\
+        --region us-south \\
+        --name "IBM Cloud Code Engine - Component Resource Overview"
+"""
+
+import argparse
+import json
+import os
+import sys
+from datetime import datetime
+from typing import Dict, Optional
+
+try:
+    import requests
+except ImportError:
+    print("Error: 'requests' module not found. Install it with: pip install requests")
+    sys.exit(1)
+
+
+class IBMCloudIAMAuth:
+    """Handles IBM Cloud IAM authentication."""
+    
+    IAM_TOKEN_URL = "https://iam.cloud.ibm.com/identity/token"
+    
+    def __init__(self, iam_api_key: str):
+        """
+        Initialize IBM Cloud IAM authentication.
+        
+        Args:
+            iam_api_key: IBM Cloud IAM API key
+        """
+        self.iam_api_key = iam_api_key
+        self._access_token = None
+        self._token_expiry = 0
+    
+    def get_access_token(self) -> str:
+        """
+        Get an IBM Cloud IAM access token.
+        
+        Returns:
+            IAM access token
+        """
+        print("Obtaining IBM Cloud IAM access token...")
+        
+        headers = {
+            "Content-Type": "application/x-www-form-urlencoded",
+            "Accept": "application/json"
+        }
+        
+        data = {
+            "grant_type": "urn:ibm:params:oauth:grant-type:apikey",
+            "apikey": self.iam_api_key
+        }
+        
+        try:
+            response = requests.post(
+                self.IAM_TOKEN_URL,
+                headers=headers,
+                data=data,
+                timeout=30
+            )
+            response.raise_for_status()
+            token_data = response.json()
+            self._access_token = token_data.get("access_token")
+            
+            if not self._access_token:
+                raise ValueError("No access token in IAM response")
+            
+            print("✓ IAM access token obtained successfully")
+            return self._access_token
+            
+        except requests.exceptions.RequestException as e:
+            print(f"Error obtaining IAM token: {e}")
+            if hasattr(e, 'response') and e.response is not None:
+                print(f"Response: {e.response.text}")
+            raise
+
+
+class SysdigDashboardManager:
+    """Manages Sysdig dashboard operations via REST API with IBM Cloud IAM authentication."""
+    
+    # IBM Cloud Monitoring regional endpoints
+    REGION_ENDPOINTS = {
+        "us-south": "https://us-south.monitoring.cloud.ibm.com",
+        "us-east": "https://us-east.monitoring.cloud.ibm.com",
+        "eu-de": "https://eu-de.monitoring.cloud.ibm.com",
+        "eu-es": "https://eu-es.monitoring.cloud.ibm.com",
+        "eu-gb": "https://eu-gb.monitoring.cloud.ibm.com",
+        "jp-tok": "https://jp-tok.monitoring.cloud.ibm.com",
+        "au-syd": "https://au-syd.monitoring.cloud.ibm.com",
+        "jp-osa": "https://jp-osa.monitoring.cloud.ibm.com",
+        "ca-tor": "https://ca-tor.monitoring.cloud.ibm.com",
+        "br-sao": "https://br-sao.monitoring.cloud.ibm.com",
+    }
+    
+    def __init__(self, iam_auth: IBMCloudIAMAuth, instance_id: str, region: str):
+        """
+        Initialize the Sysdig Dashboard Manager.
+        
+        Args:
+            iam_auth: IBM Cloud IAM authentication handler
+            instance_id: IBM Cloud Monitoring instance ID (GUID)
+            region: IBM Cloud region (e.g., 'us-south', 'eu-de')
+        """
+        if region not in self.REGION_ENDPOINTS:
+            raise ValueError(
+                f"Invalid region '{region}'. Valid regions: {', '.join(self.REGION_ENDPOINTS.keys())}"
+            )
+        
+        self.iam_auth = iam_auth
+        self.instance_id = instance_id
+        self.region = region
+        self.base_url = self.REGION_ENDPOINTS[region]
+    
+    def _get_headers(self) -> Dict[str, str]:
+        """
+        Get HTTP headers with IAM authentication.
+        
+        Returns:
+            Dictionary of HTTP headers
+        """
+        access_token = self.iam_auth.get_access_token()
+        return {
+            "Authorization": f"Bearer {access_token}",
+            "IBMInstanceID": self.instance_id,
+            "Content-Type": "application/json",
+        }
+    
+    def list_dashboards(self) -> list:
+        """
+        List all dashboards in the Sysdig instance.
+        
+        Returns:
+            List of dashboard objects
+        """
+        url = f"{self.base_url}/api/v3/dashboards"
+        
+        try:
+            response = requests.get(url, headers=self._get_headers(), timeout=30)
+            response.raise_for_status()
+            data = response.json()
+            return data.get("dashboards", [])
+        except requests.exceptions.RequestException as e:
+            print(f"Error listing dashboards: {e}")
+            if hasattr(e, 'response') and e.response is not None:
+                print(f"Response: {e.response.text}")
+            return []
+    
+    def find_dashboard_by_name(self, name: str) -> Optional[Dict]:
+        """
+        Find a dashboard by its name.
+        
+        Args:
+            name: Dashboard name to search for
+            
+        Returns:
+            Dashboard object if found, None otherwise
+        """
+        dashboards = self.list_dashboards()
+        for dashboard in dashboards:
+            print(f"dashboard: {dashboard.get("name")}, id: '{dashboard.get("id")}'")
+            if dashboard.get("name") == name:
+                return dashboard
+        return None
+    
+    def get_dashboard(self, dashboard_id: int) -> Dict:
+        """
+        Get a dashboard by its ID.
+        
+        Args:
+            dashboard_id: ID of the dashboard to retrieve
+            
+        Returns:
+            Dashboard object
+        """
+        url = f"{self.base_url}/api/v3/dashboards/{dashboard_id}"
+        
+        try:
+            response = requests.get(url, headers=self._get_headers(), timeout=30)
+            response.raise_for_status()
+            return response.json()
+        except requests.exceptions.RequestException as e:
+            print(f"Error retrieving dashboard: {e}")
+            if hasattr(e, 'response') and e.response is not None:
+                print(f"Response: {e.response.text}")
+            raise
+    
+    def export_dashboard_by_name(self, name: str, output_dir: str = ".") -> str:
+        """
+        Export a dashboard by its name to a JSON file.
+        
+        Args:
+            name: Dashboard name to export
+            output_dir: Directory to save the exported file (default: current directory)
+            
+        Returns:
+            Path to the exported file
+        """
+        print(f"Searching for dashboard '{name}'...")
+        dashboard_summary = self.find_dashboard_by_name(name)
+        
+        if not dashboard_summary:
+            raise ValueError(f"Dashboard '{name}' not found")
+        
+        dashboard_id = dashboard_summary.get("id")
+        if dashboard_id is None:
+            raise ValueError(f"Dashboard '{name}' found but has no ID")
+        
+        print(f"✓ Dashboard found (ID: {dashboard_id})")
+        print(f"Retrieving full dashboard configuration...")
+        
+        # Get the full dashboard configuration
+        dashboard_data = self.get_dashboard(dashboard_id)
+        
+        # Extract just the dashboard object (without wrapper)
+        dashboard_config = dashboard_data.get("dashboard", {})
+        
+        # Generate filename with dashboard name and timestamp
+        timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S")
+        # Sanitize dashboard name for filename
+        safe_name = "".join(c if c.isalnum() or c in (' ', '-', '_') else '_' for c in name)
+        safe_name = safe_name.replace(' ', '_').lower()
+        filename = f"{safe_name}_{timestamp}.json"
+        filepath = os.path.join(output_dir, filename)
+        
+        # Save to file
+        print(f"Saving dashboard to '{filepath}'...")
+        with open(filepath, 'w') as f:
+            json.dump(dashboard_config, f, indent=2)
+        
+        print(f"✓ Dashboard exported successfully!")
+        return filepath
+
+
+def main():
+    """Main entry point for the script."""
+    parser = argparse.ArgumentParser(
+        description="Export IBM Cloud Monitoring (Sysdig) dashboards using IBM Cloud IAM authentication",
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        epilog="""
+Examples:
+  # Using command-line arguments
+  python export_dashboard.py \\
+      --iam-api-key YOUR_IAM_KEY \\
+      --instance-id YOUR_INSTANCE_ID \\
+      --region us-south \\
+      --name "IBM Code Engine - Container Resource Overview"
+  
+  # Using environment variables
+  export IBM_CLOUD_IAM_API_KEY=YOUR_IAM_KEY
+  export SYSDIG_INSTANCE_ID=YOUR_INSTANCE_ID
+  export SYSDIG_REGION=us-south
+  python export_dashboard.py --name "My Dashboard"
+  
+  # Export to specific directory
+  python export_dashboard.py \\
+      --name "My Dashboard" \\
+      --output-dir ./exports
+
+Supported Regions:
+  us-south, us-east, eu-de, eu-es, eu-gb, jp-tok, au-syd, jp-osa, ca-tor, br-sao
+
+How to get your Instance ID:
+  1. Go to IBM Cloud Console
+  2. Navigate to your Monitoring instance
+  3. Click on "Overview" or "Settings"
+  4. Copy the Instance ID (GUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
+        """
+    )
+    
+    parser.add_argument(
+        "--iam-api-key",
+        help="IBM Cloud IAM API key (or set IBM_CLOUD_IAM_API_KEY env var)",
+        default=os.environ.get("IBM_CLOUD_IAM_API_KEY")
+    )
+    
+    parser.add_argument(
+        "--instance-id",
+        help="IBM Cloud Monitoring instance ID/GUID (or set SYSDIG_INSTANCE_ID env var)",
+        default=os.environ.get("SYSDIG_INSTANCE_ID")
+    )
+    
+    parser.add_argument(
+        "--region",
+        help="IBM Cloud region (or set SYSDIG_REGION env var)",
+        default=os.environ.get("SYSDIG_REGION")
+    )
+    
+    parser.add_argument(
+        "--name",
+        required=True,
+        help="Name of the dashboard to export"
+    )
+    
+    parser.add_argument(
+        "--output-dir",
+        default=".",
+        help="Directory to save the exported dashboard (default: current directory)"
+    )
+    
+    parser.add_argument(
+        "--list",
+        action="store_true",
+        help="List all available dashboards and exit"
+    )
+    
+    args = parser.parse_args()
+    
+    # Validate required arguments
+    if not args.iam_api_key:
+        print("Error: IAM API key is required. Provide via --iam-api-key or IBM_CLOUD_IAM_API_KEY environment variable")
+        sys.exit(1)
+    
+    if not args.instance_id:
+        print("Error: Instance ID is required. Provide via --instance-id or SYSDIG_INSTANCE_ID environment variable")
+        sys.exit(1)
+    
+    if not args.region:
+        print("Error: Region is required. Provide via --region or SYSDIG_REGION environment variable")
+        sys.exit(1)
+    
+    # Initialize IAM authentication and dashboard manager
+    try:
+        iam_auth = IBMCloudIAMAuth(args.iam_api_key)
+        manager = SysdigDashboardManager(iam_auth, args.instance_id, args.region)
+        
+        # List dashboards if requested
+        if args.list:
+            print("Listing all dashboards...")
+            dashboards = manager.list_dashboards()
+            if not dashboards:
+                print("No dashboards found")
+            else:
+                print(f"\nFound {len(dashboards)} dashboard(s):\n")
+                for i, dashboard in enumerate(dashboards, 1):
+                    name = dashboard.get("name", "Unnamed")
+                    dashboard_id = dashboard.get("id", "N/A")
+                    print(f"{i}. {name} (ID: {dashboard_id})")
+            sys.exit(0)
+        
+        # Create output directory if it doesn't exist
+        if args.output_dir != "." and not os.path.exists(args.output_dir):
+            os.makedirs(args.output_dir)
+            print(f"Created output directory: {args.output_dir}")
+        
+        # Export the dashboard
+        filepath = manager.export_dashboard_by_name(args.name, args.output_dir)
+        
+        print(f"\n✓ Export completed successfully!")
+        print(f"  File: {filepath}")
+        
+    except ValueError as e:
+        print(f"Error: {e}")
+        sys.exit(1)
+    except Exception as e:
+        print(f"Unexpected error: {e}")
+        sys.exit(1)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/metrics-collector/setup/ibm-cloud-monitoring/import_dashboard.py b/metrics-collector/setup/ibm-cloud-monitoring/import_dashboard.py
new file mode 100644
index 000000000..2dcf4263f
--- /dev/null
+++ b/metrics-collector/setup/ibm-cloud-monitoring/import_dashboard.py
@@ -0,0 +1,389 @@
+#!/usr/bin/env python3
+"""
+IBM Cloud Monitoring Dashboard Import/Update Script
+
+This script creates or updates Sysdig dashboards in IBM Cloud Monitoring using IBM Cloud IAM authentication.
+It uses an IBM Cloud IAM API key to obtain an access token, then interacts with the Sysdig API.
+
+Usage:
+    python import_dashboard.py --iam-api-key <IAM_API_KEY> --instance-id <INSTANCE_ID> --region <REGION> --dashboard <DASHBOARD_JSON>
+
+Environment Variables:
+    IBM_CLOUD_IAM_API_KEY: IBM Cloud IAM API key (alternative to --iam-api-key)
+    SYSDIG_INSTANCE_ID: IBM Cloud Monitoring instance ID (alternative to --instance-id)
+    SYSDIG_REGION: IBM Cloud Monitoring region (alternative to --region)
+
+Example:
+    python import_dashboard.py \\
+        --iam-api-key YOUR_IAM_API_KEY \\
+        --instance-id YOUR_INSTANCE_ID \\
+        --region us-south \\
+        --dashboard code-engine-component-resource-overview.json
+"""
+
+import argparse
+import json
+import os
+import sys
+from typing import Dict, Optional
+
+try:
+    import requests
+except ImportError:
+    print("Error: 'requests' module not found. Install it with: pip install requests")
+    sys.exit(1)
+
+
+class IBMCloudIAMAuth:
+    """Handles IBM Cloud IAM authentication."""
+    
+    IAM_TOKEN_URL = "https://iam.cloud.ibm.com/identity/token"
+    
+    def __init__(self, iam_api_key: str):
+        """
+        Initialize IBM Cloud IAM authentication.
+        
+        Args:
+            iam_api_key: IBM Cloud IAM API key
+        """
+        self.iam_api_key = iam_api_key
+        self._access_token = None
+        self._token_expiry = 0
+    
+    def get_access_token(self) -> str:
+        """
+        Get an IBM Cloud IAM access token.
+        
+        Returns:
+            IAM access token
+        """
+        print("Obtaining IBM Cloud IAM access token...")
+        
+        headers = {
+            "Content-Type": "application/x-www-form-urlencoded",
+            "Accept": "application/json"
+        }
+        
+        data = {
+            "grant_type": "urn:ibm:params:oauth:grant-type:apikey",
+            "apikey": self.iam_api_key
+        }
+        
+        try:
+            response = requests.post(
+                self.IAM_TOKEN_URL,
+                headers=headers,
+                data=data,
+                timeout=30
+            )
+            response.raise_for_status()
+            token_data = response.json()
+            self._access_token = token_data.get("access_token")
+            
+            if not self._access_token:
+                raise ValueError("No access token in IAM response")
+            
+            print("✓ IAM access token obtained successfully")
+            return self._access_token
+            
+        except requests.exceptions.RequestException as e:
+            print(f"Error obtaining IAM token: {e}")
+            if hasattr(e, 'response') and e.response is not None:
+                print(f"Response: {e.response.text}")
+            raise
+
+
+class SysdigDashboardManager:
+    """Manages Sysdig dashboard creation and updates via REST API with IBM Cloud IAM authentication."""
+    
+    # IBM Cloud Monitoring regional endpoints
+    REGION_ENDPOINTS = {
+        "us-south": "https://us-south.monitoring.cloud.ibm.com",
+        "us-east": "https://us-east.monitoring.cloud.ibm.com",
+        "eu-de": "https://eu-de.monitoring.cloud.ibm.com",
+        "eu-es": "https://eu-es.monitoring.cloud.ibm.com",
+        "eu-gb": "https://eu-gb.monitoring.cloud.ibm.com",
+        "jp-tok": "https://jp-tok.monitoring.cloud.ibm.com",
+        "au-syd": "https://au-syd.monitoring.cloud.ibm.com",
+        "jp-osa": "https://jp-osa.monitoring.cloud.ibm.com",
+        "ca-tor": "https://ca-tor.monitoring.cloud.ibm.com",
+        "br-sao": "https://br-sao.monitoring.cloud.ibm.com",
+    }
+    
+    def __init__(self, iam_auth: IBMCloudIAMAuth, instance_id: str, region: str):
+        """
+        Initialize the Sysdig Dashboard Manager.
+        
+        Args:
+            iam_auth: IBM Cloud IAM authentication handler
+            instance_id: IBM Cloud Monitoring instance ID (GUID)
+            region: IBM Cloud region (e.g., 'us-south', 'eu-de')
+        """
+        if region not in self.REGION_ENDPOINTS:
+            raise ValueError(
+                f"Invalid region '{region}'. Valid regions: {', '.join(self.REGION_ENDPOINTS.keys())}"
+            )
+        
+        self.iam_auth = iam_auth
+        self.instance_id = instance_id
+        self.region = region
+        self.base_url = self.REGION_ENDPOINTS[region]
+    
+    def _get_headers(self) -> Dict[str, str]:
+        """
+        Get HTTP headers with IAM authentication.
+        
+        Returns:
+            Dictionary of HTTP headers
+        """
+        access_token = self.iam_auth.get_access_token()
+        return {
+            "Authorization": f"Bearer {access_token}",
+            "IBMInstanceID": self.instance_id,
+            "Content-Type": "application/json",
+        }
+    
+    def list_dashboards(self) -> list:
+        """
+        List all dashboards in the Sysdig instance.
+        
+        Returns:
+            List of dashboard objects
+        """
+        url = f"{self.base_url}/api/v3/dashboards"
+        
+        try:
+            response = requests.get(url, headers=self._get_headers(), timeout=30)
+            response.raise_for_status()
+            data = response.json()
+            return data.get("dashboards", [])
+        except requests.exceptions.RequestException as e:
+            print(f"Error listing dashboards: {e}")
+            if hasattr(e, 'response') and e.response is not None:
+                print(f"Response: {e.response.text}")
+            return []
+    
+    def find_dashboard_by_name(self, name: str) -> Optional[Dict]:
+        """
+        Find a dashboard by its name.
+        
+        Args:
+            name: Dashboard name to search for
+            
+        Returns:
+            Dashboard object if found, None otherwise
+        """
+        dashboards = self.list_dashboards()
+        for dashboard in dashboards:
+            if dashboard.get("name") == name:
+                return dashboard
+        return None
+    
+    def create_dashboard(self, dashboard_config: Dict) -> Dict:
+        """
+        Create a new dashboard.
+        
+        Args:
+            dashboard_config: Dashboard configuration dictionary
+            
+        Returns:
+            Created dashboard object
+        """
+        url = f"{self.base_url}/api/v3/dashboards"
+        
+        try:
+            response = requests.post(
+                url,
+                headers=self._get_headers(),
+                json={"dashboard": dashboard_config},
+                timeout=30
+            )
+            response.raise_for_status()
+            return response.json()
+        except requests.exceptions.RequestException as e:
+            print(f"Error creating dashboard: {e}")
+            if hasattr(e, 'response') and e.response is not None:
+                print(f"Response: {e.response.text}")
+            raise
+    
+    def update_dashboard(self, dashboard_id: int, dashboard_config: Dict) -> Dict:
+        """
+        Update an existing dashboard.
+        
+        Args:
+            dashboard_id: ID of the dashboard to update
+            dashboard_config: New dashboard configuration
+            
+        Returns:
+            Updated dashboard object
+        """
+        url = f"{self.base_url}/api/v3/dashboards/{dashboard_id}"
+        
+        try:
+            response = requests.put(
+                url,
+                headers=self._get_headers(),
+                json={"dashboard": dashboard_config},
+                timeout=30
+            )
+            response.raise_for_status()
+            return response.json()
+        except requests.exceptions.RequestException as e:
+            print(f"Error updating dashboard: {e}")
+            if hasattr(e, 'response') and e.response is not None:
+                print(f"Response: {e.response.text}")
+            raise
+    
+    def import_or_update_dashboard(self, dashboard_config: Dict) -> Dict:
+        """
+        Import a dashboard or update it if it already exists.
+        
+        Args:
+            dashboard_config: Dashboard configuration dictionary
+            
+        Returns:
+            Dashboard object (created or updated)
+        """
+        dashboard_name = dashboard_config.get("name")
+        if not dashboard_name:
+            raise ValueError("Dashboard configuration must include a 'name' field")
+        
+        print(f"Checking if dashboard '{dashboard_name}' exists...")
+        existing_dashboard = self.find_dashboard_by_name(dashboard_name)
+        
+        if existing_dashboard:
+            dashboard_id = existing_dashboard.get("id")
+            if dashboard_id is None:
+                raise ValueError(f"Dashboard '{dashboard_name}' found but has no ID")
+            print(f"Dashboard '{dashboard_name}' found (ID: {dashboard_id}). Updating...")
+            result = self.update_dashboard(dashboard_id, dashboard_config)
+            print(f"✓ Dashboard '{dashboard_name}' updated successfully!")
+            return result
+        else:
+            print(f"Dashboard '{dashboard_name}' not found. Creating new dashboard...")
+            result = self.create_dashboard(dashboard_config)
+            dashboard_id = result.get("dashboard", {}).get("id")
+            print(f"✓ Dashboard '{dashboard_name}' created successfully (ID: {dashboard_id})!")
+            return result
+
+
+def load_dashboard_config(file_path: str) -> Dict:
+    """
+    Load dashboard configuration from a JSON file.
+    
+    Args:
+        file_path: Path to the JSON file
+        
+    Returns:
+        Dashboard configuration dictionary
+    """
+    try:
+        with open(file_path, 'r') as f:
+            return json.load(f)
+    except FileNotFoundError:
+        print(f"Error: Dashboard file '{file_path}' not found")
+        sys.exit(1)
+    except json.JSONDecodeError as e:
+        print(f"Error: Invalid JSON in dashboard file: {e}")
+        sys.exit(1)
+
+
+def main():
+    """Main entry point for the script."""
+    parser = argparse.ArgumentParser(
+        description="Import or update IBM Cloud Monitoring (Sysdig) dashboards using IBM Cloud IAM authentication",
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        epilog="""
+Examples:
+  # Using command-line arguments
+  python import_dashboard.py \\
+      --iam-api-key YOUR_IAM_KEY \\
+      --instance-id YOUR_INSTANCE_ID \\
+      --region us-south \\
+      --dashboard code-engine-component-resource-overview.json
+  
+  # Using environment variables
+  export IBM_CLOUD_IAM_API_KEY=YOUR_IAM_KEY
+  export SYSDIG_INSTANCE_ID=YOUR_INSTANCE_ID
+  export SYSDIG_REGION=us-south
+  python import_dashboard.py --dashboard code-engine-component-resource-overview.json
+
+Supported Regions:
+  us-south, us-east, eu-de, eu-gb, jp-tok, au-syd, jp-osa, ca-tor, br-sao
+
+How to get your Instance ID:
+  1. Go to IBM Cloud Console
+  2. Navigate to your Monitoring instance
+  3. Click on "Overview" or "Settings"
+  4. Copy the Instance ID (GUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
+        """
+    )
+    
+    parser.add_argument(
+        "--iam-api-key",
+        help="IBM Cloud IAM API key (or set IBM_CLOUD_IAM_API_KEY env var)",
+        default=os.environ.get("IBM_CLOUD_IAM_API_KEY")
+    )
+    
+    parser.add_argument(
+        "--instance-id",
+        help="IBM Cloud Monitoring instance ID/GUID (or set SYSDIG_INSTANCE_ID env var)",
+        default=os.environ.get("SYSDIG_INSTANCE_ID")
+    )
+    
+    parser.add_argument(
+        "--region",
+        help="IBM Cloud region (or set SYSDIG_REGION env var)",
+        default=os.environ.get("SYSDIG_REGION")
+    )
+    
+    parser.add_argument(
+        "--dashboard",
+        required=True,
+        help="Path to dashboard JSON file"
+    )
+    
+    args = parser.parse_args()
+    
+    # Validate required arguments
+    if not args.iam_api_key:
+        print("Error: IAM API key is required. Provide via --iam-api-key or IBM_CLOUD_IAM_API_KEY environment variable")
+        sys.exit(1)
+    
+    if not args.instance_id:
+        print("Error: Instance ID is required. Provide via --instance-id or SYSDIG_INSTANCE_ID environment variable")
+        sys.exit(1)
+    
+    if not args.region:
+        print("Error: Region is required. Provide via --region or SYSDIG_REGION environment variable")
+        sys.exit(1)
+    
+    # Load dashboard configuration
+    print(f"Loading dashboard configuration from '{args.dashboard}'...")
+    dashboard_config = load_dashboard_config(args.dashboard)
+    
+    # Initialize IAM authentication and dashboard manager
+    try:
+        iam_auth = IBMCloudIAMAuth(args.iam_api_key)
+        manager = SysdigDashboardManager(iam_auth, args.instance_id, args.region)
+        result = manager.import_or_update_dashboard(dashboard_config)
+        
+        # Print dashboard URL
+        dashboard_id = result.get("dashboard", {}).get("id")
+        if dashboard_id:
+            dashboard_url = f"{manager.base_url}/#/dashboards/{dashboard_id}"
+            print(f"\nDashboard URL: {dashboard_url}")
+        
+        print("\n✓ Operation completed successfully!")
+        
+    except ValueError as e:
+        print(f"Error: {e}")
+        sys.exit(1)
+    except Exception as e:
+        print(f"Unexpected error: {e}")
+        sys.exit(1)
+
+
+if __name__ == "__main__":
+    main()
+
diff --git a/metrics-collector/start.sh b/metrics-collector/start.sh
new file mode 100644
index 000000000..de2ded51b
--- /dev/null
+++ b/metrics-collector/start.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+set -e
+
+echo "Starting Code Engine Metrics Collector..."
+
+# Check if METRICS_ENABLED is set to true
+if [ "$METRICS_ENABLED" = "true" ]; then
+    echo "Prometheus metrics export enabled"
+    
+    # Check if monitoring API key secret is mounted
+    if [ ! -f "/etc/secrets/monitoring-apikey" ]; then
+        echo "ERROR: Prometheus agent requires /etc/secrets/monitoring-apikey to be mounted"
+        echo "Please create a secret with your IBM Cloud Monitoring API key and mount it at /etc/secrets/monitoring-apikey"
+        echo "Example:"
+        echo "  ibmcloud ce secret create --name monitoring-apikey --from-literal monitoring-apikey=YOUR_API_KEY"
+        echo "  ibmcloud ce job update --name metrics-collector --mount-secret /etc/secrets=monitoring-apikey"
+        exit 1
+    fi
+    
+    # Check required environment variables
+    if [ -z "$CE_SUBDOMAIN" ]; then
+        echo "ERROR: CE_SUBDOMAIN environment variable is required when METRICS_ENABLED=true"
+        exit 1
+    fi
+    
+    if [ -z "$METRICS_REMOTE_WRITE_FQDN" ]; then
+        echo "ERROR: METRICS_REMOTE_WRITE_FQDN environment variable is required when METRICS_ENABLED=true"
+        exit 1
+    fi
+
+    if [ -z "$CE_PROJECT_NAME" ]; then
+        CE_PROJECT_NAME="default"
+    fi
+    
+    # Generate prometheus.yml from template with environment variable substitution
+    echo "Generating Prometheus configuration..."
+    sed -e "s/\${CE_SUBDOMAIN}/$CE_SUBDOMAIN/g" \
+        -e "s/\${CE_PROJECT_NAME}/$CE_PROJECT_NAME/g" \
+        -e "s/\${METRICS_REMOTE_WRITE_FQDN}/$METRICS_REMOTE_WRITE_FQDN/g" \
+        /etc/prometheus/prometheus.yml.template > /tmp/prometheus.yml
+
+    echo "Starting Prometheus agent..."
+    /bin/prometheus --config.file=/tmp/prometheus.yml --agent --storage.agent.path=/tmp/agent-data --log.level info --log.format json 2>&1 &
+    PROMETHEUS_PID=$!
+    echo "Prometheus agent started with PID $PROMETHEUS_PID"
+    
+    # Give Prometheus a moment to start and check if it's actually running
+    sleep 2
+    if ! kill -0 "$PROMETHEUS_PID" 2>/dev/null; then
+        echo "ERROR: Prometheus agent failed to start"
+        exit 1
+    fi
+else
+    echo "Prometheus metrics export disabled (METRICS_ENABLED not set to 'true')"
+fi
+
+# Start the metrics collector
+echo "Starting metrics collector..."
+/app &
+APP_PID=$!
+echo "Metrics collector started with PID $APP_PID"
+
+# Function to handle shutdown
+shutdown() {
+    echo "Shutting down..."
+    if [ -n "$APP_PID" ]; then
+        kill -TERM "$APP_PID" 2>/dev/null || true
+    fi
+    if [ -n "$PROMETHEUS_PID" ]; then
+        kill -TERM "$PROMETHEUS_PID" 2>/dev/null || true
+    fi
+    wait
+    exit 0
+}
+
+# Trap signals
+trap shutdown SIGTERM SIGINT
+
+# Monitor processes
+while true; do
+    # Check if app is still running
+    if ! kill -0 "$APP_PID" 2>/dev/null; then
+        echo "ERROR: Metrics collector process died unexpectedly"
+        if [ -n "$APP_PID" ]; then
+            kill -TERM "$APP_PID" 2>/dev/null || true
+        fi
+        exit 1
+    fi
+    
+    # Check if Prometheus is still running (only if it was started)
+    if [ "$METRICS_ENABLED" = "true" ] && ! kill -0 "$PROMETHEUS_PID" 2>/dev/null; then
+        echo "ERROR: Prometheus agent process died unexpectedly"
+        kill -TERM "$PROMETHEUS_PID" 2>/dev/null || true
+        exit 1
+    fi
+    
+    sleep 5
+done
diff --git a/private-path-to-vpc-vsi/ce-app/Dockerfile b/private-path-to-vpc-vsi/ce-app/Dockerfile
index 7ae1e0829..93565d9e5 100644
--- a/private-path-to-vpc-vsi/ce-app/Dockerfile
+++ b/private-path-to-vpc-vsi/ce-app/Dockerfile
@@ -1,10 +1,10 @@
-FROM quay.io/projectquay/golang:1.23 AS build-env
+FROM quay.io/projectquay/golang:1.25 AS build-env
 WORKDIR /go/src/app
 COPY . .
 
 RUN CGO_ENABLED=0 go build -o /go/bin/app .
 
 # Copy the exe into a smaller base image
-FROM gcr.io/distroless/static-debian12
+FROM gcr.io/distroless/static-debian13
 COPY --from=build-env /go/bin/app /
 ENTRYPOINT ["/app"]
diff --git a/private-path-to-vpc-vsi/ce-app/go.mod b/private-path-to-vpc-vsi/ce-app/go.mod
index bff2499af..f65b725d1 100644
--- a/private-path-to-vpc-vsi/ce-app/go.mod
+++ b/private-path-to-vpc-vsi/ce-app/go.mod
@@ -1,5 +1,5 @@
 module github.com/IBM/CodeEngine/ce-private-path
 
-go 1.23.0
+go 1.25
 
 require github.com/lib/pq v1.10.9
diff --git a/satellite-connector-to-vpc-vsi/ce-app/Dockerfile b/satellite-connector-to-vpc-vsi/ce-app/Dockerfile
index 7ae1e0829..93565d9e5 100644
--- a/satellite-connector-to-vpc-vsi/ce-app/Dockerfile
+++ b/satellite-connector-to-vpc-vsi/ce-app/Dockerfile
@@ -1,10 +1,10 @@
-FROM quay.io/projectquay/golang:1.23 AS build-env
+FROM quay.io/projectquay/golang:1.25 AS build-env
 WORKDIR /go/src/app
 COPY . .
 
 RUN CGO_ENABLED=0 go build -o /go/bin/app .
 
 # Copy the exe into a smaller base image
-FROM gcr.io/distroless/static-debian12
+FROM gcr.io/distroless/static-debian13
 COPY --from=build-env /go/bin/app /
 ENTRYPOINT ["/app"]
diff --git a/satellite-connector-to-vpc-vsi/ce-app/go.mod b/satellite-connector-to-vpc-vsi/ce-app/go.mod
index 06d27fb97..4511f6fe9 100644
--- a/satellite-connector-to-vpc-vsi/ce-app/go.mod
+++ b/satellite-connector-to-vpc-vsi/ce-app/go.mod
@@ -1,5 +1,5 @@
 module github.com/IBM/CodeEngine/ce-satellite-connector
 
-go 1.21.0
+go 1.25
 
 require github.com/lib/pq v1.10.9
