aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets/src/http_server/mod_log.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/inets/src/http_server/mod_log.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/inets/src/http_server/mod_log.erl')
-rw-r--r--lib/inets/src/http_server/mod_log.erl256
1 files changed, 256 insertions, 0 deletions
diff --git a/lib/inets/src/http_server/mod_log.erl b/lib/inets/src/http_server/mod_log.erl
new file mode 100644
index 0000000000..de24d5a569
--- /dev/null
+++ b/lib/inets/src/http_server/mod_log.erl
@@ -0,0 +1,256 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(mod_log).
+
+%% Application internal API
+-export([error_log/2, security_log/2, report_error/2]).
+
+%% Callback API
+-export([do/1, load/2, store/2, remove/1]).
+
+-include("httpd.hrl").
+-define(VMODULE,"LOG").
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+
+%% security log
+security_log(Info, ReasonStr) ->
+ Date = httpd_util:custom_date(),
+ case httpd_log:security_entry(security_log, no_security_log, Info,
+ Date, ReasonStr) of
+ no_security_log ->
+ ok;
+ {Log, Entry} ->
+ io:format(Log, "~s", [Entry])
+ end.
+
+%% error_log
+error_log(Info, Reason) ->
+ Date = httpd_util:custom_date(),
+ error_log(Info, Date, Reason).
+
+error_log(Info, Date, Reason) ->
+ case httpd_log:error_entry(error_log, no_error_log,
+ Info, Date, Reason) of
+ no_error_log ->
+ ok;
+ {Log, Entry} ->
+ io:format(Log, "~s", [Entry])
+ end.
+
+report_error(ConfigDB, Error) ->
+ Date = httpd_util:custom_date(),
+ case httpd_log:error_report_entry(error_log, no_error_log, ConfigDB,
+ Date, Error) of
+ no_error_log ->
+ ok;
+ {Log, Entry} ->
+ io:format(Log, "~s", [Entry])
+ end.
+
+%%%=========================================================================
+%%% CALLBACK API
+%%%=========================================================================
+%%--------------------------------------------------------------------------
+%% do(ModData) -> {proceed, OldData} | {proceed, NewData} | {break, NewData}
+%% | done
+%% ModData = #mod{}
+%%
+%% Description: See httpd(3) ESWAPI CALLBACK FUNCTIONS
+%%-------------------------------------------------------------------------
+do(Info) ->
+ AuthUser = auth_user(Info#mod.data),
+ Date = httpd_util:custom_date(),
+ log_internal_info(Info,Date,Info#mod.data),
+ case proplists:get_value(status, Info#mod.data) of
+ %% A status code has been generated!
+ {StatusCode, _PhraseArgs, Reason} ->
+ transfer_log(Info,"-",AuthUser,Date,StatusCode,0),
+ if
+ StatusCode >= 400 ->
+ error_log(Info,Date,Reason);
+ true ->
+ not_an_error
+ end,
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case proplists:get_value(response, Info#mod.data) of
+ {already_sent,StatusCode,Size} ->
+ transfer_log(Info,"-",AuthUser,Date,StatusCode,Size),
+ {proceed,Info#mod.data};
+ {response, Head, _Body} ->
+ Size = proplists:get_value(content_length,Head,unknown),
+ Code = proplists:get_value(code,Head,unknown),
+ transfer_log(Info, "-", AuthUser, Date, Code, Size),
+ {proceed, Info#mod.data};
+ {_StatusCode, Response} ->
+ transfer_log(Info,"-",AuthUser,Date,200,
+ httpd_util:flatlength(Response)),
+ {proceed,Info#mod.data};
+ undefined ->
+ transfer_log(Info,"-",AuthUser,Date,200,0),
+ {proceed,Info#mod.data}
+ end
+ end.
+
+%%--------------------------------------------------------------------------
+%% load(Line, Context) -> eof | ok | {ok, NewContext} |
+%% {ok, NewContext, Directive} |
+%% {ok, NewContext, DirectiveList} | {error, Reason}
+%% Line = string()
+%% Context = NewContext = DirectiveList = [Directive]
+%% Directive = {DirectiveKey , DirectiveValue}
+%% DirectiveKey = DirectiveValue = term()
+%% Reason = term()
+%%
+%% Description: See httpd(3) ESWAPI CALLBACK FUNCTIONS
+%%-------------------------------------------------------------------------
+load("TransferLog " ++ TransferLog, []) ->
+ {ok,[],{transfer_log,httpd_conf:clean(TransferLog)}};
+load("ErrorLog " ++ ErrorLog, []) ->
+ {ok,[],{error_log,httpd_conf:clean(ErrorLog)}};
+load("SecurityLog " ++ SecurityLog, []) ->
+ {ok, [], {security_log, httpd_conf:clean(SecurityLog)}}.
+
+%%--------------------------------------------------------------------------
+%% store(Directive, DirectiveList) -> {ok, NewDirective} |
+%% {ok, [NewDirective]} |
+%% {error, Reason}
+%% Directive = {DirectiveKey , DirectiveValue}
+%% DirectiveKey = DirectiveValue = term()
+%% Reason = term()
+%%
+%% Description: See httpd(3) ESWAPI CALLBACK FUNCTIONS
+%%-------------------------------------------------------------------------
+store({transfer_log,TransferLog}, ConfigList) when is_list(TransferLog)->
+ case create_log(TransferLog,ConfigList) of
+ {ok,TransferLogStream} ->
+ {ok,{transfer_log,TransferLogStream}};
+ {error,Reason} ->
+ {error,Reason}
+ end;
+store({transfer_log,TransferLog}, _) ->
+ {error, {wrong_type, {transfer_log, TransferLog}}};
+store({error_log,ErrorLog}, ConfigList) when is_list(ErrorLog) ->
+ case create_log(ErrorLog,ConfigList) of
+ {ok,ErrorLogStream} ->
+ {ok,{error_log,ErrorLogStream}};
+ {error,Reason} ->
+ {error,Reason}
+ end;
+store({error_log,ErrorLog}, _) ->
+ {error, {wrong_type, {error_log, ErrorLog}}};
+store({security_log, SecurityLog}, ConfigList) when is_list(SecurityLog) ->
+ case create_log(SecurityLog, ConfigList) of
+ {ok, SecurityLogStream} ->
+ {ok, {security_log, SecurityLogStream}};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+store({security_log, SecurityLog}, _) ->
+ {error, {wrong_type, {security_log, SecurityLog}}}.
+
+%%--------------------------------------------------------------------------
+%% remove(ConfigDb) -> _
+%%
+%% Description: See httpd(3) ESWAPI CALLBACK FUNCTIONS
+%%-------------------------------------------------------------------------
+remove(ConfigDB) ->
+ lists:foreach(fun([Stream]) -> file:close(Stream) end,
+ ets:match(ConfigDB,{transfer_log,'$1'})),
+ lists:foreach(fun([Stream]) -> file:close(Stream) end,
+ ets:match(ConfigDB,{error_log,'$1'})),
+ lists:foreach(fun([Stream]) -> file:close(Stream) end,
+ ets:match(ConfigDB,{security_log,'$1'})),
+ ok.
+
+%%%========================================================================
+%%% Internal functions
+%%%========================================================================
+%% transfer_log
+transfer_log(Info,RFC931,AuthUser,Date,StatusCode,Bytes) ->
+ case httpd_log:access_entry(transfer_log, no_transfer_log,
+ Info, RFC931, AuthUser, Date,
+ StatusCode, Bytes) of
+ no_transfer_log ->
+ ok;
+ {Log, Entry} ->
+ io:format(Log, "~s", [Entry])
+ end.
+
+create_log(LogFile, ConfigList) ->
+ Filename = httpd_conf:clean(LogFile),
+ case filename:pathtype(Filename) of
+ absolute ->
+ case file:open(Filename, [read, write]) of
+ {ok,LogStream} ->
+ file:position(LogStream,{eof,0}),
+ {ok,LogStream};
+ {error,_} ->
+ {error,?NICE("Can't create "++Filename)}
+ end;
+ volumerelative ->
+ case file:open(Filename, [read, write]) of
+ {ok,LogStream} ->
+ file:position(LogStream,{eof,0}),
+ {ok,LogStream};
+ {error,_} ->
+ {error,?NICE("Can't create "++Filename)}
+ end;
+ relative ->
+ case proplists:get_value(server_root,ConfigList) of
+ undefined ->
+ {error,
+ ?NICE(Filename++
+ " is an invalid logfile name beacuse "
+ "ServerRoot is not defined")};
+ ServerRoot ->
+ AbsoluteFilename=filename:join(ServerRoot,Filename),
+ case file:open(AbsoluteFilename, [read, write]) of
+ {ok,LogStream} ->
+ file:position(LogStream,{eof,0}),
+ {ok,LogStream};
+ {error, _Reason} ->
+ {error,?NICE("Can't create "++AbsoluteFilename)}
+ end
+ end
+ end.
+
+%% log_internal_info
+log_internal_info(_Info, _Date, []) ->
+ ok;
+log_internal_info(Info,Date,[{internal_info,Reason}|Rest]) ->
+ error_log(Info, Date, Reason),
+ log_internal_info(Info,Date,Rest);
+log_internal_info(Info,Date,[_|Rest]) ->
+ log_internal_info(Info,Date,Rest).
+
+auth_user(Data) ->
+ case proplists:get_value(remote_user, Data) of
+ undefined ->
+ "-";
+ RemoteUser ->
+ RemoteUser
+ end.
+
+