Nimblechen parsecでNGNXアクセスログを解析する
最近、私はいくつかの文字列解析で遊んで、仕事を完璧にするライブラリ
文字列のマッチングを開始するには、パーサを新しいファイルに定義する必要があります.
完全なIPアドレスを抽出して、以下のようなパーサーを作成します.
本日書いたファイルは以下の通りです.
< div >
nimble_parsec
を見つけました.私はどのようにNGinxのログを変換する方法を何かを読むことが表示されます.典型的なログ行は次のようになります.127.0.0.1 - - [25/Dec/2020:08:15:53 +0000]
"GET /img/key.svg HTTP/1.1" 200 8305
"http://localhost/styles/css/app.css"
"Mozilla/5.0 Firefox/84.0"
このフィールドは以下の通りです:remote_addr - remote_user [time_local]
"request" status bytes_sent
"referer"
"user_agent"
私はstack overflowで説明を見つけました文字列のマッチングを開始するには、パーサを新しいファイルに定義する必要があります.
defmodule NginxParsex do
import NimbleParsec
defparsec( :ngnix_parser, integer(1))
end
これは整数から始まる文字列にマッチしますiex(1)> log = "127.0.0.1 - - "
iex(2)> NginxParsex.ngnix_parser(log)
{:ok, [1], "27.0.0.1 - - ", %{}, {1, 0}, 1}
ここで何が起こるのかは、パーサが最初の整数にマッチし、:ok
のタプル、1にマッチした項目のリスト、および残りの文字列を返します.タプル内の他の項目は、パーサーが使用する追加のデータです.完全なIPアドレスを抽出して、以下のようなパーサーを作成します.
ip =
integer(min: 1, max: 3)
|> ignore(string("."))
|> integer(min: 1, max: 3)
|> ignore(string("."))
|> integer(min: 1, max: 3)
|> ignore(string("."))
|> integer(min: 1, max: 3)
defparsec( :ngnix_parser, ip)
そして、それを実行した後iex(1)> NginxParsex.ngnix_parser(log)
{:ok, [127, 0, 0, 1], " - - ", %{}, {1, 0}, 9}
すべての数値を抽出してドットを省略しているので、文字列が十分でないので、数字とドットからなる文字列として抽出することもできます.ip = ascii_string([?., ?0..?9], min: 7, max: 15)
今すぐ戻ってくるiex(1)> NginxParsex.ngnix_parser(log)
{:ok, ["127.0.0.1"], " - - ", %{}, {1, 0}, 9}
次の部分は私たちにとって本当に有用ではありません ip =
ascii_string([?., ?0..?9], min: 7, max: 15)
|> ignore(string(" - - "))
そして、我々の最初のテストストリングはパースされますiex(1)> NginxParsex.ngnix_parser(log)
{:ok, ["127.0.0.1"], "", %{}, {1, 0}, 14}
問題は2番目のダッシュが" - - "
であるかもしれません、我々はスキップして、remote_user
ip =
ascii_string([?., ?0..?9], min: 7, max: 15)
|> ignore(eventually(ascii_char([?[])))
我々の現在のログがこの部分が不足していたので、私はそれを加えます:log = ~s(127.0.0.1 - - [25/Dec/2020:08:15:53 +0000] )
iex(1)> NginxParsex.ngnix_parser(log)
{:ok, ["127.0.0.1"], "25/Dec/2020:08:15:53 +0000]", %{}, {1, 0}, 15}
一致する必要がある次の部分は日付文字列です.これは非常によくdocumentationで説明されています.また、日付と時刻のパーサーを展開します.モジュールは以下のようになります.defmodule NginxParsex do
import NimbleParsec
ip =
ascii_string([?., ?0..?9], min: 7, max: 15)
date =
integer(2)
|> ignore(string("/"))
|> ascii_string([?a..?z, ?A..?Z], 3)
|> ignore(string("/"))
|> integer(4)
time =
integer(2)
|> ignore(string(":"))
|> integer(2)
|> ignore(string(":"))
|> integer(2)
|> ignore(string(" "))
|> ignore(ascii_char([?-, ?+]))
|> ignore(integer(4))
defparsec( :ngnix_parser,
ip
|> ignore(eventually(ascii_char([?[])))
|> concat(date)
|> ignore(string(":"))
|> concat(time)
|> ignore(string("] "))
)
end
我々が得たコードを実行するとき:iex(1)> NginxParsex.ngnix_parser(log)
{:ok, ["127.0.0.1", 25, "Dec", 2020, 8, 15, 53], "", %{}, {1, 0}, 43}
クール私たちの日付と時刻を解析され、我々はラインからより多くのものを追加することができますlog = ~s(127.0.0.1 - - [25/Dec/2020:08:15:53 +0000] "GET /img/key.svg HTTP/1.1" 200 8305 "http://localhost/styles/css/app.css" "Mozilla/5.0 Firefox/84.0")
ここで引用符の中で文字列にマッチする必要があります. string_in_quotes =
ignore(ascii_char([?"]))
|> ascii_string([not: ?"], min: 1)
|> ignore(ascii_char([?"]))
defparsec( :ngnix_parser,
ip
|> ignore(eventually(ascii_char([?[])))
...
|> concat(string_in_quotes)
)
結果NginxParsex.ngnix_parser(log)
{:ok, ["127.0.0.1", 25, "Dec", 2020, 8, 15, 53, "GET /img/key.svg HTTP/1.1"],
" 200 8305 \"http://localhost/styles/css/app.css\" \"Mozilla/5.0 Firefox/84.0\"",
%{}, {1, 0}, 70}
いくつかの空白、数字、2つ引用符で囲まれた文字列-私たちはすでに持っている部品を再利用することができますし、我々の完全なパーサーが今見ています defparsec( :ngnix_parser,
ip
|> ignore(eventually(ascii_char([?[])))
|> concat(date)
|> ignore(string(":"))
|> concat(time)
|> ignore(string("] "))
|> concat(string_in_quotes)
|> ignore(string(" "))
|> integer(min: 1)
|> ignore(string(" "))
|> integer(min: 1)
|> ignore(string(" "))
|> concat(string_in_quotes)
|> ignore(string(" "))
|> concat(string_in_quotes)
結果は次のようになります.{:ok,
["127.0.0.1", 25, "Dec", 2020, 8, 15, 53, "GET /img/key.svg HTTP/1.1", 200,
8305, "http://localhost/styles/css/app.css", "Mozilla/5.0 Firefox/84.0"], "",
%{}, {1, 0}, 144}
データを取得するには、結果にマッチパターンを設定できます. {:ok,
[ ip, day, month, year, hour, minute, seconds, request, code, size, referrer, user_agent ],
_, _, _, _} = NginxParsex.ngnix_parser(log)
{:ok,
["127.0.0.1", 25, "Dec", 2020, 8, 15, 53, "GET /img/key.svg HTTP/1.1", 200,
8305, "http://localhost/styles/css/app.css", "Mozilla/5.0 Firefox/84.0"], "",
%{}, {1, 0}, 144}
iex(111)> user_agent
"Mozilla/5.0 Firefox/84.0"
すべての変数を得たとき、私たちは、それらを処理し、地図にそれをラップすることができます @month_map %{
"Jan" => 1,
"Feb" => 2,
"Mar" => 3,
"Apr" => 4,
"May" => 5,
"Jun" => 6,
"Jul" => 7,
"Aug" => 8,
"Oct" => 9,
"Sep" => 10,
"Nov" => 11,
"Dec" => 12
}
%{
ip: ip,
date: Date.new!(year, @month_map[month], day),
time: Time.new!(hour, minute, seconds),
request: request,
code: code,
size: size,
referrer: URI.decode(referrer),
user_agent: user_agent
}
%{
code: 200,
date: ~D[2020-12-25],
ip: "127.0.0.1",
referrer: "http://localhost/styles/css/app.css",
request: "GET /img/key.svg HTTP/1.1",
size: 8305,
time: ~T[08:15:53],
user_agent: "Mozilla/5.0 Firefox/84.0"
}
読書のおかげで、私は私がローカルマシンに持っている2 MBのファイルでそれをテストしました.本日書いたファイルは以下の通りです.
< div >
Reference
この問題について(Nimblechen parsecでNGNXアクセスログを解析する), 我々は、より多くの情報をここで見つけました https://dev.to/dkuku/parse-nginx-access-log-with-nimbleparsec-e1lテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol