LoginSignup
1
1

More than 5 years have passed since last update.

ELBのアクセスログをJava8のStreamで見る

Last updated at Posted at 2015-05-25

普段インラインのスクリプトで中身を調べてたELBのアクセスログを、Java8のStreamを使って見てみたら意外に使い勝手が良かったのでメモ。
パッケージ名は適当に変更してください。

コードは下に貼っておきます。

サンプル

ログの個数を調べる

System.out.println(parser.getLogs().size());

Backend Processing Timeの最大値・最小値・平均を調べる

OptionalDouble max = parser.getLogs().stream()
  .mapToDouble(l -> { return l.backendProcessingTime; })
  .max();
OptionalDouble min = parser.getLogs().stream()
    .mapToDouble(l -> { return l.backendProcessingTime; })
    .min();
OptionalDouble avg = parser.getLogs().stream()
    .mapToDouble(l -> { return l.backendProcessingTime; })
    .average();

System.out.println(String.format("Max/Min/Avg = %s/%s/%s", max.getAsDouble(), min.getAsDouble(), avg.getAsDouble()));

Backend Status Codeの種類と数を調べる

parser.getLogs().stream()
  .map(l -> { return l.backendStatusCode; })
  .collect(Collectors.groupingBy(l -> l, Collectors.counting()))
  .forEach((k, v) -> System.out.println(k + ":" + v));

Backend Processingに1秒以上掛かってるURLとMethodを調べる

parser.getLogs().stream()
  .filter(l -> { return l.backendProcessingTime > 1.0; })
  .map(l -> { return String.format("%s %s\t%s", l.requestMethod, l.requestURL, l.backendProcessingTime); } )
  .forEach(System.out::println);

ELBLogParser.java

正規表現がかなり適当だけどこんな感じのクラスを作っておく。

package com.makeitsmartjp.java;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class ElbLog {
    public String timestamp;
    public String elb;
    public String clientWithPort;
    public String backendWithPort;
    public double requestProcessingTime;
    public double backendProcessingTime;
    public double responseProcessingTime;
    public int elbStatusCode;
    public int backendStatusCode;
    public int receivedBytes;
    public int sentBytes;
    public String requestMethod;
    public String requestURL;
    public String requestHTTPVersion;

    @Override
    public String toString() {
        return String.format("timestamp:%s\telb:%s\tclientWithPort:%s\tbackendWithPort:%s\trequetProcessingTime:%s\tbackendProcessingTime:%s\tresponseProcessingTime:%s\telbStatusCode:%s\tbackendStatusCode:%s\treceivedBytes:%s\tsentBytes:%s\trequestMethod:%s\trequestURL:%s\trequestHTTPVersion:%s",
                timestamp, elb, clientWithPort, backendWithPort,
                requestProcessingTime, backendProcessingTime, responseProcessingTime,
                elbStatusCode, backendStatusCode, receivedBytes, sentBytes,
                requestMethod, requestURL, requestHTTPVersion
                );
    }
}

public class ELBLogParser {
    protected final String patternString = "^(.[^ ]+) (.[^ ]+) (.[^ ]+) (.[^ ]+) (.[^ ]+) (.[^ ]+) (.[^ ]+) (.[^ ]+) (.[^ ]+) (\\d+) (\\d+) \"(\\w+) (.[^ ]+) (.[^ ]+)\"";
    private final Pattern elblogPattern;
    private List<ElbLog> logs;

    public ELBLogParser() {
        logs = new ArrayList<ElbLog>();
        elblogPattern = Pattern.compile(patternString);
    }

    public void parse(String filePath) {
        try (
            InputStream in = new FileInputStream(filePath);
            InputStreamReader isr = new InputStreamReader(in, Charset.forName("UTF-8"));
            BufferedReader br = new BufferedReader(isr);
        ) {
            br.lines().forEach(log -> {
                ElbLog buff = parseLine(log);
                if (buff != null) {
                    logs.add(buff);
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public List<ElbLog> getLogs() {
        return logs;
    }

    protected ElbLog parseLine(String log) {
        Matcher m = elblogPattern.matcher(log);
        if (!m.find()) {
            return null;
        } else if (m.groupCount() < 14) {
            return null;
        }
        ElbLog elbLog = new ElbLog();
        elbLog.timestamp = m.group(1);
        elbLog.elb = m.group(2);
        elbLog.clientWithPort = m.group(3);
        elbLog.backendWithPort = m.group(4);
        elbLog.requestProcessingTime = Double.valueOf(m.group(5));
        elbLog.backendProcessingTime = Double.valueOf(m.group(6));
        elbLog.responseProcessingTime = Double.valueOf(m.group(7));
        elbLog.elbStatusCode = Integer.valueOf(m.group(8));
        elbLog.backendStatusCode = Integer.valueOf(m.group(9));
        elbLog.receivedBytes = Integer.valueOf(m.group(10));
        elbLog.sentBytes = Integer.valueOf(m.group(11));
        elbLog.requestMethod = m.group(12);
        elbLog.requestURL = m.group(13);
        elbLog.requestHTTPVersion = m.group(14);

        return elbLog;
    }
}

Main.java

Mainではこんな感じでダウンロードしたファイルを読み込ませる。

package com.makeitsmartjp.java;


public class Main {

    public static void main(String[] args) {
        String path = "/path/to/elb.log";
        ELBLogParser parser = new ELBLogParser();
        parser.parse(path);

    // 以下に調べたいコードを書いてく
    }
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1