用cowboy这个库,没有日志功能,所以研究了otp提供的日志功能。

1.启动SASL的方式


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,可自己指定目录。

还可以用 application:start(sasl). 在代码里启动应用。默认会读取代码ebin下的sasl.app,可去源码复制一份sasl.app然后修改 env参数。

sasl是通过application:get_env(sasl,xxx) 获得配置信息 。

2、sasl配置文件:

{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}  %限定日志个数。
]}

3、error_logger:

参考官方文档

设置日志error_logger输出日志到文件:error_logger:logfile({open,Filename}).

注: 每次执行error_logger:logfile({open,Filename}).都会删掉之前Filename文件。

4、自定义日志功能:

由于业务需要,我想按照日期切分日志,该日志主要是为了记录业务操作。

思路:每次写日志到日志文件,先判断日志文件的最新修改日期是否跟当前日期一致,不一致就对该日志文件重命名(后缀添加日期),并重新创建日志文件。

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

erlang日志功能。的更多相关文章

  1. .NET跨平台之旅:增加文件日志功能遇到的挫折

    在将我们的ASP.NET 5示例站点(about.cnblogs.com)升级至ASP.NET 5 RC1的时候,我们增加了控制台日志功能. 在ASP.NET 5添加日志功能很简单,只需在projec ...

  2. 01Spring_基本jia包的导入andSpring的整体架构and怎么加入日志功能

    1.什么是Spring : v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:u ...

  3. Spring AOP 实现写事件日志功能

    什么是AOP?AOP使用场景?AOP相关概念?Spring AOP组件?如何使用Spring AOP?等等这些问题请参考博文:Spring AOP 实现原理 下面重点介绍如何写事件日志功能,把日志保存 ...

  4. jboss7访问日志功能及使用goaccess工具分析

    网络上虽然很多文章分别讲到jboss7的访问日志如何配置,goaccess工具怎么分析nginx/tomcat等日志.但将两者放在一起即“通过goaccess分析jboss访问日志”的倒是没搜索到. ...

  5. 干货:yii日志功能详解

    转载请注明来自souldak,微博:@evagle 一.基本日志功能 详细的介绍查看官网的document:http://www.yiiframework.com/doc/guide/1.1/en/t ...

  6. MongoDB实战指南(四):MongoDB的Journaling日志功能

    mongoDB的Journaling日志功能与常见的log日志是不一样的,mongoDB也有log日志,它只是简单记录了数据库在服务器上的启动信息.慢查询记录.数据库异常信息.客户端与数据库服务器连接 ...

  7. SSIS从理论到实战,再到应用(6)----SSIS的自带日志功能

    原文:SSIS从理论到实战,再到应用(6)----SSIS的自带日志功能 上期回顾: SSIS从理论到实战,再到应用(5)----流程控制之Foreach循环 博主最近新负责了一个ssis大项目的架构 ...

  8. Nginx之旅系列 - Nginx日志功能 PK Linux内核printk

    题记:Nginx之旅系列是用来记录Nginx从使用到源码学习的点点滴滴,分享学习Nginx的快乐 Nginx 首页: http://nginx.org/ Nginx日志功能 PK Linux内核pri ...

  9. (译)Windsor入门教程---第五部分 添加日志功能

    介绍     现在我们已经有了基础的框架了,是时候添加内容了,那么我们首先应该考虑的就是在应用程序中添加日志功能.我们会使用Windsor来配置,在这一部分,你将学习Windsor之外的其他功能. L ...

随机推荐

  1. 足球游戏AI_资料收集

    实况足球中文官网 浅谈足球游戏的人工智能 用遗传算法加强足球游戏的人工智能 足球规则图解 守门员的技巧你知道吗? 教你足球守门员守门技术练习方法和技巧 足球守门员规则 判断点球方向

  2. Eclipse创建Maven时提示错误could not resolve archetype

    今天用Eclipse创建Maven多模块项目的时候提示错误: could not resolve archetype ******release from any of the configured ...

  3. Chrome & Linux font

    1 $ sudo apt-get install texlive-full # 较大 2 $ mkdir -p ~/.fonts 3 下载这个win7字体包解压后放到~/.fonts下 4 $ sud ...

  4. for xml 字符串拼接

    SELECT TOP 10 B.user_gid,LEFT(StuList,LEN(StuList)-1) as hobby FROM (SELECT user_gid,( SELECT CAST(a ...

  5. Android Studio使用org.apache.http报错

    Android Studio使用org.apache.http报错需要加上这句话:useLibrary 'org.apache.http.legacy'

  6. 记录容易忘记的知识点(html 内容)

    <xx 表文件名> 导入外部样式表 <link type="text/css" rel="stylesheet" href="xx. ...

  7. Nginx-->基础-->排错-->nginx错误总结

    一.启动时错误 1.错误提示: 2016/11/16 17:36:41 [emerg] 2458#2458: getpwnam("nginx") failed 查看错误日志文件内容 ...

  8. Android Studio线下版和线上版都使用正式签名脚本(保证keysore签名文件和项目在同级目录),不用再因为繁琐的发正式版而烦恼

    场景:调用微信等第三方应用时如果生成的版本不是正式签名的可能会调用失败,使用如下脚本不用再为繁琐的发正式签名版而烦恼 app项目中的build.gradle追加如下代码: //使用正式签名脚本(保证k ...

  9. Nginx:针对IPv4的内核参数优化

    这里提及的参数是和IPv4网络有关的linux内核参数,我们可以将这些内核参数的值追加到linux系统的/etc/sysctl.conf文件中,然后使用如下命令使修改生效: [root@bogon ~ ...

  10. 【转】Win7 64bit Oracle 11g 使用PL/SQL Developer 连接时提示“SQL*Net not properly installed”

    转载:http://www.cnblogs.com/xihuaodc/p/3189257.html  因为之前的Oracle不能用了,所以重新安装了64位的Oracle,安装一路正常 完了之后安装了P ...