Console
The console API provides a small JavaScript-like console for C++ developers.
It is designed for people who are used to writing:
console.log("hello")
console.warn("careful")
console.error("failed")In Vix, you can write:
vix::console.log("hello");
vix::console.warn("careful");
vix::console.error("failed");This API is for development comfort, demos, examples, quick debugging, and making C++ feel more familiar for developers coming from JavaScript.
It is not the production logging API.
Header
#include <vix/console.hpp>Some projects may expose it through:
#include <vix.hpp>For direct usage, prefer:
#include <vix/console.hpp>Basic usage
#include <vix/console.hpp>
int main()
{
vix::console.log("Hello from Vix");
vix::console.info("Server started on port", 8080);
vix::console.warn("Cache is empty");
vix::console.error("Failed to open file");
vix::console.debug("Debug value", 42);
return 0;
}Output shape:
09:31:25 [info] Hello from Vix
09:31:25 [info] Server started on port 8080
09:31:25 [warn] Cache is empty
09:31:25 [error] Failed to open filedebug is hidden by default because the default level is Info.
Why this API exists
vix::console exists to make C++ friendlier for developers who are used to JavaScript.
Instead of writing:
std::cout << "user " << id << " connected\n";
std::cerr << "error: failed\n";you can write:
vix::console.log("user", id, "connected");
vix::console.error("failed");The goal is not to replace professional structured logging.
The goal is to provide a simple and familiar developer console.
Public API overview
| API | Purpose | Stream |
|---|---|---|
vix::console.log(...) | General development output. | stdout |
vix::console.info(...) | Informational development output. | stdout |
vix::console.warn(...) | Warning output. | stderr |
vix::console.error(...) | Error output. | stderr |
vix::console.debug(...) | Debug output, hidden unless level is Debug. | stdout |
vix::console.set_level(level) | Change the minimum visible level. | - |
vix::console.level() | Read the current level. | - |
Global object
The console API is exposed through a global object:
vix::consoleExample:
vix::console.log("hello");Internally, vix::console is an inline global instance of vix::Console.
Levels
Console messages have levels.
enum class Level : uint8_t
{
Debug = 0,
Info = 1,
Warn = 2,
Error = 3,
Off = 4
};The current level controls what is printed.
| Current level | Printed |
|---|---|
Debug | debug, info, warn, error |
Info | info, warn, error |
Warn | warn, error |
Error | error |
Off | nothing |
Default level:
Infolog
log prints a normal development message.
vix::console.log("Hello", "Vix");Output shape:
09:31:25 [info] Hello Vixlog uses the Info level.
It writes to stdout.
info
info is equivalent to an informational message.
vix::console.info("Server ready on port", 8080);Output shape:
09:31:25 [info] Server ready on port 8080info writes to stdout.
warn
warn prints a warning message.
vix::console.warn("Missing optional config:", ".env.local");Output shape:
09:31:25 [warn] Missing optional config: .env.localwarn writes to stderr.
Warnings are not rate-limited.
error
error prints an error message.
vix::console.error("Failed to connect to database");Output shape:
09:31:25 [error] Failed to connect to databaseerror writes to stderr.
Errors are not rate-limited.
debug
debug prints a debug message only when the console level allows it.
vix::console.debug("user_id", 42);By default, this is hidden because the default level is Info.
Enable debug:
vix::console.set_level(vix::Console::Level::Debug);
vix::console.debug("user_id", 42);Output shape:
09:31:25 [debug] user_id 42Set the level in code
vix::console.set_level(vix::Console::Level::Debug);Example:
#include <vix/console.hpp>
int main()
{
vix::console.debug("hidden by default");
vix::console.set_level(vix::Console::Level::Debug);
vix::console.debug("visible now");
return 0;
}Read the current level
auto level = vix::console.level();Example:
if (vix::console.level() == vix::Console::Level::Debug)
{
vix::console.log("debug mode is enabled");
}Set the level with environment variables
vix::console reads environment variables during construction.
Use:
VIX_CONSOLE_LEVEL=debug ./appSupported values:
debugtraceinfologwarnwarningerrorerroffnonesilentnever0
Examples:
VIX_CONSOLE_LEVEL=debug ./app
VIX_CONSOLE_LEVEL=warn ./app
VIX_CONSOLE_LEVEL=error ./app
VIX_CONSOLE_LEVEL=off ./appLevel aliases
| Value | Result |
|---|---|
debug | Debug |
trace | Debug |
info | Info |
log | Info |
warn | Warn |
warning | Warn |
error | Error |
err | Error |
off | Off |
none | Off |
silent | Off |
never | Off |
0 | Off |
If the value is unknown, Vix falls back to Info.
Colors
Console supports ANSI colors.
Color behavior is controlled by:
VIX_COLOR=auto
VIX_COLOR=always
VIX_COLOR=neverDefault:
autoIn auto mode, colors are enabled only when the output is a terminal.
Disable colors
Use:
NO_COLOR=1 ./appor:
VIX_COLOR=never ./appNO_COLOR has priority.
Force colors
VIX_COLOR=always ./appThis can be useful when your terminal supports ANSI but auto-detection is not enough.
Output format
A console line has this shape:
HH:MM:SS [level] messageExample:
09:31:25 [info] Server ready
09:31:26 [warn] Missing optional file
09:31:27 [error] Failed to connectThe timestamp uses local time.
Streams
| Method | Stream |
|---|---|
log | stdout |
info | stdout |
debug | stdout |
warn | stderr |
error | stderr |
This mirrors the usual developer expectation:
normal messages → stdout
warnings/errors → stderrArguments
Console methods accept multiple arguments:
vix::console.log("user", 42, "connected");
vix::console.warn("retry", 3, "failed");
vix::console.error("port", 8080, "already in use");Arguments are separated by a single space.
Supported argument types
The console API is intentionally small and fast.
It supports common primitive and string-like values:
| Category | Examples |
|---|---|
| Strings | const char *, char *, std::string, std::string_view |
| Booleans | bool |
| Integers | int, long, std::uint64_t, etc. |
| Floating point | float, double, long double |
| Enums | enum values are printed as their underlying integer |
| Pointers | printed as addresses |
| String-view convertible values | values convertible to std::string_view |
| Other objects | printed as [object] |
Strings
vix::console.log("hello");
vix::console.log(std::string{"hello"});
vix::console.log(std::string_view{"hello"});Output shape:
09:31:25 [info] hello
09:31:25 [info] hello
09:31:25 [info] helloBooleans
vix::console.log(true, false);Output:
09:31:25 [info] true falseNumbers
vix::console.log("port", 8080);
vix::console.log("ratio", 3.14159);Output shape:
09:31:25 [info] port 8080
09:31:25 [info] ratio 3.14159Floating point values are formatted compactly.
Enums
enum class Status
{
Ready = 1,
Failed = 2
};
vix::console.log("status", Status::Ready);Output:
09:31:25 [info] status 1Enums are printed as their underlying integer value.
Pointers
int value = 42;
int *ptr = &value;
vix::console.log("ptr", ptr);
vix::console.log("null", static_cast<int *>(nullptr));Output shape:
09:31:25 [info] ptr 0x7ffd...
09:31:25 [info] null nullOther objects
The console API does not deeply inspect arbitrary objects.
struct User
{
int id{};
};
User user{1};
vix::console.log(user);Output:
09:31:25 [info] [object]Use vix::print or vix::inspect when you want structured rendering for STL containers, custom types, or nested data.
Console vs Print vs Inspect
| API | Use for |
|---|---|
vix::console | JavaScript-like development messages. |
vix::print | Friendly C++ output with STL rendering. |
vix::inspect | Deep debugging and diagnostics. |
Examples:
vix::console.log("server started");
vix::print(std::vector<int>{1, 2, 3});
vix::inspect(config);Not for production logging
vix::console is intentionally a developer convenience API.
Use it for:
- examples,
- tutorials,
- demos,
- local debugging,
- quick development output,
- making C++ feel familiar to JavaScript developers.
Avoid treating it as a production logger.
It does not provide:
- structured log fields,
- JSON log format,
- log rotation,
- sinks,
- persistent storage,
- tracing context,
- request IDs,
- distributed tracing,
- log shipping,
- production retention policies.
For production logging, use your application logging system.
Rate limiting
log and info are rate-limited to protect development output from hot-loop spam.
Default limit:
200 log/info lines per secondWhen the limit is exceeded, Vix suppresses extra log and info messages and may print a warning like:
09:31:25 [warn] (console) suppressed 120 log/info lines (rate limit)warn, error, and debug are not rate-limited.
Why rate limiting exists
This is a developer-safety feature.
A loop like this can flood your terminal:
for (int i = 0; i < 1'000'000; ++i)
{
vix::console.log("i", i);
}The console rate limiter prevents the terminal from being overwhelmed.
Thread safety
Console writes are protected by a global mutex.
This means each complete console line is written atomically, avoiding interleaved output between threads.
Example:
std::thread a([] {
vix::console.log("from thread A");
});
std::thread b([] {
vix::console.log("from thread B");
});
a.join();
b.join();You should see complete lines, not mixed half-lines.
Fixed buffer
Console uses a fixed internal line buffer.
Capacity:
8192 bytesIf a line is too long, it is truncated and marked.
This keeps the console API simple and allocation-light.
No iostream formatting
Console does not use std::ostream formatting for arbitrary types.
That is intentional.
The goal is:
fast simple console output for developmentNot:
deep generic object formattingFor object formatting, use:
vix::print(value);
vix::inspect(value);Examples
Server startup
vix::console.info("Server started on port", 8080);Output:
09:31:25 [info] Server started on port 8080Route debugging
app.get("/health", [](Request &, Response &res) {
vix::console.log("GET /health");
res.json({
"ok", true
});
});Warning
vix::console.warn("Using default config");Error
vix::console.error("Failed to read", "config.json");Debug
vix::console.set_level(vix::Console::Level::Debug);
vix::console.debug("cache size", 42);Disable output
vix::console.set_level(vix::Console::Level::Off);
vix::console.log("this will not print");
vix::console.error("this will not print either");Complete example
#include <vix.hpp>
#include <vix/console.hpp>
using namespace vix;
int main()
{
console.info("Starting API");
App app;
app.get("/", [](Request &, Response &res) {
console.log("GET /");
res.json({
"message", "Hello from Vix",
"console", "JavaScript-like developer API"
});
});
app.get("/health", [](Request &, Response &res) {
console.debug("health check called");
res.json({
"ok", true
});
});
app.run(8080);
return 0;
}Run with debug enabled:
VIX_CONSOLE_LEVEL=debug vix run main.cppTest:
curl -i http://127.0.0.1:8080/
curl -i http://127.0.0.1:8080/healthEnvironment variable examples
Show debug messages
VIX_CONSOLE_LEVEL=debug vix run main.cppShow only warnings and errors
VIX_CONSOLE_LEVEL=warn vix run main.cppShow only errors
VIX_CONSOLE_LEVEL=error vix run main.cppDisable console output
VIX_CONSOLE_LEVEL=off vix run main.cppDisable colors
VIX_COLOR=never vix run main.cppor:
NO_COLOR=1 vix run main.cppCommon mistakes
Expecting debug to print by default
vix::console.debug("debug value", 42);This is hidden by default.
Enable it:
vix::console.set_level(vix::Console::Level::Debug);or:
VIX_CONSOLE_LEVEL=debug vix run main.cppExpecting arbitrary objects to be printed deeply
std::vector<int> values = {1, 2, 3};
vix::console.log(values);Output:
09:31:25 [info] [object]Use:
vix::print(values);or:
vix::inspect(values);Using console as production logging
This is fine for local development:
vix::console.log("user connected");But vix::console is not intended to be your production logging layer.
Use your production logging system for deployed services.
Forgetting the namespace
console.log("hello");If you are not using using namespace vix;, write:
vix::console.log("hello");Expecting VIX_CONSOLE_LEVEL to change after startup
The global console reads environment configuration during construction.
Set environment variables before starting the process:
VIX_CONSOLE_LEVEL=debug ./appBest practices
Use console.log for familiar development messages:
vix::console.log("route called", "/users");Use console.info for lifecycle messages:
vix::console.info("server ready", 8080);Use console.warn for recoverable warnings:
vix::console.warn("missing optional config");Use console.error for visible local errors:
vix::console.error("cannot open file");Use console.debug for noisy details:
vix::console.debug("payload size", size);Keep console messages short.
For complex values, use:
vix::print(value);
vix::inspect(value);API reference
vix::Console
class Console final;The console class behind the global object.
You usually do not need to create your own instance.
Use:
vix::console.log("hello");vix::console
inline Console console;Global console object.
vix::console.info("ready");Console::Level
enum class Level : uint8_t
{
Debug = 0,
Info = 1,
Warn = 2,
Error = 3,
Off = 4
};Controls the minimum visible console level.
log
template <typename... Ts>
void log(Ts &&...xs) noexcept;Prints an info-level message to stdout.
vix::console.log("hello", 42);info
template <typename... Ts>
void info(Ts &&...xs) noexcept;Prints an info-level message to stdout.
vix::console.info("server ready");warn
template <typename... Ts>
void warn(Ts &&...xs) noexcept;Prints a warning message to stderr.
vix::console.warn("config missing");error
template <typename... Ts>
void error(Ts &&...xs) noexcept;Prints an error message to stderr.
vix::console.error("failed");debug
template <typename... Ts>
void debug(Ts &&...xs) noexcept;Prints a debug message to stdout when the level is Debug.
vix::console.debug("value", 42);set_level
void set_level(Level lvl) noexcept;Sets the minimum visible level.
vix::console.set_level(vix::Console::Level::Warn);level
Level level() const noexcept;Returns the current console level.
auto lvl = vix::console.level();Summary
vix::console is a small JavaScript-like developer console for C++.
Use it when you want familiar output:
vix::console.log("hello");
vix::console.info("ready");
vix::console.warn("careful");
vix::console.error("failed");
vix::console.debug("value", 42);It is best for:
- developers coming from JavaScript,
- examples,
- demos,
- tutorials,
- quick local debugging,
- friendly C++ onboarding.
It is not a production logging system.
For rich value formatting, use vix::print.
For deep diagnostics, use vix::inspect.