Technofara

Golangエンジニア!仕事で必要になって勉強した事とか、新しい事とか色々まとめたりを緩くやります。技術系と思考系だけにしておきます、

Elastic MapReduceで解析した結果を、D3.jsを使ってグラフ化してみたお話

ふりかえり

前回「Elastic MapReduceを使って、FluentdでS3上に格納した、Ltsv形式のNginxのアクセスログを解析してみたお話。」URL -> http://shinofara.hateblo.jp/entry/2013/09/15/000202

では、複数台のサーバで稼働するNginxのアクセスログを、Fluentdを使って回収して、S3上に格納して、 EMR(Elastic MapReduce)を使って、ログ解析をするという簡単ながれを書きました。

今回なぜ、Elastic MapReduceでの解析結果を使ってD3.jsの調査をしたのか

前回の解析結果のデータだけではパッと見てわかりにくかったりするので、 パッと見てわかりやすくする為に 今回は、前回解析したデータを、グラフしてみました。 ※テストデータの内容レベルなら、グラフ化は不要なのですが、調査ということで.....

ちなみにD3.jsとは

D3.js とは、

HTML や SVGCSSを使ってデータに命を吹き込みます。D3は WEB 標準に重点を置いており、強力な視覚化コンポーネントとデータドリブン (データ駆動型)DOM 操作手法の組み合わせにより、特定のフレームワークに縛られることなく、モダンブラウザの性能をフルに 引き出すことができます。 まとめると、svg,cssを使ってブラウザの性能をフルに使って、グラフを作成する。かな?まとめ過ぎかもしれません

実際にやる

使うデータは前回作成した、データと言いたいところですが、少し変更します。

といっても前回の

hive> CREATE EXTERNAL TABLE IF NOT EXISTS archiveLog (status int, cnt int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
LOCATION 's3://<バケット名>/archives/${DATE}';
OK
Time taken: 0.197 seconds 

hive> CREATE EXTERNAL TABLE IF NOT EXISTS archiveLog (status int, cnt int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'
LOCATION 's3://<バケット名>/archives/${DATE}';
OK
Time taken: 0.197 seconds 

に変更するだけですが、、どこが変わったの???

ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' と変更する事で、区切り文字を, 改行文字を\nにする事が出来ます。 これはcsv形式で出力する為の設定です。

そして前回と同じようにhiveで、queryを実行します。(詳しくは前回の記事参照でお願いします。)

INSERT OVERWRITE TABLE  archiveLog
SELECT
  status, count(*) as cnt
FROM
  fluentLog LATERAL VIEW
    json_tuple(fluentLog.json,  'ua', 'status') j
      AS ua,status
WHERE pt >='2013-09-09'
GROUP BY status;

するとS3上に以下の内容のcsvが書きだされます。 ※グラフの見た目がわかりやすくなる様に数字は変更しています。

200,210
302,60
400,36
404,20
500,70

ここまでの準備が出来たら後は、HTML,CSS,Javascriptを少し書くだけです。あと少し。

土台となるHTML

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Script-Type" content="text/javascript" charset="utf-8" />
  <title>sample1</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
  <div id="graph"></div>
</body>
</html>

気になるjsの処理

jsを書く場所は
<script>
ここにjsを記述
</script>
</body>
キャンバス、色、レイアウト関連の定義

グラフを書くsvgのサイズなど定義

var width = 400,
    height = 300,
    radius = Math.min(width, height) / 2;
````

グラフの形、色定義
var color = d3.scale.ordinal()
    .range(["#F8D870","#E57F75", "#BE7AC3", "#8A9BCB", "#5AB0D2", "#56C8BB"]);
var arc = d3.svg.arc()
    .outerRadius(radius - 10)
    .innerRadius(radius - 70);

var pie = d3.layout.pie()
    .sort(null)
    .value(function(d) { return d[1]; });

var svg = d3.select("#graph").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

…このあたりは省略します。

メインとなるのはここから、

csvからデータを取得して、表示

本来は、 https://s3-ap-northeast-1.amazonaws.com/<バケット名>/archives/c516867a-c387-4fd4-9b16-697e3e3c6fa9_000000 というURLになるのですが、今回はこのファイルをgithub上にrenameして説明していきます。(URLが変わるだけですので、動きは同じ)

var data = [];
(function(){
 d3.text("https://rawgithub.com/shinofara/work/master/emr/csv/01.csv", function(csvFile) {
     var csvData = d3.csv.parseRows(csvFile);
     csvData.forEach(function(line) {
         //グラフの値は数値型なので、変換
         line[1] = +line[1];
     });
     
var g = svg.selectAll(".arc")
      .data(pie(csvData))
    .enter().append("g")
      .attr("class", "arc");

     
  g.append("path")
      .attr("d", arc)
      .style("fill", function(d) { return color(d.data[0]);});

  //項目ごとのテキスト
  g.append("text")
      .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
      .attr("dy", ".35em")
      .style("text-anchor", "middle")
      .text(function(d) { return d.data[0]; });
 }); 
})();

グラフの見た目も大事!

<style>
.arc path {
  stroke: #fff;
  stroke-opacity: .2;
}
body {
   font-size:10px;
}
</style>

簡単にですが、色をつけました。

簡単な調査を終えて

思った事

EMR + S3 + D3.jsを使っての、ログの可視化の説明だったので、処理説明等々は省略させていただきました。 そして、今回メインとなったD3.jsjavascriptの書き方が少しハードルが高いかなーと思いましたが、 このくらいのグラフなら慣れれば簡単になるのかな? 複雑なグラフは、もっと難しいのかな?とか と思いました。

最後に一言

最後に、jsfiddleで公開した物をペタっ ※最近こういった検証には、jsfiddleを使ってます。。