ray-dbg
Rust client library for the Ray debugging app.
[!Warning] with default features (
debug-macros), all Ray macros are disabled in non-debug builds. In release builds they return a disabled handle and send nothing. If you want Ray output in release, disable thedebug-macrosfeature or constructRaymanually with an enabledRayConfig.
Quickstart
Add the crate (crates.io, path for this workspace, or git):
[]
= { = "0.1", = "ray-dbg" }
# or
= { = "crates/ray", = "ray-dbg" }
# or
= { = "https://github.com/bnomei/ray-dbg", = "ray-dbg" }
The published package name is ray-dbg, but the crate remains ray, so you can
use ray::... as usual.
Send a message (fluent chaining is the intended style):
use ray;
Learning path (Rust)
This sequence mirrors the Ray PHP usage guide and keeps the learning curve gentle. Start at step 1 and stop when you've reached what you need.
ray!() returns a Ray handle. ray!(value, ...) logs and returns the same handle so
you can keep chaining. For Debug-only types, use ray!().raw(&value).
1. Send values to Ray
use ray;
use Serialize;
2. Multiple arguments
use ray;
3. See the caller of a function
use ray;
Enable the origin-backtrace feature to capture full stacks; otherwise Ray gets the
callsite frame.
4. Pausing execution (stub)
pause() is not supported in ray-dbg for parity with PHP Ray; it does not block, wait
for input, or throw.
use ray;
5. Halting the process
Use die() to terminate the process. rd! is the macro alias for
ray!(...).die().
use ;
die/rd! only terminate the process when Ray is enabled (e.g. debug builds with
default macros).
6. Counting execution times
count() increments a counter for the current callsite and updates a single Ray
entry each time. Use count_named() to reuse the same counter across callsites,
and counter_value() to read it back (named counters only).
use ray;
Counters are process-global (the name or callsite fingerprint is the key), so pick unique names when you want isolated counters.
7. Measuring performance and memory usage
use ray;
use thread;
use Duration;
Memory usage is best-effort by platform and may be reported as 0 when unavailable.
The Rust API does not accept a callable for measure; call it before/after the
work you want to time.
8. Display the class name of an object
use ray;
9. Displaying private properties and methods (not supported)
invade() is not implemented in ray-dbg and is not planned (Rust does not expose
private access). See the PHP vanilla compatibility section for parity notes.
10. Updating displayed items
use ray;
use thread;
use Duration;
11. Conditionally showing items
PHP Ray uses showIf. In Rust, use when to decide whether to send at all:
use ray;
12. Conditionally sending items to Ray
PHP Ray has an if() chain; ray-dbg only supports the callback style via when.
If you want to gate an entire chain, use if in Rust or wrap the chain in when.
use ray;
13. Removing items
use ray;
use thread;
use Duration;
14. Returning items
use ray;
15. Showing Rust info (phpinfo alias)
PHP Ray exposes phpinfo(). The Rust version renders a compact HTML table with
runtime and build metadata (aliases: phpinfo*).
use ray;
16. Displaying exceptions
use ray;
17. Callables and handling exceptions
catch accepts a callable that returns a Result. On error, it logs the error
via exception and keeps execution going.
use ray;
18. Showing raw values
use ray;
To always send raw values, set RayConfig.always_send_raw_values or
RAY_ALWAYS_SEND_RAW_VALUES=true.
19. Creating a new screen
use ray;
20. Clearing everything including history
use ray;
21. Showing and hiding the app
use ray;
22. Enabling and disabling Ray
use ray;
23. Displaying a notification
use ray;
24. Shooting confetti
use ray;
25. Putting it together: Ray app workflow
use ray;
use Serialize;
Additional helpers (Rust)
Limiting output (once/limit)
Use limit(n) to allow only n payloads from a callsite. once() is shorthand
for limit(1). once_send() sends a value immediately once, and ray_once! is
the macro variant.
use ;
Rate limiting
rate_limiter() exposes a global limiter for the current client. When the limit
is reached, Ray shows a single "Rate limit" entry and drops further payloads
until you clear() or relax the limit.
use ray;
Display timestamps with carbon (UTC)
We keep the carbon name for parity with the PHP Ray API; this does not use the PHP Carbon
library and simply formats Rust SystemTime values in UTC.
use ray;
use SystemTime;
Custom rendering helpers
Use the helper payloads to format values:
use ray;
use Serialize;
ray_json! is an explicit alias for JSON logging if you prefer to use a separate macro.
For links, pass an absolute URL or pre-parse with RayUrl::parse/url::Url and use
try_url/try_link to surface errors. If the scheme is omitted, https:// is assumed.
Send semantics (immediate vs buffered)
By default, every chained call sends a request immediately (best-effort by default).
Chainable methods intentionally ignore transport errors; try_* variants surface
serialization issues, and transport errors only when RayConfig.swallow_errors is false
(or you use ray_strict! / ray_async_strict!).
Updating a single Ray entry (reuse the same Ray handle to keep the UUID stable):
use ray;
If you want to buffer several payloads from the same handle (same UUID) and send
them in a single request, use batch():
use ray;
batch() does not create multiple Ray entries; it batches the same payloads you would
otherwise send immediately. This is useful for combining log + styling updates (or
reducing HTTP calls). To create separate entries, call ray!() again to get a new handle.
ray_dbg macro (Rust-only)
ray_dbg! mirrors dbg!: it labels the entry with the expression and returns the value.
It uses Debug formatting, so any Debug value works.
use ray_dbg;
Panic hook (Rust-only)
Install a panic hook that sends panic details to Ray (and keeps the default panic output).
Async support (feature: transport-reqwest)
Enable the transport-reqwest feature to get async send support.
= { = "crates/ray", = "ray-dbg", = ["transport-reqwest"] }
Then you can call the async API (requires an async runtime like Tokio):
use ray_async;
async
To surface errors, use the try_* variants with ?:
use ;
use ;
async
To force transport errors to bubble up, set RAY_SWALLOW_ERRORS=false or use
ray_strict! / ray_async_strict! (async requires transport-reqwest).
Tracing integration (feature: tracing)
Enable the tracing feature to forward tracing events to Ray.
= { = "crates/ray", = "ray-dbg", = ["tracing"] }
RUST_LOG controls the filtering level, just like tracing-subscriber.
Debug-only macros (feature: debug-macros)
debug-macros is enabled by default to make the core macros no-op outside debug builds.
If you want the macros to always run, disable the default features and opt into a transport:
= { = "crates/ray", = "ray-dbg", = false, = ["transport-ureq"] }
Swap transport-ureq for transport-reqwest if you want async support.
Enable transport-ureq-tls if you need HTTPS with the ureq transport.
PHP vanilla compatibility (core)
Based on the PHP vanilla reference: https://myray.app/docs/php/vanilla-php/reference For full parity notes and edge cases, see the notes below.
| PHP core area (vanilla) | Status in ray-dbg | Rust entry points |
|---|---|---|
| Logging and values (ray, text, raw, toJson, json) | Implemented (json multi-arg partial) | ray!, Ray::text, Ray::raw, Ray::to_json, Ray::json |
| Item updates (send) | Partial | Ray::send (alias: Ray::log) |
| Rendering and files (html, xml, table, image, file) | Implemented | Ray::html, Ray::xml, Ray::table, Ray::image, Ray::file |
| Types and exceptions (className, exception) | Implemented | Ray::class_name, Ray::exception |
| Debugging and stack (caller, trace, backtrace) | Implemented | Ray::caller, Ray::trace, Ray::backtrace |
| Links and URLs (link, url) | Implemented | Ray::link, Ray::url |
| Screens and layout (newScreen, clearScreen, clearAll, separator) | Implemented | Ray::new_screen, Ray::clear_screen, Ray::clear_all, Ray::separator |
| Styling (label, color, size) | Implemented | Ray::label, Ray::color, Ray::{small, large} |
| App UI (notify, confetti, hide, showApp/hideApp, remove) | Implemented | Ray::notify, Ray::confetti, Ray::hide, Ray::show_app, Ray::hide_app, Ray::remove |
| Control flow (if, catch, die/rd, once) | Implemented | Ray::when, Ray::catch, Ray::die, Ray::rd, Ray::once |
| Counters and rate limiting (count, limit, rateLimiter) | Implemented | Ray::count, Ray::limit, Ray::rate_limiter |
| Diagnostics (measure, carbon, phpinfo, pause) | Partial | Ray::measure, Ray::carbon, Ray::rust_info, Ray::pause |
| Private access (invade) | Won't implement | Rust privacy is compile-time only |
Notes on differences:
- json multi-arg: use
.batch().json(...).json(...). - send:
Ray::sendaliasesRay::logand reuses UUIDs when you keep the same handle. - measure: memory usage is best-effort; unsupported platforms report
0. - phpinfo/pause/carbon: Rust info table, pause is a no-op,
carbonis a UTCSystemTimeformatter (no PHP Carbon dependency). - invade: not implemented due to Rust privacy rules.
Examples
Run the usage-focused example (aligned with the Ray PHP usage docs where possible):
Testing
Unit tests use httpmock to validate request envelopes.
Async tests require transport-reqwest:
For live Ray testing on your local setup, enable the live-tests feature and opt into ignored tests:
Async live tests require transport-reqwest:
Configuration
Configuration is loaded from (in increasing priority):
- defaults
ray.json(searched from the current directory upwards)- environment variables
The default Client/configuration is cached on first use for performance.
Use RayConfig::load_strict() to surface invalid ray.json or environment values.
Environment variables
RAY_ENABLED(default:true)RAY_HOST(default:localhost)RAY_PORT(default:23517)RAY_SWALLOW_ERRORS(default:true)RAY_STRICT(iftrue, forcesRAY_SWALLOW_ERRORS=false)RAY_PROJECT_NAME(optional)RAY_TIMEOUT_MS(default:250)RAY_CANONICALIZE_PATHS(default:false)RAY_SEND_META(default:true)RAY_ALWAYS_SEND_RAW_VALUES(default:false)RAY_LOCAL_PATH(optional)RAY_REMOTE_PATH(optional)
In strict mode (RayConfig::load_strict()), invalid or zero values return a ConfigError.
When both local/remote paths are set, callsite file paths are rewritten from the local prefix to the remote prefix.
When always_send_raw_values is enabled, ray!(...) and Ray::log send RAW preformatted JSON instead of log payloads.
ray.json
Keys are optional; strict forces swallow_errors=false when true.
Example:
Developing with ray-proxy
See permafrost-dev/ray-proxy for details.
- In Ray app preferences, set the port to
23516. - Run:
- Point this crate to the proxy:
Then run any code/tests that use ray! or ray_async!, or run the example: