|
@ -15,15 +15,15 @@ |
|
|
|
|
|
|
|
|
-record(state, { |
|
|
-record(state, { |
|
|
parent :: pid() |
|
|
parent :: pid() |
|
|
, fBaseName :: file:filename_all() |
|
|
|
|
|
|
|
|
, fDir :: file:filename_all() %% file base name |
|
|
|
|
|
, fBaseName :: file:filename_all() %% file base name |
|
|
, size = 0 :: non_neg_integer() |
|
|
, size = 0 :: non_neg_integer() |
|
|
, fMaxSize :: infinity | non_neg_integer() |
|
|
, fMaxSize :: infinity | non_neg_integer() |
|
|
, ioDevice :: file:io_device() |
|
|
, ioDevice :: file:io_device() |
|
|
, fEventFrame :: pos_integer() |
|
|
|
|
|
, eventsThisFrame = 0 :: non_neg_integer() |
|
|
|
|
|
, buffer = <<>> :: binary() |
|
|
|
|
|
|
|
|
|
|
|
, tcmIsCut = false |
|
|
, tcmIsCut = false |
|
|
|
|
|
, fMaxMsg = 0 :: non_neg_integer() |
|
|
|
|
|
, msgCnt = 0 |
|
|
|
|
|
, msgList = [] |
|
|
}). |
|
|
}). |
|
|
|
|
|
|
|
|
start_link(Opts) -> |
|
|
start_link(Opts) -> |
|
@ -34,7 +34,9 @@ init(Parent, TracerOpts) -> |
|
|
process_flag(message_queue_data, off_heap), |
|
|
process_flag(message_queue_data, off_heap), |
|
|
process_flag(trap_exit, true), |
|
|
process_flag(trap_exit, true), |
|
|
%% No need to close the file, it'll be closed when the process exits. |
|
|
%% No need to close the file, it'll be closed when the process exits. |
|
|
Filename = maps:get(fBaseName, TracerOpts, "traces.lz4"), |
|
|
|
|
|
|
|
|
FDir = maps:get(fDir, TracerOpts, <<"./">>), |
|
|
|
|
|
FBaseName = maps:get(fBaseName, TracerOpts, <<"traces.zip">>), |
|
|
|
|
|
Filename = fileName(FDir, FBaseName), |
|
|
{ok, IoDevice} = file:open(Filename, [write, raw]), |
|
|
{ok, IoDevice} = file:open(Filename, [write, raw]), |
|
|
|
|
|
|
|
|
TcmIsCut = maps:get(tcmIsCut, TracerOpts, maps:get(tcmDepth, ?defTcmMap)), |
|
|
TcmIsCut = maps:get(tcmIsCut, TracerOpts, maps:get(tcmDepth, ?defTcmMap)), |
|
@ -53,15 +55,16 @@ init(Parent, TracerOpts) -> |
|
|
|
|
|
|
|
|
State = #state{ |
|
|
State = #state{ |
|
|
parent = Parent |
|
|
parent = Parent |
|
|
, fBaseName = Filename |
|
|
|
|
|
|
|
|
, fDir = FDir |
|
|
|
|
|
, fBaseName = FBaseName |
|
|
, ioDevice = IoDevice |
|
|
, ioDevice = IoDevice |
|
|
, fMaxSize = maps:get(fMaxSize, TracerOpts, infinity) |
|
|
|
|
|
, fEventFrame = maps:get(fEventFrame, TracerOpts, 100000) |
|
|
|
|
|
|
|
|
, fMaxSize = maps:get(fMaxSize, TracerOpts, 104857600) |
|
|
|
|
|
, fMaxMsg = maps:get(fMaxMsg, TracerOpts, 150) |
|
|
, tcmIsCut = TcmIsCut |
|
|
, tcmIsCut = TcmIsCut |
|
|
}, |
|
|
}, |
|
|
loop(State). |
|
|
loop(State). |
|
|
|
|
|
|
|
|
loop(State = #state{parent = Parent, size = Size, ioDevice = IoDevice, fEventFrame = MaxEvents, eventsThisFrame = NumEvents0, buffer = Buffer0, tcmIsCut = TcmIsCut}) -> |
|
|
|
|
|
|
|
|
loop(#state{parent = Parent, size = Size, fDir = FDir, fBaseName = FBaseName, ioDevice = IoDevice, fMaxSize = MaxSize, tcmIsCut = TcmIsCut, fMaxMsg = FMaxMsg, msgCnt = MsgCnt, msgList = MsgList} = State) -> |
|
|
receive |
|
|
receive |
|
|
{system, From, Request} -> |
|
|
{system, From, Request} -> |
|
|
sys:handle_system_msg(Request, From, Parent, ?MODULE, [], State); |
|
|
sys:handle_system_msg(Request, From, Parent, ?MODULE, [], State); |
|
@ -69,31 +72,30 @@ loop(State = #state{parent = Parent, size = Size, ioDevice = IoDevice, fEventFra |
|
|
terminate(Reason, State); |
|
|
terminate(Reason, State); |
|
|
RMsg -> |
|
|
RMsg -> |
|
|
Msg = case TcmIsCut of true -> tpTermCut:cut(RMsg); _ -> RMsg end, |
|
|
Msg = case TcmIsCut of true -> tpTermCut:cut(RMsg); _ -> RMsg end, |
|
|
Bin = term_to_binary(Msg), |
|
|
|
|
|
BinSize = byte_size(Bin), |
|
|
|
|
|
Buffer = <<Buffer0/binary, BinSize:32, Bin/binary>>, |
|
|
|
|
|
NumEvents = NumEvents0 + 1, |
|
|
|
|
|
if |
|
|
|
|
|
MaxEvents =:= NumEvents -> |
|
|
|
|
|
Frame = lz4f:compress_frame(Buffer), |
|
|
|
|
|
ok = file:write(IoDevice, Frame), |
|
|
|
|
|
maybe_rotate(State#state{size = Size + byte_size(Frame), |
|
|
|
|
|
eventsThisFrame = 0, buffer = <<>>}); |
|
|
|
|
|
|
|
|
NewMsgList = [Msg | MsgList], |
|
|
|
|
|
NewMsgCnt = MsgCnt + 1, |
|
|
|
|
|
|
|
|
|
|
|
case NewMsgCnt >= FMaxMsg of |
|
|
true -> |
|
|
true -> |
|
|
loop(State#state{eventsThisFrame = NumEvents, buffer = Buffer}) |
|
|
|
|
|
|
|
|
MsgListBin = zlib:compress(term_to_binary(NewMsgList)), |
|
|
|
|
|
MsgListSize = byte_size(MsgListBin), |
|
|
|
|
|
NewSize = Size + MsgListSize, |
|
|
|
|
|
ok = file:write(IoDevice, [<<NewSize:32>>, MsgListBin]), |
|
|
|
|
|
|
|
|
|
|
|
case NewSize >= MaxSize of |
|
|
|
|
|
true -> |
|
|
|
|
|
ok = file:close(IoDevice), |
|
|
|
|
|
Filename = fileName(FDir, FBaseName), |
|
|
|
|
|
{ok, NewIoDevice} = file:open(Filename, [write, raw]), |
|
|
|
|
|
loop(State#state{ioDevice = NewIoDevice, size = 0, msgCnt = 0, msgList = []}); |
|
|
|
|
|
_ -> |
|
|
|
|
|
loop(State#state{size = NewSize, msgCnt = 0, msgList = []}) |
|
|
|
|
|
end; |
|
|
|
|
|
_ -> |
|
|
|
|
|
loop(State#state{msgCnt = NewMsgCnt, msgList = NewMsgList}) |
|
|
end |
|
|
end |
|
|
end. |
|
|
end. |
|
|
|
|
|
|
|
|
%%IMY-todo 干掉这个函数 同时对于旋转的文件名 使用时间 年月日时分 |
|
|
|
|
|
maybe_rotate(State = #state{fBaseName = Filename, size = Size, fMaxSize = MaxSize, |
|
|
|
|
|
ioDevice = OldIoDevice}) when Size > MaxSize -> |
|
|
|
|
|
ok = file:close(OldIoDevice), |
|
|
|
|
|
ok = file:rename(Filename, Filename ++ ".bak"), |
|
|
|
|
|
{ok, NewIoDevice} = file:open(Filename, [write, raw]), |
|
|
|
|
|
loop(State#state{size = 0, ioDevice = NewIoDevice}); |
|
|
|
|
|
maybe_rotate(State) -> |
|
|
|
|
|
loop(State). |
|
|
|
|
|
|
|
|
|
|
|
system_continue(_, _, State) -> |
|
|
system_continue(_, _, State) -> |
|
|
loop(State). |
|
|
loop(State). |
|
|
|
|
|
|
|
@ -105,6 +107,18 @@ system_code_change(Misc, _, _, _) -> |
|
|
{ok, Misc}. |
|
|
{ok, Misc}. |
|
|
|
|
|
|
|
|
-spec terminate(any(), #state{}) -> no_return(). |
|
|
-spec terminate(any(), #state{}) -> no_return(). |
|
|
terminate(Reason, #state{ioDevice = IoDevice, buffer = Buffer}) -> |
|
|
|
|
|
_ = file:write(IoDevice, lz4f:compress_frame(Buffer)), |
|
|
|
|
|
|
|
|
terminate(Reason, #state{ioDevice = IoDevice, size = Size, msgList = MsgList}) -> |
|
|
|
|
|
MsgListBin = zlib:compress(term_to_binary(MsgList)), |
|
|
|
|
|
MsgListSize = byte_size(MsgListBin), |
|
|
|
|
|
NewSize = Size + MsgListSize, |
|
|
|
|
|
ok = file:write(IoDevice, [<<NewSize:32>>, MsgListBin]), |
|
|
|
|
|
ok = file:close(IoDevice), |
|
|
exit(Reason). |
|
|
exit(Reason). |
|
|
|
|
|
|
|
|
|
|
|
fileName(Dir, FBaseName) -> |
|
|
|
|
|
{{Year, Month, Day}, {Hour, Minute, _Second}} = erlang:localtime(), |
|
|
|
|
|
TimeStr = eFmt:formatBin("~B~2.10.0B~2.10.0B~B~2.10.0B_", [Year, Month, Day, Hour, Minute]), |
|
|
|
|
|
FileName = <<TimeStr/binary, FBaseName/binary>>, |
|
|
|
|
|
WholeName = filename:absname(filename:join(Dir, FileName)), |
|
|
|
|
|
ok = filelib:ensure_dir(WholeName), |
|
|
|
|
|
WholeName. |