Added accesslog parameter to record requests log in a file similar to Apache (thanks to Jerome Sautret)

SVN Revision: 2169
This commit is contained in:
Badlop 2009-06-16 13:44:32 +00:00
parent eedef994a9
commit 99fe76f8bc
1 changed files with 106 additions and 9 deletions

View File

@ -15,14 +15,16 @@
-behaviour(gen_mod).
-export([
start/2,
stop/1,
process/2
start/2,
stop/1,
process/2,
ctl_process/2
]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-include("ejabberd_http.hrl").
-include("ejabberd_ctl.hrl").
%%%----------------------------------------------------------------------
%%% REQUEST HANDLERS
@ -30,7 +32,7 @@
%%-----------------------------------------------------------------------
%% FUNCTION
%%
%%
%% process/2
%%
%% PURPOSE
@ -48,8 +50,21 @@
%%
%%-----------------------------------------------------------------------
process(LocalPath, _Request) ->
process(LocalPath, Request) ->
?DEBUG("Requested ~p", [LocalPath]),
Result = serve(LocalPath),
case ets:lookup(mod_http_fileserver, accessfile) of
undefined ->
ok;
[{accessfile, AccessFile}] ->
{Code, _, _} = Result,
log(AccessFile, Code, Request)
end,
Result.
serve(LocalPath) ->
[{docroot, DocRoot}] = ets:lookup(mod_http_fileserver, docroot),
FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
case file:read_file(FileName) of
@ -68,11 +83,40 @@ process(LocalPath, _Request) ->
end
end.
ctl_process(_Val, ["reopen-weblog"]) ->
mod_http_fileserver_server ! reopenlog,
?STATUS_SUCCESS;
ctl_process(Val, _Args) ->
Val.
%%%----------------------------------------------------------------------
%%% UTILITIES
%%%----------------------------------------------------------------------
join([], _) ->
"";
join([E], _) ->
E;
join([H | T], Separator) ->
lists:foldl(fun(E, Acc) -> lists:concat([Acc, Separator, E]) end, H, T).
log(File, Code, Request) ->
{{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(),
IP = join(tuple_to_list(Request#request.ip), "."),
Path = join(Request#request.path, "/"),
Query = case join(lists:map(fun(E) -> lists:concat([element(1, E), "=", element(2, E)]) end,
Request#request.q), "&") of
[] ->
"";
String ->
[$? | String]
end,
% combined apache like log format :
% 127.0.0.1 - - [28/Mar/2007:18:41:55 +0200] "GET / HTTP/1.1" 302 303 "-" "tsung"
% XXX TODO some fields are harcoded/missing (reply size, user agent or referer for example)
io:format(File, "~p - - [~p/~p/~p:~p:~p:~p] \"~s /~s~s\" ~p -1 \"-\" \"-\"~n",
[IP, Day, Month, Year, Hour, Minute, Second, Request#request.method, Path, Query, Code]).
content_type(Filename) ->
case httpd_util:to_lower(filename:extension(Filename)) of
".jpg" -> "image/jpeg";
@ -88,25 +132,78 @@ content_type(Filename) ->
_Else -> "application/octet-stream"
end.
open_file(Filename) ->
case file:open(Filename, [append]) of
{ok, File} ->
ets:insert(mod_http_fileserver, {accessfile, File}),
ok;
{error, _Reason} ->
{'EXIT', {unaccessible_accessfile, ?MODULE}}
end.
loop(Filename) ->
receive
reopenlog ->
case ets:lookup(mod_http_fileserver, accessfile) of
undefined ->
ok;
[{accessfile, AccessFile}] ->
file:close(AccessFile),
case open_file(Filename) of
ok ->
ok;
_ ->
error
end
end,
loop(Filename);
stop ->
ok
end.
%%%----------------------------------------------------------------------
%%% BEHAVIOUR CALLBACKS
%%%----------------------------------------------------------------------
start(_Host, Opts) ->
ejabberd_ctl:register_commands([{"reopen-weblog", "reopen http fileserver log file"}],
?MODULE, ctl_process),
case gen_mod:get_opt(docroot, Opts, undefined) of
undefined ->
{'EXIT', {missing_document_root, ?MODULE}};
DocRoot ->
case filelib:is_dir(DocRoot) of
true ->
ets:new(mod_http_fileserver, [named_table, bag]),
% XXX WARNING, using a single ets table name will
% not work with virtual hosts
ets:new(mod_http_fileserver, [named_table, public]),
ets:insert(mod_http_fileserver, [{docroot, DocRoot}]),
ok;
case gen_mod:get_opt(accesslog, Opts, undefined) of
undefined ->
ok;
Filename ->
% XXX same remark as above for proc name
register(mod_http_fileserver_server, spawn(?MODULE, loop, [Filename])),
open_file(Filename)
end;
_Else ->
{'EXIT', {unaccessible_document_root, ?MODULE}}
end
end
end.
stop(_Host) ->
ok.
case ets:info(mod_http_fileserver, name) of
undefined ->
ok;
_ ->
case ets:lookup(mod_http_fileserver, accessfile) of
undefined ->
ok;
[{accessfile, AccessFile}] ->
mod_http_fileserver_server ! stop,
file:close(AccessFile)
end,
ets:delete(mod_http_fileserver)
end,
ok.