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.

629 regels
22 KiB

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