用cowboy這個庫,沒有日誌功能,因此研究了otp提供的日誌功能。html
shell
erl –boot start_sasl 默認配置文件下啓動SASL, {env, [{sasl_error_logger, tty},{errlog_type, all}]},,見源碼 sasl.app文件。
erl -boot start_sasl -config xxxx.config 啓動指定配置文件例如 elog1.config ,elog2.config 。。。配置文件默認目錄是ebin,可本身指定目錄。app
還能夠用 application:start(sasl). 在代碼裏啓動應用。默認會讀取代碼ebin下的sasl.app,可去源碼複製一份sasl.app而後修改 env參數。debug
sasl是經過application:get_env(sasl,xxx) 得到配置信息 。日誌
{env, [{sasl_error_logger, {file,"../../logs/error_logs/THELOG"}},%將sasl信息輸出到文件中(不記錄error_logger發送的信息)。另外,tty :輸出sasl信息到shell中(默認配置),false:不輸出sasl信息。 {errlog_type, all}, %過濾sasl_error_logger中的輸出信息(error,progress) {error_logger_mf_dir,"../../logs/error_logs"}, %循環日誌路徑(記錄sasl信息以及error_logger發送的信息)。 {error_logger_mf_maxbytes,10485760}, %限定單個日誌大小。 {error_logger_mf_maxfiles,10} %限定日誌個數。 ]}
參考官方文檔code
設置日誌error_logger輸出日誌到文件:error_logger:logfile({open,Filename}).orm
注: 每次執行error_logger:logfile({open,Filename}).都會刪掉以前Filename文件。server
因爲業務須要,我想按照日期切分日誌,該日誌主要是爲了記錄業務操做。htm
思路:每次寫日誌到日誌文件,先判斷日誌文件的最新修改日期是否跟當前日期一致,不一致就對該日誌文件重命名(後綴添加日期),並從新建立日誌文件。進程
daylog_app.erl:
-module(daylog_app). -behaviour(application). -export([init/1]). -export([start/0,start/2,stop/1]). -define(SERVER,?MODULE). -define(LOGFILE,"info.log"). start() -> application:start(daylog). start(_StartType,_StartArgs) -> LogFile = get_app_env(log_file,?LOGFILE), supervisor:start_link({local,?SERVER},?MODULE,[daylog,LogFile]). stop(_State) -> ok. init([Module,LogFile]) -> Element = {Module,{Module,start_link,[LogFile]}, temporary,2000,worker,[Module]}, %%如何啓動和管理子進程 Children = [Element] , RestartStrategy = {one_for_one,0,1}, %%重啓策略 {ok,{RestartStrategy,Children}}. %%監督規範 %%---------------------------------------------------------------------- %% Internal functions %%---------------------------------------------------------------------- get_app_env(Opt, Default) -> case application:get_env(daylog, Opt) of {ok, Val} -> Val; _ -> case init:get_argument(Opt) of [[Val | _]] -> Val; error -> Default end end.
daylog.erl
%%%------------------------------------------------------------------- %%% Author : kingson <kingsoncai2013@gmail.com> %%% Description : Cutting logs every day. %%% %%% Created : 4 Mar 2015 by kingson <kingsoncai2013@gmail.com> %%%------------------------------------------------------------------- -module(daylog). -behaviour(gen_server). %% API -export([start_link/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([add_logfiles/1,info_log/1,info_log/2,logger/2,logger/3]). -define(SERVER,?MODULE). -record(state, {filename,other_files}). add_logfiles(Files) -> gen_server:cast(?SERVER,{add_logfile,Files}). info_log(Msg) -> %通知類型日誌(默認) info_log(Msg,[]). info_log(Format,Data) -> gen_server:cast(?SERVER,{accept,Format,Data}). logger(FileName,Msg) -> logger(FileName,Msg,[]). logger(FileName,Format,Data) -> gen_server:cast(?SERVER,{accept,FileName,Format,Data}). %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- start_link(LogFile) when is_list(LogFile) -> gen_server:start_link({local, ?SERVER}, ?MODULE, [LogFile], []). %%==================================================================== %% gen_server callbacks %%==================================================================== %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- init([LogFile]) -> process_flag(trap_exit, true), {ok,F} = file:open(LogFile,[append]), put(LogFile,F), {ok, #state{filename=LogFile},0}. %%-------------------------------------------------------------------- %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | %% {stop, Reason, State} %% Description: Handling call messages %%-------------------------------------------------------------------- handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. %%-------------------------------------------------------------------- %% Function: handle_cast(Msg, State) -> {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} %% Description: Handling cast messages %%-------------------------------------------------------------------- handle_cast({accept,Format,Data}, #state{filename=FileName}=State) -> write(Format,Data,FileName), {noreply, State}; handle_cast({accept,FileName,Format,Data},State) -> write(Format,Data,FileName), {noreply,State}; handle_cast({add_logfile,LogFiles},State) -> open_files(LogFiles), State2 = State#state{other_files=LogFiles}, {noreply,State2}; handle_cast(_Msg, State) -> {noreply, State}. %%-------------------------------------------------------------------- %% Function: handle_info(Info, State) -> {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- handle_info(timeout, State) -> gen_server:cast(?SERVER,{accept,"Has started daylog application~n",[]}), {noreply, State}; handle_info(_Info, State) -> {noreply, State}. %%-------------------------------------------------------------------- %% Function: terminate(Reason, State) -> void() %% Description: This function is called by a gen_server when it is about to %% terminate. It should be the opposite of Module:init/1 and do any necessary %% cleaning up. When it returns, the gen_server terminates with Reason. %% The return value is ignored. %%-------------------------------------------------------------------- terminate(_Reason, State) -> #state{filename=FileName,other_files=OtherFiles} = State, close_files(OtherFiles), F = get(FileName), io:format("Has stoped daylog application~n"), io:format(F,"Has stoped daylog application~n",[]), file:close(F), ok. %%-------------------------------------------------------------------- %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} %% Description: Convert process state when code is changed %%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- write(Format,Data,Filename) -> LocalTime = calendar:local_time(), case filelib:last_modified(Filename) of {Last_Modified_Date,_} -> {Today,_} = LocalTime, {Date_diff,_} = calendar:time_difference({Last_Modified_Date,{0,0,0}},{Today,{0,0,0}}), if Date_diff /= 0 -> %not the same date {Y,M,D} = Last_Modified_Date, Newname = Filename ++ "." ++ integer_to_list(Y) ++ "-" ++ integer_to_list(M) ++ "-" ++ integer_to_list(D), file:close(get(Filename)), file:rename(Filename,Newname), {ok,F} = file:open(Filename,[append]), put(Filename,F); true -> false end; 0 -> false % the file does not exist. end, FileHandle = get(Filename), {{Year,Month,Day},{Hour,Minute,Second}} = LocalTime, do_write(FileHandle,"[~p-~p-~p T ~p:~p:~p] ", [Year,Month,Day,Hour,Minute,Second]), Format2 = Format ++ "~n", do_write(FileHandle,Format2,Data). do_write(FileHandle,Format,Data) -> io:format(Format, Data), io:format(FileHandle,Format,Data). open_files([]) -> ok; open_files([File|Others]) -> {ok,FileHandle} = file:open(File,[append]), put(File,FileHandle), open_files(Others). close_files([]) -> ok; close_files([File|Others]) -> FileHandle = get(File), file:close(FileHandle), close_files(Others).
daylog.app
{application,daylog, %%應用名 [ {description,""}, {vsn,"0.1.0"}, {modules,[]}, %%應用中的模塊,可留空。 {registered,[]}, %%進程註冊名,沒進行實際註冊操做,用於告知otp系統哪一個進程註冊了哪一個名字,可留空 {applications,[kernel,stdlib]}, %%先行啓動的全部應用,不能留空 {mod,{daylog_app,[]}}, %%指定應用啓動模塊,不能留空 {env,[{log_file,"../../logs/info.log"}]} ]}.
compile.sh
for f in *.erl;do erlc +debug_info -o ../ebin $f;done
reference.txt
API Reference: Module:daylog add_logfiles(Files): Types: Files : a list for filenames info_log(Msg): Types: Msg: string descript:output log to default file which is descripted in ebin/daylog.app. info_log(Format,Datas) Types: Format: string Datas: list for data logger(FileName,Msg) -> Types: FileName: string Msg: String logger(FileName,Format,Datas) -> Types: FileName: string Format: string Datas: list for data