ようへいの日々精進XP

よかろうもん

2020 年 05 月 03 日 (🌅)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, 完全休養
  • 引き続き, 安静にしておく

ギョーム

夕飯

  • 奥さん初挑戦の手羽の甘辛炒め, とても美味しかった

シュッとグラフ画像が欲しい時に image-charts.com を使ったら助かったのでメモ

tl;dr

ある数値を集計して円グラフを描いてその画像を Slack に貼り付けたいなあと調べていたら image-charts.com なるサービスが提供されていたので利用してみました.

www.image-charts.com

Google Chart API も選択肢として検討しましたが, 画像を S3 バケットに保存したかったり, Node.js から利用したかったりという要件に合わなかった (探せていないだけかもしれませんが) 為, 今回は image-charts.com を利用することにしました.

developers.google.com

image-charts.com

API でグラフを生成することが出来る

image-charts.com のトップページに以下のように記載されています.

No need to spend hours to setup and develop a complex server-side solution. We spent months tuning our chart API generation infrastructure so you don't have to. One API call url = one chart.

スーパーざっくりと申し上げると, 簡単に REST API を利用してグラフイメージを生成することが出来るサービスです.

例えば, 以下のように curl を利用してリクエストを送信することで...

$ curl -s 'https://image-charts.com/chart?cht=p3&chs=700x100&chd=t:60,40&chl=Hello|World&chf=ps0-0,lg,45,ffeb3b,0.2,f44336,1|ps0-1,lg,45,8bc34a,0.2,009688,1' -o helloworld.png

helloworld.png を開くと以下のような円グラフ画像が生成されます.

f:id:inokara:20200503154036p:plain

また, パラメータに &chan を付与してリクエストを送信すると...

$ curl -s 'https://image-charts.com/chart?cht=p3&chs=700x100&chd=t:60,40&chl=Hello|World&chf=ps0-0,lg,45,ffeb3b,0.2,f44336,1|ps0-1,lg,45,8bc34a,0.2,009688,1&chan' -o helloworld.gif

以下のように GIF アニメーションの円グラフ画像が生成されます.

f:id:inokara:20200503154249g:plain

パラメータ

描画するグラフのタイプやサイズ, 出力のフォーマット (デフォルトは PNG) 等設定可能なパラメータが非常に多いです.

documentation.image-charts.com

詳細はドキュメントをご確認いただければと思いますが, 先述の円グラフリクエストに付与しているパラメータについて書きます.

パラメータ 用途 サンプル値
cht グラフのタイプ指定 (bvs = バー, p = 円, ls = 折れ線) p3
chs 出力する画像サイズ指定 700x100
chd データフォーマット指定 t:60,40
chl グラフラベル指定 Hello|World
chf グラフの塗りつぶし指定 ps0-0,lg,45,ffeb3b,0.2,f44336,1|ps0-1,lg,45,8bc34a,0.2,009688,1
chn GIF アニメーションで出力する

以下のように image-charts.com のサイト上で, 実際にパラメータを調整しながらグラフ画像を確認することが可能です.

f:id:inokara:20200503160659p:plain

Node.js から利用する

Image Charts Node.js Library

以下のように npm で提供されているので, yarn add image-charts 等で自身のプロジェクトに追加しましょう.

www.npmjs.com

雑なサンプルコード

Node.js (JavaScript) も Hello World な身分で恐縮ですが, 以下のような円グラフを描画するサンプルスクリプトを書きました.

const imageCharts = require('image-charts')({});
const fs = require("fs");

const buildGraphArgs = (graphData) => {
    let imageArgs = {};
    let datas = [];
    let labels = [];
    let legendLabels = [];
    const total = graphData.total
    let counts = 0;
    for (let i in graphData.values) {
        counts += graphData.values[i].count;
        percent = Math.round(graphData.values[i].count / total * 100);
        datas.push(percent);
        labels.push(percent + '%');
        legendLabels.push(graphData.values[i].name);
    }
    const others = Math.round((total - counts) / total * 100);
    datas.push(others);
    labels.push(others + '%');
    legendLabels.push('others');

    return {
      title: 'Percentage of Total', 
      size: [ 500, 300 ], 
      data: datas,
      labels: labels,
      legendLables: legendLabels
    };
};

// ここはサンプルを拝借
const buildImage = async (imageArgs) => {
    const pieChart = imageCharts.pie(imageArgs);
 
    try {
        const b = await pieChart.buffer();
        return b;
    } catch (err) {
        return Promise.reject(err);
    }
};

const main = async () => {
    graphData = {
      total: 100,
      values: [
        { name: 'aa', count: 30 },
        { name: 'bb', count: 18 },
        { name: 'cc', count: 12 },
      ]
    };

    imageArgs = buildGraphArgs(graphData);
    imageData = await buildImage(imageArgs);
    fs.writeFile('sample.png', imageData, (err) => {
      if (err) throw err;
      console.log('Image written successfully.');
    });
}

main();

実行すると, 以下のように出力されるだけですが...

$ node sample.js
Image written successfully.

同じディレクトリに sample.png というファイルが生成されるので開いてみます.

$ open sample.png

以下のような円グラフ画像が生成されています.

f:id:inokara:20200503170105p:plain

良い感じです.

円グラフ以外にも...

棒グラフの場合には, 以下のように書きます.

const buildGraphArgs = (graphData) => {
... 略...
    legendLabels.unshift('0:');

    return {
      title: 'Percentage of Total', 
      size: [ 500, 300 ], 
      data: datas,
      labels: labels,
      axis: [ 'x', 'y' ],
      axisLabels: [ legendLabels ]
    };
};

const buildImage = async (imageArgs) => {
    const barChart = imageCharts.bar(imageArgs);
 
    try {
        const b = await barChart.buffer();
        return b;
    } catch (err) {
        return Promise.reject(err);
    }
};

X 軸, Y 軸にラベルを付与するパラメータを付与して imageCharts.bar() を呼び出します.

以下のような棒グラブの画像が生成されました.

f:id:inokara:20200503173852p:plain

ついでに GIF アニメーションも生成してみました.

f:id:inokara:20200503174956g:plain

GIF アニメーションを生成する場合, パラメータは以下のようなパラメータを付与します.

... 略 ...
    return {
      title: 'Percentage of Total', 
      size: [ 500, 300 ], 
      data: datas,
      labels: labels,
      axis: [ 'x', 'y' ],
      axisLabels: [ legendLabels ],
      animation: ['1200','easeOutBack'],
      format: '.gif'
    };

以上

シュッと

image-charts.com を Node.js から使ってみたメモでした. ライブラリ自体は初心者の自分でも何となく雰囲気を掴むことが出来, コードやテストコードを読みながら試行錯誤することが出来ました.

他にも似たようなサービスがあるのかもしれませんが, シュッとグラフ画像を作成して Slack に張りたい場合等に利用を検討したいなあと思います.

ちなみに, おいくら万円?

www.image-charts.com

image-charts.com では, 以下のように, Developer プラン, Enterprise プラン, Enterprise+ プランが提供されています.

f:id:inokara:20200503223416p:plain

Docker イメージによるオンプレミス環境での利用も可能 (Enterprise プラン以上) です.

2020 年 05 月 02 日 (土)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, 完全休養
  • 引き続き, 安静にしておく
  • 久しぶりに山王公園で散歩 with 奥さん

ギョーム

  • お休みだけど, ギョーム半分, 趣味半分で DDoS 検知の仕組みを作ったりした

夕飯

  • おろしハンバーグ, 昨晩の残りものだったけど美味しかったし, 大根おろし山盛りで有り難かった

Elasticsearch 上のデータを割と簡単にダンプして他の Elasticsearch にインポート出来る elasticsearch-dump を使ってみた

ti;dr

VPC 内で動いている Amazon Elasticsearch Service (以後, AES) 上の一部のインデックスデータを手元の端末の Elasticsearch でも利用したいと思った時に散々悩んで調査した結果, 以下のようなツールが OSS で提供されていたので使ってみましたのでメモです.

github.com

本来ならば, Logstash を使ったりするのが順当なところなのかもしれませんが, mysqldump みたいなカジュアル利用出来るので気持ち良かったです.

taskrabbit/elasticsearch-dump

セットアップ

github.com

Node.js で実装されていて, npm install でインストールするか, Docker イメージが配布されています.

今回は, Amazon Elasticsearch Service からデータをダンプする環境では Docker イメージを利用しました.

$ docker pull taskrabbit/elasticsearch-dump

ダンプされたデータをインポートする環境では npm install でインストールしました.

$ npm install elasticdump

使い方

詳細は README をご一読頂ければと思いますが, とてもシンプルに使い始めることが出来ると思います. 以下はドキュメントより引用させて頂きました.

elasticdump \
  --input=http://production.es.com:9200/my_index \
  --output=http://staging.es.com:9200/my_index \
  --type=data
  • --input はソースとなる Elasticsearch インデックスのエンドポイント
  • --output はデータをインポートする Elasticsearch インデックスのエンドポイント
  • --type では data を指定するとデータ (Document) そのもの, --mapping を指定すると, その名の通りマッピングもインポートが可能

試しにヘルプを確認してみましたが, かなり多くのオプションが用意されており, プロキシ経由での接続もサポートされたりしているので, プロキシを介してリモートの Elasticsearch からローカルマシン上の Elasticsearch へのデータ移行もカジュアルに行えると思います.

$ elasticdump --help

さて

今回は

以下のようなステップでダンプ, インポートを行いました.

  1. VPC 上の AES にアクセス出来るホストで elasticsearch-dump Docker コンテナを利用してダンプ
  2. ダンプしたデータを SCP でローカルマシンにダウンロード
  3. ローカルマシン上に Elasticsearch を起動
  4. 起動した Elasticsearch にダンプしたデータをインポート
  5. データを確認

ダンプ (松本)

AES にアクセス出来るホスト (EC2 インスタンス) 上にて, 以下のように実行しました.

$ docker run --rm -ti -v /tmp/data:/tmp taskrabbit/elasticsearch-dump \
  --input=https://vpc-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com/cwl-YYYY.MM.D1 \
  --output=/tmp/cwl-YYYY.MM.D1.json \
  --type=data
$ docker run --rm -ti -v /tmp/data:/tmp taskrabbit/elasticsearch-dump \
  --input=https://vpc-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com/cwl-YYYY.MM.D2 \
  --output=/tmp/cwl-YYYY.MM.D2.json \
  --type=data
$ docker run --rm -ti -v /tmp/data:/tmp taskrabbit/elasticsearch-dump \
  --input=https://vpc-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com/cwl-YYYY.MM.D3 \
  --output=/tmp/cwl-YYYY.MM.D3.json \
  --type=data

ホスト上の /tmp/data 以下に cwl-YYYY.MM.D1.json から cwl-YYYY.MM.D3.json が生成されます.

尚, マッピングテンプレートもダンプすることが可能ですので, 必要に応じてダンプしておきましょう.

$ docker run --rm -ti -v /tmp/data:/tmp taskrabbit/elasticsearch-dump \
  --input=https://vpc-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com/template \
  --output=/tmp/template.json \
  --type=template

インポート

ホスト上のデータを何らかの方法 (自分は SCP を使いました) で取得し, 以下のようにデータをインポートします. インデックスへのマッピングの適用が必要な場合には, 事前にマッピングもンポートしておきましょう.

$ node_modules/.bin/elasticdump \
  --input=data/cwl-YYYY.MM.D1.json --output=http://localhost:9200/cwl-YYYY.MM.D1 --type=data
$ node_modules/.bin/elasticdump \
  --input=data/cwl-YYYY.MM.D2.json --output=http://localhost:9200/cwl-YYYY.MM.D2 --type=data
$ node_modules/.bin/elasticdump \
  --input=data/cwl-YYYY.MM.D3.json --output=http://localhost:9200/cwl-YYYY.MM.D3 --type=data

データ確認

以下のようにインデックスとして登録されていることを確認しました.

f:id:inokara:20200502073847p:plain

良い感じですね.

hits.total あたりを確認してみます.

$ curl -s -H "Content-Type: application/json" localhost:9200/cwl-YYYY.MM.D1/_search -d '
{
   "query": { "match_all": {} }
}' | jq .hits.total
4184

良い感じですね.

以上

このツールに出会うまで, 色々と試行錯誤しました. 一旦, データを CSV で書き出しておいて, インポートのスクリプトを書こうとしたり, ローカルマシンから直接 VPC 内の AES にアクセスする為にプロキシサーバーを立てようとしたり... だいぶん疲弊したところに出会った elasticsearch-dump はまさに神ツールでした.

作者の方には感謝しかありません. ありがとうございました.

2020 年 05 月 01 日 (🈲)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, 完全休養
  • 引き続き, 安静にしておく

ギョーム

  • ウィークリーレポートを書いたり
  • ECS AMI アップデート
  • ちょっと DDoS っぽいことがあったので, 対策の検討
  • ちょっとしたアプリの修正依頼があったので修正
  • Elasticsearch に蓄積されているデータを利用した仕組みを作る為, 検証環境の準備

夕飯

  • 奥さんの十八番, おろしポン酢のハンバーグ!安定の美味しさだった

2020 年 04 月 30 日 (木)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, 完全休養
  • 引き続き, 安静にしておく

ギョーム

  • 今日は受け身の仕事が多かった
  • EKS matsuri というオンラインイベントを聞きながら

EKS matsuri は Kubernetes 初心者の自分でもとてもわかり易く説明さされていて EKS 色があんまり感じられないイベントだった.

夕飯

  • 実家から送られてきたキャベツとか玉ねぎをそのまま無水調理で食べたけど, 素材の味がそのまま味わえて美味しゅうございました

2020 年 04 月 29 日 (水)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, 完全休養
  • 引き続き, 安静にしておく

ギョーム

  • お休み
  • 奥さん従兄弟の職場の PC メンテナンスをリモート対応, 最初は手間取ったものの上手く対応出来た

ふと思い立って CloudWatch Alarm を Slack に通知する Lambda ファンクションを作ったけど, 半分くらい出来たところで AWS Chatbot がリリースされていることを思い出して笑えた.

aws.amazon.com

シュッと使いたい場合には, AWS Chatbot で十分なんだろうなあ.

夕飯

  • たこ焼きパーリー

2020 年 04 月 28 日 (🔥)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, 完全休養
  • 引き続き, 安静にしておく

ギョーム

  • メンテナンス作業
  • CloudFront キャッシュクリアの仕組みの改修
  • RDS スナップショットコピーする仕組みの改修
  • など

夕飯

  • 豚バラ肉とさつまいもの炒めもの, 奥さんにしては珍しく味が尖った (お酒や醤油がキツく) 感じた

2020 年 04 月 27 日 (月)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, 完全休養
  • 引き続き, 安静にしておく

ギョーム

  • メンテナンス作業準備
  • 一年前に作った Lambda 関数の改修

夕飯

  • 筍とジャコのご飯
  • 最近, カルシウムは摂りすぎなくらい摂っているはずなので, せめて骨折は治っていて欲しい

2020 年 04 月 26 日 (日)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, 完全休養
  • 引き続き, 安静にしておく

ギョーム

  • ギョームじゃないけど, コンテナランタイムについて手を動かしたり
  • CodeDeploy が特集された記事を読んだりしてた

読書

夕飯

  • またまたパスタを作る
  • 筍とジャコとトマト, 今日は昨日の反省を生かすことでまあまあの出来だった