Configure VHost and application context logging for Wowza Streaming Engine (legacy)

Wowza Streaming Engine™ media server software uses the Apache Log4j Java logging framework for logging. This article describes how to use the context logging feature in Log4j to assign different loggers to different levels or contexts. Log4j defines these contexts much like you would define a package class path using dot notation (for example, com.mypackage.myclass).

Note: The instructions in this article apply to Wowza Streaming Engine 4.8.5 and earlier. For version 4.8.8.01 and later, see Configure VHost and application context logging for Wowza Streaming Engine.

Contents


About Log4j context logging
Extending Log4j context logging
Enabling the default contexts
Creating custom logging contexts and appenders
Logging messages to a specific context

About Log4j context logging


When using context logging, loggers are created at different positions in the context. The different loggers are arranged in a hierarchy based on their position in the context. When a message is set to log at a low context (for example, com.mypackage.myclass), it's also logged at all higher contexts where a logger is configured (for example, com.mypackage). Messages set to log at a higher context aren't written to lower context loggers.

At the top of the hierarchy is a special logger called the root logger. All messages are logged here. This is the only logger that's enabled by default in Wowza Streaming Engine.

For the root logger and for each context, you can set the severity level of messages that are logged. When a level is set at a specific context, that level overrides the level set at higher contexts and for the root logger. As an example, you could set the DEBUG level on an application context so that all application debug messages are written to the application log file and higher context files.

For more information about the Apache Log4j framework, see Log4j Architecture.

Extending Log4j context logging


Normally with Log4j, an application uses existing class or package paths to define the different logging contexts and then provides a configuration file to set up the different loggers. Wowza Streaming Engine extends this by providing some default contexts for streaming with the ability to configure loggers based on different server operation levels. You can also create your own custom contexts as will be explained later.

The following default contexts are included with Wowza Streaming Engine:
 
  • log4j.rootCategory. This is the top of the hierarchy. All messages are logged here. The default level is INFO, meaning that all INFO and higher level messages (WARN, ERROR, FATAL) are logged. Lower level messages from other contexts are also logged if that context is enabled and a lower level is set.
     
  • log4j.logger.[vhost]. All messages set to log at the [vhost] level are logged here. The default level is INFO. These messages are also logged by the root logger at the level set by the [vhost] context.
     
  • log4j.logger.[vhost].[application]. All application messages at the set level and higher are logged here and at the [vhost] and root loggers. The default level is INFO.
     
  • log4j.logger.[vhost].[application].[appInstance]. All appInstance messages at the set level and higher are logged here and at the [application], [vhost], and root loggers. Because there's usually only one appInstance per application. This context isn't configured by default. See Creating custom logging contexts and appenders to enable appInstance level logging if needed.
Wowza Streaming Engine also separates messages into different categories based on events that happen for each category. The default categories are: server, vhost, application, session, stream, and rtsp.

If a category isn't defined for a message, the message is logged as a server message. For standard logging messages, these categories are related to the different contexts and are logged to the correct context (and higher contexts) automatically, if it's enabled and at the same or higher level.

You can log your own messages at the context you choose and you're not restricted to using the default categories and events. You can add your own categories and events as needed. For more information about how to log to specific categories, see information about WMSLogger in the Wowza Streaming Engine Java API reference documentation.

Enabling the default contexts


Logging is configured in the [install-dir]/conf/log4j.properties file. By default, only the root logger is configured and enabled in Wowza Streaming Engine. The file includes sample configurations for enabling the [vhost] and [vhost].[application] contexts (these are commented-out by default). To enable one of these contexts, remove the comment marks and restart Wowza Streaming Engine.

The root logger and each context has a separate appender for each log file type. The appender is what actually writes the file. If you don't want a certain appender to be enabled, remove it from the line that defines the context. For the root logger, this is the first line. For other contexts, this is the line that begins with log4j.logger.

You can use wildcards to match the [vhost], [application] and [appInstance] names so that you don't have to define a separate configuration for every [vhost], [application], or [appInstance]. Contexts are created automatically for matching wildcards. The wildcards are:
 
  • ${com.wowza.wms.context.VHost}
     
  • ${com.wowza.wms.context.Application}
     
  • ${com.wowza.wms.context.ApplicationInstance}
When you look in the [install-dir]/logs folder, you'll see a new folder created for the VHost. If you enabled the [vhost].[application] context, you'll see folders created in the VHost folder for each application that's started. In each folder for the enabled contexts, you should see a wowzastreamingengine_access.log file being created for each appender that's enabled.

Creating custom logging contexts and appenders


The following example adds an [appInstance] context and an appender to write a wowzastreamingengine_access.log file to the appropriate [appInstance] folder:

log4j.logger.${com.wowza.wms.context.VHost}.${com.wowza.wms.context.Application}.${com.wowza.wms.context.ApplicationInstance}=INFO, ${com.wowza.wms.context.VHost}_${com.wowza.wms.context.Application}_${com.wowza.wms.context.ApplicationInstance}_access

log4j.appender.${com.wowza.wms.context.VHost}_${com.wowza.wms.context.Application}_${com.wowza.wms.context.ApplicationInstance}_access=org.apache.log4j.DailyRollingFileAppender
log4j.appender.${com.wowza.wms.context.VHost}_${com.wowza.wms.context.Application}_${com.wowza.wms.context.ApplicationInstance}_access.DatePattern='.'yyyy-MM-dd
log4j.appender.${com.wowza.wms.context.VHost}_${com.wowza.wms.context.Application}_${com.wowza.wms.context.ApplicationInstance}_access.File=${com.wowza.wms.ConfigHome}/logs/${com.wowza.wms.context.VHost}/${com.wowza.wms.context.Application}/${com.wowza.wms.context.ApplicationInstance}/wowzastreamingengine_access.log
log4j.appender.${com.wowza.wms.context.VHost}_${com.wowza.wms.context.Application}_${com.wowza.wms.context.ApplicationInstance}_access.layout=com.wowza.wms.logging.ECLFPatternLayout
log4j.appender.${com.wowza.wms.context.VHost}_${com.wowza.wms.context.Application}_${com.wowza.wms.context.ApplicationInstance}_access.layout.Fields=x-severity,x-category,x-event;date,time,c-client-id,c-ip,c-port,cs-bytes,sc-bytes,x-duration,x-sname,x-stream-id,x-spos,sc-stream-bytes,cs-stream-bytes,x-file-size,x-file-length,x-ctx,x-comment
log4j.appender.${com.wowza.wms.context.VHost}_${com.wowza.wms.context.Application}_${com.wowza.wms.context.ApplicationInstance}_access.layout.OutputHeader=true
log4j.appender.${com.wowza.wms.context.VHost}_${com.wowza.wms.context.Application}_${com.wowza.wms.context.ApplicationInstance}_access.layout.QuoteFields=false
log4j.appender.${com.wowza.wms.context.VHost}_${com.wowza.wms.context.Application}_${com.wowza.wms.context.ApplicationInstance}_access.layout.Delimeter=tab
You can also define your own logging contexts that either extend the default contexts or are part of a separate hierarchy. One scenario where this might be needed is if you're working with a third-party product that uses Log4j, but with different contexts. To create your own contexts, add the information to the [install-dir]/conf/log4j.properties file to create the logger and appenders. You can also create loggers and appenders dynamically by using Log4j and Wowza Streaming Engine logging APIs. For more information, see the Wowza Streaming Engine Server-Side API documentation.

Logging messages to a specific context


Messages that are logged during normal server operation are written to the correct context automatically based on the message category. For custom modules, the static method provided by ModuleBase.getLogger() can be used to return a reference to the root logger so that logging messages that are written using this method are written only to the root logger irrespective of the category or event that's set. For classes that don't extend ModuleBase, a static factory method (WMSLoggerFactory.getLogger(Class classObj) can be used to return a specific context logger. The WMSLoggerFactory.getInstance().getLoggerObj(String context) factory method gets a custom context.

The following example shows how to use the different methods to get the root logger or a specific context logger:

package com.wowza.wms.example.logging;

import com.wowza.wms.application.IApplicationInstance;
import com.wowza.wms.logging.WMSLogger;
import com.wowza.wms.logging.WMSLoggerFactory;
import com.wowza.wms.module.ModuleBase;

public class LoggingExample extends ModuleBase {

public void onAppStart(IApplicationInstance appInstance) {
String fullname = appInstance.getApplication().getName() + "/" + appInstance.getName();

// Get a reference to the VHost logger object.
WMSLogger vhostLogger = WMSLoggerFactory.getLoggerObj(appInstance.getVHost());

// Get a reference to the Application logger object.
WMSLogger appLogger = WMSLoggerFactory.getLoggerObj(appInstance.getApplication());

// Get a reference to the Application Instance logger object.
WMSLogger appInstLogger = WMSLoggerFactory.getLoggerObj(appInstance);

// Get a reference to custom context logger object.
WMSLogger customLogger = WMSLoggerFactory.getInstance().getLoggerObj("my.custom.logging.context");

// Write a message to just the top level logger.
getLogger().info("Top level onAppStart: " + fullname);

// Write a message to the VHost level logger.
vhostLogger.info("VHost logger onAppStart: " + fullname);

// Write a message to the Application level logger.
appLogger.info("Application logger onAppStart: " + fullname);

// Write a message to the Application Instance level logger.
appInstLogger.info("Application Instance level onAppStart: " + fullname);

// Write a message to the custom logger.
customLogger.info("Custom level onAppStart: " + fullname);
}
}