JAva-grok正規表現によるログの解析

6846 ワード

プロジェクトの中で1つの新しい需要があって、ログを解析する必要があって、ログの中の部分のデータの分析をシステムのために取得して使用して、通俗的に言えばログの中の部分の役に立つ情報をつかむことで、例えば以下のapacheログの情報、私は各行のログを解析する必要があって、各行のログのIPアドレス、ユーザー、作成時間、要求方式を取得しますアドレス....javaを単純に使用すると、ファイルストリームを介してログ情報を読み取り、文字列を行単位で解析することが考えられるかもしれませんが、この方法は複雑すぎて効率が低く、ネット上で関連資料を検索し、logstashのgrokツールを使用することを決定し、ネット上でも対応するjava実装があり、その実現原理はカスタム正規表現であり、正規表現でログを解析するメリットは、mapやjsonなど、ログ内の不規則なデータをルールのデータに変換できることです.また、一度式を書いた後、複数の場所で実行できることです.何か違うところがあれば、正規表現を修正するだけでいいのではないでしょうか.
64.242.88.10 - - [07/Mar/2004:16:05:49 -0800] "GET/twiki/bin/edit/Main/Double_bounce_sender?topicparent=Main.ConfigurationVariables HTTP/1.1"401 12846 64.242.88.10 - - [07/Mar/2004:16:06:51 -0800] "GET/twiki/bin/rdiff/TWiki/NewUserTemplate?rev1=1.3&rev2=1.2 HTTP/1.1"200 4523 64.242.88.10 - - [07/Mar/2004:16:10:02 -0800] "GET/mailman/listinfo/hsdivision HTTP/1.1"200 6291 64.242.88.10 - - [07/Mar/2004:16:11:58 -0800] "GET/twiki/bin/view/TWiki/WikiSyntax HTTP/1.1"200 7352 64.242.88.10 - - [07/Mar/2004:16:20:55 -0800] "GET/twiki/bin/view/Main/DCCAndPostFix HTTP/1.1"200 5253
      ネット上のgrokの定義は、GrokはLogstashの最も重要なプラグインです.grokで名前付き正規表現を事前に定義し、後で(grokパラメータまたは他の正規表現で)参照することができます.参考ブログ:http://udn.yyuap.com/doc/logstash-best-practice-cn/filter/grok.html
      Java api方式でgrokを統合し、githubに関連するプロジェクトプロジェクトが実現され、githubでこのプロジェクトを取得することができます.https://github.com/thekrakken/java-grok、またはパッケージ化されたjarパッケージと関連する依存パッケージを直接使用して、私のリソースディレクトリでダウンロードできます.http://download.csdn.net/detail/harderxin/9923587
     依存パッケージには、commons-beanutils-1.8.3.jar、commons-lang 3-3.1.jar、commons-logging-1.1.1.jar、gson-2.2.2.jar、slf 4 j-api-1.7.5.jarが含まれます.バージョン番号は上記と同じではありません.
      mavenプロジェクトの場合はpom.xmlファイルに次の依存を追加できますが、他の依存パッケージは自分で導入する必要があります.

  io.thekraken
  grok
  0.1.5

 
   では、関連apiの操作を開始します.新しいプロジェクトを作成し、関連するjarパッケージを導入します.java-grokプロジェクトのデフォルトの正規表現ファイルを導入します.数字、テキスト、日付、IPアドレスなどの列の基礎データを定義した正規表現です.参考:https://github.com/thekrakken/java-grok/blob/master/patterns/patterns
     Java-grokを使用するには、まず正規表現ファイルのパスを定義してGrokオブジェクトを作成する必要があります.単一列モードとして定義できます.
package com.harderxin.grok.core;

import io.thekraken.grok.api.Grok;
import io.thekraken.grok.api.exception.GrokException;

public class GrokInstance {

	private static Grok grok;

	private GrokInstance() {

	}

	public static Grok getGrokInstance(String grokPatternPath) {
		if (grok == null) {
			try {
				grok = Grok.create(grokPatternPath);
			} catch (GrokException e) {
				e.printStackTrace();
			}
		}
		return grok;
	}
}
     
Grokオブジェクトを取得したら、解析するログの式名と変換するログメッセージを入力して、Matchオブジェクトを作成します.
	public static Match getMatch(String pattern, String message) {
		Match match = null;
		try {
			grok.compile(pattern);
			match = grok.match(message);
			match.captures();
		} catch (GrokException e) {
			e.printStackTrace();
			match = null;
		}
		return match;
	}
     
Matchオブジェクトを取得すると、対応するMapまたはJsonデータにデータを変換できます.補助クラスを書きました.
package com.harderxin.grok.core;

import java.util.Map;

import io.thekraken.grok.api.Grok;
import io.thekraken.grok.api.Match;
import io.thekraken.grok.api.exception.GrokException;

public class GrokUtils {

	private static final String GROK_PATTERN_PATH = "conf/agent_patterns";

	private static Grok grok = GrokInstance.getGrokInstance(GROK_PATTERN_PATH);

	public static Map toMap(String pattern, String message) {
		Match match = getMatch(pattern, message);
		if (match != null) {
			return match.toMap();
		}
		return null;
	}

	public static String toJson(String pattern, String message) {
		Match match = getMatch(pattern, message);
		if (match != null) {
			return match.toJson();
		}
		return null;
	}

	private static Match getMatch(String pattern, String message) {
		Match match = null;
		try {
			grok.compile(pattern);
			match = grok.match(message);
			match.captures();
		} catch (GrokException e) {
			e.printStackTrace();
			match = null;
		}
		return match;
	}

}
     
テストクラスを作成します.注意:
上の各解析では、ログ内の1行のデータしか解析できません.ログ・ファイルを解析するには、そのファイルを行ごとに解析する必要があります.次の行のログを解析する必要があります.
64.242.88.10--[07/Mar/2004:16:45:56-0800]"GET/twiki/bin/attach/Main/PostfixCommands HTTP/1.1"401,846、プログラム解析後、clientip=64.242.88.10、timestamp= 07/Mar/2004:16:45:56-0800、verb=GET、httpversion=1.1などのフォーマットされたデータは、私たちの上のプログラムでできます.
patternsファイルで、解析ログの正規表現を定義します.
XINTEST %{IPORHOST:clientip} %{USER:ident;boolean} %{USER:auth}[%{HTTPDATE:timestamp;date;dd/MMM/yyyy:HH:mm:ss Z}\]\"(?:%{WORD:verb;string} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion;float})?|%{DATA:rawrequest})\"%{NUMBER:response;int} (?:%{NUMBER:bytes;long}|-)
IPORHOSTはpatternで定義されている正規表現です.以下に示すように、clientipは解析後のデータのKeyの別名です.別名がない場合、デフォルト名は正規表現の名前です.
IP (?:%{IPV6:UNWANTED}|%{IPV4:UNWANTED}) HOSTNAME\b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(\.?|\b)
IPORHOST(?:%{HOSTNAME:UNWANTED}|%{IP:UNWANTED})私たちのpattern式が作成されました.名前はXINTESTです.次は私たちのコードを使ってテストすることができます.テストの時、pattern式は%{}を使って名前を入れる必要があります.これは規定です.
package com.harderxin.grok.test;

import java.util.Map;

import com.harderxin.grok.core.GrokUtils;

public class GrokTest2 {
	public static void main(String[] args) {
		String pattern = "%{XINTEST}";
		String message = "64.242.88.10 - - [07/Mar/2004:16:45:56 -0800] \"GET /twiki/bin/attach/Main/PostfixCommands HTTP/1.1\" 401 12846";
		String json = GrokUtils.toJson(pattern, message);
		System.out.println(json);
		Map map = GrokUtils.toMap(pattern, message);
		System.out.println(map.toString());
	}

}

コード出力のjsonデータは以下の通りです.
{
    "HOUR": "16", 
    "INT": "-0800", 
    "MINUTE": "45", 
    "MONTH": "Mar", 
    "MONTHDAY": "07", 
    "SECOND": "56", 
    "TIME": "16:45:56", 
    "XINTEST": "64.242.88.10 - - [07/Mar/2004:16:45:56 -0800] \"GET /twiki/bin/attach/Main/PostfixCommands HTTP/1.1\" 401 12846", 
    "YEAR": "2004", 
    "auth": "-", 
    "bytes": 12846, 
    "clientip": "64.242.88.10", 
    "httpversion": 1.1, 
    "ident": false, 
    "request": "/twiki/bin/attach/Main/PostfixCommands", 
    "response": 401, 
    "timestamp": "Mar 8, 2004 8:45:56 AM", 
    "verb": "GET"
}
     
ログに関連するデータは私たちのプログラムで解析されました!!実はその原理は私たちが正規表現をカスタマイズして、それから正規表現を通じて各行のデータをマッチングして、ユーザー定義のkey:valueデータに変換します!この機能があれば、私たちが解くことができるログはどんなに複雑で変化しても、その中のデータが一定の正規表現に従う限り式マッチングルールで、必要なデータに変換できます!