rewrite from lager
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

629 行
22 KiB

4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
  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.