rewrite from lager
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

626 lines
22 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. -module(rumUtil).
  2. -include("rumCom.hrl").
  3. -include("rumDef.hrl").
  4. -include_lib("kernel/include/file.hrl").
  5. -export([
  6. levels/0
  7. , levelToNum/1
  8. , levelToChr/1
  9. , numToLevel/1
  10. , validateLogLevel/1
  11. , configToMask/1
  12. , atomCfgToLevels/1
  13. , maskToLevels/1
  14. , nowMs/0
  15. , msToBinStr/0
  16. , msToBinStr/1
  17. , parseRotateSpec/1
  18. , calcNextRotateMs/1
  19. , calcNextRotateMs/2
  20. , calcNextRotateDt/2
  21. , validate_trace/1
  22. , check_traces/4
  23. , isLoggAble/3
  24. , trace_filter/1
  25. , trace_filter/2
  26. , parsePath/1
  27. , find_file/2
  28. , checkHwm/1
  29. , checkHwm/2
  30. , makeInnerSinkName/1
  31. , maybeFlush/2
  32. , isFileChanged/3
  33. , get_env/2
  34. , get_opt/3
  35. ]).
  36. levels() ->
  37. [debug, info, notice, warning, error, critical, alert, emergency, none].
  38. levelToNum(debug) -> ?debug;
  39. levelToNum(info) -> ?info;
  40. levelToNum(notice) -> ?notice;
  41. levelToNum(warning) -> ?warning;
  42. levelToNum(error) -> ?error;
  43. levelToNum(critical) -> ?critical;
  44. levelToNum(alert) -> ?alert;
  45. levelToNum(emergency) -> ?emergency;
  46. levelToNum(none) -> ?none.
  47. numToLevel(?debug) -> debug;
  48. numToLevel(?info) -> info;
  49. numToLevel(?notice) -> notice;
  50. numToLevel(?warning) -> warning;
  51. numToLevel(?error) -> error;
  52. numToLevel(?critical) -> critical;
  53. numToLevel(?alert) -> alert;
  54. numToLevel(?emergency) -> emergency;
  55. numToLevel(?none) -> none.
  56. levelToChr(debug) -> $D;
  57. levelToChr(info) -> $I;
  58. levelToChr(notice) -> $N;
  59. levelToChr(warning) -> $W;
  60. levelToChr(error) -> $E;
  61. levelToChr(critical) -> $C;
  62. levelToChr(alert) -> $A;
  63. levelToChr(emergency) -> $M;
  64. levelToChr(none) -> $ .
  65. -spec validateLogLevel(atom()|string()) -> false | rumMaskLevel().
  66. validateLogLevel(Level) ->
  67. try rumUtil:configToMask(Level) of
  68. Levels ->
  69. Levels
  70. catch
  71. _:_ ->
  72. false
  73. end.
  74. -spec configToMask(atom()|string()) -> rumMaskLevel().
  75. configToMask(Conf) ->
  76. Levels = atomCfgToLevels(Conf),
  77. levelsToMask(Levels, 0).
  78. -spec levelsToMask([rumAtomLevel()], rumMaskLevel()) -> rumMaskLevel().
  79. levelsToMask([], Acc) ->
  80. Acc;
  81. levelsToMask([Level | Left], Acc) ->
  82. levelsToMask(Left, levelToNum(Level) bor Acc).
  83. -spec maskToLevels(rumMaskLevel()) -> [rumAtomLevel()].
  84. maskToLevels(Mask) ->
  85. maskToLevels(?RumLevels, Mask, []).
  86. maskToLevels([], _Mask, Acc) ->
  87. lists:reverse(Acc);
  88. maskToLevels([Level | Levels], Mask, Acc) ->
  89. case (levelToNum(Level) band Mask) /= 0 of
  90. true ->
  91. maskToLevels(Levels, Mask, [Level | Acc]);
  92. _ ->
  93. maskToLevels(Levels, Mask, Acc)
  94. end.
  95. -spec atomCfgToLevels(atom()) -> [rumAtomLevel()].
  96. atomCfgToLevels(Cfg) ->
  97. binCfgToLevels(atom_to_binary(Cfg, utf8)).
  98. binCfgToLevels(<<"!", Rest/binary>>) ->
  99. ?RumLevels -- binCfgToLevels(Rest);
  100. binCfgToLevels(<<"=<", Rest/binary>>) ->
  101. riseInWhile(?RumLevels, levelBinToAtom(Rest), []);
  102. binCfgToLevels(<<"<=", Rest/binary>>) ->
  103. riseInWhile(?RumLevels, levelBinToAtom(Rest), []);
  104. binCfgToLevels(<<">=", Rest/binary>>) ->
  105. dropInWhile(?RumLevels, levelBinToAtom(Rest));
  106. binCfgToLevels(<<"=>", Rest/binary>>) ->
  107. dropInWhile(?RumLevels, levelBinToAtom(Rest));
  108. binCfgToLevels(<<"=", Rest/binary>>) ->
  109. [levelBinToAtom(Rest)];
  110. binCfgToLevels(<<"<", Rest/binary>>) ->
  111. riseOutWhile(?RumLevels, levelBinToAtom(Rest), []);
  112. binCfgToLevels(<<">", Rest/binary>>) ->
  113. dropOutWhile(?RumLevels, levelBinToAtom(Rest));
  114. binCfgToLevels(Rest) ->
  115. [levelBinToAtom(Rest)].
  116. dropInWhile([], _Level) ->
  117. [];
  118. dropInWhile([CurLevel | Left] = Rest, Level) ->
  119. case CurLevel == Level of
  120. true ->
  121. Rest;
  122. _ ->
  123. dropInWhile(Left, Level)
  124. end.
  125. dropOutWhile([], _Level) ->
  126. [];
  127. dropOutWhile([CurLevel | Left], Level) ->
  128. case CurLevel == Level of
  129. true ->
  130. Left;
  131. _ ->
  132. dropOutWhile(Left, Level)
  133. end.
  134. riseInWhile([], _Level, Acc) ->
  135. Acc;
  136. riseInWhile([CurLevel | Left], Level, Acc) ->
  137. case CurLevel == Level of
  138. true ->
  139. [CurLevel | Acc];
  140. _ ->
  141. riseInWhile(Left, Level, [CurLevel | Acc])
  142. end.
  143. riseOutWhile([], _Level, Acc) ->
  144. Acc;
  145. riseOutWhile([CurLevel | Left], Level, Acc) ->
  146. case CurLevel == Level of
  147. true ->
  148. Acc;
  149. _ ->
  150. riseOutWhile(Left, Level, [CurLevel | Acc])
  151. end.
  152. levelBinToAtom(BinStr) ->
  153. AtomLevel = binary_to_atom(BinStr, utf8),
  154. case lists:member(AtomLevel, ?RumLevels) of
  155. true ->
  156. AtomLevel;
  157. _ ->
  158. erlang:error(badarg)
  159. end.
  160. nowMs() ->
  161. erlang:system_time(millisecond).
  162. msToBinStr() ->
  163. msToBinStr(nowMs()).
  164. msToBinStr(MsTick) ->
  165. ThisSec = MsTick div 1000,
  166. ThisMs = MsTick rem 1000,
  167. {{Y, M, D}, {H, Mi, S}} = erlang:universaltime_to_localtime(erlang:posixtime_to_universaltime(ThisSec)),
  168. <<(integer_to_binary(Y))/binary, "-", (i2b(M))/binary, "-", (i2b(D))/binary, " ", (i2b(H))/binary, ":", (i2b(Mi))/binary, ":", (i2b(S))/binary, ".", (i3b(ThisMs))/binary>>.
  169. i2b(Num) ->
  170. if
  171. Num < 10 ->
  172. <<"0", (integer_to_binary(Num))/binary>>;
  173. true ->
  174. integer_to_binary(Num)
  175. end.
  176. i3b(Num) ->
  177. if
  178. Num < 10 ->
  179. <<"00", (integer_to_binary(Num))/binary>>;
  180. Num < 100 ->
  181. <<"0", (integer_to_binary(Num))/binary>>;
  182. true ->
  183. integer_to_binary(Num)
  184. end.
  185. %% last parse hour
  186. parseRotateHourSpec([], DayOrMonthF, Hour, Minute, DayOrMonthV) ->
  187. {DayOrMonthF, Hour, Minute, DayOrMonthV};
  188. parseRotateHourSpec([$H, M1, M2], DayOrMonthF, Hour, _Minute, DayOrMonthV) when M1 >= $0, M1 =< $9, M2 >= $0, M2 =< $9 ->
  189. Min = list_to_integer([M1, M2]),
  190. ?IIF(Min >= 0 andalso Min =< 59, {DayOrMonthF, Hour, Min, DayOrMonthV}, {error, invalid_date_spec});
  191. parseRotateHourSpec([$H, M], DayOrMonthF, Hour, _Minute, DayOrMonthV) when M >= $0, M =< $9 ->
  192. {DayOrMonthF, Hour, M - $0, DayOrMonthV};
  193. parseRotateHourSpec(_, _DayOrMonth, _Hour, _Minute, _DayOrMonthV) ->
  194. {error, invalid_date_spec}.
  195. %% second parse day Default to 00:00:00 rotation
  196. parseRotateDaySpec([], DayOrMonthF, Hour, Minute, DayOrMonthV) ->
  197. {DayOrMonthF, Hour, Minute, DayOrMonthV};
  198. parseRotateDaySpec([$D, D1, D2 | T], DayOrMonthF, _Hour, _Minute, DayOrMonthV) when D1 > $0, D1 < $9, D2 > $0, D2 < $9 ->
  199. Day = list_to_integer([D1, D2]),
  200. ?IIF(Day >= 0 andalso Day =< 23, parseRotateHourSpec(T, DayOrMonthF, Day, 0, DayOrMonthV), {error, invalid_date_spec});
  201. parseRotateDaySpec([$D, D | T], DayOrMonthF, _Hour, _Minute, DayOrMonthV) when D >= $0, D =< $9 ->
  202. parseRotateHourSpec(T, DayOrMonthF, D - $0, 0, DayOrMonthV);
  203. parseRotateDaySpec(T, DayOrMonth, Hour, Minute, DayOrMonthV) ->
  204. parseRotateHourSpec(T, DayOrMonth, Hour, Minute, DayOrMonthV).
  205. %% first parse date or week
  206. parseRotateDateSpec([$$, $W, W | T], _DayOrMonthF, _Hour, _Minute, _DayOrMonthV) when W >= $1, W =< $7 ->
  207. parseRotateDaySpec(T, day, 0, 0, W - $0);
  208. parseRotateDateSpec([$$, $M, L | T], _DayOrMonthF, _Hour, _Minute, DayOrMonthV) when L == $L; L == $l ->
  209. parseRotateDaySpec(T, last, 0, 0, DayOrMonthV);
  210. parseRotateDateSpec([$$, $M, M1, M2 | T], _DayOrMonthF, _Hour, _Minute, _DayOrMonthV) when M1 >= $0, M1 =< $9, M2 >= $0, M2 =< $9 ->
  211. Date = list_to_integer([M1, M2]),
  212. ?IIF(Date >= 1 andalso Date =< 31, parseRotateDaySpec(T, date, 0, 0, Date), {error, invalid_date_spec});
  213. parseRotateDateSpec([$$, $M, M | T], _DayOrMonthF, _Hour, _Minute, _DayOrMonthV) when M >= $1, M =< $9 ->
  214. parseRotateDaySpec(T, date, 0, 0, M - $0);
  215. parseRotateDateSpec([$$ | T], DayOrMonthF, Hour, Minute, DayOrMonthV) ->
  216. parseRotateDaySpec(T, DayOrMonthF, Hour, Minute, DayOrMonthV);
  217. parseRotateDateSpec(_, _DayOrMonthF, _Hour, _Minute, _DayOrMonthV) ->
  218. {error, invalid_date_spec}.
  219. parseRotateSpec(Spec) ->
  220. case parseRotateDateSpec(Spec, undefined, undefined, undefined, undefined) of
  221. {error, _} = ErrRet ->
  222. ErrRet;
  223. {undefined, undefined, undefined, _} ->
  224. {error, invalid_date_spec};
  225. STuple ->
  226. {ok, STuple}
  227. end.
  228. calcNextRotateMs(Spec) ->
  229. {Date, Time} = NowDataTime = erlang:localtime(),
  230. NextTime = calcNextRotate(Spec, Date, Time),
  231. (rumTime:lDateTimeToSec(NextTime) - rumTime:lDateTimeToSec(NowDataTime)) * 1000.
  232. calcNextRotateMs(Spec, NowDataTime) ->
  233. {Date, Time} = NowDataTime,
  234. NextTime = calcNextRotate(Spec, Date, Time),
  235. (rumTime:lDateTimeToSec(NextTime) - rumTime:lDateTimeToSec(NowDataTime)) * 1000.
  236. calcNextRotateDt(Spec, NowDataTime) ->
  237. {Date, Time} = NowDataTime,
  238. calcNextRotate(Spec, Date, Time).
  239. calcNextRotate({undefined, SHour, SMinute, _SMonthV}, CurDate, CurTime) ->
  240. case SHour of
  241. undefined ->
  242. {CurHour, CurMinute, _} = CurTime,
  243. case CurMinute < SMinute of
  244. true ->
  245. %% rotation is this hour
  246. {CurDate, {CurHour, SMinute, 0}};
  247. _ ->
  248. %% rotation is next hour
  249. NexSec = rumTime:lDateTimeToSec({CurDate, {CurHour, SMinute, 0}}) + 3600,
  250. rumTime:secToLDateTime(NexSec)
  251. end;
  252. _ ->
  253. case CurTime < {SHour, SMinute, 0} of
  254. true ->
  255. %% rotation is this day
  256. {CurDate, {SHour, SMinute, 0}};
  257. _ ->
  258. %% rotation is next day
  259. NexSec = rumTime:lDateTimeToSec({CurDate, {SHour, SMinute, 0}}) + 86400,
  260. rumTime:secToLDateTime(NexSec)
  261. end
  262. end;
  263. calcNextRotate({day, SHour, SMinute, SDay}, CurDate, CurTime) ->
  264. CurWeekDay = rumTime:weekDay(CurDate),
  265. if
  266. CurWeekDay < SDay ->
  267. %% rotation is this week
  268. DiffDays = SDay - CurWeekDay,
  269. NexSec = rumTime:lDateTimeToSec({CurDate, {SHour, SMinute, 0}}) + (86400 * DiffDays),
  270. rumTime:secToLDateTime(NexSec);
  271. CurWeekDay > SDay ->
  272. %% rotation is next week
  273. DiffDays = ((7 - CurWeekDay) + SDay),
  274. NexSec = rumTime:lDateTimeToSec({CurDate, {SHour, SMinute, 0}}) + (86400 * DiffDays),
  275. rumTime:secToLDateTime(NexSec);
  276. true ->
  277. case CurTime < {SHour, SMinute, 0} of
  278. true ->
  279. %% rotation is this week
  280. {CurDate, {SHour, SMinute, 0}};
  281. _ ->
  282. %% rotation is next week
  283. NexSec = rumTime:lDateTimeToSec({CurDate, {SHour, SMinute, 0}}) + (86400 * 7),
  284. rumTime:secToLDateTime(NexSec)
  285. end
  286. end;
  287. calcNextRotate({last, SHour, SMinute, _SMonthV}, CurDate, CurTime) ->
  288. {CurYear, CurMonth, CurDay} = CurDate,
  289. CurMonthDay = rumTime:monthDay(CurYear, CurMonth),
  290. case CurMonthDay == CurDay of
  291. true ->
  292. case CurTime < {SHour, SMinute, 0} of
  293. true ->
  294. %% rotation is this last month day
  295. {CurDate, {SHour, SMinute, 0}};
  296. _ ->
  297. %% rotation is next last month day
  298. NexSec = rumTime:lDateTimeToSec({CurDate, {23, 59, 59}}) + 1, %% 下个月1号凌晨
  299. {NewNDate, _NewNTime} = rumTime:secToLDateTime(NexSec),
  300. {NewNYear, NewNMonth, _} = NewNDate,
  301. NewMonthDay = rumTime:monthDay(NewNYear, NewNMonth),
  302. {{NewNYear, NewNMonth, NewMonthDay}, {SHour, SMinute, 0}}
  303. end;
  304. _ ->
  305. %% rotation is this last month day
  306. {{CurYear, CurMonth, CurMonthDay}, {SHour, SMinute, 0}}
  307. end;
  308. calcNextRotate({date, SHour, SMinute, SDate}, CurDate, CurTime) ->
  309. {CurYear, CurMonth, CurDay} = CurDate,
  310. if
  311. CurDay < SDate ->
  312. %% rotation is this month day
  313. {{CurYear, CurMonth, SDate}, {SHour, SMinute, 0}};
  314. CurDay > SDate ->
  315. %% rotation is next month day
  316. CurMonthDay = rumTime:monthDay(CurYear, CurMonth),
  317. NexSec = rumTime:lDateTimeToSec({{CurYear, CurMonth, CurMonthDay}, {23, 59, 59}}) + 1,
  318. {NewNDate, _NewNTime} = rumTime:secToLDateTime(NexSec),
  319. {NewNYear, NewNMonth, _} = NewNDate,
  320. {{NewNYear, NewNMonth, SDate}, {SHour, SMinute, 0}};
  321. true ->
  322. case CurTime < {SHour, SMinute, 0} of
  323. true ->
  324. %% rotation is this month day
  325. {CurDate, {SHour, SMinute, 0}};
  326. _ ->
  327. %% rotation is next month day
  328. CurMonthDay = rumTime:monthDay(CurYear, CurMonth),
  329. NexSec = rumTime:lDateTimeToSec({{CurYear, CurMonth, CurMonthDay}, {23, 59, 59}}) + 1,
  330. {NewNDate, _NewNTime} = rumTime:secToLDateTime(NexSec),
  331. {NewNYear, NewNMonth, _} = NewNDate,
  332. {{NewNYear, NewNMonth, SDate}, {SHour, SMinute, 0}}
  333. end
  334. end.
  335. -spec trace_filter(Query :: 'none' | [tuple()]) -> {ok, any()}.
  336. trace_filter(Query) ->
  337. trace_filter(?RumDefTracer, Query).
  338. %% TODO: Support multiple trace modules
  339. %-spec trace_filter(Module :: atom(), Query :: 'none' | [tuple()]) -> {ok, any()}.
  340. trace_filter(Module, Query) when Query == none; Query == [] ->
  341. {ok, _} = glc:compile(Module, glc:null(false));
  342. trace_filter(Module, Query) when is_list(Query) ->
  343. {ok, _} = glc:compile(Module, glc_lib:reduce(trace_any(Query))).
  344. validate_trace({Filter, Level, {Destination, ID}}) when is_tuple(Filter); is_list(Filter), is_atom(Level), is_atom(Destination) ->
  345. case validate_trace({Filter, Level, Destination}) of
  346. {ok, {F, L, D}} ->
  347. {ok, {F, L, {D, ID}}};
  348. Error ->
  349. Error
  350. end;
  351. validate_trace({Filter, Level, Destination}) when is_tuple(Filter); is_list(Filter), is_atom(Level), is_atom(Destination) ->
  352. ValidFilter = validate_trace_filter(Filter),
  353. try configToMask(Level) of
  354. _ when not ValidFilter ->
  355. {error, invalid_trace};
  356. L when is_list(Filter) ->
  357. {ok, {trace_all(Filter), L, Destination}};
  358. L ->
  359. {ok, {Filter, L, Destination}}
  360. catch
  361. _:_ ->
  362. {error, invalid_level}
  363. end;
  364. validate_trace(_) ->
  365. {error, invalid_trace}.
  366. validate_trace_filter(Filter) when is_tuple(Filter), is_atom(element(1, Filter)) =:= false ->
  367. false;
  368. validate_trace_filter(Filter) when is_list(Filter) ->
  369. lists:all(fun validate_trace_filter/1, Filter);
  370. validate_trace_filter({Key, '*'}) when is_atom(Key) -> true;
  371. validate_trace_filter({any, L}) when is_list(L) -> lists:all(fun validate_trace_filter/1, L);
  372. validate_trace_filter({all, L}) when is_list(L) -> lists:all(fun validate_trace_filter/1, L);
  373. validate_trace_filter({null, Bool}) when is_boolean(Bool) -> true;
  374. validate_trace_filter({Key, _Value}) when is_atom(Key) -> true;
  375. validate_trace_filter({Key, '=', _Value}) when is_atom(Key) -> true;
  376. validate_trace_filter({Key, '!=', _Value}) when is_atom(Key) -> true;
  377. validate_trace_filter({Key, '<', _Value}) when is_atom(Key) -> true;
  378. validate_trace_filter({Key, '=<', _Value}) when is_atom(Key) -> true;
  379. validate_trace_filter({Key, '>', _Value}) when is_atom(Key) -> true;
  380. validate_trace_filter({Key, '>=', _Value}) when is_atom(Key) -> true;
  381. validate_trace_filter(_) -> false.
  382. trace_all(Query) ->
  383. glc:all(trace_acc(Query)).
  384. trace_any(Query) ->
  385. glc:any(Query).
  386. trace_acc(Query) ->
  387. trace_acc(Query, []).
  388. trace_acc([], Acc) ->
  389. lists:reverse(Acc);
  390. trace_acc([{any, L} | T], Acc) ->
  391. trace_acc(T, [glc:any(L) | Acc]);
  392. trace_acc([{all, L} | T], Acc) ->
  393. trace_acc(T, [glc:all(L) | Acc]);
  394. trace_acc([{null, Bool} | T], Acc) ->
  395. trace_acc(T, [glc:null(Bool) | Acc]);
  396. trace_acc([{Key, '*'} | T], Acc) ->
  397. trace_acc(T, [glc:wc(Key) | Acc]);
  398. trace_acc([{Key, '!'} | T], Acc) ->
  399. trace_acc(T, [glc:nf(Key) | Acc]);
  400. trace_acc([{Key, Val} | T], Acc) ->
  401. trace_acc(T, [glc:eq(Key, Val) | Acc]);
  402. trace_acc([{Key, '=', Val} | T], Acc) ->
  403. trace_acc(T, [glc:eq(Key, Val) | Acc]);
  404. trace_acc([{Key, '!=', Val} | T], Acc) ->
  405. trace_acc(T, [glc:neq(Key, Val) | Acc]);
  406. trace_acc([{Key, '>', Val} | T], Acc) ->
  407. trace_acc(T, [glc:gt(Key, Val) | Acc]);
  408. trace_acc([{Key, '>=', Val} | T], Acc) ->
  409. trace_acc(T, [glc:gte(Key, Val) | Acc]);
  410. trace_acc([{Key, '=<', Val} | T], Acc) ->
  411. trace_acc(T, [glc:lte(Key, Val) | Acc]);
  412. trace_acc([{Key, '<', Val} | T], Acc) ->
  413. trace_acc(T, [glc:lt(Key, Val) | Acc]).
  414. check_traces(_, _, [], Acc) ->
  415. lists:flatten(Acc);
  416. check_traces(Attrs, Level, [{_, FilterLevel, _} | Flows], Acc) when (Level band FilterLevel) == 0 ->
  417. check_traces(Attrs, Level, Flows, Acc);
  418. check_traces(Attrs, Level, [{Filter, _, _} | Flows], Acc) when length(Attrs) < length(Filter) ->
  419. check_traces(Attrs, Level, Flows, Acc);
  420. check_traces(Attrs, Level, [Flow | Flows], Acc) ->
  421. check_traces(Attrs, Level, Flows, [check_trace(Attrs, Flow) | Acc]).
  422. check_trace(Attrs, {Filter, _Level, Dest}) when is_list(Filter) ->
  423. check_trace(Attrs, {trace_all(Filter), _Level, Dest});
  424. check_trace(Attrs, {Filter, _Level, Dest}) when is_tuple(Filter) ->
  425. Made = gre:make(Attrs, [list]),
  426. glc:handle(?RumDefTracer, Made),
  427. Match = glc_lib:matches(Filter, Made),
  428. case Match of
  429. true ->
  430. Dest;
  431. false ->
  432. []
  433. end.
  434. -spec isLoggAble(rumMsg:rumMsg(), rumMaskLevel(), term()) -> boolean().
  435. isLoggAble(Msg, Mask, MyName) ->
  436. (rumMsg:severity_as_int(Msg) band Mask) /= 0 orelse lists:member(MyName, rumMsg:destinations(Msg)).
  437. parsePath(RelPath) ->
  438. NewRelPath =
  439. case rumUtil:get_env(logRoot, undefined) of
  440. undefined ->
  441. RelPath;
  442. LogRoot ->
  443. case filename:dirname(RelPath) of
  444. "." ->
  445. filename:join(LogRoot, RelPath);
  446. false ->
  447. RelPath
  448. end
  449. end,
  450. filename:absname(NewRelPath).
  451. %% Find a file among the already installed handlers.
  452. %%
  453. %% The file is already expanded (i.e. lager_util:expand_path already added the
  454. %% "logRoot"), but the file paths inside Handlers are not.
  455. find_file(_File1, _Handlers = []) ->
  456. false;
  457. find_file(File1, [{{lager_file_backend, File2}, _Handler, _Sink} = HandlerInfo | Handlers]) ->
  458. File1Abs = File1,
  459. File2Abs = lager_util:expand_path(File2),
  460. case File1Abs =:= File2Abs of
  461. true ->
  462. % The file inside HandlerInfo is the same as the file we are looking
  463. % for, so we are done.
  464. HandlerInfo;
  465. false ->
  466. find_file(File1, Handlers)
  467. end;
  468. find_file(File1, [_HandlerInfo | Handlers]) ->
  469. find_file(File1, Handlers).
  470. %% conditionally check the HWM if the event would not have been filtered
  471. checkHwm(Shaper = #rumShaper{filter = Filter}, Event) ->
  472. case Filter(Event) of
  473. true ->
  474. {true, 0, Shaper};
  475. _ ->
  476. checkHwm(Shaper)
  477. end.
  478. %% 日志速率限制S i.e. 即传入消息的高水位标记
  479. checkHwm(#rumShaper{id = Id, hwm = Hwm, mps = Mps, lastTime = LastTime, dropped = Drop, flushQueue = FlushQueue, flushThreshold = FlushThreshold, timer = Timer, filter = Filter} = Shaper) ->
  480. if
  481. Hwm == undefined ->
  482. {true, 0, Shaper};
  483. Mps < Hwm ->
  484. NowTime = rumTime:now(),
  485. case LastTime == NowTime of
  486. true ->
  487. {true, 0, Shaper#rumShaper{mps = Mps + 1}};
  488. _ ->
  489. %different second - reset mps
  490. {true, 0, Shaper#rumShaper{dropped = 0, mps = 1, lastTime = NowTime}}
  491. end;
  492. true ->
  493. %% are we still in the same second?
  494. NowTimeMs = rumTime:nowMs(),
  495. NowTime = NowTimeMs div 1000,
  496. PastMs = NowTimeMs rem 1000,
  497. case LastTime == NowTime of
  498. true ->
  499. %% still in same second, but have exceeded the high water mark
  500. NewDrops = ?IIF(isNeedFlush(FlushQueue, FlushThreshold), dropMsg(NowTime, Filter, 0), 0),
  501. NewTimer = ?IIF(erlang:read_timer(Timer) =/= false, Timer, erlang:send_after(1000 - PastMs, self(), {mShaperExpired, Id})),
  502. {false, 0, Shaper#rumShaper{dropped = Drop + NewDrops + 1, timer = NewTimer}};
  503. _ ->
  504. _ = erlang:cancel_timer(Shaper#rumShaper.timer),
  505. %% different second, reset all counters and allow it
  506. {drop, Drop, Shaper#rumShaper{dropped = 0, mps = 1, lastTime = NowTime}}
  507. end
  508. end.
  509. isNeedFlush(true, FlushThreshold) ->
  510. case FlushThreshold of
  511. 0 ->
  512. true;
  513. _ ->
  514. PInfo = process_info(self(), message_queue_len),
  515. element(2, PInfo) > FlushThreshold
  516. end;
  517. isNeedFlush(_FlushQueue, _FlushThreshold) ->
  518. false.
  519. dropMsg(LastTime, Filter, Count) ->
  520. CurTime = rumTime:now(),
  521. case CurTime == LastTime of
  522. true ->
  523. receive
  524. %% we only discard gen_event notifications, because
  525. %% otherwise we might discard gen_event internal
  526. %% messages, such as trapped EXITs
  527. {'$gen_info', Event} ->
  528. NewCount = ?IIF(Filter(Event), Count, Count + 1),
  529. dropMsg(LastTime, Filter, NewCount)
  530. after 0 ->
  531. Count
  532. end;
  533. _ ->
  534. Count
  535. end.
  536. %% @private Build an atom for the gen_event process based on a sink name.
  537. %% For historical reasons, the default gen_event process for lager itself is named
  538. %% `lager_event'. For all other sinks, it is SinkName++`_lager_event'
  539. makeInnerSinkName(Sink) ->
  540. binary_to_atom(<<(atom_to_binary(Sink, utf8))/binary, "Event">>).
  541. maybeFlush(undefined, #rumShaper{} = S) ->
  542. S;
  543. maybeFlush(Flag, #rumShaper{} = S) ->
  544. S#rumShaper{flushQueue = Flag}.
  545. -spec isFileChanged(FileName :: file:name_all(), Inode :: pos_integer(), Ctime :: file:date_time()) -> {boolean(), file:file_info() | undefined}.
  546. isFileChanged(FileName, Inode, Ctime) ->
  547. case file:read_file_info(FileName, [raw]) of
  548. {ok, FileInfo} ->
  549. case os:type() of
  550. {win32, _} ->
  551. % Note: on win32, Inode is always zero So check the file's ctime to see if it needs to be re-opened
  552. {Ctime =/= FileInfo#file_info.ctime, FileInfo};
  553. _ ->
  554. {Inode =/= FileInfo#file_info.inode, FileInfo}
  555. end;
  556. _ ->
  557. {true, undefined}
  558. end.
  559. -spec get_env(Par :: atom(), Def :: term()) -> Val :: term().
  560. get_env(Key, Def) ->
  561. case application:get_env(?RumAppName, Key) of
  562. {ok, Val} ->
  563. Val;
  564. _ ->
  565. Def
  566. end.
  567. get_opt(Key, Opts, Def) ->
  568. case lists:keyfind(Key, 1, Opts) of
  569. false ->
  570. Def;
  571. V ->
  572. element(2, V)
  573. end.