この付録では、OCMSのAccounting Event APIについて説明します。内容は次のとおりです。
logEvent(SipServletRequest req, Map<Object, Object> additional)メソッド
logEvent(SipServletResponse resp, Map<Object, Object> additional)メソッド
OCMSには、アカウンティングと請求に使用できるSIPイベント・データを作成するためのAccounting Event APIが付属しています。イベント出力データを後処理して、CDRを作成できます。
Accounting Event APIは、次の2つのインタフェースで構成されています。
oracle.sdp.sipservletframework.eventlogger.EventLoggerFactory
oracle.sdp.sipservletframework.eventlogger.EventLogger
コンテナは、ServletContext属性から使用できるoracle.sdp.sipservlet.EventLoggerFactory.EVENT_LOGGER_FACTORYという名前のEventLoggerFactoryインスタンスを作成します。文字列そのものは使用できません。次のように指定する必要があります。
EventLoggerFactory elf = getServletContext().getAttribute(oracle.sdp.sipservletframework.eventlogger. EventLoggerFactory.EVENT_LOGGER_FACTORY
EventLoggerインタフェースは、EventLoggerFactory.getLogger(String loggerName)メソッドによって作成されるログ出力によって実装されます。EventLoggerインスタンスは、実際のロギングに内部でApache Log4jを使用します。Log4jを使用すると、出力先をファイルや集中化されたログ・サーバー(syslogを使用)などに柔軟に設定できます。
EventLoggerインタフェースには、ロギング・イベント用の3つのメソッドがあります(例C-1を参照)。
logEvent(SipServletRequest req, Map<Object, Object> additional)
logEvent(SipServletResponse resp, Map<Object, Object> additional)
logEvent(Map<Object, Object> event, String category)
例C-1 EventLoggerインタフェースでのイベントのロギング
public interface EventLogger
{
public void logEvent(SipServletRequest req, Map<Object, Object> additional);
public void logEvent(SipServletResponse resp, Map<Object, Object> additional);
public void logEvent(Map<Object, Object> event, String category);
public boolean isEnabled(SipServletRequest req);
public boolean isEnabled(SipServletResponse resp);
public boolean isEnabled(String category);
}
logEvent(SipServletResponse resp, Map<Object, Object> additional)メソッドは、指定された追加イベント属性とともにリストされた特性リクエスト属性を使用してイベントを記録します。表C-1は、logEventメソッドのリクエスト属性の説明です。イベントは、次のLog4jカテゴリ名に記録されます。
"eventlogger." + loggerName + ".REQUEST." + method.
表C-1 logEvent(SipServletRequest req, Map<Object, Object> additional)メソッドのリクエスト属性
| 属性 | 説明 |
|---|---|
|
RequestUri |
Request-URIの値。 |
|
Method |
methodの値。 |
|
To |
Toヘッダーの値。 |
|
From |
Fromヘッダーの値。 |
|
Call-ID |
Call-IDヘッダーの値。 |
|
CSeq |
CSeqヘッダーの値。 |
|
Via |
セミコロン(;)で区切られた、すべてのViaヘッダーの値の文字列。 |
|
Content-Type |
Content-Typeヘッダーの値、または""。 |
|
Content-Length |
Content-Lengthヘッダーの値、または""。 |
|
MEDIA |
セミコロン(;)で区切られた、すべてのSDPメディア行(m=に続く部分)の値の文字列。SDPコンテンツが存在しない場合、INVITEリクエストのこの属性のみが含まれます。 |
|
Service |
イベントを生成するサービスの名前(完全なLog4jカテゴリ名)。 |
public void logEvent(SipServletResponse resp, Map<Object, Object> additional)メソッドは、指定された追加イベント属性とともに、表C-2にリストされた特性レスポンス属性を使用してイベントを記録します。イベントは、次の完全なLog4jカテゴリ名に記録されます。
"eventlogger." + loggerName + ".RESPONSE." + method + "." + statuscode.
表C-2は、public void logEvent(SipServletResponse resp, Map<Object, Object> additional)の属性の説明です。
表C-2 logEvent(SipServletResponse resp, Map<Object, Object> additional)メソッドのレスポンス属性
| 属性 | 説明 |
|---|---|
|
StatusCode |
レスポンスのステータス・コード。 |
|
Method |
methodの値。 |
|
To |
Toヘッダーの値。 |
|
From |
Fromヘッダーの値。 |
|
Call-ID |
Call-IDヘッダーの値。 |
|
CSeq |
CSeqヘッダーの値。 |
|
Via |
セミコロン(;)で区切られた、すべてのViaヘッダーの値の文字列。 |
|
Content-Type |
Content-Typeヘッダーの値、または""。 |
|
Content-Length |
Content-Lengthヘッダーの値、または""。 |
|
MEDIA |
セミコロン(;)で区切られた、すべてのSDPメディア行(m=に続く部分)の値の文字列。SDPコンテンツが存在しない場合、INVITEリクエストのこの属性のみが含まれます。 |
|
Service |
イベントを生成するサービスの名前(完全なLog4jカテゴリ名)。 |
public void logEvent(Map <Object, Object> event, String category)メソッドは、任意の種類のイベントを属性マップの形式で記録できる汎用メソッドです。表C-3にリストされている属性も、Service属性マップに追加されます。イベントは完全なLog4jカテゴリ名に記録され、次のいずれかの形式をとります。
"eventlogger." + loggerName
"eventlogger." + loggerName + "." + category(null以外のカテゴリが指定された場合)
表C-3は、このメソッドの属性のリストです。
表C-3 logEvent(Map <Object, Object> event, String category)メソッドの属性
| 属性キー | 属性値の説明 |
|---|---|
|
Service |
イベントを生成するサービスの名前(完全なLog4jカテゴリ名)。 |
isEnabledメソッドは、Log4jフィルタが、同じ引数を持つlogEventメソッドのコールが記録されるように構成されている場合のみtrueを返します。例C-2は、サーブレットでAccounting Event APIを使用して、すべてのリクエストとレスポンスのイベントを記録する方法を示します。
public class EventTestServlet extends SipServlet
{
private EventLogger eventLogger;
public void init() {
ServletContext sc = getServletContext();
EventLoggerFactory factory = (EventLoggerFactory) sc
.getAttribute("oracle.sdp.sipservlet.EventLoggerFactory");
eventLogger = factory.getLogger(EventTestServlet.class);
}
public void doRequest(SipServletRequest req) {
if (eventLogger.isEnabled(req)) {
eventLogger.logEvent(req, null);
}
URI requestURI = req.getRequestURI();
req.getProxy().proxyTo(requestURI);
}
public void doResponse(SipServletResponse resp) {
if (eventLogger.isEnabled(resp)) {
Map additional = new HashMap();
additional.put("foo", "bar")
eventLogger.logEvent(resp, additional);
}
}
}
Log4jは次のタスクを実行します。
イベントのフィルタ処理
イベントのフォーマット
イベントの送信先の決定
これらの構成は、Log4j構成ファイル(log4j.xml)を編集して、実行時に変更できます。
Log4jの詳細は、http://logging.apache.org/log4jを参照してください。
Log4j構成ファイル(log4j.xml)のカテゴリをコメントにするかどうかで、例C-3に示すように、イベントを有効または無効にすることができます。Log4jの構成により、サーブレットから生成されたイベントをevent.logファイルに記録するかどうかが決まります。
例C-3は、EventTestServletらのINVITEおよびBYEリクエストに対する200(「OK」)レスポンスを表示するLog4jの構成を示しています。これらのレスポンスは、event.logファイルに記録されます。
例C-3 BYEリクエストとINVITEリクエストに対する200(OK)レスポンスを表示するLog4jの構成
<category name="eventlogger.com.example.EventTestServlet.RESPONSE.INVITE.200" additivity="false"> <priority value="ALL"/> <appender-ref ref="EVENTLOGGER"/> <appender-ref ref="EVENTLOGGER_LOCAL" /> </category> <category name="eventlogger.com.example.EventTestServlet.REQUEST.BYE" additivity="false"> <priority value="ALL"/> <appender-ref ref="EVENTLOGGER"/> <appender-ref ref="EVENTLOGGER_LOCAL" /> </category>
RESPONSE/REQUESTのクラス名とタイプの注釈に注意してください。
event.logのイベントのフォーマットは、Log4jのレイアウト・クラスによって決まります。SipServletのイベント・ロギングに使用されるデフォルトのレイアウト・クラスはoracle.sdp.eventlogger.BasicLayoutで、各イベントを1行に記録し、属性をカンマで区切ります。その後、属性キーと値でメソッドtoString()がコールされ、等号(=)で連結されます。BasicLayoutクラスも、表C-4で説明する属性を追加します。必要に応じて、新しいレイアウト・クラスを作成できます。
| 属性キー | 属性値の説明 |
|---|---|
|
Creation Time |
yyyy-MM-dd'T'HH:mm:ss.SSS'Z'の形式で表されるイベント作成日時 |
|
TimeZoneOffset |
GMTからのオフセット(分) |
構成によって、コンソール、ファイル、syslog、リモート・ソケット、JMSなどのイベントの送信先も決まります。例C-4では、イベントは、syslogを使用して、localhost (127.0.0.1)のファイルに記録されます。Log4jの詳細は、http://logging.apache.org/log4jを参照してください。
<appender name="EVENTLOGGER_LOCAL" class="org.oracle.logging.appender.RollingFileAppender"> <param name="File" value="/var/log/sdp/events.log"/> <param name="Append" value="true"/> <param name="MaxFileSize" value="100000KB"/> <param name="MaxBackupIndex" value="10"/> <layout class="oracle.sdp.eventlogger.BasicLayout"> </layout> </appender>
BasicLayoutの出力例
各属性が1行ずつ表示され、キーは太字で示されます。
REQUEST.INVITE:
CreationTime=2005-04-15T07:50:51.767Z, To=<sip:08505@example.com>;tag=0f54d930-f916-4702-8293-d8b014810a29, TimeZoneOffset=120, Method=INVITE, Content-Type=application/sdp, Service=eventlogger.com.example.EventTestServlet.REQUEST.INVITE, Call-ID=8e02578d-2021-4d06-b98d-bf9827c93003@192.0.2.0, RequestUri=sip:08505@example.com;transport=TCP, MEDIA=audio 8502 RTP/AVP 97 103 100 101 0 8 102 18 107, CSeq=2 INVITE, Content-Length=418, Via=SIP/2.0/TCP 192.0.2.0:5060;branch=z9hG4bKc549d2be44c901ac050be55ff622e1c8; rport; SIP/2.0/TCP 192.0.2.0:2051;received=192.0.2.0;branch=z9hG4bK-b20b96e2- 1fac-4500-8030-580da1d81051.1;rport=2051, From=Alice <sip:alice@example.com>;tag=35ec862a-1d03-4f78-904c- 1accf44d15fe
RESPONSE.INVITE.200
CreationTime=2005-04-15T07:50:51.830Z,To=<sip:08505@example.com>;tag=0f54d930-f916-4702-8293-d8b014810a29, TimeZoneOffset=120, Method=INVITE, Content-Type=application/sdp, Service=eventlogger.com.example.EventTestServlet.RESPONSE.INVITE.200, Call-ID=8e02578d-2021-4d06-b98d-bf9827c93003@192.0.2.0, StatusCode=200, MEDIA=audio 8502 RTP/AVP 0 8, CSeq=2 INVITE, Content-Length=392, Via=SIP/2.0/TCP 192.0.2.0:5060;branch=z9hG4bKc549d2be44c901ac050be55ff622e1c8; rport; SIP/2.0/TCP 192.0.2.0:2051;received=192.0.2.0;branch=z9hG4bK-b20b96e2- 1fac-4500-8030-580da1d81051.1;rport=2051, From=Alice <sip:alice@example.com>;tag=35ec862a-1d03-4f78-904c- 1accf44d15fe