Logger の設定

Red5 サーバサイドアプリでのロギングを試してみました。

javaflex などのコンパイル・ビルドに関しては、emacs の設定も含めて別記事(ant -find build.xml)としました。

ログファイル

クライアントはVODの再生アプリで、Red5 にアクセスしVODサービスを受けます。15秒間の動画が終了した後、クライアントを終了させました。次のようなログが得られます。パスは、「 c:/Program Files/Red5/log/newbieLogger.log 」です。

20:46:07.968 [main] DEBUG root - Starting up context newbieLogger
20:46:10.796 [Launcher:/newbieLogger] DEBUG o.e.Application - appStart: true
20:46:23.562 [NioProcessor-1] DEBUG o.e.Application - streamPlaylistItemPlay
20:46:23.562 [NioProcessor-1] DEBUG o.e.Application - __ item.getName: MaxFactor -powcealer 15s.flv
20:46:23.562 [NioProcessor-1] DEBUG o.e.Application - __ item.getSize: 637010
20:46:23.562 [NioProcessor-1] DEBUG o.e.Application - __ item.getLength: -1000
20:46:23.562 [NioProcessor-1] DEBUG o.e.Application - __ isLive: false
20:46:23.765 [NioProcessor-1] DEBUG o.e.Application - streamPlaylistItemPlay
20:46:23.765 [NioProcessor-1] DEBUG o.e.Application - __ item.getName: MaxFactor -powcealer 15s.flv
20:46:23.765 [NioProcessor-1] DEBUG o.e.Application - __ item.getSize: 637010
20:46:23.765 [NioProcessor-1] DEBUG o.e.Application - __ item.getLength: 0
20:46:23.765 [NioProcessor-1] DEBUG o.e.Application - __ isLive: false
20:46:23.796 [NioProcessor-1] DEBUG o.e.Application - streamPlaylistItemPlay
20:46:23.796 [NioProcessor-1] DEBUG o.e.Application - __ item.getName: MaxFactor -powcealer 15s.flv
20:46:23.796 [NioProcessor-1] DEBUG o.e.Application - __ item.getSize: 637010
20:46:23.796 [NioProcessor-1] DEBUG o.e.Application - __ item.getLength: -1000
20:46:23.796 [NioProcessor-1] DEBUG o.e.Application - __ isLive: false
20:46:43.203 [NioProcessor-1] DEBUG o.e.Application - appLeave


『 時:分:秒,ミリ秒 [スレッド名] モード クラス名 メッセージ 』
のようになっています。これはSLF4Jのレイアウトで指定したものです(後述)。

サーバサイド

フォルダ構成

少なくとも僕には、ちょっとややこしくなってきました。記事2009.10.20 はじめて記事2009.10.21 VOD のフォルダ構成を合わせたようなものになってます。

streams フォルダには VOD 再生用の動画ファイル。classes フォルダにはロギング用の設定ファイル。lib フォルダにはアプリケーション。red5-web.xmlred5にアプリを登録・設定を行うもの。それと、前回まで不要としていた、web.xml が必要になります。

red5-web.xml

これまでと変わりませんが、クラス名は Appication とし、Red5 の典型に沿いました。クライアントから見えるアプリ名は contextPath に記述した newbieLogger です。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
	  "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
  <bean id="web.context" class="org.red5.server.Context" autowire="byType"/>
  <bean id="web.scope" class="org.red5.server.WebScope"	init-method="register">
    <property name="server" ref="red5.server"/>
    <property name="parent" ref="global.scope"/>
    <property name="context" ref="web.context"/>
    <property name="handler" ref="web.handler"/>
    <property name="contextPath" value="/newbieLogger"/>
    <property name="virtualHosts" value="localhost, 127.0.0.1"/>
  </bean>
  <bean id="web.handler" 
	class="org.eggtoothcroc.Application" singleton="true"/>
</beans>
web.xml

LogBack と呼ばれる、Red5 で推奨されているロギングを使う為の設定です。LoggingSetup に説明があります。

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 
   xmlns="http://java.sun.com/xml/ns/j2ee" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
   version="2.4"> 
 
    <display-name>newbieLogger</display-name>
	
    <context-param>
      <param-name>webAppRootKey</param-name>
      <param-value>/newbieLogger</param-value>
    </context-param>
    
    <listener>
        <listener-class>org.red5.logging.ContextLoggingListener</listener-class>
    </listener>
    
    <filter>
        <filter-name>LoggerContextFilter</filter-name>
        <filter-class>org.red5.logging.LoggerContextFilter</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>LoggerContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
   
</web-app>
classes/logback-newbieLogger.xml

classes フォルダに無いと動きませんが、LoggingSetup には、lib フォルダでも良いとされています。コメントにしてある、jmxConfigurator は無くても動いています。何故かは追求していません。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

  <contextName>newbieLogger</contextName>
  <!-- jmxConfigurator contextName="newbieLogger"/ -->

  <appender name="NEWBIE" class="ch.qos.logback.core.FileAppender">
    <File>log/newbieLogger.log</File>
    <Append>false</Append>
    <Encoding>UTF-8</Encoding>
    <BufferedIO>false</BufferedIO>
    <ImmediateFlush>true</ImmediateFlush>
    <layout class="ch.qos.logback.classic.PatternLayout">
      <Pattern>
	%date{HH:mm:ss.SSS} [%thread] %-5level %logger{15} - %msg%n
      </Pattern>
    </layout>
  </appender>

  <root>
    <appender-ref ref="NEWBIE" />
  </root>	

  <logger name="org.eggtoothcroc.newbieLogger">
    <level value="DEBUG" />
  </logger>		

</configuration>

一番気になったのが、レイアウトのパタン(layout, Pattern)です。これで、出力のフォーマットを調整します。詳細は、LogBackマニュアル第5章レイアウトにあります。「%date」のみの指定は、『YYYY-MM-DD HH:mm:ss,SSS』となります。また、「%logger{15}」の数値指定は長くなりがちなクラス名を適当に省略してくれます。次のような例と比較して下さい。

<layout class="ch.qos.logback.classic.PatternLayout">
  <Pattern>
     %date [%thread] %-5level %logger - %msg%n
  </Pattern>
</layout>

2009-10-23 21:17:19,328 [NioProcessor-1] DEBUG org.eggtoothcroc.Application - streamPlaylistItemPlay

サーバサイドアプリケーション(Application.java)

Red5 マニュアル第3章 移行ガイドに appStart など、アプリ実行時に呼ばれる関数などの説明があります。また、IScope, IClient, IPlayItem のメンバなどについては、Red5 のクラスライブラリAPIを参照しました。

package org.eggtoothcroc;

import org.slf4j.Logger;
import org.red5.logging.Red5LoggerFactory;

import org.red5.server.adapter.ApplicationAdapter;
import org.red5.server.api.IScope;
import org.red5.server.api.IClient;

import org.red5.server.api.stream.IPlayItem;
import org.red5.server.api.stream.IPlaylistSubscriberStream;

public class Application extends ApplicationAdapter
{
  private static Logger log
    =Red5LoggerFactory.getLogger(Application.class, "newbieLogger");

  @Override public boolean appStart(IScope app)
  {
    boolean b =super.appStart(app);
    log.debug("appStart: {}", b);
    return b;
  }

  @Override 
    public void streamPlaylistItemPlay(IPlaylistSubscriberStream stream, 
				       IPlayItem item, boolean isLive)
  {
    super.streamPlaylistItemPlay(stream, item, isLive);
    log.debug("streamPlaylistItemPlay");
    log.debug("__ item.getName: {}", item.getName());
    log.debug("__ item.getSize: {}", item.getSize());
    log.debug("__ item.getLength: {}", item.getLength());
    log.debug("__ isLive: {}", isLive);
  }

  @Override public void appLeave(IClient client, IScope app)
  {
    super.appLeave(client,app);
    log.debug("appLeave");
  }
}

クライアントサイド

flex4-air1.5 のアプリです。以前の記事2009.10.21 VOD と同じです。これまでの経緯を引きずり名前は SuonoDolce になっています。

<?xml version="1.0" encoding="utf-8"?>

<s:WindowedApplication
   xmlns:fx="http://ns.adobe.com/mxml/2009"
   xmlns:s="library://ns.adobe.com/flex/spark"
   xmlns:mx="library://ns.adobe.com/flex/halo">

  <s:VideoPlayer autoPlay="true">
    <s:StreamingVideoSource
       serverURI="rtmp://localhost/newbieLogger">
      <s:StreamItem streamName="MaxFactor -powcealer 15s.flv"/>
    </s:StreamingVideoSource>
  </s:VideoPlayer>

</s:WindowedApplication>

起動は次のようにします。

$ adl.exe SuonoDolce.xml