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.
Swift
Objective-C
Android
React Native
JavaScript
Node.js
JavaScript SSR
JVM
C#
Python
Go
Ruby
PHP
C
C++
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()
.withVerboseLevel(RoxOptions.VerboseLevel.VERBOSE_LEVEL_DEBUG)
.build();
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">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="io.rollout" level="DEBUG"/>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
public class internalLogger : ILogger
{
public void Debug(string message)
{
Console.WriteLine(message);
}
public void Debug(string message, Exception ex)
{
Console.WriteLine(message + ex.ToString());
}
public void Warn(string message)
{
Console.WriteLine(message);
}
public void Warn(string message, Exception ex)
{
Console.WriteLine(message + ex.ToString());
}
public void Error(string message)
{
Console.WriteLine(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(
logger=MyLogger()
)
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
end
def error(message, ex = nil)
puts 'error msg:', message
end
def warn(message, ex = nil)
puts 'warn msg:', message
end
end
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, [
sys_get_temp_dir(),
'rollout',
'logs',
'demo.log'
]);
LoggerFactory::setup((new MonologLoggerFactory())
->setDefaultHandlers([
new StreamHandler($logFile, Logger::DEBUG)
])
);
void _file_logging_handler(void *target, RoxLogMessage *message) {
assert(target);
assert(message);
FILE *file = (FILE *) target;
fprintf(file, "(%s) %s\n", message->level_name, message->message);
fflush(file);
}
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
rox_logging_init(&cfg);
// initialize rox
RoxOptions *options = rox_options_create();
rox_setup(DEFAULT_API_KEY, options);
// do rox things here
// close
rox_shutdown();
fclose(file);
}
class LoggingHandler : public Rox::LogMessageHandlerInterface {
public:
void HandleLogMessage(Rox::LogMessage *message) {
// do something with message
}
}
int main(int argc, char **argv) {
LoggingHandler loggingHandler;
// to change to logging level
Rox::Logging::SetLogLevel(RoxLogLevelDebug);
// to change the default handler
Rox::Logging::SetLogMessageHandler(&loginHandler);
}