Skip to content

Instantly share code, notes, and snippets.

@AstroTom
Created April 26, 2026 14:20
Show Gist options
  • Select an option

  • Save AstroTom/2266393e40b74bae9e6350013cfa9b24 to your computer and use it in GitHub Desktop.

Select an option

Save AstroTom/2266393e40b74bae9e6350013cfa9b24 to your computer and use it in GitHub Desktop.
report the top 10 most expensive lambda calls for a function (based on log group) similar to AWS console under Monitor tab
#!/usr/bin/env bash
#
# Show top 10 most expensive Lambda invocations (GB-seconds)
# for log group: Instance-Scheduler-default-scheduling-logs
#
# Requirements:
# - AWS CLI v2 configured with permissions for CloudWatch Logs
# - jq installed
#
# Usage:
# ./top_lambda_gb_seconds.sh
set -euo pipefail
#
# Update these variables
#
LOG_GROUP="Instance-Scheduler-default-scheduling-logs" # usually "/aws/lambda/FUNC_NAME"
REGION="${AWS_REGION:-eu-west-1}"
PROFILE_OPT="${AWS_PROFILE:+--profile $AWS_PROFILE}"
LOOKBACK_HOURS="${1:-24}"
#
# End variables
#
# Time range for the query
START_TIME="$(date -d "${LOOKBACK_HOURS} hours ago" +%s)"
END_TIME="$(date +%s)"
# CloudWatch Logs Insights query:
# - Use Lambda REPORT lines (@type="REPORT")
# - Compute GB-seconds = billedDuration(ms) * memory(MB) / 1024 / 1000
# - Aggregate by requestId
read -r -d '' QUERY << 'EOF' || true
filter @type = "REPORT"
| stats
max(@timestamp) as timestamp,
max(@billedDuration) as billed_ms,
max(@memorySize) as memory_mb,
max(@maxMemoryUsed) as max_memory_used_mb,
max(@billedDuration * @memorySize) / 1024 / 1000 as gb_seconds
by @requestId
| sort gb_seconds desc
| limit 10
EOF
echo "Running Logs Insights query on log group '${LOG_GROUP}' for the last ${LOOKBACK_HOURS} hours in region ${REGION}..." 1>&2
# Start the query
QUERY_ID=$(
aws logs start-query \
--log-group-name "${LOG_GROUP}" \
--start-time "${START_TIME}" \
--end-time "${END_TIME}" \
--query-string "${QUERY}" \
--region "${REGION}" \
${PROFILE_OPT:-} \
--output text \
--query 'queryId'
)
# Poll until complete
STATUS="Running"
while [[ "${STATUS}" == "Running" || "${STATUS}" == "Scheduled" ]]; do
sleep 2
STATUS=$(
aws logs get-query-results \
--query-id "${QUERY_ID}" \
--region "${REGION}" \
${PROFILE_OPT:-} \
--output text \
--query 'status'
)
done
if [[ "${STATUS}" != "Complete" ]]; then
echo "Query failed with status: ${STATUS}" 1>&2
exit 1
fi
# Fetch results and format similar to the Lambda console "Most expensive invocations in GB-seconds"
RESULTS_JSON=$(
aws logs get-query-results \
--query-id "${QUERY_ID}" \
--region "${REGION}" \
${PROFILE_OPT:-} \
--output json
)
echo -e "timestamp\trequestId\tbilled_ms\tmemory_mb\tmaxMemoryUsedMB\tgb_seconds"
echo "${RESULTS_JSON}" | jq -r '
.results[]
| (map({( .field ): .value}) | add) as $r
| "\($r.timestamp)\t\($r."@requestId")\t\($r.billed_ms)\t\($r.memory_mb)\t\($r.max_memory_used_mb)\t\($r.gb_seconds)"
'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment