ArangoDB v2.8 reached End of Life (EOL) and is no longer supported.
This documentation is outdated. Please see the most recent version here: Try latest
Foxx console
Foxx injects a console object into each Foxx app that allows writing log entries to the database in addition to the ArangoDB log file and querying them from within the app itself.
The console object supports the CommonJS Console API found in Node.js and modern browsers, while also providing some ArangoDB-specific additions.
ArangoDB also provides the console
module which only supports the CommonJS Console API and only writes log entries to the ArangoDB log.
When working with transactions, keep in mind that the Foxx console will attempt to write to the _foxxlog
system collection. This behaviour can be disabled using the setDatabaseLogging
method if you don’t want to explicitly allow writing to the log collection during transactions or for performance reasons.
Logging
Logging console messages
Write an arbitrary message to the app’s log.
console.log([format,] ...parameters)
Applies util.format
to the arguments and writes the resulting string to the app’s log.
If the first argument is not a formatting string or any of the additional arguments are not used by the formatting string, they will be concatenated to the result string.
Examples
console.log("%s, %s!", "Hello", "World"); // => "Hello, World!"
console.log("%s, World!", "Hello", "extra"); // => "Hello, World! extra"
console.log("Hello,", "beautiful", "world!"); // => "Hello, beautiful world!"
console.log(1, 2, 3); // => "1 2 3"
Logging with different log levels
The console object provides additional methods to log messages with different log levels:
console.debug
for log level DEBUGconsole.info
for log level INFOconsole.warn
for log level WARNconsole.error
for log level ERROR
By default, console.log
uses log level INFO, making it functionally equivalent to console.info
. Other than the log level, all of these methods behave identically to console.log
.
The built-in log levels are:
- -200: TRACE
- -100: DEBUG
- 0: INFO
- 100: WARN
- 200: ERROR
Logging with timers
You can start and stop timers with labels.
console.time(label)
/ console.timeEnd(label)
Passing a label to console.time
starts the timer. Passing the same label to console.timeEnd
ends the timer and logs a message with the label and the expired time in milliseconds.
Calling console.timeEnd
with an invalid label or calling it with the same label twice (without first starting a new timer with the same label) results in an error.
By default, the timing messages will be logged with log level INFO.
Examples
console.time('do something');
// ... more code ...
console.time('do more stuff');
// ... even more code ...
console.timeEnd('do more stuff'); // => "do more stuff: 23ms"
// ... a little bit more ....
console.timeEnd('do something'); // => "do something: 52ms"
Don’t do this:
console.timeEnd('foo'); // fails: label doesn't exist yet.
console.time('foo'); // works
console.timeEnd('foo'); // works
console.timeEnd('foo'); // fails: label no longer exists.
Logging stack traces
You can explicitly log a message with a stack trace.
console.trace(message)
This creates a stack trace with the given message.
By default the stack traces will be logged with a log level of TRACE.
Examples
console.trace('Hello');
/* =>
Trace: Hello
at somefile.js:1:1
at ...
*/
Logging assertions
This creates an assertion that will log an error if it fails.
console.assert(statement, message)
If the given statement is not true (e.g. evaluates to false
if treated as a boolean), an AssertionError
with the given message will be created and its stack trace will be logged.
By default, the stack trace will be logged with a log level of ERROR and the error will be discarded after logging it (instead of being thrown).
Examples
console.assert(2 + 2 === 5, "I'm bad at maths");
/* =>
AssertionError: I'm bad at maths
at somefile.js:1:1
at ...
*/
Inspecting an object
This logs a more detailed string representation of a given object.
console.dir(value)
The regular logging functions try to format messages as nicely and readable as possible. Sometimes that may not provide you with all the information you actually want.
The dir method instead logs the result of util.inspect
.
By default the message will be logged with the log level INFO.
Examples
console.log(require('org/arangodb').db); // => '[ArangoDatabase "_system"]'
console.dir(require('org/arangodb').db);
/* =>
{ [ArangoDatabase "_system"]
_version: [Function: _version],
_id: [Function: _id],
...
}
*/
Custom log levels
This lets you define your own log levels.
console.custom(name, value)
If you need more than the built-in log levels, you can easily define your own.
This method returns a function that logs messages with the given log level (e.g. an equivalent to console.log
that uses your custom log level instead).
Parameter
- name: name of the log level as it appears in the database, usually all-uppercase
- value (optional): value of the log level. Default:
50
The value is used when determining whether a log entry meets the minimum log level that can be defined in various places. For a list of the built-in log levels and their values see the section on logging with different log levels above.
Preventing entries from being logged
You can define a minimum log level entries must match in order to be logged.
console.setLogLevel(level)
The level can be a numeric value or the case-sensitive name of an existing log level.
Any entries with a log level lower than the given value will be discarded silently.
This can be helpful if you want to toggle logging diagnostic messages in development mode that should not be logged in production.
The default log level is set to -999
. For a list of built-in log levels and their values see the section on logging with different log levels.
Enabling extra stack traces
You can toggle the logging of stack trace objects for every log entry.
console.setTracing(trace)
If trace is set to true
, all log entries will be logged with a parsed stack trace as an additional stack
property that can be useful for identifying where the entry originated and how the code triggering it was called.
Because this results in every logging call creating a stack trace (which may have a significant performance impact), this option is disabled by default.
Disabling logging to the ArangoDB console
You can toggle whether logs should be written to the ArangoDB console.
console.setNativeLogging(nativeLogging)
If nativeLogging is set to false
, log entries will not be logged to the ArangoDB console (which usually writes to the file system).
Disabling logging to the database
You can toggle whether logs should be written to the database.
console.setDatabaseLogging(databaseLogging)
If databaseLogging is set to false
, log entries will not be logged to the internal _foxxlog
collection.
This is only useful if logging to the ArangoDB console is not also disabled.
Enabling assertion errors
You can toggle whether console assertions should throw if they fail.
console.setAssertThrows(assertThrows)
If assertThrows is set to true
, any failed assertions in console.assert
will result in the generated error being thrown instead of being discarded after it is logged.
By default, this setting is disabled.
Changing the default log levels
Most of the logging methods have an implied log level that is set to a reasonable default. If you would like to have them use different log levels, you can easily change them.
console.log.level
defaults to INFOconsole.dir.level
defaults to INFOconsole.time.level
defaults to INFOconsole.trace.level
defaults to TRACEconsole.assert.level
defaults to ERROR
To use different log levels, just set these properties to the case-sensitive name of the desired log level.
Examples
console.log('this uses "INFO"');
console.log.level = 'WARN';
console.log('now it uses "WARN"');
Known custom levels work, too:
console.custom('BANANA', 23);
console.log.level = 'BANANA';
console.log('now it uses "BANANA"');
Unknown levels result in an error:
console.log.level = 'POTATO';
console.log('this throws'); // => Error: Unknown log level: POTATO
Querying a Foxx app’s log entries
As the log entries are logged to a collection in the database, you can easily query them in your own application.
The logs object
The logs object can be found on the console itself:
console.logs
It provides three easy methods for querying the log entries:
logs.list([opts])
logs.searchByMessage(message, [opts])
logs.searchByFileName(fileName, [opts])
Each method takes an optional opts
argument, which can be an object with any of the following properties:
- startTime: the oldest time to include (in milliseconds). Default: 2 hours ago.
- endTime: the most recent time to include (in milliseconds).
- level: only return entries with this log level (name or value).
- minLevel: only return entries with this log level or above (name or value).
- sort: sorting direction of the result (ASC or DESC by time). Default: ASC.
- limit: maximum number of entries to return.
- offset: if limit is set, skip this many entries.
The default value for startTime can be changed by overriding logs.defaultMaxAge
with a different time offset in milliseconds.
Search by message
This lists all log entries with messages that contain the given token.
logs.searchByMessage(message, [opts])
This works like logs.list
except it only returns log entries containing the given message part in their message.
Search by file name
This lists all log entries with stack traces that contain the given token.
logs.searchByFileName(fileName, [opts])
This works like logs.list
except it only returns log entries containing the given fileName part in one of the file names of their stack trace.
This method can only be used if the console has tracing enabled. See the section on enabling extra stack traces.
Note that entries that were logged while tracing was not enabled can not be found with this method because they don’t have any parsed stack traces associated with them. This method does not search the log entries messages for the file name, so entries generated by console.assert
or console.trace
are not treated differently.