Logging and Diagnostics
The Client SDK provides configurable logging to help with integration, debugging, and production monitoring. Log output covers internal HTTP traffic, API calls, WebRTC events, and session lifecycle.
Log Levels
Set the logging level when creating the client. Available levels, from most to least verbose:
| Level | Use case |
|---|---|
Verbose |
Full trace output — useful during initial integration |
Debug |
Detailed diagnostic information |
Info |
General operational messages |
Warn |
Potential issues that don't prevent operation |
Error |
Failures only |
None |
Logging disabled |
Configuration
You can set a log level directly, disable the internal logger entirely, or provide custom logger implementations that route SDK output to your own logging infrastructure.
const clientA = new VonageClient({
loggingLevel: LoggingLevel.Error
});
// or setup custom loggers
const clientB = new VonageClient({
disableInternalLogger: true,
customLoggers: [
{
name: 'CustomLoggerOne',
minLogLevel: LoggingLevel.Debug,
topics: ['HTTP', Topics.API],
onLog: (level, topic, message) => {
console.log(`${level} ${topic.name} ${topic.tag} ${message}`);
}
},
createVonageLogger('CustomLoggerTwo', (level, topic, message) => {
console.log(`${level} ${topic.name} ${topic.tag} ${message}`);
})
]
});
val config = VGClientInitConfig(LoggingLevel.Verbose)
val clientA = VonageClient(ctx, config)
// or
val clientB = VonageClient(
ctx,
VGClientInitConfig().apply {
loggingLevel = LoggingLevel.Error
}
)
// or setup custom loggers
val clientC = VonageClient(
ctx,
VGClientInitConfig(
disableInternalLogger = true,
customLoggers = listOf(
object : VonageLogger {
override val name: String = "CustomLoggerOne"
override val minLogLevel: LoggingLevel = LoggingLevel.Debug
override val topics: List<Topic> = listOf(Topic.HTTP, Topic.API).flatten()
override fun onLog(logLevel: LoggingLevel, topic: Topic, message: String, throwable: Throwable?) {
println("$logLevel ${topic.name} ${topic.tag} $message")
}
},
createVonageLogger("CustomLoggerTwo"){ logLevel, topic, message, _ ->
println("$logLevel ${topic.name} ${topic.tag} $message")
}
)
)
)
LoggingLevel logLevelA = LoggingLevel.Verbose;
VGClientInitConfig configA = new VGClientInitConfig(logLevelA);
VonageClient clientA = VonageClient.createClient(ctx, configA);
// or
VGClientInitConfig configB = new VGClientInitConfig();
configB.setLoggingLevel(LoggingLevel.Error);
VonageClient clientB = VonageClient.createClient(ctx, configB);
// or setup custom loggers
VGClientInitConfig configC = new VGClientInitConfig();
configC.setDisableInternalLogger(true);
configC.setCustomLoggers(Arrays.asList(
new VonageLogger() {
@NotNull
@Override
public String getName() {
return "CustomLoggerOne";
}
@NotNull
@Override
public LoggingLevel getMinLogLevel() {
return LoggingLevel.Debug;
}
@NotNull
@Override
public List<Topic> getTopics() {
List<Topic> flattenedList = new ArrayList<>();
for (List<? extends Topic> subList : Arrays.asList(Topic.Companion.getHTTP(), Topic.Companion.getAPI())) {
flattenedList.addAll(subList);
}
return flattenedList;
}
@Override
public void onLog(@NotNull LoggingLevel logLevel, @NotNull Topic topic, @NotNull String message, Throwable throwable) {
System.out.println(logLevel + " " + topic.getName() + " " + topic.getTag() + " " + message);
}
},
createVonageLogger(
"CustomLoggerTwo",
null, null,
(logLevel, topic, message, throwable) -> {
System.out.println(logLevel + " " + topic.getName() + " " + topic.getTag() + " " + message);
return null;
}
)
));
VonageClient clientC = VonageClient.createClient(ctx, configC);
let configA = VGClientInitConfig(loggingLevel: .verbose)
let clientA = VGVonageClient(configA)
// or
let configB = VGClientInitConfig()
configB.loggingLevel = .error
let clientB = VGVonageClient(configB)
// or setup custom loggers
class MyLogger : NSObject, VGLogger {
let name: String = "CustomLoggerOne"
let minLogLevel: VGLoggingLevel = .debug
let topics: [VGTopicGroup] = [VGTopic.HTTP, VGTopic.API]
func didReceiveLog(logLevel: VGLoggingLevel, topic: VGTopic, message: String) {
print("\(logLevel) \(topic.name) \(topic.tag) \(message)")
}
}
let clientC = VGVonageClient(
VGClientInitConfig(
disableInternalLogger: true,
customLoggers: [
MyLogger(),
VGCustomLogger("CustomLoggerTwo"){ logLevel,topic, message in
print("\(logLevel) \(topic.name) \(topic.tag) \(message)")
}
]
)
)
VGClientInitConfig *configA = [[VGClientInitConfig alloc]
initWithLoggingLevel:VGLoggingLevelVerbose
disableInternalLogger:VGDefaultDisableInternalLogger
customLoggers:[NSArray array]
region:VGDefaultRegion
apiUrl:nil
websocketUrl:nil
websocketPath:nil
enableWebSocketInvites:VGDefaultEnableWebsocketInvites
rtcStatsTelemetry:VGDefaultRtcStatsTelemetry
autoReconnectMedia:VGDefaultAutoReconnectMedia
enableNoiseSuppression:VGDefaultEnableNoiseSuppression
emergencyPrimaryRegion:nil
emergencySecondaryRegion:nil];
VGVonageClient* clientA = [[VGVonageClient alloc] initWithConfig:configA];
// or
VGClientInitConfig *configB = [[VGClientInitConfig alloc] init];
configB.loggingLevel = VGLoggingLevelError;
VGVonageClient* clientB = [[VGVonageClient alloc] initWithConfig:configB];
// or setup custom loggers
// 1. Implement the VGLogger protocol
id<VGLogger> customLoggerOne;
// 2. Use the VGCustomLogger class
VGCustomLogger *customLoggerTwo = [[VGCustomLogger alloc]
initWithName:@"CustomLoggerTwo"
minLogLevel:VGDefaultLoggingLevel()
topics:VGDefaultTopics()
onLog:^(VGLoggingLevel logLevel, VGTopic * _Nonnull topic, NSString * _Nonnull message) {
NSLog(@"%ld %@ %@ %@", logLevel, topic.name, topic.tag, message);
}];
VGClientInitConfig *configC = [[VGClientInitConfig alloc] init];
configC.disableInternalLogger = true;
configC.customLoggers = [NSArray arrayWithObjects:customLoggerOne, customLoggerTwo, nil];
VGVonageClient *clientC = [[VGVonageClient alloc] initWithConfig:configC];
Custom Loggers
Custom loggers receive structured log events with:
- level — the severity of the log entry
- topic — categorizes the log source (e.g.
HTTP,API,WebRTC) - message — the log content
Use custom loggers to integrate SDK diagnostics with your existing logging or crash reporting tools (e.g. Sentry, Datadog, Crashlytics).
Topic Filtering
Each logger can subscribe to specific topics to reduce noise. Available topic groups include HTTP, API, and others. Filtering by topic is useful in production where you may only want to capture network-level events without verbose internal state logging.
Recommendations
- Use
Verboseduring development and initial integration to understand call flow and event ordering. - Use
ErrororWarnin production builds to minimize performance overhead. - If you need production diagnostics without full verbosity, use a custom logger filtered to specific topics.