{"id":18753242,"url":"https://github.com/kpn/mq-hammer","last_synced_at":"2025-04-13T00:31:33.991Z","repository":{"id":94298188,"uuid":"197130054","full_name":"kpn/mq-hammer","owner":"kpn","description":"MQTT Load Tester and Monitoring Tool","archived":false,"fork":false,"pushed_at":"2023-08-04T14:19:59.000Z","size":184,"stargazers_count":12,"open_issues_count":8,"forks_count":3,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-26T18:57:15.816Z","etag":null,"topics":["go","golang","hammer","load-testing","mqtt","stop","time"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kpn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-16T06:00:52.000Z","updated_at":"2024-01-27T05:07:59.000Z","dependencies_parsed_at":"2024-06-20T13:05:29.392Z","dependency_job_id":"f36c1162-88ed-47f8-974d-5ce5002a21f7","html_url":"https://github.com/kpn/mq-hammer","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kpn%2Fmq-hammer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kpn%2Fmq-hammer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kpn%2Fmq-hammer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kpn%2Fmq-hammer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kpn","download_url":"https://codeload.github.com/kpn/mq-hammer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248650590,"owners_count":21139670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","hammer","load-testing","mqtt","stop","time"],"created_at":"2024-11-07T17:24:57.449Z","updated_at":"2025-04-13T00:31:33.323Z","avatar_url":"https://github.com/kpn.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MQ Hammer\n\n[![CircleCI](https://circleci.com/gh/kpn/mq-hammer.svg?style=svg)](https://circleci.com/gh/kpn/mq-hammer)\n[![Go Report Card](https://goreportcard.com/badge/github.com/kpn/mq-hammer)](https://goreportcard.com/report/github.com/kpn/mq-hammer)\n\nMQ Hammer is an MQTT load testing and monitoring tool.\n\nStop! Hammer time! \n\n# :helicopter: Overview\n\nMQ Hammer spins up a specified number of agents. Each agent has an MQTT connection to a broker and follows a scenario. A scenario dictates at which time an agent should subscribe or publish a message. Optionally, via a reference data set the correctness of received (retained) messages can be verified.\n\nThe primary output are metrics in the Prometheus exposition format. A summary of these metrics is output to the console as well.\n\nMQ Hammer has been used to run 60k clients concurrently on commodity hardware.\n\nOne application of MQ Hammer is load testing. Another possible application is to run MQ Hammer continuously with a moderate amount of agents and use its metrics to assess the performance of the system it targets.\n\n# :construction_worker: Building\n\nBinaries for Linux and macOS are available from the [releases](https://github.com/kpn/mq-hammer/releases/) page.\n\nA docker image is available on [dockerhub](https://hub.docker.com/r/kpnnl/mq-hammer), e.g.:\n\n    docker run -it kpnnl/mq-hammer version\n\nFor manual building, assuming a working Go environment and `dep` installed:\n\n    make bootstrap test build\n\nWill produce a binary in `./build/`.\n\n# :rocket: Quick Start\n\nIn one terminal, subscribe with the [mosquitto client](https://mosquitto.org/download/):\n\n    mosquitto_sub -h iot.eclipse.org -t '/mq-hammer/#' -v\n\nIn another terminal, run the example scenario with MQ Hammer:\n\n    ./build/mqhammer --broker iot.eclipse.org -n 1 --scenario example/quick-start/scenario.json\n\nWhile MQ Hammer runs, the mosquitto client will repeatedly output the following lines as MQ Hammer publishes:\n\n    /mq-hammer/favourite/bird rollulus\n    /mq-hammer/birds/rollulus rouloul\n\nNote that `iot.eclipse.org` is a public sandbox broker [ran by the community](https://iot.eclipse.org/getting-started/). Do not abuse it by running more than a few agents; use your own broker for that. And note that since it is a public broker, when you run the example you might see other MQ Hammer users doing the same.\n\n# :notebook: Usage\n\n    $ ./build/mqhammer --help\n    MQ Hammer is an MQTT load testing tool\n\n    MQ Hammer will create --num-agents goroutines, each subscribing, unsubscribing\n    and publish to topics at given timestamps according to the instructions in the\n    --scenario file.\n\n    It is possible to provide a reference data set that can be used for validation\n    of static (and retained) data. With it, MQ Hammer knows when after a\n    subscription the complete contents came in, how long it took to complete, if\n    messages are missing, etc.\n\n    By default, agents do not log to stderr to keep things clean a bit. For\n    diagnostics, it is possible through --agent-logs to output logs to a file, one\n    for each agent. Giving --agent-logs=- as argument will make the agents log to the\n    default logger.\n\n    All arguments can be specified through identically named environment variables\n    as well.\n\n    Usage:\n    mqhammer [flags]\n    mqhammer [command]\n\n    Available Commands:\n    help        Help about any command\n    version     Print the version number of MQ Hammer\n\n    Flags:\n        --agent-logs string    Filename to output per-agent logs. Go-templated, e.g. 'agent-{{ .ClientID }}.log', or - to log to stderr\n    -b, --broker string        Broker address, host[:port]; port defaults to 8883 for TLS or 1883 for plain text \n        --client-id string     Client ID prefix; a UUID is appended to it per agent to guarantee uniqueness (default \"mq-hammer:v0.1.0-dirty:\")\n        --credentials string   Filename with username,password and client id in CSV\n        --disable-mqtt-tls     Disable TLS for MQTT, use plain tcp sockets to the MQTT broker\n    -h, --help                 help for mqhammer\n    -k, --insecure             Don't validate TLS hostnames / cert chains\n        --nss-key-log string   Filename to append TLS master secrets in NSS key log format to\n    -n, --num-agents int       Number of agents to spin up (default 1)\n    -p, --password string      Password for connecting\n        --prometheus string    Export Prometheus metrics at this address (default \":8080\")\n    -r, --ref string           Filename with the expected reference data as JSON\n    -s, --scenario string      Filename containing the scenario as JSON\n        --sleep duration       Duration to wait between spinning up each agent (default 250ms)\n    -u, --username string      Username for connecting\n    -v, --verbose              Verbose: output paho mqtt's internal logging (crit, err and warn) to stderr\n    -w, --verboser             Verboser: output paho mqtt's internal logging (crit, err, warn and debug) to stderr\n\n    Use \"mqhammer [command] --help\" for more information about a command.\n\n\nScenarios are performed in this way: each agent starts at a random position and loops infinitely through the Scenario.\n\nFor capturing packet dumps of TLS traffic, MQ Hammer can be instructed to output TLS master secrets in [NSS Key log format](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format) to a file. This file can be used in for instance Wireshark to decipher the encrypted traffic.\n\n## Examples\n\n### Verifying retained message with a reference set\n\nFirst, publish the expected retained messages on the broker:\n\n    ./example/retained/publish-reference-set.sh iot.eclipse.org\n\nNext, run MQ Hammer, and point it at the reference set:\n\n    ./build/mqhammer --broker iot.eclipse.org -n 1 --scenario example/retained/scenario.json --ref example/retained/reference.json\n\nWith the reference set, MQ Hammer knows what messages to expect after a subscribe, and tests for their existence and correctness.\n\n# :chart_with_upwards_trend: Metrics\n\nMetrics are available to be scraped by Prometheus. An example Grafana dashboard to get you started can be found [here](./example/grafana/dashboard.json). The Dashboard looks like this:\n\n![Grafana Dashboard](./example/grafana/screenshot.png)\n\n## Console Metrics\n\nThe metrics are output to the console in a condensed form every two seconds and look like this:\n\n    ag=64 subs=288 (70.5/s) unsubs=9 (3.0/s) pubs=31 (8.0/s) 1.622kB inmsgs=0 (0.0/s) 0B unexp=0 dup=0 miss=0 badpl=0 err={c=0,p=0,s=0,u=0}\n    t_connect: 64 samples; 0.05% \u003c= 46.917ms; 0.10% \u003c= 47.481ms; 0.50% \u003c= 54.133ms; 0.90% \u003c= 70.384ms; 0.95% \u003c= 75.062ms; 0.99% \u003c= 82.67ms\n    t_firstMsg - t_subscribe: 0 samples;\n    t_lastMsg - t_firstMsg  : 0 samples;\n\nThe first line means that there are 64 agents, 288 subscriptions and 9 unsubscriptions have been made in total. A number of 31 messages has been published weighing 1.622kB, and 0 messages have been received. Then for the reference data, there were 0 unexpected messages received, 0 duplicates, 0 missing messages, 0 messages had an incorrect payload. Then `err` gives the mqtt errors encountered during connecting, publishing, subscribing and unsubscribing respectively.\n\nThe second line is a summary of the time it took to connect.\n\n# :floppy_disk: Data File Formats\n\nAll data files, except for the credentials file, are in JSON. The credentials file is a CSV.\n\n## Reference Set\n\nThe reference set is a map from topic to base64 encoded payload. E.g.:\n\n```json\n{\n    \"/tt/example/1/2/3/hello\":\"Y29vbAo=\",\n    \"/tt/example/4/5/6/hello\":\"Y3JhcAo=\"\n}\n```\n\nWhen this reference set it published under `/tt/example`, subscribing to `/tt/example/1/2/#` will result in a single message with key `/tt/example/1/2/3/hello` and payload \"cool\".\n\n## Scenario\n\nA scenario is an array of `Step` objects. Each `Step` has at least `t`, the relative time in seconds at which this Step is to be performed. Furthermore, it can contain a `publish`, a `subscribe` or a `disconnect`, each optional. `publish` is an array of messages to publish, objects with a topic and a base64 payload. `subscribe` is an array of topics to be subscribed to in this step. Any topics previously subscribed to, that are not in this set, are implicitly unsubscribed from. `disconnect` is a bool that makes the mqtt client disconnect. An example can be found [here](./example/simple-scenario.json).\n\n## Credentials\n\nCredentials are in CSV format, with in the first column the username, and the second column the password and the third column the client id.\n\n# :art: Software Design\n\nA rough outline of the dataflow is as follows.\n\nA `Scenario` dictate the topics and pace. An `agent` subscribes / unsubscribes or publishes according to this. A `MessageHandlerer` provides message handlers that deal with incoming messages. It is either a (non-validating) `messageHandler` or a `validatingHandler`. Those handlers produce `events` like `subscribe` or `message`, which are collected by the `EventFunnel`, a `channeledFunnel` to be more concrete. In its `Process()` loop it computes metrics on incoming events.\n\n# :couple: Related Work\n\n- [MQTT JMeter Plugin](https://github.com/emqx/mqtt-jmeter);\n- [MQTT Stresser](https://github.com/inovex/mqtt-stresser);\n- [MQTTBox](https://www.hivemq.com/blog/mqtt-toolbox-mqttbox/).\n\n# :handbag: Varia\n\nBeware of your OS' limits:\n\n    echo 16384 | sudo tee /proc/sys/fs/inotify/max_user_watches\n    ulimit -n 16384\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkpn%2Fmq-hammer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkpn%2Fmq-hammer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkpn%2Fmq-hammer/lists"}