chmonitor · ClickHouse monitoring dashboard and CLI

0 people used it yesterday · 0 this week · 0 this month.

2 users and 18 events so far today, live. 5.4k events in the last 365 days.

Daily users

1k users1k events
Daily users and events, Oct 20 to Oct 19. Peak 1,033 users on Jul 3; 5,445 events in total.
Oct 20Oct 19
The line is daily users; the bars are events on their own scale. 365 days. Yesterday closes at 00:10 UTC; today refreshes every few minutes.

Breakdown

EventsUser-daysEvents
ping4.8k4.8k
app_loaded0265
queries_viewed0210
health_viewed0168
ai_query_sent050
cluster_connected01
VersionsUser-daysEvents
0.2.1511
Operating systemsUser-daysEvents
macos311311
linux217217
windows118118
unknown3131
android1111
ios99
CountriesUser-daysEvents
UNKNOWN198198
IN9494
SG6161
VN5252
US4444
DE3535
ZA3232
KZ3131
RU2020
KE1414
ID1313
ES1212
MX1111
RS88
CN66
RO66
NL55
TH55
GB44
TR44
prop · ch_flavorUser-daysEvents
unknown4941.2k
oss200201
altinity33
prop · ch_versionUser-daysEvents
26.36161
26.43030
25.112424
25.81717
26.51717
26.71212
25.31111
24.377
24.1066
24.844
26.644
25.1022
24.622
25.1222
26.222
26.812
99.911
23.811
25.611
prop · deploy_targetUser-daysEvents
unknown4.1k4.2k
docker401706
cf228483
dev121

Integrate

Ingest URL https://telemetry.anyr.workers.dev/chmonitor, OTLP endpoint https://telemetry.anyr.workers.dev/chmonitor/v1. Pick a client below, or let an agent do it.

curl -fsS -m 1 -X POST https://telemetry.anyr.workers.dev/chmonitor \
  -H 'content-type: application/json' \
  -d '{"event":"ping","id":"<random-install-id>","version":"1.0.0","os":"linux","arch":"x64"}'
# Anonymous install ping. Put it near the end of install.sh. No id: counts daily users only.
# An env var is "set" for any value except empty, 0 or false.
truthy() { case $(printf %s "$1" | tr '[:upper:]' '[:lower:]') in ""|0|false) return 1 ;; *) return 0 ;; esac; }
if ! truthy "${DO_NOT_TRACK-}" && ! truthy "${CHMONITOR_TELEMETRY_DISABLED-}" \
  && { ! truthy "${CI-}" || truthy "${CHMONITOR_TELEMETRY_CI-}"; }; then
  os=$(uname -s | tr '[:upper:]' '[:lower:]')
  arch=$(uname -m | tr '[:upper:]' '[:lower:]')
  if truthy "${CI-}"; then ci=true; else ci=false; fi
  body=$(printf '{"event":"install","os":"%s","arch":"%s","ci":%s}' "$os" "$arch" "$ci")
  if truthy "${CHMONITOR_TELEMETRY_DEBUG-}"; then
    echo "[telemetry] $body" >&2
  else
    (curl -fsS -m 1 -X POST -H 'content-type: application/json' -d "$body" https://telemetry.anyr.workers.dev/chmonitor >/dev/null 2>&1 &)
  fi
fi
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { homedir } from "node:os";
import { dirname, join } from "node:path";

const ENDPOINT = "https://telemetry.anyr.workers.dev/chmonitor";
const VERSION = "0.0.0"; // set from your package metadata
const env = process.env;

// "Set" means any value except empty, 0 or false.
const truthy = (v?: string): boolean => !!v && !["0", "false"].includes(v.toLowerCase());

function enabled(): boolean {
	if (truthy(env.DO_NOT_TRACK) || truthy(env.CHMONITOR_TELEMETRY_DISABLED)) return false;
	return !truthy(env.CI) || truthy(env.CHMONITOR_TELEMETRY_CI);
}

// Returns undefined when the event must be skipped: the id cannot be saved (fail closed).
// Debug mode never writes. It reads the id, or shows a placeholder.
function installId(debug: boolean): string | undefined {
	const file = join(env.XDG_CONFIG_HOME || join(homedir(), ".config"), "chmonitor", "telemetry-id");
	try {
		const id = readFileSync(file, "utf8").trim();
		if (id) return id;
	} catch {}
	if (debug) return "new-install-id";
	try {
		const id = crypto.randomUUID();
		mkdirSync(dirname(file), { recursive: true });
		writeFileSync(file, id);
		console.error("chmonitor collects anonymous usage data. Opt out: CHMONITOR_TELEMETRY_DISABLED=1 or DO_NOT_TRACK=1. Details: https://telemetry.anyr.workers.dev/chmonitor"); // stderr suits a CLI. A daemon or plugin should use its log channel.
		return id;
	} catch {
		return undefined;
	}
}

export function track(event: string, props: Record<string, string | number | boolean> = {}): void {
	try {
		if (!enabled()) return;
		const debug = truthy(env.CHMONITOR_TELEMETRY_DEBUG);
		const id = installId(debug);
		if (!id) return;
		const body = JSON.stringify({
			event,
			id,
			version: VERSION,
			os: process.platform,
			arch: process.arch,
			ci: truthy(env.CI),
			props,
		});
		if (debug) {
			console.error("[telemetry]", body);
			return;
		}
		fetch(ENDPOINT, {
			method: "POST",
			headers: { "content-type": "application/json" },
			body,
			signal: AbortSignal.timeout(1000),
		}).catch(() => {});
	} catch {}
}
// Cargo.toml: ureq = "2"
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hasher};
use std::path::PathBuf;
use std::{env, fs, thread, time::Duration};

const ENDPOINT: &str = "https://telemetry.anyr.workers.dev/chmonitor";

/// "Set" means any value except empty, 0 or false.
fn truthy(key: &str) -> bool {
    env::var(key).map_or(false, |v| !matches!(v.to_ascii_lowercase().as_str(), "" | "0" | "false"))
}

fn enabled() -> bool {
    if truthy("DO_NOT_TRACK") || truthy("CHMONITOR_TELEMETRY_DISABLED") {
        return false;
    }
    !truthy("CI") || truthy("CHMONITOR_TELEMETRY_CI")
}

fn random_id() -> String {
    // 128 random bits from the std hasher seed, no extra crate needed.
    (0..2).map(|_| format!("{:016x}", RandomState::new().build_hasher().finish())).collect()
}

/// None means skip the event: the id cannot be saved (fail closed).
/// Debug mode never writes. It reads the id, or shows a placeholder.
fn install_id(debug: bool) -> Option<String> {
    let file = env::var_os("XDG_CONFIG_HOME")
        .map(PathBuf::from)
        .or_else(|| env::var_os("HOME").map(|h| PathBuf::from(h).join(".config")))
        .or_else(|| env::var_os("APPDATA").map(PathBuf::from))?
        .join("chmonitor")
        .join("telemetry-id");
    if let Ok(id) = fs::read_to_string(&file) {
        if !id.trim().is_empty() {
            return Some(id.trim().to_string());
        }
    }
    if debug {
        return Some("new-install-id".to_string());
    }
    let id = random_id();
    fs::create_dir_all(file.parent()?).ok()?;
    fs::write(&file, &id).ok()?;
    eprintln!("chmonitor collects anonymous usage data. Opt out: CHMONITOR_TELEMETRY_DISABLED=1 or DO_NOT_TRACK=1. Details: https://telemetry.anyr.workers.dev/chmonitor"); // stderr suits a CLI. A daemon or plugin should use its log channel.
    Some(id)
}

/// Fire and forget. Event names must be plain literals. A short-lived CLI can
/// join the returned handle before exit: the request is bounded by the 1 s timeout.
pub fn track(event: &str) -> Option<thread::JoinHandle<()>> {
    if !enabled() {
        return None;
    }
    let debug = truthy("CHMONITOR_TELEMETRY_DEBUG");
    let id = install_id(debug)?;
    let body = format!(
        r#"{{"event":"{event}","id":"{id}","version":"{}","os":"{}","arch":"{}","ci":{}}}"#,
        env!("CARGO_PKG_VERSION"),
        env::consts::OS,
        env::consts::ARCH,
        truthy("CI")
    );
    if debug {
        eprintln!("[telemetry] {body}");
        return None;
    }
    Some(thread::spawn(move || {
        let _ = ureq::post(ENDPOINT)
            .timeout(Duration::from_secs(1))
            .set("content-type", "application/json")
            .send_string(&body);
    }))
}
package telemetry

import (
	"bytes"
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

const endpoint = "https://telemetry.anyr.workers.dev/chmonitor"
const version = "0.0.0" // set from your build, for example with -ldflags

// truthy: "set" means any value except empty, 0 or false.
func truthy(key string) bool {
	switch strings.ToLower(os.Getenv(key)) {
	case "", "0", "false":
		return false
	}
	return true
}

func enabled() bool {
	if truthy("DO_NOT_TRACK") || truthy("CHMONITOR_TELEMETRY_DISABLED") {
		return false
	}
	return !truthy("CI") || truthy("CHMONITOR_TELEMETRY_CI")
}

// installID returns "" when the event must be skipped: the id cannot be saved (fail closed).
// Debug mode never writes. It reads the id, or shows a placeholder.
func installID(debug bool) string {
	dir, err := os.UserConfigDir()
	if err != nil {
		return ""
	}
	file := filepath.Join(dir, "chmonitor", "telemetry-id")
	if b, err := os.ReadFile(file); err == nil {
		if id := strings.TrimSpace(string(b)); id != "" {
			return id
		}
	}
	if debug {
		return "new-install-id"
	}
	buf := make([]byte, 16)
	if _, err := rand.Read(buf); err != nil {
		return ""
	}
	id := hex.EncodeToString(buf)
	if os.MkdirAll(filepath.Dir(file), 0o755) != nil || os.WriteFile(file, []byte(id), 0o600) != nil {
		return ""
	}
	fmt.Fprintln(os.Stderr, "chmonitor collects anonymous usage data. Opt out: CHMONITOR_TELEMETRY_DISABLED=1 or DO_NOT_TRACK=1. Details: https://telemetry.anyr.workers.dev/chmonitor") // stderr suits a CLI. A daemon or plugin should use its log channel.
	return id
}

// Track sends one event in the background. The channel closes when the attempt
// ends (at most 1 s), so a short-lived CLI can wait on it before exit.
func Track(event string, props map[string]any) <-chan struct{} {
	done := make(chan struct{})
	if !enabled() {
		close(done)
		return done
	}
	debug := truthy("CHMONITOR_TELEMETRY_DEBUG")
	id := installID(debug)
	if id == "" {
		close(done)
		return done
	}
	payload := map[string]any{
		"event":   event,
		"id":      id,
		"version": version,
		"os":      runtime.GOOS,
		"arch":    runtime.GOARCH,
		"ci":      truthy("CI"),
	}
	if len(props) > 0 {
		payload["props"] = props
	}
	body, err := json.Marshal(payload)
	if err != nil {
		close(done)
		return done
	}
	if debug {
		fmt.Fprintf(os.Stderr, "[telemetry] %s\n", body)
		close(done)
		return done
	}
	go func() {
		defer close(done)
		client := http.Client{Timeout: time.Second}
		if resp, err := client.Post(endpoint, "application/json", bytes.NewReader(body)); err == nil {
			resp.Body.Close()
		}
	}()
	return done
}
import json
import os
import platform
import sys
import threading
import urllib.request
import uuid
from pathlib import Path

ENDPOINT = "https://telemetry.anyr.workers.dev/chmonitor"
VERSION = "0.0.0"  # set from your package metadata


def _truthy(key):
    # "Set" means any value except empty, 0 or false.
    return os.environ.get(key, "").lower() not in ("", "0", "false")


def _enabled():
    if _truthy("DO_NOT_TRACK") or _truthy("CHMONITOR_TELEMETRY_DISABLED"):
        return False
    return not _truthy("CI") or _truthy("CHMONITOR_TELEMETRY_CI")


def _install_id(debug):
    # Returns None when the event must be skipped: the id cannot be saved (fail closed).
    # Debug mode never writes. It reads the id, or shows a placeholder.
    try:
        base = Path(os.environ.get("XDG_CONFIG_HOME") or Path.home() / ".config")
        file = base / "chmonitor" / "telemetry-id"
        try:
            found = file.read_text().strip()
            if found:
                return found
        except OSError:
            pass
        if debug:
            return "new-install-id"
        install_id = uuid.uuid4().hex
        file.parent.mkdir(parents=True, exist_ok=True)
        file.write_text(install_id)
        # stderr suits a CLI. A daemon or plugin should use its log channel.
        print("chmonitor collects anonymous usage data. Opt out: CHMONITOR_TELEMETRY_DISABLED=1 or DO_NOT_TRACK=1. Details: https://telemetry.anyr.workers.dev/chmonitor", file=sys.stderr)
        return install_id
    except Exception:
        return None


def track(event, **props):
    try:
        if not _enabled():
            return
        debug = _truthy("CHMONITOR_TELEMETRY_DEBUG")
        install_id = _install_id(debug)
        if not install_id:
            return
        body = {
            "event": event,
            "id": install_id,
            "version": VERSION,
            "os": platform.system().lower(),
            "arch": platform.machine().lower(),
            "ci": _truthy("CI"),
        }
        if props:
            body["props"] = props
        if debug:
            print("[telemetry]", json.dumps(body), file=sys.stderr)
            return

        def send():
            try:
                req = urllib.request.Request(
                    ENDPOINT,
                    json.dumps(body).encode(),
                    {"content-type": "application/json"},
                )
                urllib.request.urlopen(req, timeout=1).close()
            except Exception:
                pass

        # Daemon thread: never delays exit. A very short script may exit before it sends.
        threading.Thread(target=send, daemon=True).start()
    except Exception:
        pass
const ENDPOINT = "https://telemetry.anyr.workers.dev/chmonitor";
const ID_KEY = "chmonitor-telemetry-id";
const OFF_KEY = "chmonitor-telemetry-disabled";

export function track(event, props) {
	try {
		if (navigator.doNotTrack === "1" || navigator.globalPrivacyControl === true) return;
		if (localStorage.getItem(OFF_KEY) === "1") return;
		let id = localStorage.getItem(ID_KEY);
		if (!id) {
			id = crypto.randomUUID();
			localStorage.setItem(ID_KEY, id);
		}
		const body = JSON.stringify({ event, id, props });
		navigator.sendBeacon(ENDPOINT, new Blob([body], { type: "application/json" }));
	} catch {}
}

// track("ping"); // once per page load or once per day. Never send URLs, paths or user input.
export OTEL_EXPORTER_OTLP_ENDPOINT=https://telemetry.anyr.workers.dev/chmonitor
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json
export OTEL_SERVICE_NAME=chmonitor
# The install id keeps users distinct. Generate it once and persist it.
export OTEL_RESOURCE_ATTRIBUTES=service.instance.id=<random-install-id>,service.version=1.0.0

With an agent

Copy this prompt into Claude Code, Codex or Cursor. It points the agent at the project playbook.

Add anonymous usage telemetry to this repo. Follow https://telemetry.anyr.workers.dev/chmonitor/install.md exactly. Respect DO_NOT_TRACK, add an opt-out env var and a Telemetry section to the README, never send PII, never block the main path.