概要
CloudWatchLogsのログイベントをAWS LambdaでClojure使って取得したらけっこう面倒だった
CloudWatchLogsの仕様
Lambda の配列を含むレスポンスが表示されます。Lambda レコードの [Data] 属性は、Base64 でエンコードされており、gzip 形式で圧縮されています。Lambda が受け取る実際のペイロードは、{ "awslogs": {"data": "BASE64ENCODED_GZIP_COMPRESSED_DATA"} } の形式になります。raw データは、コマンドラインから次の UNIX コマンドを使用して調べることができます。
結構面倒だぞ、最初Base64だけかと思ってたけどGZIP圧縮もされてる。
Java8あるしClojure使おう
設定は Writing AWS Lambda Functions in Clojure を参考にした
ソースサンプル
- テストデータがJSON型だとイベントハンドラの関数もそれに対応した型を宣言しないとだめっぽい
-
(defn -handleEvent [^java.util.HashMap m]
← これ - それをClojureのMapに変換
(def am (into {} m))
-
get-in
で取り出し(def data (get-in am ["awslogs" "data"]))
Rubyのdig
関数っぽい
-
core.clj
(ns core
(:import org.apache.solr.common.util.Base64)
(:import java.io.ByteArrayInputStream)
(:import java.util.zip.GZIPInputStream)
(:import org.apache.commons.io.IOUtils)
(:gen-class
:methods [^:static [handleEvent [java.util.HashMap] String]]))
(defn -handleEvent [^java.util.HashMap m]
(def am (into {} m))
;; CloudWatchLogsはBase64形式で来る => {awslogs={data=XXX}}
(def data (get-in am ["awslogs" "data"]))
(println (str "aws cloud logs with Base64 => " data))
;; デコードしてGZIP解凍するべし
(let [bytes (Base64/base64ToByteArray data)
bi (new ByteArrayInputStream bytes)
zi (new GZIPInputStream bi)
json (IOUtils/toString zi)]
;; やっと表示
(println (str "aws cloud logs => " json)
json)))
ライブラリは以下を使用した
project.clj
[org.apache.solr/solr-solrj "6.0.0"]
[commons-io/commons-io "2.5"]
[com.amazonaws/aws-lambda-java-core "1.1.0"]
Clojureをもっと使っていきたい