Turning on verbose logging

Developer productivity

Verbosity level is a way to control the verbosity of the SDK. By default, the verbosity level is set to silent. Sometimes, in order to troubleshoot things, we will want to turn on the verbosity.
To turn verbosity using the SDK, we need to change the verbosity level to debug.

SwiftObjective-CAndroidReact NativeJavaScriptNode.jsJavaScript SSRJVMC#PythonGoRubyPHPCC++
let options = ROXOptions()
options.verbose = ROXOptionsVerboseLevelDebug
ROX.setup(withKey:ROLLOUT_KEY, options:options)

let allPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = allPaths.first!
let pathForLog = documentsDirectory.stringByAppendingString("/yourFile.txt")

freopen(pathForLog.cStringUsingEncoding(NSASCIIStringEncoding)!, "a+", stderr)
ROXOptions *options = [[ROXOptions alloc] init];
options.verbose = ROXOptionsVerboseLevelDebug;
[ROX setupWithKey:@"ROLLOUT_KEY" options: options];

NSArray *allPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [allPaths objectAtIndex:0];
NSString *pathForLog = [documentsDirectory stringByAppendingPathComponent:@"yourFile.txt"];

freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
RoxOptions options = new RoxOptions.Builder()

Rox.setup(this, options);
Rox.setup(ROLLOUT_KEY, {
  debugLevel: 'verbose'
Rox.setup(ROLLOUT_KEY, {
  debugLevel: 'verbose'
Rox.setup(ROLLOUT_KEY, {
  debugLevel: 'verbose'
import {Rox} from 'rox-ssr';

Rox.setup(ROLLOUT_KEY, {
  debugLevel: 'verbose'
JVM verbose logging is done using SLF4J library.
In order to turn on verbosity of the SDK, you need to set the logger level for io.rollout to debug in your logging library configration.

Here is anexample on how to turn on verbosity with Logback logger

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" debug="false">

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>

  <logger name="io.rollout" level="DEBUG"/>

  <root level="INFO">
    <appender-ref ref="STDOUT" />
public class internalLogger : ILogger
  public void Debug(string message)
  public void Debug(string message, Exception ex)
    Console.WriteLine(message + ex.ToString());

  public void Warn(string message)
  public void Warn(string message, Exception ex)
    Console.WriteLine(message + ex.ToString());

  public void Error(string message)
  public void Error(string message, Exception ex)
    Console.WriteLine(message + ex.ToString());

var Options = new RoxOptions(new RoxOptions.RoxOptionsBuilder {
    Logger = new internalLogger() // commenting this line,"io.rollout" will be used

await Rox.Setup(<ROLLOUT_KEY>, Options);
from rox.server.rox_options import RoxOptions

# example of a naive Logger
class MyLogger:
    def error(self, msg, ex=None):
        print('error: %s exception: %s' %(msg, ex))

    def warn(self, msg, ex=None):
        print('warn: %s' % msg)

    def debug(self, msg, ex=None):
        print('debug: %s' % msg)

options = RoxOptions(

my_container = MyContainer()
Rox.register('test', my_container)
cancel_event = Rox.setup(<ROLLOUT_KEY>, options).result();
type logger struct {

func (*logger) Debug(message string, err interface{}) {
  fmt.Println("debug:", message)

func (*logger) Warn(message string, err interface{}) {
  fmt.Println("warn:", message)

func (*logger) Error(message string, err interface{}) {
  fmt.Println("error:", message)

options = RoxOptions(
    Logger:    &logger{},

<-rox.Setup(<ROLLOUT_KEY>, options)
# example of a naive Logger, if not set ruby's logger will be used with STDOUT
  class Log
    def debug(message, ex = nil)
      puts 'debug msg:', message

    def error(message, ex = nil)
      puts 'error msg:', message

    def warn(message, ex = nil)
      puts 'warn msg:', message

option = Rox::Server::RoxOptions.new(
             logger: Log.new

container = Container.new
Rox::Server::RoxServer.register('', container)
Rox::Server::RoxServer.setup(<ROLLOUT_KEY>, option).join
$logFile = join(DIRECTORY_SEPARATOR, [

LoggerFactory::setup((new MonologLoggerFactory())
    new StreamHandler($logFile, Logger::DEBUG)
void _file_logging_handler(void *target, RoxLogMessage *message) {
    FILE *file = (FILE *) target;
    fprintf(file, "(%s) %s\n", message->level_name, message->message);

int main(int argc, char **argv) {
    // creating a log config struct with debug log level
  RoxLoggingConfig cfg = ROX_LOGGING_CONFIG_INITIALIZER(RoxLogLevelDebug); // RoxLogLevel enum value

  // !!! custom handler code start !!!

  // example of writing logs to file instead of using default stdout
  FILE *file = fopen(LOG_FILE_PATH, "w");
  if (!file) {
    fprintf(stderr, "Cannot open %s\n", LOG_FILE_PATH);
    return -1;

  // setting target and handler - in case we want to change the default
    cfg.target = file; // default: stdout
  cfg.handler = &_file_logging_handler;

  // !!! custom handler code end !!!

    // initializing logging with the configurations created

  // initialize rox
  RoxOptions *options = rox_options_create();
  rox_setup(DEFAULT_API_KEY, options);

  // do rox things here

  // close
class LoggingHandler : public Rox::LogMessageHandlerInterface {
        void HandleLogMessage(Rox::LogMessage *message) {
      // do something with message

int main(int argc, char **argv) {
    LoggingHandler loggingHandler;

  // to change to logging level

  // to change the default handler