erlang日志功能。
用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日志功能。的更多相关文章
- .NET跨平台之旅:增加文件日志功能遇到的挫折
在将我们的ASP.NET 5示例站点(about.cnblogs.com)升级至ASP.NET 5 RC1的时候,我们增加了控制台日志功能. 在ASP.NET 5添加日志功能很简单,只需在projec ...
- 01Spring_基本jia包的导入andSpring的整体架构and怎么加入日志功能
1.什么是Spring : v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:u ...
- Spring AOP 实现写事件日志功能
什么是AOP?AOP使用场景?AOP相关概念?Spring AOP组件?如何使用Spring AOP?等等这些问题请参考博文:Spring AOP 实现原理 下面重点介绍如何写事件日志功能,把日志保存 ...
- jboss7访问日志功能及使用goaccess工具分析
网络上虽然很多文章分别讲到jboss7的访问日志如何配置,goaccess工具怎么分析nginx/tomcat等日志.但将两者放在一起即“通过goaccess分析jboss访问日志”的倒是没搜索到. ...
- 干货:yii日志功能详解
转载请注明来自souldak,微博:@evagle 一.基本日志功能 详细的介绍查看官网的document:http://www.yiiframework.com/doc/guide/1.1/en/t ...
- MongoDB实战指南(四):MongoDB的Journaling日志功能
mongoDB的Journaling日志功能与常见的log日志是不一样的,mongoDB也有log日志,它只是简单记录了数据库在服务器上的启动信息.慢查询记录.数据库异常信息.客户端与数据库服务器连接 ...
- SSIS从理论到实战,再到应用(6)----SSIS的自带日志功能
原文:SSIS从理论到实战,再到应用(6)----SSIS的自带日志功能 上期回顾: SSIS从理论到实战,再到应用(5)----流程控制之Foreach循环 博主最近新负责了一个ssis大项目的架构 ...
- Nginx之旅系列 - Nginx日志功能 PK Linux内核printk
题记:Nginx之旅系列是用来记录Nginx从使用到源码学习的点点滴滴,分享学习Nginx的快乐 Nginx 首页: http://nginx.org/ Nginx日志功能 PK Linux内核pri ...
- (译)Windsor入门教程---第五部分 添加日志功能
介绍 现在我们已经有了基础的框架了,是时候添加内容了,那么我们首先应该考虑的就是在应用程序中添加日志功能.我们会使用Windsor来配置,在这一部分,你将学习Windsor之外的其他功能. L ...
随机推荐
- 使用id名称和name直接获取元素
我们知道一些第三方的js库对如何快速选取html中的元素做了一些简化,貌似十分高深莫测,其实也不然.而且js本身自带了对于特殊元素的简便选取的方法,下面就为大家简单介绍下. 在html中,一般最直接的 ...
- h5 js 图片预览并判断 ajax上传
//建立一個可存取到該file的url function getObjectURL(file) { var url = null; if (window.createObjectURL != unde ...
- redis——持久化篇
众所周知,redis是内存数据库,它把数据存储在内存中,这样在加快读取速度的同时也对数据安全性产生了新的问题,即当redis所在服务器发生宕机后,redis数据库里的所有数据将会全部丢失. 为了解决这 ...
- Coursera 机器学习课程 机器学习基础:案例研究 证书
完成了课程1 机器学习基础:案例研究 贴个证书,继续努力完成后续的课程:
- Robotium-无源码测试
[总结] 1.新建工程,选择Android Application Project,选择This Project: PS:新建测试工程时报NULL错误,新建一个Android工程,然后再按上诉步骤建立 ...
- Apizza可以进行本地调试,也可以进行跨域调试,但是需要chrome插件
装Apizza Chrome插件 1 1. 进入Apizza官方网站.注册账号,进入控制台,可以看到提示安装chrome插件 2. 进入google app商店,搜索apiano 找到对于插件安装 ...
- myeclipse,eclipse打开当前文件所在文件夹
方法一: eclipse打开当前文件所在文件夹的插件Run-->External Tools-->External Tools Configurations...new 一个 progra ...
- freeCodeCamp:Slasher Flick
返回一个数组被截断n个元素后还剩余的元素,截断从索引0开始. /*思路 利用splice截断数组arr,返回运算后的数组arr; 如果howMany大于或等于数组长度,则返回空数组: */ funct ...
- css3小总结
一.边框 1.border-radius:x,y,模糊半径,color(x为负数时左移动,y为负数是上移动) 2.box-radius:x,y,模糊半径,阴影半径,color 3.border-ima ...
- Unity3D安卓打包参数配置与兼容性的关系分析
前言 在使用Unity3D工程导出安卓安装包的时候,往往会遇到兼容性的问题,针对某些机型,要么无法打开游戏,要么会出现卡机的现象.面对这种情况,我们可以调节相关的参数来提高兼容性. 为了了解在打包时候 ...