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 <[email protected]>
%%% Description : Cutting logs every day.
%%%
%%% Created : 4 Mar 2015 by kingson <[email protected]>
%%%-------------------------------------------------------------------
-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
时间: 2024-12-15 03:42:04

erlang日志功能。的相关文章

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

1.什么是Spring : v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4 /* Style De

如何实现企业管理系统的操作日志功能

如何实现企业管理系统的操作日志功能 实现思路解析:在做企业管理系统的同时,操作日志这一功能是必不可少的:所谓的操作日志就是记录一个用户从登陆时开始,到退出登陆时结束,记录这一过程中用户的全部操作:这里用.Net MVC为例 第一步:数据库 表1:用户日志(Sys_UserLoginLog) 列名 数据类型 主键/外键 说明 LoginID int 主键 日志ID StaffID int 外键 员工ID operationLog nchar(50) 操作内容 operationDate datet

log4js实现node的日志功能

nodejs实现日志功能可以使用log4js,但其github只是简单的介绍了一下,我在使用的时候也遇到了一些问题,总结出来,希望能给初学者一些帮助. log4在java和net里都有,相信大家都用过,所以就不介绍基本概念了,直接给出node代码. 首先,安装 npm install log4js 之后,我们建立一个log.js文件,用来配置log4js. var log4js = require('log4js');log4js.configure({appenders: [ { type:

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

介绍 现在我们已经有了基础的框架了,是时候添加内容了,那么我们首先应该考虑的就是在应用程序中添加日志功能.我们会使用Windsor来配置,在这一部分,你将学习Windsor之外的其他功能. Logging Facility 在上一部分说过,Windsor有很多自带的可选的功能组件,他们扩展了Windsor的即用性.在这一部分,我们将在程序中添加日志功能. Logging Facility提供了一些常用的日志框架比如Log4net.Nlog,以及mvc内置的日志框架Trace.Logging Fa

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

在将我们的ASP.NET 5示例站点(about.cnblogs.com)升级至ASP.NET 5 RC1的时候,我们增加了控制台日志功能. 在ASP.NET 5添加日志功能很简单,只需在project.json中添加Microsoft.Extensions.Logging.Console的引用: "dependencies":{ "Microsoft.Extensions.Logging.Console": "1.0.0-*" } 并且在 St

【.NET】AOP思想下的日志功能

AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programming,面向对象编程)的补充和完善. 我们说了这么久的OOP,对于OO的理解也越来越深入,OO的伟大让我们一度折服.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.可当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力. 也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日

如何在通用权限管理系统中集成log4net日志功能

开发人员都知道,在系统运行中要记录各种日志,自己写一个日志功能,无论是在效率还是功能扩展上来说都不是很好,目前大多用的是第三方的日志系统,其中一个非常有名,用的最多的就是log4net.下面是关于这个组件的介绍 ”Log4net是基于.net开发的一款非常著名的记录日志开源组件.最早是2001年7月由NeoWorks Limited启动的项目,基本的框架源, 于另外的一个非常著名的姐妹组件-log4j.现由Apache组织开发与维护.此日志架构是可灵活扩展,且通过配置文件来设置日志的属性及输出,

Percona5.6首次提供了审计日志功能

如果有一天数据库里丢失了一条记录,开发让你查什么时候被谁从哪个IP,执行了delete操作,那么在之前的版本是无法查到的,而Percona最新版本5.6.17首次提供了审计日志功能. (注:截止2014年5月19日,官方MySQL5.6.17和MariaDB10.0.11均没有提供该功能) 版本: 5.6.17-65.0-rel65.0-log Percona Server with XtraDB (GPL), Release rel65.0, Revision 587 安装插件: INSTAL

【java】java自带的java.util.logging.Logger日志功能

偶然翻阅到一篇文章,注意到Java自带的Logger日志功能,特地来细细的看一看,记录一下. 1.Java自带的日志功能,默认的配置 ①Logger的默认配置,位置在JRE安装目录下lib中的logging.properties中 ②logging.properties日志文件内容如下: ############################################################ # Default Logging Configuration File # # You