ようへいの日々精進XP

よかろうもん

(超メモ)Python で Base64 と gzip で固められたデータを復元するメモ(CloudWatch Logs Subscriptions で Kinesis ストリームに入ったレコードを復元する)

何がしたいの?

CloudWatch Logs Subscriptions で Kinesis に入ったレコードを取得すると以下のように gzip で固められて Base64エンコードされたデータになっている。

H4sIAAAAAAAAAJ2RTY+CMBCG/wrpXgXb0lLgZrJqTPbjoDdjTJWJNlIgpega43/fAbMfpz3sqZN3Ju887/RGLLStPsDq2gDJyfNkNdm+TpfLyXxKRqS+VOBQ5pIxSdM4SShFuawPc1d3DXaKen8CF6Ly0JfegbbYaGunrbYQNqaB0lSw5ZTJkNGQKRxtu127d6bxpq5mpvTgWpKvyYu2u0I/TLb+AuDJZvCdnqHy/ciNmALtY865SngsOE0TJWjMleI8TZhgMhNKZkpKpSjPUFY8EzLFkUT09N5gZq8t4jMhJMNUTCSKj75ugfaLUbD+5k1XNMuFzGMaSUFxY/DEkk2weJu9B2EY5MHR+yYfjxvLZeTROzJVfdJOR/vajk/Xrr1245/00dHbEjngwzu991DMDJQFZruRQnvo8fqT/7m9v2DDcSwfKoZvGPY/cB7g+wqGEhnJ72D/Qb3fN/dPf1Js6SkCAAA=

この文字列を元のデータに Python で復元したい。


どうするの?

StringIO と gzip モジュールで解決

以下のように StringIO モジュールと gzip モジュールを利用することで復元出来た。

#!/usr/bin/env python

import base64
import gzip
from StringIO import StringIO

event = "H4sIAAAAAAAAAJ2RTY+CMBCG/wrpXgXb0lLgZrJqTPbjoDdjTJWJNlIgpega43/fAbMfpz3sqZN3Ju887/RGLLStPsDq2gDJyfNkNdm+TpfLyXxKRqS+VOBQ5pIxSdM4SShFuawPc1d3DXaKen8CF6Ly0JfegbbYaGunrbYQNqaB0lSw5ZTJkNGQKRxtu127d6bxpq5mpvTgWpKvyYu2u0I/TLb+AuDJZvCdnqHy/ciNmALtY865SngsOE0TJWjMleI8TZhgMhNKZkpKpSjPUFY8EzLFkUT09N5gZq8t4jMhJMNUTCSKj75ugfaLUbD+5k1XNMuFzGMaSUFxY/DEkk2weJu9B2EY5MHR+yYfjxvLZeTROzJVfdJOR/vajk/Xrr1245/00dHbEjngwzu991DMDJQFZruRQnvo8fqT/7m9v2DDcSwfKoZvGPY/cB7g+wqGEhnJ72D/Qb3fN/dPf1Js6SkCAAA="

decoded_data = event.decode("base64")
print gzip.GzipFile(fileobj=StringIO(decoded_data)).read()

結果

以下のように JSON で格納されていることが解った。

% python test.py | jq .
{
  "logEvents": [
    {
      "extractedFields": {
        "message": "http://pm25.test.inokara.com/kyusyu/2015-10-17.html",
        "lev": "INFO",
        "lv": "I,",
        "sp1": "--",
        "sp2": ":",
        "datetime": "2015-10-18T09:45:30.540420 #16"
      },
      "message": "I, [2015-10-18T09:45:30.540420 #16] INFO -- : http://pm25.test.inokara.com/kyusyu/2015-10-17.html",
      "timestamp": 1445136614672,
      "id": "32227623420867403277228614159475975577029772729458032640"
    }
  ],
  "subscriptionFilters": [
    "LambdaStream_tweet"
  ],
  "logStream": "soramame-pipeline_2015-10-17",
  "logGroup": "docker-log",
  "owner": "xxxxxxxxxxxxx",
  "messageType": "DATA_MESSAGE"
}

ちなみに、logEventsextractedFields.message だけ取得したい場合には以下のように書けば取得出来る。

decoded_data = event.decode("base64")
json_data = json.loads(gzip.GzipFile(fileobj=StringIO(decoded_data)).read())
for data in json_data['logEvents']:
    print data['extractedFields']['message']

以下のように出力される。

% python test.py
http://pm25.test.inokara.com/kyusyu/2015-10-17.html

参考

有難うございます。

以上。