{"id":13393542,"url":"https://github.com/sqshq/sampler","last_synced_at":"2025-05-13T22:06:11.279Z","repository":{"id":38808371,"uuid":"167483271","full_name":"sqshq/sampler","owner":"sqshq","description":"Tool for shell commands execution, visualization and alerting. Configured with a simple YAML file.","archived":false,"fork":false,"pushed_at":"2024-02-22T10:21:15.000Z","size":2230,"stargazers_count":13191,"open_issues_count":60,"forks_count":596,"subscribers_count":163,"default_branch":"master","last_synced_at":"2025-04-09T19:14:44.140Z","etag":null,"topics":["alerting","charts","cmd","command-line","command-line-tool","dashbord","golang","monitoring","sampler","shell","terminal","visualization"],"latest_commit_sha":null,"homepage":"https://sampler.dev","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sqshq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","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},"funding":{"custom":["http://sampler.dev/sponsor"]}},"created_at":"2019-01-25T04:10:21.000Z","updated_at":"2025-04-09T17:51:00.000Z","dependencies_parsed_at":"2023-02-09T15:16:22.696Z","dependency_job_id":"75c4dba3-33e0-42db-85e5-ec51c6a610c2","html_url":"https://github.com/sqshq/sampler","commit_stats":{"total_commits":244,"total_committers":14,"mean_commits":"17.428571428571427","dds":0.07786885245901642,"last_synced_commit":"9bc7ba732d31f32a917ad4b5605f00b76ebe0891"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqshq%2Fsampler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqshq%2Fsampler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqshq%2Fsampler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqshq%2Fsampler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sqshq","download_url":"https://codeload.github.com/sqshq/sampler/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251338336,"owners_count":21573539,"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":["alerting","charts","cmd","command-line","command-line-tool","dashbord","golang","monitoring","sampler","shell","terminal","visualization"],"created_at":"2024-07-30T17:00:55.642Z","updated_at":"2025-04-28T15:29:36.113Z","avatar_url":"https://github.com/sqshq.png","language":"Go","readme":"# Sampler. Visualization for any shell command.\n[![Build Status](https://travis-ci.com/sqshq/sampler.svg?token=LdyRhxxjDFnAz1bJg8fq\u0026branch=master)](https://travis-ci.com/sqshq/sampler) [![Go Report Card](https://goreportcard.com/badge/github.com/sqshq/sampler)](https://goreportcard.com/report/github.com/sqshq/sampler)\n\nSampler is a tool for shell commands execution, visualization and alerting. Configured with a simple YAML file.\n\n![sampler](https://user-images.githubusercontent.com/6069066/56404396-70b14d00-6234-11e9-93cd-54461bf40c96.gif)\n\n## Why do I need it?\nOne can sample any dynamic process right from the terminal — observe changes in the database, monitor MQ in-flight messages,  trigger a deployment script and get notification when it's done. \n\nIf there is a way to get a metric using a shell command, then it can be visualized with Sampler momentarily.\n\n## Installation\n\n### macOS\n\n[HomeBrew](https://brew.sh):\n```bash\nbrew install sampler\n```\n\n[MacPorts](https://www.macports.org):\n```bash\nsudo port install sampler\n```\n\nor\n```bash\nsudo curl -Lo /usr/local/bin/sampler https://github.com/sqshq/sampler/releases/download/v1.1.0/sampler-1.1.0-darwin-amd64\nsudo chmod +x /usr/local/bin/sampler\n```\n\n### Linux\n```bash\nsudo wget https://github.com/sqshq/sampler/releases/download/v1.1.0/sampler-1.1.0-linux-amd64 -O /usr/local/bin/sampler\nsudo chmod +x /usr/local/bin/sampler\n```\nNote: `libasound2-dev` system library is required to be installed for Sampler to play a [trigger](https://github.com/sqshq/sampler#triggers) sound tone. Usually the library is in place, but if not - you can install it with your favorite package manager, e.g `apt install libasound2-dev`\n#### Packaging status\n- [Fedora](https://apps.fedoraproject.org/packages/golang-github-sqshq-sampler) `sudo dnf install golang-github-sqshq-sampler` (F31+)\n- [Arch](https://aur.archlinux.org/packages/sampler) `yay -S sampler`\n### Windows (experimental)\nRecommended to use with advanced console emulators, e.g. [Cmder](https://cmder.app/)\n\nVia [Chocolatey](https://chocolatey.org/docs)\n```powershell\nchoco install sampler\n```\nor\n\n[Download .exe](https://github.com/sqshq/sampler/releases/download/v1.1.0/sampler-1.1.0-windows-amd64.exe)\n\n### Docker\n\n```\n# Create a configuration file\nvim config.yml\n\n# Build the container image\ndocker build --tag sampler .\n\n# Run a container\ndocker run --interactive --tty --volume $(pwd)/config.yml:/root/config.yml sampler --config /root/config.yml\n```\n\n## Usage\nYou specify shell commands, Sampler executes them with a required rate. The output is used for visualization.\n\nUsing Sampler is basically a 3-step process:\n- Define your shell commands in a YAML configuration file\n- Run `sampler -c config.yml`\n- Adjust components size and location on UI\n\n## But there are so many monitoring systems already\nSampler is by no means an alternative to full-scale monitoring systems, but rather an easy to setup development tool.\n\nIf spinning up and configuring [Prometheus with Grafana](https://prometheus.io) is complete overkill for you task, Sampler might be the right solution. No servers, no databases, no deploy - you specify shell commands, and it just works.\n\n## Then it should be installed on every server I monitor?\nNo, you can run Sampler on local, but still gather telemetry from multiple remote machines. Any visualization might have `init` command, where you can ssh to a remote server. See the [SSH example](https://github.com/sqshq/sampler#ssh)\n\n## Contents\n\n- [Components](#components)\n  - [Runchart](#runchart)\n  - [Sparkline](#sparkline)\n  - [Barchart](#barchart)\n  - [Gauge](#gauge)\n  - [Textbox](#textbox)\n  - [Asciibox](#asciibox)\n- [Bells and whistles](#bells-and-whistles)\n  - [Triggers (conditional actions)](#triggers)\n  - [Interactive shell (database interaction, remote server access, etc)](#interactive-shell-support)\n  - [Variables](#variables)\n  - [Color theme](#color-theme)\n- [Real-world recipes (contributions welcome!)](#real-world-recipes)\n  - [Databases (MySQL, PostgreSQL, MongoDB, Neo4j)](#databases)\n  - [Kafka](#kafka)\n  - [Docker](#docker)\n  - [SSH](#ssh)\n  - [JMX](#jmx)\n\n## Components\nThe following is a list of configuration examples for each component type, with macOS compatible sampling scripts. \n\n### Runchart\n![runchart](https://user-images.githubusercontent.com/6069066/59168666-aff96d00-8b04-11e9-99b6-34d8bae37bd2.png)\n```yml\nruncharts:\n  - title: Search engine response time\n    rate-ms: 500        # sampling rate, default = 1000\n    scale: 2            # number of digits after sample decimal point, default = 1\n    legend:\n      enabled: true     # enables item labels, default = true\n      details: false    # enables item statistics: cur/min/max/dlt values, default = true\n    items:\n      - label: GOOGLE\n        sample: curl -o /dev/null -s -w '%{time_total}'  https://www.google.com\n        color: 178      # 8-bit color number, default one is chosen from a pre-defined palette\n      - label: YAHOO\n        sample: curl -o /dev/null -s -w '%{time_total}'  https://search.yahoo.com\n      - label: BING\n        sample: curl -o /dev/null -s -w '%{time_total}'  https://www.bing.com\n```\n### Sparkline\n![sparkline](https://user-images.githubusercontent.com/6069066/59167746-de754900-8b00-11e9-9305-c9a4176634d2.png)\n```yml\nsparklines:\n  - title: CPU usage\n    rate-ms: 200\n    scale: 0\n    sample: ps -A -o %cpu | awk '{s+=$1} END {print s}'\n  - title: Free memory pages\n    rate-ms: 200\n    scale: 0\n    sample: memory_pressure | grep 'Pages free' | awk '{print $3}'\n```\n### Barchart\n![barchart](https://user-images.githubusercontent.com/6069066/59167751-de754900-8b00-11e9-8d01-efd04ae1eec6.png)\n```yml\nbarcharts:\n  - title: Local network activity\n    rate-ms: 500        # sampling rate, default = 1000\n    scale: 0            # number of digits after sample decimal point, default = 1\n    items:\n      - label: UDP bytes in\n        sample: nettop -J bytes_in -l 1 -m udp | awk '{sum += $4} END {print sum}'\n      - label: UDP bytes out\n        sample: nettop -J bytes_out -l 1 -m udp | awk '{sum += $4} END {print sum}'\n      - label: TCP bytes in\n        sample: nettop -J bytes_in -l 1 -m tcp | awk '{sum += $4} END {print sum}'\n      - label: TCP bytes out\n        sample: nettop -J bytes_out -l 1 -m tcp | awk '{sum += $4} END {print sum}'\n```\n### Gauge\n![gauge](https://user-images.githubusercontent.com/6069066/59318799-4c06ae00-8c96-11e9-868a-7fef803f3739.png)\n```yml\ngauges:\n  - title: Minute progress\n    rate-ms: 500        # sampling rate, default = 1000\n    scale: 2            # number of digits after sample decimal point, default = 1\n    percent-only: false # toggle display of the current value, default = false\n    color: 178          # 8-bit color number, default one is chosen from a pre-defined palette\n    cur:\n      sample: date +%S  # sample script for current value\n    max:\n      sample: echo 60   # sample script for max value\n    min:\n      sample: echo 0    # sample script for min value\n  - title: Year progress\n    cur:\n      sample: date +%j\n    max:\n      sample: echo 365\n    min:\n      sample: echo 0\n```\n### Textbox\n![textbox](https://user-images.githubusercontent.com/6069066/59168949-192db000-8b06-11e9-900b-0e92ff494f62.png)\n```yml\ntextboxes:\n  - title: Local weather\n    rate-ms: 10000      # sampling rate, default = 1000\n    sample: curl wttr.in?0ATQF\n    border: false       # border around the item, default = true\n    color: 178          # 8-bit color number, default is white\n  - title: Docker containers stats\n    rate-ms: 500\n    sample: docker stats --no-stream --format \"table {{.Name}}\\t{{.CPUPerc}}\\t{{.MemUsage}}\\t{{.PIDs}}\"\n```\n### Asciibox\n![asciibox](https://user-images.githubusercontent.com/6069066/59169283-aa515680-8b07-11e9-8beb-716a387aed1b.png)\n```yml\nasciiboxes:\n  - title: UTC time\n    rate-ms: 500        # sampling rate, default = 1000\n    font: 3d            # font type, default = 2d\n    border: false       # border around the item, default = true    \n    color: 43           # 8-bit color number, default is white\n    sample: env TZ=UTC date +%r\n```\n\n## Bells and whistles\n\n### Triggers\nTriggers allow to perform conditional actions, like visual/sound alerts or an arbitrary shell command.\nThe following examples illustrate the concept.\n\n#### Clock gauge, which shows minute progress and announces current time at the beginning of each minute\n\n```yml\ngauges:\n  - title: MINUTE PROGRESS\n    position: [[0, 18], [80, 0]]  \n    cur:\n      sample: date +%S\n    max:\n      sample: echo 60\n    min:\n      sample: echo 0\n    triggers:\n      - title: CLOCK BELL EVERY MINUTE\n        condition: '[ $label == \"cur\" ] \u0026\u0026 [ $cur -eq 0 ] \u0026\u0026 echo 1 || echo 0'  # expects \"1\" as TRUE indicator\n        actions:\n          terminal-bell: true  # standard terminal bell, default = false\n          sound: true    # NASA quindar tone, default = false\n          visual: false  # notification with current value on top of the component area, default = false\n          script: say -v samantha `date +%I:%M%p`  # an arbitrary script, which can use $cur, $prev and $label variables\n```\n\n#### Search engine latency chart, which alerts user when latency exceeds a threshold\n\n```yml\nruncharts:\n  - title: SEARCH ENGINE RESPONSE TIME (sec)\n    rate-ms: 200\n    items:\n      - label: GOOGLE\n        sample: curl -o /dev/null -s -w '%{time_total}'  https://www.google.com\n      - label: YAHOO\n        sample: curl -o /dev/null -s -w '%{time_total}'  https://search.yahoo.com     \n    triggers:\n      - title: Latency threshold exceeded\n        condition: echo \"$prev \u003c 0.3 \u0026\u0026 $cur \u003e 0.3\" |bc -l  # expects \"1\" as TRUE indicator\n        actions:\n          terminal-bell: true  # standard terminal bell, default = false\n          sound: true   # NASA quindar tone, default = false\n          visual: true  # visual notification on top of the component area, default = false\n          script: 'say alert: ${label} latency exceeded ${cur} second' # an arbitrary script, which can use $cur, $prev and $label variables\n```\n\n### Interactive shell support\nIn addition to the `sample` command, one can specify `init` command (executed only once before sampling) and `transform` command (to post-process `sample` command output). That covers interactive shell use case, e.g. to establish connection to a database only once, and then perform polling within interactive shell session.\n\n#### Basic mode\n```yml\ntextboxes:\n  - title: MongoDB polling\n    rate-ms: 500\n    init: mongo --quiet --host=localhost test # executes only once to start the interactive session\n    sample: Date.now();                       # executes with a required rate, in scope of the interactive session\n    transform: echo result = $sample          # executes in scope of local session, $sample variable is available for transformation\n```\n\n#### PTY mode\nIn some cases interactive shell won't work, because its stdin is not a terminal. We can fool it, using PTY mode:\n```yml\ntextboxes:\n  - title: Neo4j polling\n    pty: true  # enables pseudo-terminal mode, default = false\n    init: cypher-shell -u neo4j -p pwd --format plain\n    sample: RETURN rand();\n    transform: echo \"$sample\" | tail -n 1\n  - title: Top on a remote server\n    pty: true  # enables pseudo-terminal mode, default = false\n    init: ssh -i ~/user.pem ec2-user@1.2.3.4\n    sample: top    \n```\n\n#### Multistep init\nIt is also possible to execute multiple init commands one after another, before you start sampling.\n```yml\ntextboxes:\n  - title: Java application uptime\n    multistep-init:\n      - java -jar jmxterm-1.0.0-uber.jar\n      - open host:port # or local PID\n      - bean java.lang:type=Runtime\n    sample: get Uptime\n```    \n\n### Variables\nIf the configuration file contains repeated patterns, they can be extracted into the `variables` section.\nAlso variables can be specified using `-v`/`--variable` flag on startup, and any system environment variables will also be available in the scripts.\n\n```yml\nvariables:\n    mongoconnection: mongo --quiet --host=localhost test\nbarcharts:\n  - title: MongoDB documents by status\n    items:\n      - label: IN_PROGRESS\n        init: $mongoconnection\n        sample: db.getCollection('events').find({status:'IN_PROGRESS'}).count()\n      - label: SUCCESS\n        init: $mongoconnection\n        sample: db.getCollection('events').find({status:'SUCCESS'}).count()\n      - label: FAIL\n        init: $mongoconnection\n        sample: db.getCollection('events').find({status:'FAIL'}).count()\n```\n\n### Color theme\n![light-theme](https://user-images.githubusercontent.com/6069066/59959405-994c0200-9484-11e9-856b-c4d18716e1de.png)\n```yml\ntheme: light # default = dark\nsparklines:\n  - title: CPU usage\n    sample: ps -A -o %cpu | awk '{s+=$1} END {print s}'\n```\n\n## Real-world recipes\n### Databases\nThe following are different database connection examples. Interactive shell (init script) usage is recommended to establish connection only once and then reuse it during sampling.\n\n\u003cdetails\u003e\u003csummary\u003eMySQL\u003c/summary\u003e\n\n```yml\n# prerequisite: installed mysql shell\n\nvariables:\n  mysql_connection: mysql -u root -s --database mysql --skip-column-names\nsparklines:  \n  - title: MySQL (random number example)\n    pty: true\n    init: $mysql_connection\n    sample: select rand();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003ePostgreSQL\u003c/summary\u003e\n\n```yml\n# prerequisite: installed psql shell\n\nvariables:\n  PGPASSWORD: pwd\n  postgres_connection: psql -h localhost -U postgres --no-align --tuples-only\nsparklines:\n  - title: PostgreSQL (random number example)\n    init: $postgres_connection\n    sample: select random();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eMongoDB\u003c/summary\u003e\n\n```yml\n# prerequisite: installed mongo shell\n\nvariables:\n  mongo_connection: mongo --quiet --host=localhost test\nsparklines:\n  - title: MongoDB (random number example)\n    init: $mongo_connection\n    sample: Math.random();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eNeo4j\u003c/summary\u003e\n\n```yml\n# prerequisite: installed cypher shell\n\nvariables:\n  neo4j_connection: cypher-shell -u neo4j -p pwd --format plain\nsparklines:\n  - title: Neo4j (random number example)\n    pty: true\n    init: $neo4j_connection\n    sample: RETURN rand();\n    transform: echo \"$sample\" | tail -n 1\n```\n\n\u003c/details\u003e\n\n### Kafka\n\n\u003cdetails\u003e\u003csummary\u003eKafka lag per consumer group\u003c/summary\u003e\n\n```yml\nvariables:\n  kafka_connection: $KAFKA_HOME/bin/kafka-consumer-groups --bootstrap-server localhost:9092\nruncharts:\n  - title: Kafka lag per consumer group\n    rate-ms: 5000\n    scale: 0\n    items:\n      - label: A-\u003eB\n        sample: $kafka_connection --group group_a --describe | awk 'NR\u003e1 {sum += $5} END {print sum}'\n      - label: B-\u003eC\n        sample: $kafka_connection --group group_b --describe | awk 'NR\u003e1 {sum += $5} END {print sum}'\n      - label: C-\u003eD\n        sample: $kafka_connection --group group_c --describe | awk 'NR\u003e1 {sum += $5} END {print sum}'\n```\n\n\u003c/details\u003e\n\n### Docker\n\n\u003cdetails\u003e\u003csummary\u003eDocker containers stats (CPU, MEM, O/I)\u003c/summary\u003e\n\n```yml\ntextboxes:\n  - title: Docker containers stats\n    sample: docker stats --no-stream --format \"table {{.Name}}\\t{{.CPUPerc}}\\t{{.MemPerc}}\\t{{.MemUsage}}\\t{{.NetIO}}\\t{{.BlockIO}}\\t{{.PIDs}}\"\n```\n\n\u003c/details\u003e\n\n### SSH\n\n\u003cdetails\u003e\u003csummary\u003eTOP command on a remote server\u003c/summary\u003e\n\n```yml\nvariables:\n  sshconnection: ssh -i ~/my-key-pair.pem ec2-user@1.2.3.4\ntextboxes:\n  - title: SSH\n    pty: true\n    init: $sshconnection\n    sample: top\n```\n\n\u003c/details\u003e\n\n### JMX\n\n\u003cdetails\u003e\u003csummary\u003eJava application uptime example\u003c/summary\u003e\n\n```yml\n# prerequisite: download [jmxterm jar file](https://docs.cyclopsgroup.org/jmxterm)\n\ntextboxes:\n  - title: Java application uptime\n    multistep-init:\n      - java -jar jmxterm-1.0.0-uber.jar\n      - open host:port # or local PID\n      - bean java.lang:type=Runtime\n    sample: get Uptime\n    transform: echo $sample | tr -dc '0-9' | awk '{printf \"%.1f min\", $1/1000/60}'\n```\n\n\u003c/details\u003e\n","funding_links":["http://sampler.dev/sponsor"],"categories":["Popular","Go","Misc","Command Line","\u003ca name=\"monitoring\"\u003e\u003c/a\u003emonitoring","📦 Legacy \u0026 Inactive Projects","Go (531)","HarmonyOS","终端","Tools","visualization","Packages","命令行工具","\u003ca name=\"data-management\"\u003e\u003c/a\u003eData management","\u003ca id=\"1d9dec1320a5d774dc8e0e7604edfcd3\"\u003e\u003c/a\u003e工具-新添加的"],"sub_categories":["Terminal Dashboard","Windows Manager","网络服务_其他","Go","CLI Tools","\u003ca id=\"8f1b9c5c2737493524809684b934d49a\"\u003e\u003c/a\u003e文章\u0026\u0026视频"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqshq%2Fsampler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsqshq%2Fsampler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqshq%2Fsampler/lists"}