Last active
August 12, 2016 14:27
-
-
Save tanishiking/48bb1fe147c0e2457778032f9724c7b1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
host:127.0.0.1 user:frank epoch:1372694390 req:GET /apache_pb.gif HTTP/1.0 status:200 size:2326 referer:http://www.hatena.ne.jp/ | |
host:127.0.0.1 user:john epoch:1372794390 req:GET /apache_pb.gif HTTP/1.0 status:200 size:1234 referer:http://b.hatena.ne.jp/hotentry | |
host:127.0.0.1 user:- epoch:1372894390 req:GET /apache_pb.gif HTTP/1.0 status:503 size:9999 referer:http://www.example.com/start.html | |
host:127.0.0.1 user:frank epoch:1372694390 req:GET /apache_pb.gif HTTP/1.0 status:500 size:2326 referer:http://www.hatena.ne.jp/ | |
host:127.0.0.1 user:frank epoch:1372794395 req:GET /notfound.gif HTTP/1.0 status:404 size:100 referer:- |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
OCAMLOPT=ocamlopt | |
TARGETS=parse | |
INCLUDES=str.cmxa | |
SRCS=utils.ml parser.ml | |
OBJS=$(SRCS:.ml=.cmx) | |
all: $(TARGETS) $(OBJS) | |
$(TARGETS): $(OBJS) | |
$(OCAMLOPT) -o $@ $(INCLUDES) $(OBJS) | |
.SUFFIXES: .ml .mli .cmo .cmi .cmx | |
.ml.cmx: | |
$(OCAMLOPT) -c $< | |
clean: | |
$(RM) *~ $(TARGETS) *.cm[iox] *.o | |
.PHONY: clean |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type log_entry = { | |
req_method: string; | |
req_path: string; | |
req_protocol: string; | |
req_url: string; | |
req_time: int; | |
} | |
module EntryMap = Map.Make(String) | |
let print_log_entry log_entry = | |
print_string ("method: " ^ log_entry.req_method ^ "\n"); | |
print_string ("path: " ^ log_entry.req_path ^ "\n"); | |
print_string ("protocol: " ^ log_entry.req_protocol ^ "\n"); | |
print_string ("url: " ^ log_entry.req_url ^ "\n"); | |
print_string ("time: " ^ (string_of_int log_entry.req_time) ^ "\n"); | |
print_string "\n" | |
let entry_map_find_or_else k v entry_map = | |
try EntryMap.find k entry_map | |
with _ -> v | |
let split_once input delimiter = | |
let splitted = Str.split (Str.regexp_string delimiter) input in | |
if List.length splitted < 2 then (input, "") | |
else (List.hd splitted, String.concat "" (List.tl splitted)) | |
let parse_line line = | |
let elems = Str.split (Str.regexp_string "\t") line in | |
let entry_map = List.fold_left | |
(fun acc elem -> | |
let (k, v) = split_once elem ":" in | |
EntryMap.add k v acc) | |
EntryMap.empty | |
elems in | |
let host = (entry_map_find_or_else "host" "-" entry_map) in | |
let epoch = int_of_string (entry_map_find_or_else "epoch" "0" entry_map) in | |
let req = (entry_map_find_or_else "req" "-" entry_map) in | |
let req_info = Str.split (Str.regexp_string " ") req in | |
try | |
let req_method = List.nth req_info 0 in | |
let req_path = List.nth req_info 1 in | |
let req_protocol = List.nth req_info 2 in | |
{ req_method = req_method; | |
req_path = req_path; | |
req_protocol = req_protocol; | |
req_url = "http://" ^ host ^ req_path; | |
req_time = epoch } | |
with _ -> | |
let (req_method, req_path, req_protocol) = ("-", "-", "-") in | |
{ req_method = req_method; | |
req_path = req_path; | |
req_protocol = req_protocol; | |
req_url = "http://" ^ host ^ req_path; | |
req_time = epoch } | |
let line_stream_of_channel channel = | |
Stream.from | |
(fun _ -> try Some (input_line channel) | |
with End_of_file -> None) | |
let _ = | |
let len = Array.length Sys.argv in | |
if len = 2 then | |
let file_path = Sys.argv.(1) in | |
let ic = open_in file_path in | |
let lines = line_stream_of_channel ic in | |
try | |
let entry_stream = Utils.Stream.map parse_line lines in | |
Stream.iter print_log_entry entry_stream; | |
close_in ic | |
with e -> | |
close_in ic; | |
raise e | |
else | |
print_string "Invalid number of argument\n" | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Stream = struct | |
let fold f stream init = | |
let res = ref init in | |
Stream.iter | |
(fun x -> res := f x !res) | |
stream; | |
!res | |
let map f stream = | |
let rec next i = | |
try Some (f (Stream.next stream)) | |
with Stream.Failure -> None in | |
Stream.from next | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment