BoxLang 🚀 A New JVM Dynamic Language Learn More...
BxLens is the free debug bar and ops console for BoxLang. Find the slow query, the N+1 loop, the failing call, the starved thread and the runaway AI agent in seconds, with built in AI observability for BoxLang AI. Everything stays on your server: no cloud, no agent to install, no data sent anywhere.
Documentation | Walkthroughs | Free and BoxLang+ | BoxLang+ plans
Watch the trailer on bxlens.boxlang.io.
install-bx-module bx-lens # or: box install bx-lens
Turn on the bar in boxlang.json, restart, and open any
page from the same machine:
{ "modules": { "bxLens": { "settings": { "bar": { "enabled": true } } } } }
A strip appears at the bottom of every HTML page. Click it to open the timeline of the request you just made. BxLens is off by default and answers only to the local machine until you say otherwise.
boxlang.json
Everything lives under modules.bxLens.settings. Every
setting has a default, so add only what you need. The password for the
console can also be set in the console itself the first time you open it.
The bar and the console
{
"modules": {
"bxLens": {
"settings": {
"bar": { "enabled": true },
"console": { "enabled": true }
}
}
}
}
The console is at /~bxlens/index.bxm. Use
"password":
"${env.BXLENS_PASSWORD}" or a bxsecret:
value (boxlang generatesecret "your password")
to set it from config. Both the bar and the console answer to the
local machine only until you change access.
Turn on AI observability
"collectors": { "aiobs": { "enabled": true } }
Optional: "content": "preview" keeps
a redacted preview of prompts and answers, "attach":
false stops BxLens from attaching its recorder to your agents,
and "failurePct",
"rateLimits" and
"slowFactor" tune what needs attention.
Turn on Lensy, the Box Agent (BoxLang+; a local Ollama model by default, or OpenAI, Claude, Gemini and more)
"ai": { "enabled": true, "provider": "ollama", "model": "llama3.2", "baseUrl": "http://localhost:11434" }
Set the API key for a hosted provider in the console (Settings, Security) and it is kept encrypted. It never goes in the file.
Watch bx-mail
"collectors": { "mail": { "enabled": true } }
Many servers in one console (BoxLang+). The same file on each server, with its own name:
"store": { "dir": "/mnt/shared/lens-store" },
"secrets": { "dir": "/mnt/shared/lens-secrets" },
"server": { "name": "web-a" }
Every setting is described in the Configuration reference, with a guide for several servers and running in production.
lensMessage(),
lensMeasure(), lensDump() and
lensPanel() add messages, timers and panels from your code.orders = lensMeasure( "load orders", () => orderService.list() );
lensPanel( "orm", "ORM" ).columns( [ "Entity", "ms" ] ).rows( rows ).badge( rows.len(), "none" );
Live requests and what is running right now, errors grouped by cause, p50, p95 and p99 reports, query and HTTP statistics, datasources with a connection test, caches, logs with a live tail, executors, scheduled tasks, heap and threads. Light and dark, keyboard friendly, and air gapped: the console makes no calls to other sites.
The first time you open the console it asks you to set the admin password right there, and stores it hashed. Secrets such as API keys live in an encrypted Secret Store, never in plain text.
Ask in plain words: what got slow after the deploy? Lensy reads the same data you see, explains it, and can act on your server after you approve each step. It runs on BoxLang AI and can use your own MCP servers.
BxLens is the LLM and AI agent observability for
BoxLang. It traces every BoxLang AI (bx-ai) run with no
code change: agents, tool calls, MCP servers, models, tokens,
estimated cost, rate limits and errors, with a step by step
trace of each run, how each agent is composed, and a failing tool
called out by name.
The full pages are part of BoxLang+ (the 14 day trial covers them). Free shows the run counters for the last hour.
Everything is collected in memory by Java code inside your server. Passwords and keys are redacted from what you see, the console has an admin and a read only role, an audit log, and a read only mode. A server with no console password stays locked until you set one. See Security and the privacy notice.
BxLens is free for one server, in production too. BoxLang+ lifts the limits and adds history, actions, many servers, alerts and AI. Registering a server for the console is free and starts a 14 day trial of BoxLang+.
| Free | BoxLang+ | |
|---|---|---|
| The bar, every tab | Yes | Yes, plus request cost |
| Console: requests, executors, datasources, logs, environment | Yes (free registration) | Yes |
| Errors and reports | Last hour, in memory | Saved to disk, up to 15 days |
| Task, cache and heap dump actions, log download | No | Yes |
| Alerts, reports and channels | No | Yes |
| Lensy and AI observability | No | Yes |
| Many servers in one console | No | Yes |
Compare everything in Free and BoxLang+.
BoxLang 1.19 or newer, Java 21, and MiniServer, CommandBox or a servlet container.
Everything is at bxlens.boxlang.io: Getting started, the console, configuration, the BIFs, extending BxLens and running it in production.
Bug reports and ideas are welcome at BLMODULES.
BxLens is a product of Ortus Solutions, Corp. License terms apply, see the BoxLang+ plans page and Licensing. Phosphor Icons are MIT licensed.
BoxLang is a professional open-source project and it is completely funded by the community and Ortus Solutions, Corp. Ortus Patreons get many benefits like a cfcasts account, a FORGEBOX Pro account and so much more. If you are interested in becoming a sponsor, please visit our patronage page: https://patreon.com/ortussolutions
"I am the way, and the truth, and the life; no one comes to the Father, but by me (JESUS)" Jn 14:1-12
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
GET settings gives each setting an area, section, adv, unit, title, hint (and option, subsection, pair where they apply) and the list of areas.src/main/bx/console and joined at build time; the script and stylesheet are minified (about 26 percent and 14 percent smaller). Pages are built when their tab opens, so the console starts with a fraction of the DOM, and a thin neon bar runs while a page loads. The debug bar is unchanged. The build needs node for the minifier (-PskipMinify=true skips it).GET overview/fleet and GET overview/reports, see Overview.server.group and server.kind (environment LENS_SERVER_GROUP and LENS_SERVER_KIND). The fleet is sorted and filtered by group. Each server has an icon for what it runs in (a host, Docker, Kubernetes, Podman, LXC, AWS Lambda, ECS, Cloud Run, Azure; Docker Swarm is set by hand), and shows its BoxLang and Java version, with the servers that differ marked. The identity of every server, in instance.json and the server block of each snapshot, now carries group, kind, kindLabel, icon, ephemeral, kindDetail, boxlang, java and bxlens.server.forget).fleet.heapWarn, fleet.heapCrit, fleet.cpuWarn, fleet.cpuCrit, fleet.errorWarn, fleet.silentSec and fleet.goneMin, with the volume limits volumes.warnPct and volumes.critPct, in a Fleet card in Settings. A warn value at or above its critical value is refused.reports.json) now carries the latency counts of its URLs, so the slowest route of a fleet has a real p95.The version badge no longer reads the console state before it is loaded.
The BxLens version is shown as a badge in the console header and next to the title of the Settings page (for example v1.0.0-snapshot). The hover text has the full version with the build number. It comes from the module version that the build writes, so there is nothing to set.
Threads (JVM > Threads) show who blocks whom (blockedBy, waitingOn, held locks, daemon, CPU use now from a bounded sampler, a stack key), blocked chains under their root holder, groups of threads with the same stack, a pool summary with busy percent, and up to five in-memory snapshots to compare for likely stuck threads (POST threads/snapshot, GET threads/snapshots, GET threads/compare). The JVM page also gives attention (from the findings, which stay) and threads.pools.
System is now the machine under BoxLang: type (physical, virtual machine, container) with the cloud and instance type from the DMI texts, operating system, kernel, CPU model and count, memory and swap, container and Kubernetes names, container CPU and memory limits (cgroup v1 and v2), machine and BoxLang uptime, live CPU, load, memory, swap, disk I/O, network, open files and CPU throttling, and 15 minutes of history from a small bounded sampler. What an operating system cannot report is null and listed in unsupported. No external process is started. The old system keys stay.
System storage shows the folders that matter (logs, the BxLens store, the BoxLang home, temp and the working directory) with their volume and status, and every other mount under "other", with kernel and in-memory file systems listed there only.
Environment has highlights (runtime, container, Java, heap max, time zone), one list of variables, JVM arguments and system properties with a source, a hidden flag and a JDK noise flag per row, and counts. The older keys stay for the diagnostic bundle.
One runtime detector (MiniServer, CommandBox, servlet container, command line) shared by the System, Environment and Web server pages.
System detail for the tabs CPU, Memory, Disks, Network and Processes: per core CPU with frequency, temperature, context switches and interrupts, memory with cache, available, swap in and out and page faults, disks (kind, mounts, busy, read and write, queue), network interfaces (speed, state, in, out, errors, drops), TCP counts and retransmissions, DNS servers and gateway, the top 20 processes by CPU and by memory (names only, never a command line; open files and disk I/O where the system allows), one hour of history, and a shared "Needs attention" list (full locations, load, low memory, swapping, container throttling, a pinned core, a hot process, a saturated disk, interface errors, TIME_WAIT). Linux reads /proc and /sys; macOS and Windows use the bundled OSHI library through one bridge class, restricted to calls that start no external process. What a system cannot give is null and listed in unsupported. The health snapshot keeps the old keys, the attention list and 15 minutes of history, without the process list and the per core readings.
First Release
MCP rate limits in AI observability (needs bx-ai 3.7 or later on the hosted servers). The MCP page and the page of each hosted server show the rate limit: a Rate limited tile and column, a Rate limit card (limits, blocked, store errors, history kept, trusted proxies), Top consumers for today, 7 days, 30 days and all time, a sample of recent hits, and hints. Clients are an IP or a short hash, never a key.
An admin can pause or resume a hosted MCP server, turn its rate limit off or on, reset the counters and clear the stats from its page (BoxLang+, refused when the console is read only, audited as ai.mcp.host).
Two alert rules, MCP rate limited and MCP rate limiter failing (17 rules now), that can be switched on and off alone. The AI rule no longer sends those items. New setting collectors.aiobs.mcpRateLimited (30 blocked calls in 10 minutes).
The daily, weekly and monthly reports have an MCP rate limits section: calls and blocked calls per MCP server and the top clients.
Free gets a fourth counter, MCP calls blocked, and a locked preview.
JVM page (Runtime, after System): heap and every memory pool, garbage collection from a bounded ring of the last 100 collections with cause notes, time in GC, allocation rate, threads by state, classes and JIT, buffers, open files, JVM flags with plain suggestions, a "Needs a look" box and a 15 minute history. Threads moved into it as a tab. New route jvm, collector jvm, health snapshot part jvm, and jvm.json in the diagnostic bundle.
Web server page (Runtime, admin only): the runtime (MiniServer, CommandBox or a servlet container), listeners, workers, request counters, findings and a 15 minute history, read only from what the server reports. collectors.webserver.enabled, route webserver, also in the health snapshot for other servers. See docs/reference/web-server-data.md.
$
box install bx-lens