技術開発日記

技術やら日々思ったことを綴ってます。

Amazon Kinesis Log4j Appenderの jar が最新じゃない件

Amazon Kinesis Log4j Appenderの公式ドキュメントからjarをダウンロードしても最新の修正が反映されていないため、下記のエラーが発生。(2015/7/4時点)docs.aws.amazon.com

エラー内容

log4j:ERROR Stream SampleStream doesn't exist for appender: KINESISERROR [main] (KinesisAppender.java:69) - Stream SampleStream doesn't exist for appender: KINESIS
com.amazonaws.services.kinesis.model.ResourceNotFoundException: Stream SampleStream under account 123456789012 not found. (Service: AmazonKinesis; Status Code: 400; Error Code: ResourceNotFoundException; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
	at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1160)
	at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:748)
	at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:467)
	at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:302)
	at com.amazonaws.services.kinesis.AmazonKinesisClient.invoke(AmazonKinesisClient.java:2472)
	at com.amazonaws.services.kinesis.AmazonKinesisClient.describeStream(AmazonKinesisClient.java:860)
	at com.amazonaws.services.kinesis.AmazonKinesisClient.describeStream(AmazonKinesisClient.java:1904)
	at com.amazonaws.services.kinesis.log4j.KinesisAppender.activateOptions(KinesisAppender.java:112)
	at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:307)
	at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:172)
	at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:104)
	at org.apache.log4j.PropertyConfigurator.parseAppender(PropertyConfigurator.java:809)
	at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:735)
	at org.apache.log4j.PropertyConfigurator.parseCatsAndRenderers(PropertyConfigurator.java:639)
	at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:504)
	at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:547)
	at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:483)
	at org.apache.log4j.LogManager.<clinit>(LogManager.java:127)
	...

原因

古いライブラリの場合 region を指定することが出来ず、デフォルトの us-east-1 が指定されてしまっているので、それ以外の region で Kinesis を使用していると指定したストリームが存在しないと怒られてしまう。

対応

githubリポジトリからプロジェクトをクローンしてビルドしたjarを使用

手順

  1. プロジェクトのクローン git clone https://github.com/awslabs/kinesis-log4j-appender
  2. ビルド mvn clean install
  3. target配下にビルドされたjarが作成されるので、パスを通してあげる
  4. log4j.propertiesにリージョンを設定

#東京リージョンの場合
log4j.appender.KINESIS.region=ap-northeast-1

※エンドポイントも設定できるが、指定すると下記のWARNが出力されてしまう。

WARN [main] (KinesisAppender.java:118) - Received configuration for both region as well as Amazon Kinesis endpoint. (kinesis.ap-northeast-1.amazonaws.com) will be used as endpoint instead of default endpoint for region (ap-northeast-1)

ソースを確認する限りエンドポイントを指定しなくてもリージョンから自動的にエンドポイントを設定してくれているので設定しなくても問題なし。

対象コード
KinesisAppender.java

boolean regionProvided = !Validator.isBlank(region);  // <== リージョンを指定している場合にtrue
if (!regionProvided) {
  region = AppenderConstants.DEFAULT_REGION;
}
if (!Validator.isBlank(endpoint)) {
  if (regionProvided) {                               
   LOGGER
    .warn("Received configuration for both region as well as Amazon Kinesis endpoint. ("
	+ endpoint
	+ ") will be used as endpoint instead of default endpoint for region ("
	+ region + ")");
  }
kinesisClient.setEndpoint(endpoint,
AppenderConstants.DEFAULT_SERVICE_NAME, region);
} else {
  kinesisClient.setRegion(Region.getRegion(Regions.fromName(region)));  // <== エンドポイントが指定されていない場合は自動で設定
}

AmazonWebServiceClient.java

public void setRegion(Region region) throws IllegalArgumentException { // <= 上記のsetRegion
if (region == null) {
    throw new IllegalArgumentException("No region provided");
}
    final String serviceNameForEndpoint = getServiceNameIntern();
    URI uri = new DefaultServiceEndpointBuilder(serviceNameForEndpoint, clientConfiguration.getProtocol()
            .toString()).withRegion(region).getServiceEndpoint();
    Signer signer = computeSignerByServiceRegion(serviceNameForEndpoint, region.getName(), signerRegionOverride, false);
    synchronized (this) {
        this.endpoint = uri;
        this.signer = signer;
    }
}

参考
awslabs/kinesis-log4j-appender · GitHub