diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/inets/src/http_server/mod_log.erl | |
download | otp-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.erl | 256 |
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. + + |