# Log level for verbosity (error, warn, info, debug, trace) When working with the [Zoom Realtime Media Streams (RTMS) SDK](https://github.com/zoom/rtms), understanding how to control logging is essential for debugging, monitoring, and integrating with your existing logging infrastructure. This guide covers everything you need to know about RTMS SDK logging. ## Quick start with environment variables The [RTMS Quickstart app](https://github.com/zoom/rtms-quickstart-js) provides a `.env.example` file that demonstrates the three key logging parameters: ```ini # Log level for verbosity (error, warn, info, debug, trace) ZM_RTMS_LOG_LEVEL=info # Log format (progressive for human-readable, json for machine-readable) ZM_RTMS_LOG_FORMAT=progressive # Enable or disable logging ZM_RTMS_LOG_ENABLED=true ``` Simply copy `.env.example` to `.env` and configure these values before running your application. ## Understanding log levels The RTMS SDK supports five log levels, from least to most verbose: | Level | Value | Use Case | | ------- | ----- | -------------------------------------------- | | `error` | 0 | Production - critical errors only | | `warn` | 1 | Production - errors and warnings | | `info` | 2 | Development - general information (default) | | `debug` | 3 | Debugging - detailed diagnostic info | | `trace` | 4 | Deep debugging - includes all SDK operations | ## Log format options ### Progressive format (human-readable) Best for development and console output: ```ini ZM_RTMS_LOG_FORMAT=progressive ``` **Output example:** ```shell rtms | 2025-10-03T10:15:30.123Z | INFO | Connecting to meeting rtms | 2025-10-03T10:15:31.456Z | DEBUG | WebSocket connection established ``` ### JSON format (machine-readable) Ideal for log aggregation systems like Elasticsearch, Splunk, or CloudWatch: ```ini ZM_RTMS_LOG_FORMAT=json ``` **Output example:** ```json {"timestamp":"2025-10-03T10:15:30.123Z","level":"info","component":"rtms","message":"Connecting to meeting"} {"timestamp":"2025-10-03T10:15:31.456Z","level":"debug","component":"rtms","message":"WebSocket connection established"} ``` ## Redirecting SDK logs The RTMS SDK writes to `stdout`. Use standard shell redirection to send logs to files or processing pipelines: ### Redirect to file ```shell # All output to file npm start > rtms.log 2>&1 # Only stdout (SDK logs) to file npm start > rtms.log # Separate stdout and stderr npm start > rtms.log 2> errors.log ``` ### Pipe to log processor ```shell # Send to journald npm start | systemd-cat -t rtms-app # Process with jq (for JSON format) npm start | jq -r '.message' # Stream to remote syslog npm start | nc syslog-server 514 ``` ### Dockerized applications In your Dockerfile or docker-compose.yml: ```yaml services: rtms-app: build: . environment: - ZM_RTMS_LOG_LEVEL=info - ZM_RTMS_LOG_FORMAT=json logging: driver: "json-file" options: max-size: "10m" max-file: "3" ``` ## Programmatic configuration Override environment variables at runtime using the `configureLogger()` function: ```javascript import rtms from "@zoom/rtms"; // Configure logging programmatically rtms.configureLogger({ level: rtms.LogLevel.DEBUG, format: rtms.LogFormat.JSON, enabled: true, }); ``` This is useful for: - Dynamic log level adjustment based on runtime conditions - Different logging configurations per environment - Testing scenarios requiring specific log outputs ## Disabling SDK logging for custom solutions If you prefer to use your own logging framework (Winston, Pino, Bunyan, etc.), disable the SDK's internal logging and implement logging in the callbacks: 1. Disable SDK logging ```ini # In .env ZM_RTMS_LOG_ENABLED=false ``` Or programmatically: ```javascript rtms.configureLogger({ enabled: false }); ``` 2. Implement custom logging in callbacks Here's a complete example using a custom logger: ```javascript import rtms from "@zoom/rtms"; import winston from "winston"; // Set up your custom logger const logger = winston.createLogger({ level: "info", format: winston.format.json(), transports: [ new winston.transports.File({ filename: "rtms-error.log", level: "error", }), new winston.transports.File({ filename: "rtms-combined.log" }), ], }); // Disable SDK logging rtms.configureLogger({ enabled: false }); const client = new rtms.Client(); // Log join confirmation client.onJoinConfirm((reason) => { logger.info("Meeting joined", { reason, timestamp: Date.now(), }); }); // Log session updates client.onSessionUpdate((op, sessionInfo) => { logger.info("Session update", { operation: op, sessionId: sessionInfo.sessionId, status: sessionInfo.status, }); }); // Log participant changes client.onUserUpdate((op, participantInfo) => { logger.info("User update", { operation: op, userId: participantInfo.userId, userName: participantInfo.userName, eventType: op === rtms.USER_EVENT_JOIN ? "join" : "leave", }); }); // Log media data with metrics client.onAudioData((buffer, size, timestamp, metadata) => { logger.debug("Audio data received", { userName: metadata.userName, userId: metadata.userId, size, timestamp, }); }); client.onVideoData((buffer, size, timestamp, trackId, metadata) => { logger.debug("Video data received", { userName: metadata.userName, trackId, size, timestamp, }); }); client.onTranscriptData((buffer, size, timestamp, metadata) => { const text = buffer.toString("utf8"); logger.info("Transcript received", { userName: metadata.userName, text, timestamp, }); }); // Log disconnection client.onLeave((reason) => { logger.warn("Meeting ended", { reason, timestamp: Date.now(), }); }); ``` ## Production best practices 1. Use JSON format for production ```ini ZM_RTMS_LOG_FORMAT=json ZM_RTMS_LOG_LEVEL=warn ``` JSON logs integrate seamlessly with log aggregation platforms and make querying much easier. 2. Implement structured logging Add context to your callback logs: ```javascript client.onAudioData((buffer, size, timestamp, metadata) => { logger.info({ event: "audio_received", meeting_id: client.uuid(), stream_id: client.streamId(), participant: { user_id: metadata.userId, user_name: metadata.userName, }, metrics: { size_bytes: size, timestamp: timestamp, }, }); }); ``` 3. Monitor key metrics Track important events for monitoring: ```javascript const metrics = { audioFrames: 0, videoFrames: 0, participants: new Set(), }; client.onAudioData((buffer, size, timestamp, metadata) => { metrics.audioFrames++; metrics.participants.add(metadata.userId); }); // Log metrics periodically setInterval(() => { logger.info("RTMS metrics", metrics); metrics.audioFrames = 0; metrics.videoFrames = 0; }, 60000); // Every minute ``` 4. Handle errors gracefully Always log error scenarios: ```javascript client.onLeave((reason) => { if (reason !== 0) { logger.error("Abnormal disconnect", { reason_code: reason, meeting_id: client.uuid(), }); // Implement reconnection logic here } }); ``` ## Debugging tips ### Enable trace logging temporarily ```javascript // Enable detailed logging for debugging if (process.env.NODE_ENV !== "production") { rtms.configureLogger({ level: rtms.LogLevel.TRACE, format: rtms.LogFormat.PROGRESSIVE, }); } ``` ### Filter logs by component When using JSON format, filter by component: ```shell npm start | jq 'select(.component == "rtms")' ``` ### Correlate logs with meeting IDs Always include meeting context: ```javascript const meetingContext = { uuid: client.uuid(), streamId: client.streamId(), }; logger.info("Processing started", meetingContext); ``` ## Resources - [RTMS SDK Repository](https://github.com/zoom/rtms) - Core SDK documentation - [RTMS Quickstart App](https://github.com/zoom/rtms-quickstart-js) - Example implementation - [RTMS Developer Documentation](/docs/rtms/) - Example implementation - [Zoom Developer Forum](https://devforum.zoom.us/) - Community support and discussions ## Summary The RTMS SDK provides flexible logging options through environment variables or programmatic configuration. For production use, disable SDK logging and implement custom logging within the callback functions to maintain full control over your logging infrastructure. This approach allows you to: - Integrate with existing logging frameworks - Add business-specific context to logs - Control log retention and rotation policies - Implement custom alerting and monitoring Need help? Join the conversation on the [Zoom Developer Forum](https://devforum.zoom.us/)!