Skip to content

Instantly share code, notes, and snippets.

@nickvsnetworking
Created March 10, 2025 21:24
Show Gist options
  • Select an option

  • Save nickvsnetworking/e5438d43b27f36b2c1f40f8f4d98bb00 to your computer and use it in GitHub Desktop.

Select an option

Save nickvsnetworking/e5438d43b27f36b2c1f40f8f4d98bb00 to your computer and use it in GitHub Desktop.
Kamailio Shared Memory to Prometheus Exporter
# Script to dump Kamailio shared memory stats to Prometheus
# Nick Jones - 2025
#Writeup about what this does and why it's here is at:
# https://nickvsnetworking.com/profiling-kamailio-module-memory-usage/
import time
import subprocess
import re
from prometheus_client import start_http_server, Gauge
# Create Prometheus Gauge metrics
KAMAILIO_SHM_STATS = Gauge(
"kamailio_shm_stats",
"Kamailio shared memory statistics",
["module", "key"]
)
KAMAILIO_SHM_TOTALS = Gauge(
"kamailio_shm_totals",
"Kamailio shared memory totals per module",
["module"]
)
def execute_kamcmd():
"""
Execute the 'kamcmd mod.stats all shm' command and return its output.
"""
try:
result = subprocess.run(
["kamcmd", "mod.stats", "all", "shm"],
capture_output=True,
text=True,
check=True
)
return result.stdout
except subprocess.CalledProcessError as e:
print(f"Error executing 'kamcmd mod.stats all shm': {e}")
return None
def parse_kamcmd_output(output):
"""
Parse the output of 'kamcmd mod.stats all shm' into a structured format.
"""
data = {}
totals = {}
module = None
for line in output.splitlines():
line = line.strip()
if line.startswith("Module:"):
module = line.split(":")[1].strip()
data[module] = {}
totals[module] = 0 # Initialize total for the module
elif line.startswith("Total:"):
if module:
# Extract the total value
total_value = int(line.split(":")[1].strip())
totals[module] = total_value
elif line and module:
# Match lines like "counters_prefork_init(211): 213248"
match = re.match(r"(.+?)\(\d+\):\s+(\d+)", line)
if match:
key = match.group(1).strip()
value = int(match.group(2))
data[module][key] = value
return data, totals
def update_metrics(data, totals):
"""
Update Prometheus metrics with the parsed data and totals.
"""
for module, metrics in data.items():
# Update individual metrics
for key, value in metrics.items():
KAMAILIO_SHM_STATS.labels(module=module, key=key).set(value)
# Update the total for the module
KAMAILIO_SHM_TOTALS.labels(module=module).set(totals.get(module, 0))
def main():
# Start the Prometheus HTTP server on port 9097
start_http_server(9097)
print("Prometheus metrics server started on port 9097")
# Run in an infinite loop
while True:
# Execute the kamcmd command
output = execute_kamcmd()
if output:
# Parse the output
data, totals = parse_kamcmd_output(output)
# Update Prometheus metrics
update_metrics(data, totals)
print("Metrics updated")
else:
print("Failed to fetch metrics")
# Wait for 60 seconds before the next update
time.sleep(60)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment