読者です 読者をやめる 読者になる 読者になる

割と普通なブログ

Microsoft Azure や ASP.NET、Java EE 系の話題を記載します

Application Insights for Java の JavaEE 対応

Microsoft Azure 上でアプリに対して運用監視を行うサービスとして定評のある Application Insights が Java SDK に対応 したことはご存じの方も多いと思う。今回は新たに JavaEE 向けに追加機能が提供されたので紹介する。
また、今回利用したサンプルは https://github.com/normalian/JavaEEAppInsigtsApp に配置しているので参照してほしい。

利用方法

インターセプタとして提供されるため 0.9.6 以上のバージョンの applicationinsights-web.jar を参照する(以下は pom.xml の記載例)。

<dependency>
	<groupId>com.microsoft.azure</groupId>
	<artifactId>applicationinsights-web</artifactId>
	<version>0.9.6</version>
</dependency>

上記の jar に含まれるクラスのうち、以下を利用する。

まずは beans.xml に以下の様な記載をし、インターセプタを有効化する。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
	<interceptors>
		<class>com.microsoft.applicationinsights.web.javaee.RequestNameInterceptor</class>
	</interceptors>
</beans>

次に RequestName アノテーションを以下の様に監視対象のクラスに付与する。

package com.domain.mavenjavaeeapp1.action;

import com.domain.mavenjavaeeapp1.dto.IndexViewDto;
import com.microsoft.applicationinsights.web.javaee.RequestName;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;

@RequestScoped
@Named
public class IndexAction {

	@Inject
	IndexViewDto indexViewDto;

	@RequestName
	public String do1(String arg) {
		System.out.println("IndexAction#do1(" + arg + ") = "
				+ indexViewDto.getName());
		return "/index.xhtml";
	}

	public String do2() {
		return "0";
	}
}

参考となるが、利用する画面は以下になる。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html">
<h:head>
	<script type="text/javascript">
	//<![CDATA[
    var appInsights=window.appInsights||function(config){
        function s(config){t[config]=function(){var i=arguments;t.queue.push(function(){t[config].apply(t,i)})}}var t={config:config},r=document,f=window,e="script",o=r.createElement(e),i,u;for(o.src=config.url||"//az416426.vo.msecnd.net/scripts/a/ai.0.js",r.getElementsByTagName(e)[0].parentNode.appendChild(o),t.cookie=r.cookie,t.queue=[],i=["Event","Exception","Metric","PageView","Trace"];i.length;)s("track"+i.pop());return config.disableExceptionTracking||(i="onerror",s("_"+i),u=f[i],f[i]=function(config,r,f,e,o){var s=u&&u(config,r,f,e,o);return s!==!0&&t["_"+i](config,r,f,e,o),s}),t
    }({
        instrumentationKey:"your key"
    });
    
    window.appInsights=appInsights;
    appInsights.trackPageView();
  //]]>
</script>
	<title>Facelet Title</title>
</h:head>
<h:body>
	<span>hello Facelets</span>
	<h:form>
		<div>
			名前を入力して下さい
			<h:inputText value="#{indexViewDto.name}" />
		</div>
		<h:commandButton value="button"
			action="#{indexAction.do1('some argument')}" />
	</h:form>
</h:body>
</html>

結果

上記のアプリケーションに対してブラウザアクセスを行い、"button" のボタンを押下することで以下の様にアクセスされたアクション/HTTPメソッドが確認できる。
f:id:waritohutsu:20150629232426p:plain

Windows 上で WildFly 8.x 実行時に "java.net.BindException: Address already in use" が発生する

WildFly 8.x, "java.net.BindException: Address already in use" on fresh install in windows Vista/7/8 の記事に記載があるが、WindowsVista, 7, 8 )で WildFly 8.x 実行時に "java.net.BindException: Address already in use" が発生する場合がある。

普通は「Tomcat を起動しっぱなしだった」や「JBoss AS や別バージョンの WildFly を起動しっぱなしだった」が原因だが、どうやら NVIDIA Network Service が問題らしい。WindowsVista, 7, 8 )で NVIDIA を利用しており、WildFly 8.x を利用する場合は以下のプロセスを停止することで暫定対策ができる。
f:id:waritohutsu:20150605143726p:plain

DocumentDB の Java SDK で jackson を使う場合の TIPS

随分前に発表された DocumentDB だが、意外にサンプルが少ないので触ってみたところを軽く記載する。DocumentDB は JSON 形式でデータをやり取りするため、Java オブジェクトを JSON 形式に変換する必要がある。

Build a Java web application using DocumentDB に記載されたサンプルを見ると Project Lombok を利用しているが、今回は jackson を使ってみた。

まず、あらかじめ管理ポータルから DocumentDB アカウントを作成し、"TestDB" というデータベースの作成、"TestCollection" というコレクションの作成、以下の様にドキュメントの作成を実施する。
f:id:waritohutsu:20150524151856p:plain

次に、管理ポータルからエンドポイントとキーを取得し、以下のコードを実行する。

package com.mydomain.documentdb;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.microsoft.azure.documentdb.ConnectionPolicy;
import com.microsoft.azure.documentdb.ConsistencyLevel;
import com.microsoft.azure.documentdb.Database;
import com.microsoft.azure.documentdb.Document;
import com.microsoft.azure.documentdb.DocumentClient;
import com.microsoft.azure.documentdb.DocumentClientException;
import com.microsoft.azure.documentdb.DocumentCollection;
import com.microsoft.azure.documentdb.RequestOptions;
import com.mydomain.model.Person;

public class SampleTest {

	// Define an id for your database and collection
	private static final String DATABASE_ID = "TestDB";
	private static final String COLLECTION_ID = "TestCollection";

	// documentdb.properties から情報を取得
	private static String END_POINT;
	private static String MASTER_KEY;

	private static DocumentClient documentClient;
	private static Database databaseCache;
	private static DocumentCollection collectionCache;

	@Before
	public void testInitialize() throws IOException {
		// TODO: 外部設定ファイルを作成すること
		String path = "documentdb.properties";
		InputStream in = SampleTest.class.getClassLoader().getResourceAsStream(
				path);
		if (in == null) {
			throw new IllegalArgumentException(path + " not found.");
		}
		Properties props = new Properties();
		props.load(in);

		END_POINT = props.getProperty("END_POINT");
		MASTER_KEY = props.getProperty("MASTER_KEY");
		documentClient = new DocumentClient(END_POINT, MASTER_KEY,
				ConnectionPolicy.GetDefault(), ConsistencyLevel.Session);
	}

	@Test
	public void readTest01() throws DocumentClientException,
			JsonParseException, JsonMappingException, IOException {
		Person expected = new Person();
		Person actual;

		expected.setAge(45);
		expected.setName("割と普通");

		List<Document> documentList = documentClient
				.queryDocuments(getTestCollection().getSelfLink(),
						"SELECT * FROM root r WHERE r.id='" + 1 + "'", null)
				.getQueryIterable().toList();
		ObjectMapper mapper = new ObjectMapper();
		actual = mapper.readValue(documentList.get(0).toString(), Person.class);

		Assert.assertEquals(expected, actual);
	}

	private Database getTestDBDatabase() {
		if (databaseCache == null) {
			// Get the database if it exists
			List<Database> databaseList = documentClient
					.queryDatabases(
							"SELECT * FROM root r WHERE r.id='" + DATABASE_ID
									+ "'", null).getQueryIterable().toList();

			if (databaseList.size() > 0) {
				// Cache the database object so we won't have to query for it
				// later to retrieve the selfLink.
				databaseCache = databaseList.get(0);
			} else {
				// Create the database if it doesn't exist.
				try {
					Database databaseDefinition = new Database();
					databaseDefinition.setId(DATABASE_ID);

					databaseCache = documentClient.createDatabase(
							databaseDefinition, null).getResource();
				} catch (DocumentClientException e) {
					// TODO:
					e.printStackTrace();
				}
			}
		}

		return databaseCache;
	}

	private DocumentCollection getTestCollection() {
		if (collectionCache == null) {
			// Get the collection if it exists.
			List<DocumentCollection> collectionList = documentClient
					.queryCollections(
							getTestDBDatabase().getSelfLink(),
							"SELECT * FROM root r WHERE r.id='" + COLLECTION_ID
									+ "'", null).getQueryIterable().toList();

			if (collectionList.size() > 0) {
				// Cache the collection object so we won't have to query for it
				// later to retrieve the selfLink.
				collectionCache = collectionList.get(0);
			} else {
				// Create the collection if it doesn't exist.
				try {
					DocumentCollection collectionDefinition = new DocumentCollection();
					collectionDefinition.setId(COLLECTION_ID);

					// Configure the new collection performance tier to S1.
					RequestOptions requestOptions = new RequestOptions();
					requestOptions.setOfferType("S1");

					collectionCache = documentClient.createCollection(
							getTestDBDatabase().getSelfLink(),
							collectionDefinition, requestOptions).getResource();
				} catch (DocumentClientException e) {
					// TODO:
					e.printStackTrace();
				}
			}
		}

		return collectionCache;
	}
}
package com.mydomain.model;

public class Person {
	int age;
	String name;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Person == false)
			return false;

		Person p = (Person) obj;
		boolean isAgeSame = age == p.getAge();
		boolean isNameSame = name == null ? p.getName() == null : //
				name.equals(p.getName());
		return isAgeSame && isNameSame;
	}
}

上記を実行すると、以下のエラーが発生する。

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "_attachments" (Class com.mydomain.model.Person), not marked as ignorable
 at [Source: java.io.StringReader@1bb5a082; line: 1, column: 18] (through reference chain: com.mydomain.model.Person["_attachments"])
	at org.codehaus.jackson.map.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:53)
	at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:246)
	at org.codehaus.jackson.map.deser.StdDeserializer.reportUnknownProperty(StdDeserializer.java:604)
	at org.codehaus.jackson.map.deser.StdDeserializer.handleUnknownProperty(StdDeserializer.java:590)
	at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:689)
	at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:514)
	at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:350)
	at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2395)
	at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1595)
	at com.mydomain.documentdb.SampleTest.readTest01(SampleTest.java:61)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	(中略)


不明なフィールドである _attachments が存在する様だ。念のためやり取りされる JSON データを見ると以下の様に複数のフィールドが追加されている。

{_attachments=attachments/, _rid=i-ZOANFBawACAAAAAAAAAA==, name=割と普通, id=1, _self=dbs/i-ZOAA==/colls/i-ZOANFBawA=/docs/i-ZOANFBawACAAAAAAAAAA==/, age=45, _etag="00001000-0000-0000-0000-5560769f0000", _ts=1432385183}

こちらの問題に対応するには以下の様に jackson 特有のアノテーションを追加して不明なプロパティの無視を指定する。

package com.mydomain.model;

import org.codehaus.jackson.annotate.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Person {
	int age;
	String name;

	//(中略)


読み込みの場合は上記で良いのだが、書き込みの場合(特に更新)では今回無視したフィールドが必要なことが懸念される。こちらに対する調査はまた後日で。

Maven でコンパイルするとラムダ式使えないと怒られる件

JDK 1.8 が出てだいぶ経つので、各位もラムダ式を使っていることだと思う。今回はラムダ式を利用したモジュールで Maven コンパイルを実施する場合の軽い TIPS を紹介する。ご存じな方はご存じだと思うが、毎度 pom.xml に記載用の情報を検索するのも面倒なので以下に記載しておきたい。

ハマるポイントとして、ラムダ式を利用したソースで "mvn compile" 等を実行した場合に以下のエラーが発生する点だ。

D:\opt\workspace\Java8CodingProject>mvn compile
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Java8CondigProject 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
<中略>
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /D:/opt/workspace/Java8CodingProject/src/test/java/com/mydomain/lambda/SampleTest.java:[18,33] ラムダ式は-source 1.5でサポートされていません  (ラムダ式を使用可能にするには、-source 8以上を使用してください)
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.798 s
[INFO] Finished at: 2015-05-23T16:58:51+09:00
[INFO] Final Memory: 10M/491M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.
1:testCompile (default-testCompile) on project Java8CondigProject: Compilation failure
[ERROR] /D:/opt/workspace/Java8CodingProject/src/test/java/com/mydomain/lambda/SampleTest.java:[18,33] ラムダ式は-source 1.5でサポートされていません
[ERROR] (ラムダ式を使用可能にするには、-source 8以上を使用してください)
[ERROR] -> [Help 1]

上記のエラーを見れば一目瞭然だが、Maven さん(使っているのは 3.2.5 )は JDK 1.5 ベースでコンパイルしているらしい(流石に古すぎだろうと思うが)。。。。


解決方法は以下の様に pom.xml に追記すればよい。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mydomain</groupId>
	<artifactId>Java8CondigProject</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<properties>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
	</properties>
	<dependencies>
		<dependency>
        (中略)

次回以降は 1.8 ベースでのコンパイルが実行される。

Windows Azure Storage Emulator のインストールに失敗する場合の TIPS

Web Platform Installer 等を利用して Azure SDK のセットアップをする際、Windows Azure Storage Emulator のインストールに失敗することがある。今回はこちらを解決するかもしれない TIPS を紹介する。今回の作業による影響範囲は見切っていないので、実施は自己責任でお願いしたい

概要

Web Platform Installer 等を利用してインストールに失敗した場合、エラーダイアログからログを閲覧することができる。インストールの失敗ログを開き、以下のエラーが存在しているかを確認する。

<中略>
Action start 11:02:11: InstallFinalize.
CAQuietExec:  Windows Azure Storage Emulator 3.4.0.0 command line tool
CAQuietExec:  Error: Cannot create database.
CAQuietExec:  Error 0xfffffff3: Command line returned an error.
CAQuietExec:  Error 0xfffffff3: CAQuietExec Failed
CustomAction RunInitialize returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Action ended 11:02:12: InstallFinalize. Return value 3.
Action ended 11:02:12: INSTALL. Return value 3.
Property(S): UpgradeCode = {CF5CD495-AEDE-42DA-B7CF-A70D398D4E6A}
<中略>

上記を見ると、どうやらデータベースを作成できないらしい。ご存知の方もいるかもしれないが、Azure のエミュレータはローカルにデータベースを持つので、そちらが再作成がうまくいっていないようだ。
こちらのエラーで検索すると MSDN フォーラムで "CAQuietExec: Error: Cannot create database." の記事を見つけた。いろいろと議論がある様だが、ポイントは以下だ。

Hi,

That may not be sufficient.

As far as I'm concerned, my first install attemp left some files in my c:\users\[user] directory :

WAStorageEmulatorDb30.mdf
WAStorageEmulatorDb30_log.ldf

The sqllocaldb logs would mention these files still existed and it would not erase them.

I just deleted them manually.
Recreated the v11.0 (without the double quotes, please):

sqllocaldb stop v11.0
sqllocaldb delete v11.0
sqllocaldb create v11.0

私の場合は C:\users\[user directory] に以下のファイルが存在したので、すべて削除(別フォルダに移動)した。

  • WAStorageEmulatorDb33.mdf
  • WAStorageEmulatorDb33_log.ldf
  • WAStorageEmulatorDb34.mdf
  • WAStorageEmulatorDb34_log.ldf

次にコマンドラインを開き(管理者権限は不要)、以下のコマンドを実行した。

sqllocaldb stop v11.0
sqllocaldb delete v11.0
sqllocaldb create v11.0

後は再度 Azure SDK のインストールを実行すれば問題なくインストールが完了すると思われる。

Azure Redis Cache を Java で利用する

Azure Redis Cache が日本でも利用可能になってしばらくたつが、確認のために Java から疎通を取ったので簡単にメモ。

使うまでの手順

Azure の新ポータル側 https://portal.azure.com にアクセスし、Data + Storage から Redis Cache を選択する。
f:id:waritohutsu:20150321191729j:plain

次に設定からアクセスポートを選択し「SSL によるアクセスのみ許可する」で「いいえ」を選択する。これは Redis の Java クライアントである Jedis が SSL 接続をサポートしていないためだ。
f:id:waritohutsu:20150321192134j:plain

管理ポータルの設定は以上なので、次は Java プロジェクトを作成し、pom.xml に以下を追記して Jedis の依存関係を解決する。

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.6.2</version>
        </dependency>

以下のコードを利用して Azure Redis Cache を利用できる。

package com.domain.redisclientproject;

import redis.clients.jedis.Jedis;

public class Main {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("<site name>.redis.cache.windows.net", 6379);
        jedis.auth("<管理ポータルから取得できるキー>");
        jedis.set("foo", "bar");
        String value = jedis.get("foo");
        System.out.println(value);
    }
}

疎通までとなるが、上記の様に簡単に利用することができるのが分かる。

Application Insight の Java モジュールの拡張ポイントを弄ってみる

前回の記事で Java アプリケーション向けに Application Insight を動作させる方法を紹介したが、こちらに対してイベント処理を追加することができる。拡張に利用することのできるクラスは以下の二つだ。

  • applicationinsights-core-0.9.1.jar に含まれる TelemetryModule.java
  • applicationinsights-web-0.9.1.jar に含まれる WebTelemetryModule.java

拡張ポイントについて

TelemetryModule.java と WebTelemetryModule.java はそれぞれインターフェースであり、コードは以下になる。

package com.microsoft.applicationinsights.extensibility;
import com.microsoft.applicationinsights.TelemetryConfiguration;
public abstract interface TelemetryModule
{
  public abstract void initialize(TelemetryConfiguration paramTelemetryConfiguration);
}
package com.microsoft.applicationinsights.web.extensibility.modules;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public abstract interface WebTelemetryModule
{
  public abstract void onBeginRequest(ServletRequest paramServletRequest, ServletResponse paramServletResponse);
  
  public abstract void onEndRequest(ServletRequest paramServletRequest, ServletResponse paramServletResponse);
}

眺めて頂けば察しがつくと思うが、モジュール初期化時、リクエスト前後で処理が追加できることが分かる。

拡張コードと設定

以下のクラスを作成した。

package com.mydomain.applicationinsightmodule;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import com.microsoft.applicationinsights.TelemetryConfiguration;
import com.microsoft.applicationinsights.extensibility.TelemetryModule;
import com.microsoft.applicationinsights.web.extensibility.modules.WebTelemetryModule;

public class MyTelemetryModule implements WebTelemetryModule, TelemetryModule {

	@Override
	public void initialize(TelemetryConfiguration initializer) {
		System.out.println("@@@@InstrumentationKey="
				+ initializer.getInstrumentationKey());
	}

	@Override
	public void onBeginRequest(ServletRequest paramServletRequest,
			ServletResponse paramServletResponse) {
		System.out
				.println("@@@@onBeginRequest at " + this.getClass().getName());
	}

	@Override
	public void onEndRequest(ServletRequest paramServletRequest,
			ServletResponse paramServletResponse) {
		System.out.println("@@@@onEndRequest at " + this.getClass().getName());
	}

}

さらに ApplicationInsights.xml に設定を追記した。

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<ApplicationInsights
	xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings"
	schemaVersion="2014-05-30">
	<InstrumentationKey><自分のキー>
	</InstrumentationKey>
	<ContextInitializers>
	</ContextInitializers>
	<TelemetryInitializers>
		<Add
			type="com.microsoft.applicationinsights.web.extensibility.initializers.WebOperationIdTelemetryInitializer" />
		<Add
			type="com.microsoft.applicationinsights.web.extensibility.initializers.WebOperationNameTelemetryInitializer" />
	</TelemetryInitializers>
	<TelemetryModules>
		<Add
			type="com.microsoft.applicationinsights.web.extensibility.modules.WebRequestTrackingTelemetryModule" />
		<Add
			type="com.microsoft.applicationinsights.web.extensibility.modules.WebSessionTrackingTelemetryModule" />
		<Add
			type="com.microsoft.applicationinsights.web.extensibility.modules.WebUserTrackingTelemetryModule" />
		<Add type="com.mydomain.applicationinsightmodule.MyTelemetryModule" />
	</TelemetryModules>
	<Channel>
		<!-- Setting DeveloperMode to true will enable immediate transmission of 
			the telemetry events, which can be helpful during the development process. 
			Make sure to turn this off on production servers due to performance considerations. -->
		<DeveloperMode>false</DeveloperMode>
	</Channel>
	<DisableTelemetry>false</DisableTelemetry>
</ApplicationInsights>

拡張が完了したので、Java Web アプリケーションを起動すると以下の様にログが出力されていることが確認できる(ホントは slf4j とか使った方がいいのは置いといて)。

情報: Starting Servlet Engine: Apache Tomcat/8.0.9
3 15, 2015 12:47:44 午後 org.apache.jasper.servlet.TldScanner scanJars
情報: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
@@@@InstrumentationKey=<自分のキー>
3 15, 2015 12:47:44 午後 org.apache.coyote.AbstractProtocol start
情報: Starting ProtocolHandler ["http-nio-8080"]
3 15, 2015 12:47:44 午後 org.apache.coyote.AbstractProtocol start
情報: Starting ProtocolHandler ["ajp-nio-8009"]
3 15, 2015 12:47:44 午後 org.apache.catalina.startup.Catalina start
情報: Server startup in 1987 ms
@@@@onBeginRequest at com.mydomain.applicationinsightmodule.MyTelemetryModule
@@@@onEndRequest at com.mydomain.applicationinsightmodule.MyTelemetryModule
@@@@onBeginRequest at com.mydomain.applicationinsightmodule.MyTelemetryModule
@@@@onEndRequest at com.mydomain.applicationinsightmodule.MyTelemetryModule