Code Engine job that demonstrates how to collect resource consumption metrics (vCPU and memory) of running Code Engine apps, jobs, and builds.
Resource consumption metrics can either be render in IBM Cloud Monitoring (see instructions)
or in IBM Cloud Logs (see instructions)
Furthermore, this asset can collect custom metrics of running apps and jobs (see instructions).
The metrics-collector is an as-is asset, that can be use to transmit resource consumption metrics (like vCPU and memory), and user-defined metrics (also known as custom metrics) to any target IBM Cloud Monitoring instance. To collect metrics through the metrics-collector, an instance needs to be running. It's recommended to run the metrics-collector as a daemon job.
Note: metrics-collector is project scoped, which means only metrics of the corresponding project in which the metrics-collector instance itself resides are collected. To scrape metrics of multiple projects, a metrics-collector instance needs to get deployed and started into each of the projects.
While resource consumption metrics are automatically collected of all running app, jobrun and buildrun instances, user-defined metrics are only scraped if enabled on the corresponding application or job.
At a high level, the metrics-collector has following characteristics
- An instance comprises of mainly two processes
- an HTTP server that exposes vCPU and memory information as Prometheus metrics on
localhost:9100/metrics - a prometheus agent which scrapes metrics and sends them to IBM Cloud Monitoring
- an HTTP server that exposes vCPU and memory information as Prometheus metrics on
- Metrics are scraped every 30 seconds
- For user-defined metrics the agent discovers and scrapes instances that are annotated with
codeengine.cloud.ibm.com/userMetricsScrape: 'true' - All metrics are forwarded to IBM Cloud Monitoring via remote write
- If one of the aforementioned processes crashes, the container exits with a non-zero code to trigger a restart
The metrics-collector supports two authentication methods for accessing IBM Cloud Monitoring:
- Option 1: Trusted Profile Authentication (Recommended) - Automatically obtains monitoring API keys using IBM Cloud Trusted Profiles
- Option 2: Explicit API Key Secret - Manually create and mount a monitoring API key as a secret
Step 1: You need an IBM Cloud Monitoring instance
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
# Create new Code Engine project
ibmcloud ce project create --name <yourCodeEngineProjectName>
# Select an existing Code Engine project
ibmcloud ce project select --name <yourProjectName>This method automatically obtains the monitoring API key using IBM Cloud Trusted Profiles. No manual secret creation or rotation is required.
Step 3a: Create an IBM Cloud Trusted Profile
Create a Trusted Profile that allows Code Engine compute resources to authenticate:
# Create the Trusted Profile
ibmcloud iam trusted-profile-create metrics-collector-profile \
--description "Trusted profile for Code Engine metrics collector"
# Add Code Engine compute resources as trusted entities
ibmcloud iam trusted-profile-rule-create metrics-collector-profile \
--name code-engine-rule \
--type Profile-CR \
--cr-type CE \
--conditions claim:project_name,operator:EQUALS,value:"$(ibmcloud ce proj current --output json|jq -r '.name')" \
--conditions claim:component_type,operator:EQUALS,value:"job" \
--conditions claim:component_name,operator:EQUALS,value:"metrics-collector"
# Grant the profile access to the Monitoring instance
ibmcloud iam trusted-profile-policy-create metrics-collector-profile \
--roles Viewer,Writer \
--service-name sysdig-monitor \
--service-instance $MONITORING_INSTANCE_GUIDNote: Replace <your-ce-project-namespace> with your Code Engine project's Kubernetes namespace (typically in the format <project-guid>).
Step 4a: Create your metrics-collector job with Trusted Profile configuration
ibmcloud ce job create \
--name metrics-collector \
--src "." \
--mode daemon \
--cpu 0.25 \
--memory 0.5G \
--service-account reader \
--build-size xlarge \
--trusted-profiles-enabled \
--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')" \
--env MONITORING_INSTANCE_GUID="$MONITORING_INSTANCE_GUID" \
--env MONITORING_REGION="$REGION" \
--env TRUSTED_PROFILE_NAME="metrics-collector-profile"Step 5a: Submit a daemon job run
ibmcloud ce jobrun submit \
--job metrics-collectorThis method requires manually creating and mounting a monitoring API key. Use this option for local development, testing, or when Trusted Profiles are not available.
Step 3b: Create a secret with your IBM Cloud Monitoring API token
# 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 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_KEYStep 4b: Create your metrics-collector job with the required configuration
ibmcloud ce job create \
--name metrics-collector \
--src "." \
--mode daemon \
--cpu 0.25 \
--memory 0.5G \
--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-apikeyStep 5b: Submit a daemon job run
ibmcloud ce jobrun submit \
--job metrics-collectorThe metrics collector scrapes CPU/Memory metrics from your Code Engine applications, jobs, and builds. Metrics of all running instances are scraped every 30 seconds.
Once, metrics are ingested into an IBM Cloud Monitoring instance, the pre-populated dashboard "IBM Cloud Code Engine - Component Resource Overview" appears in Dashboard Manager.
The following Prometheus metrics are exposed as gauges:
Container Metrics:
ibm_codeengine_instance_cpu_usage_millicores: Current CPU usage in millicoresibm_codeengine_instance_cpu_limit_millicores: Configured CPU limit in millicoresibm_codeengine_instance_memory_usage_bytes: Current memory usage in bytesibm_codeengine_instance_memory_limit_bytes: Configured memory limit in bytesibm_codeengine_instance_ephemeral_storage_usage_bytes: Current ephemeral storage usage in bytes (ifCOLLECT_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 (ifMETRICS_INTERNAL_STATS=true)ibm_codeengine_collector_last_collection_timestamp_seconds: Unix timestamp of last successful collection (ifMETRICS_INTERNAL_STATS=true)ibm_codeengine_collector_collection_errors_total: Total number of collection errors (counter) (ifMETRICS_INTERNAL_STATS=true)
Sample metrics content:
# 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
All container metrics include the following labels:
ibm_codeengine_component_type: Type of component (app,job, orbuild)ibm_codeengine_component_name: Name of the Code Engine componentibm_codeengine_instance_name: Name of the pod instance (optional, see cardinality control below)ibm_codeengine_subcomponent_name: Name of the app revision (optional, see cardinality control below)
The metrics collector can discover and scrape custom Prometheus metrics from your Code Engine applications and jobs. To enable this feature, add the following annotations to your application:
Required annotation:
codeengine.cloud.ibm.com/userMetricsScrape: 'true'- Enables metrics scraping for this applicationcodeengine.cloud.ibm.com/userMetricsPath: '/metrics'- Custom metrics endpoint path (default:/metrics)codeengine.cloud.ibm.com/userMetricsPort: '2112'- Custom metrics port
How to enable scraping of custom metrics on an app:
kubectl patch ksvc myapp --type merge -p '{
"spec": {
"template": {
"metadata": {
"annotations": {
"codeengine.cloud.ibm.com/userMetricsScrape": "true",
"codeengine.cloud.ibm.com/userMetricsPath": "/metrics",
"codeengine.cloud.ibm.com/userMetricsPort": "2112"
}
}
}
}
}'How to enable scraping of custom metrics on a job:
kubectl annotate jobdefinition myjob codeengine.cloud.ibm.com/userMetricsScrape=true
kubectl annotate jobdefinition myjob codeengine.cloud.ibm.com/userMetricsPath='/metrics'
kubectl annotate jobdefinition myjob codeengine.cloud.ibm.com/userMetricsPort=2112To manage metric cardinality and reduce costs, you can control which labels are included in scraped user metrics using the following annotations:
Cardinality control annotations:
codeengine.cloud.ibm.com/userMetricsInstance: 'true'- Include theibm_codeengine_instance_namelabel (pod name)codeengine.cloud.ibm.com/userMetricsSubcomponent: 'true'- Include theibm_codeengine_subcomponent_namelabel (app revision name)
Default behavior: By default, both ibm_codeengine_instance_name and ibm_codeengine_subcomponent_name labels are excluded from user metrics to minimize cardinality. These labels can create high cardinality because:
- Instance names change with each pod restart or scale event
- Revision names change with each application update
When to enable these labels:
- Enable
userMetricsInstancewhen you need to track metrics per individual pod instance - Enable
userMetricsSubcomponentwhen you need to compare metrics across different application revisions
Example with cardinality control:
# Enable user metrics scraping with instance-level granularity
kubectl patch ksvc myapp --type merge -p '{
"spec": {
"template": {
"metadata": {
"annotations": {
"codeengine.cloud.ibm.com/userMetricsScrape": "true",
"codeengine.cloud.ibm.com/userMetricsInstance": "true"
}
}
}
}
}'
# Enable user metrics scraping with both instance and revision granularity
kubectl patch ksvc myapp --type merge -p '{
"spec": {
"template": {
"metadata": {
"annotations": {
"codeengine.cloud.ibm.com/userMetricsScrape": "true",
"codeengine.cloud.ibm.com/userMetricsInstance": "true",
"codeengine.cloud.ibm.com/userMetricsSubcomponent": "true"
}
}
}
}
}'Note: Only set these annotations to "true" when you specifically need the additional label granularity. Keeping them disabled (default) helps reduce metric cardinality and associated monitoring costs.
See the metrics-example/README.MD for language specific examples on how to emit prometheus metrics.
Once your IBM Cloud Code Engine project has detected a corresponding IBM Cloud Logs instance, which is configured to receive platform logs, you can consume the resource metrics in IBM Cloud Logs. Use the filter metric:instance-resources to filter for log lines that print resource metrics for each detected IBM Cloud Code Engine instance that is running in a project.
Follow the steps below to create a custom dashboard in your IBM Cloud Logs instance, to gain insights into resource consumption metrics.
Setup instructions:
- Navigate to the "Custom dashboards" view, hover of the "New" button, and click "Import dashboard"
- In the "Import" modal, select the file ./setup/ibm-cloud-logs/dashboard-code_engine_resource_consumption_metrics.json located in this repository, and click "Import"
- Confirm the import by clicking "Import" again
Follow the steps below to create a Logs view in your IBM Cloud Logs instance, that allows you to drill into individual instance-resources log lines.
Setup instructions:
- Filter only log lines related collected istio-proxy logs, by filtering for the following query
app:"codeengine" AND message.metric:"instance-resources"
- In the left bar, click "Add Filter" and add the following filters
ApplicationAppLabel.ProjectMessage.Component_name
- In the top-right corner, click on "Columns" and configure the following columns:
Timestamplabel.Projectmessage.component_typemessage.component_namemessage.messageText
-
Once applied adjust the column widths appropriately
-
In the top-right corner, select
1-lineas view mode -
In the graph title it says "Count all grouped by Severity". Click on
Severityand selectmessage.component_nameinstead. Furthermore, selectMaxas aggregation metric and choosemessage.memory.usageas aggregation field
- Save the view
- Utilize the custom logs view to drill into HTTP requests
Trusted Profile Authentication Failures:
- Missing environment variables: Ensure
MONITORING_INSTANCE_GUID,MONITORING_REGION, andTRUSTED_PROFILE_NAMEare all set - Container resource token not found: Verify the job is running in Code Engine with proper service account permissions
- IAM token request failed: Check that the Trusted Profile exists and has the correct trust relationship configured
- Monitoring API key retrieval failed: Verify the Trusted Profile has appropriate permissions (Viewer, Writer) for the Monitoring instance
- Invalid region: Ensure
MONITORING_REGIONmatches your Monitoring instance region (e.g.,us-south,eu-de,eu-gb)
Explicit Secret Authentication Failures:
- Missing
/etc/secrets/monitoring-apikeyfile: Ensure the secret is created and properly mounted - Invalid API key: Regenerate the monitoring API key and update the secret
General Issues:
- Missing or wrong
METRICS_REMOTE_WRITE_FQDN: Verify the endpoint matches your region's ingestion endpoint - Prometheus agent fails to start: Check the logs for configuration errors or network connectivity issues
Core Configuration:
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 totrueto 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 totrueto 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 whenMETRICS_ENABLED=true)METRICS_PORT(default:9100): HTTP server port for the Prometheus metrics endpoint. Only used whenMETRICS_ENABLED=truein daemon mode.
Trusted Profile Authentication (Option 1):
MONITORING_INSTANCE_GUID: The GUID of your IBM Cloud Monitoring instance (required for Trusted Profile authentication)MONITORING_REGION: The region where your Monitoring instance is deployed, e.g.,us-south,eu-de,eu-gb(required for Trusted Profile authentication)TRUSTED_PROFILE_NAME: The name of the IBM Cloud Trusted Profile to use for authentication (required for Trusted Profile authentication)CR_TOKEN_FILENAME(optional): Override the default container resource token file path (default:/var/run/secrets/codeengine.cloud.ibm.com/compute-resource-token/token)
Note: When all three Trusted Profile environment variables are set, the collector will attempt Trusted Profile authentication first. If it fails or the variables are not set, it will fall back to using a mounted secret at /etc/secrets/monitoring-apikey.












