• How to configure VHost and application context logging

    Wowza media server software uses the Apache Log4j Java logging framework for all 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: Wowza Media Server™ 3 or later is required.

    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 in a default Wowza media server software installation.

    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 media server software 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 server software:

    • 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.


    The Wowza media server 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. For more information about the categories and events and the different fields that are logged, see "Logging" in the Wowza Streaming Engine User's Guide.

    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 the WMSLogger API documentation in the Wowza Streaming Engine Server-Side API.

    Enabling the default contexts


    Logging is configured in the [install-dir]/conf/log4j.properties file. In the default Wowza media server installation, only the root logger is configured and enabled. 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 the server.

    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 wowzamediaserver_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 wowzamediaserver_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}/wowzamediaserver_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 3rd-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 media server software logging APIs; however, this is outside the scope of this article. 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);
        }
    }

    If you're having problems or want to discuss this article, post in our forum.