Created
March 10, 2025 21:24
-
-
Save nickvsnetworking/e5438d43b27f36b2c1f40f8f4d98bb00 to your computer and use it in GitHub Desktop.
Kamailio Shared Memory to Prometheus Exporter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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