@mui/x-telemetry
Version:
MUI X Telemetry.
71 lines (66 loc) • 2.51 kB
JavaScript
import fs from 'fs';
import isDocker from 'is-docker';
import os from 'os';
import { sha256 } from "./hash.mjs";
// Q: Why does MUI need a machine ID?
// A:
// MUI's telemetry uses a hashed machine ID to approximate unique developer counts.
// Without a stable machine ID, every session in containers or CI creates a new
// persona, inflating seat counts.
//
// Fallback chain:
// 1. node-machine-id — most reliable, uses platform-specific APIs
// (IOPlatformUUID on macOS, MachineGuid on Windows, /var/lib/dbus/machine-id on Linux)
// 2. /etc/machine-id — present in most Linux distros and containers,
// stable across container restarts (only changes on image rebuild)
// 3. /var/lib/dbus/machine-id — alternative Linux path, some distros
// use this instead of /etc/machine-id
// 4. os.hostname() — used on macOS/Windows where hostnames are user-set and stable,
// and in Docker where the hostname is the container ID (random but unique per container,
// stable for the container's lifetime). Skipped on non-Docker Linux because hostnames
// are often generic defaults (e.g., "localhost", "ubuntu") which would conflate
// different machines into the same identity.
export default async function getAnonymousMachineId() {
// 1. Try node-machine-id (platform-specific, most reliable)
try {
const nodeMachineId = await import('node-machine-id');
const id = await nodeMachineId.machineId(true);
if (id) {
return sha256(id);
}
} catch {
// Not available (e.g., sandboxed env, missing native deps)
}
// 2. Try /etc/machine-id (Linux, most containers)
try {
const id = fs.readFileSync('/etc/machine-id', 'utf-8').trim();
if (id) {
return sha256(id);
}
} catch {
// File doesn't exist (macOS, Windows, or minimal container image)
}
// 3. Try /var/lib/dbus/machine-id (alternative Linux path)
try {
const id = fs.readFileSync('/var/lib/dbus/machine-id', 'utf-8').trim();
if (id) {
return sha256(id);
}
} catch {
// File doesn't exist
}
// 4. Try hostname — only on macOS/Windows where it's user-set and stable.
// On Linux, container runtimes assign random hostnames per run,
// which would generate a different hash each session and inflate counts.
if (process.platform !== 'linux' || isDocker()) {
try {
const hostname = os.hostname();
if (hostname) {
return sha256(hostname);
}
} catch {
// os.hostname() failed
}
}
return null;
}