Posted at

Apach CamelのMessage Historyパターンで、メッセージのフローを確認する


はじめに

今回紹介するMessage Historyパターンは、Eneterprise Integration Patternsの1つになります。

Camelではコンポーネントやプロセッサー間はメッセージを介しており疎結合になっています。

そのため、具体的にメッセージがどのようなフローでルートを通ってきたかが分からなくなります。

Message Historyパターンではメッセージに履歴(足跡みたいなもの)をつけていくことで、デバッグや解析に役立てることができます。

MessageHistory.gif

画像の出典:Enterprise Integration Patterns - Message History


例外発生時のMessage History

Camelで開発していてMessage Historyを見る機会の代表例は例外発生時です。

CamelではMessage Historyパターンが自動で適用され、例外発生時にデフォルトでMessage Historyが表示されるようになっています。

以下のXMLはルートの途中で強制的にRuntimeExceptionを発生させています。

        <route>

<from uri="timer:trigges?repeatCount=1" />
<to uri="direct:a" />
<to uri="direct:b" />
<log message="body: ${body}" />
</route>
<route>
<from uri="direct:a" />
<log message="route a" />
</route>
<route>
<from uri="direct:b" />
<throwException exceptionType="java.lang.RuntimeException" message="test exception" />
<log message="route b" />
</route>

このルートを実行すると以下のログが出力されます。

"Message History"の文字列以下がMessage Historyの表示です。

メッセージが通った順番にRoute Id, Processor Id, Processorと実行時間(Elapsed)が表示されています。また、今回は例外のため、Exchange中のStackTraceの情報も表示されています。

[2019-02-14 22:15:52.294], [ERROR], o.a.c.p.DefaultErrorHandler, Camel (camel-1) thread #1 - timer://trigges, org.apache.camel.processor.DefaultErrorHandler, Failed delivery for (MessageId: ID-mky-PC-1550150150431-0-2 on ExchangeId: ID-mky-PC-1550150150431-0-1). Exhausted after delivery attempt: 1 caught: java.lang.RuntimeException: test exception

Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId ProcessorId Processor Elapsed (ms)
[route1 ] [route1 ] [timer://trigges?repeatCount=1 ] [ 16]
[route1 ] [to1 ] [direct:a ] [ 8]
[route2 ] [log2 ] [log ] [ 5]
[route1 ] [to2 ] [direct:b ] [ 0]
[route3 ] [throwException1 ] [throwException[ref:null] ] [ 1]

Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------
java.lang.RuntimeException: test exception
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_172]
~省略~


XML DSLでMessage Historyを表示する

最初の例は例外発生時にMessage Historyを表示させることを確認しましたが、明示的にMessage Historyを表示させるやり方を見ていきましょう。

XML DSLでMessage Historyを明示的に表示するには、messageHistoryプロパティを使用します。

messageHistoryプロパティを使用したルートの例は以下のようになります。

        <route>

<from uri="timer:trigges?repeatCount=1" />
<to uri="direct:a" />
<to uri="direct:b" />
<log message="body: ${body}" />
</route>
<route>
<from uri="direct:a" />
<log message="route a" />
</route>
<route>
<from uri="direct:b" />
<log message="${messageHistory}" />
<log message="route b" />
</route>

このルートを実行すると以下のようにMessage Historyが表示されます。

例外発生時のMessage Historyとほぼ同じ内容ですが、今回は例外ではないためStackTraceは表示されません。

Message History

---------------------------------------------------------------------------------------------------------------------------------------
RouteId ProcessorId Processor Elapsed (ms)
[route1 ] [route1 ] [timer://trigges?repeatCount=1 ] [ 14]
[route1 ] [to1 ] [direct:a ] [ 7]
[route2 ] [log2 ] [log ] [ 4]
[route1 ] [to2 ] [direct:b ] [ 0]
[route3 ] [log3 ] [log ] [ 0]

Exchange
---------------------------------------------------------------------------------------------------------------------------------------
Exchange[
Id ID-mky-PC-1550150269136-0-1
ExchangePattern InOnly
Headers {breadcrumbId=ID-mky-PC-1550150269136-0-1, firedTime=Thu Feb 14 22:17:50 JST 2019}
BodyType null
Body [Body is null]


Java DSLでMessage Historyを表示する

次にJava DSLでも明示的にMessage Historyを表示してみます。

こちらもmessageHistoryプロパティを使用するだけです。出力されるMessage HistoryはXML DSLと同じであるため省略します。

                    from("timer:trigger?repeatCount=1")

.to("direct:a")
.to("direct:b")
.log("Body-before: ${body}")
.log("Body-after: ${body}");
from("direct:a")
.log("route a");
from("direct:b")
.log("${messageHistory}")
.log("route b");


プロセッサ中でMessage Historyを表示する

プロセッサ中でMessage Historyを出力するには、MessageHelperクラスのdumpMessageHistoryStacktraceメソッドを使用します。dumpMessageHistoryStacktraceメソッドを使用することで整形された文字列でMessage Historyを取得することができます。

以下はプロセッサーのprocessメソッドでdumpMessageHistoryStacktraceメソッドを使用して、Message Historyを標準出力に表示した例になります。

                public void process(Exchange exchange) {

String msgHist = MessageHelper.dumpMessageHistoryStacktrace(exchange, new DefaultExchangeFormatter(), false);
System.out.println(msgHist);
}

dumpMessageHistoryStacktraceメソッドの3番目の引数はStackTraceを表示するかどうかのフラグです。

trueにしておくと例外発生時にStackTraceが一緒に表示されるようになります。この例中では"false"に設定しています。


参考