Features · Monitoring

Live logs and site monitoring.

Bothy is a native Mac app for local PHP development. As well as serving your sites, it watches them: requests and errors per site, response times, PHP-FPM status and live logs, so you find out a page is throwing 500s or getting slow before you go looking.

Why monitor a local environment at all

Local development usually has no observability: something is slow or broken, so you open a terminal, remember where the log file lives this week, and tail -f it. That works for one site. With a dozen sites, several PHP versions and a couple of database servers, the first question is often simply which thing is misbehaving.

Bothy already sits in the request path (Caddy serves every site, php-fpm runs every pool), so it has the data. It puts it on screen rather than leaving it in files.

The dashboard: the whole server at a glance

The dashboard shows which services are running, requests and 5xx errors per hour across all sites, and memory per service sampled every second. The header shows the domain, PHP and MySQL versions. If a service has stopped or a site has started returning errors, it's visible here before you've opened a browser.

  • Live memory graphs per service
  • Requests and 5xx per hour
  • Stop All / Start All
Bothy dashboard screen

Per-site stats and a traffic chart

Each site's page shows its own requests per hour, 4xx and 5xx counts, p95 response time and FPM status, with a traffic chart for the last hour and tabs for routing, environment, database, git and logs.

  • Per-site stats from Caddy access logs
  • PHP-FPM status for the site's own pool
  • Database size from information_schema
Bothy site screen

Where the numbers come from

  • Requests, 4xx/5xx and p95 come from Caddy's JSON access log. Every request is a structured line with host, status and duration, so per-site counts and latency are calculated from real traffic rather than sampled.
  • PHP stats come from each site's php-fpm status endpoint. That's only possible because every site has its own pool (see multiple PHP versions); with one shared pool, you couldn't tell which site was using the workers.
  • Database sizes come from MySQL's information_schema, for the databases assigned to the site.

Why p95 and not the average

An average response time hides the slow requests you actually care about: ninety fast cached pages and ten three-second ones average out to something that looks fine. The 95th percentile is the time that 95% of requests beat, so it moves when a real share of requests get slow: an N+1 query on a listing page, a missing index after an import, a plugin making a remote call on every load.

Live logs: access, PHP and slow

Each site's Logs tab follows its logs live, like tail -f, with a filter field and a pause button for when something scrolls past too fast. There are three kinds:

  • access: every request Caddy served for the site, with status and timing.
  • php: PHP errors, warnings and notices from the site's pool.
  • slow: php-fpm's slow log, which records a stack trace for requests that run past a time limit. It shows where a slow request was spending its time, not just that it was slow.

Service logs (Caddy, dnsmasq, PHP, MySQL) are available in the app too, which is usually where to look when a service won't start.

The same from the terminal

For scripts, for agents, or for when you just live in a terminal:

bothy stats                 # CPU/memory per service
bothy stats shop            # req/h, 4xx/5xx, p95, FPM, db size
bothy stats shop --json     # for scripts and agents
bothy logs shop --kind php  # access | php | slow
bothy logs caddy            # any service log

Details in the stats and logs docs.

Doctor: a health report that changes nothing

bothy doctor checks the Homebrew prefix, whether Caddy and dnsmasq are installed, the /etc/resolver/test file, installed PHP and database versions, and which services are running. For anything missing it names the command that fixes it, but it never runs anything itself, so it's always safe to run. bothy doctor --json gives the same report in machine-readable form, and it's the first thing to include if you ask for support.

Letting an AI assistant read the logs

Monitoring data is most useful when whoever is fixing the bug can see it. Through Bothy's MCP server, assistants get bothy_site_stats, bothy_site_logs, bothy_stats and bothy_doctor, so you can ask "show me the last 5xx errors for shop" and the assistant reads the actual PHP log instead of guessing from the code. See Bothy's MCP server.

Questions

Where does Bothy get per-site request stats from?

From Caddy's JSON access log. Requests per hour, 4xx/5xx counts and p95 response time are calculated per site from it.

What is the PHP slow log?

A php-fpm feature that writes a stack trace for requests that run longer than a set time. Follow it with bothy logs shop --kind slow or in the site's Logs tab.

Can I filter the live logs?

Yes. The Logs tab has a filter field and a pause button.

Does bothy doctor fix problems?

No. It's read-only: it reports what's missing and names the command that fixes it, but never changes anything itself.

Can I get stats as JSON?

Yes. bothy stats shop --json and bothy doctor --json, like every bothy command, support --json.

Get Bothy for $69.
One payment for every 1.x release. Version 2 will be a separate purchase.
Buy now