emqx_metrics.erl 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2017-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_metrics).
  17. -behaviour(gen_server).
  18. -include("emqx.hrl").
  19. -include("logger.hrl").
  20. -include("types.hrl").
  21. -include("emqx_mqtt.hrl").
  22. -export([
  23. start_link/0,
  24. stop/0
  25. ]).
  26. -export([
  27. new/1,
  28. new/2,
  29. ensure/1,
  30. ensure/2,
  31. all/0
  32. ]).
  33. -export([
  34. val/1,
  35. inc/1,
  36. inc/2,
  37. dec/1,
  38. dec/2,
  39. set/2
  40. ]).
  41. -export([
  42. trans/2,
  43. trans/3,
  44. commit/0
  45. ]).
  46. %% Inc received/sent metrics
  47. -export([
  48. inc_msg/1,
  49. inc_recv/1,
  50. inc_sent/1
  51. ]).
  52. %% gen_server callbacks
  53. -export([
  54. init/1,
  55. handle_call/3,
  56. handle_cast/2,
  57. handle_info/2,
  58. terminate/2,
  59. code_change/3
  60. ]).
  61. %% BACKW: v4.3.0
  62. -export([upgrade_retained_delayed_counter_type/0]).
  63. -export_type([metric_idx/0]).
  64. -compile({inline, [inc/1, inc/2, dec/1, dec/2]}).
  65. -compile({inline, [inc_recv/1, inc_sent/1]}).
  66. -opaque metric_idx() :: 1..1024.
  67. -type metric_name() :: atom() | string() | binary().
  68. -define(MAX_SIZE, 1024).
  69. -define(RESERVED_IDX, 512).
  70. -define(TAB, ?MODULE).
  71. -define(SERVER, ?MODULE).
  72. %% Bytes sent and received
  73. -define(BYTES_METRICS,
  74. % Total bytes received
  75. [
  76. {counter, 'bytes.received'},
  77. % Total bytes sent
  78. {counter, 'bytes.sent'}
  79. ]
  80. ).
  81. %% Packets sent and received
  82. -define(PACKET_METRICS,
  83. % All Packets received
  84. [
  85. {counter, 'packets.received'},
  86. % All Packets sent
  87. {counter, 'packets.sent'},
  88. % CONNECT Packets received
  89. {counter, 'packets.connect.received'},
  90. % CONNACK Packets sent
  91. {counter, 'packets.connack.sent'},
  92. % CONNACK error sent
  93. {counter, 'packets.connack.error'},
  94. % CONNACK auth_error sent
  95. {counter, 'packets.connack.auth_error'},
  96. % PUBLISH packets received
  97. {counter, 'packets.publish.received'},
  98. % PUBLISH packets sent
  99. {counter, 'packets.publish.sent'},
  100. % PUBLISH packet_id inuse
  101. {counter, 'packets.publish.inuse'},
  102. % PUBLISH failed for error
  103. {counter, 'packets.publish.error'},
  104. % PUBLISH failed for auth error
  105. {counter, 'packets.publish.auth_error'},
  106. % PUBLISH(QoS2) packets dropped
  107. {counter, 'packets.publish.dropped'},
  108. % PUBACK packets received
  109. {counter, 'packets.puback.received'},
  110. % PUBACK packets sent
  111. {counter, 'packets.puback.sent'},
  112. % PUBACK packet_id inuse
  113. {counter, 'packets.puback.inuse'},
  114. % PUBACK packets missed
  115. {counter, 'packets.puback.missed'},
  116. % PUBREC packets received
  117. {counter, 'packets.pubrec.received'},
  118. % PUBREC packets sent
  119. {counter, 'packets.pubrec.sent'},
  120. % PUBREC packet_id inuse
  121. {counter, 'packets.pubrec.inuse'},
  122. % PUBREC packets missed
  123. {counter, 'packets.pubrec.missed'},
  124. % PUBREL packets received
  125. {counter, 'packets.pubrel.received'},
  126. % PUBREL packets sent
  127. {counter, 'packets.pubrel.sent'},
  128. % PUBREL packets missed
  129. {counter, 'packets.pubrel.missed'},
  130. % PUBCOMP packets received
  131. {counter, 'packets.pubcomp.received'},
  132. % PUBCOMP packets sent
  133. {counter, 'packets.pubcomp.sent'},
  134. % PUBCOMP packet_id inuse
  135. {counter, 'packets.pubcomp.inuse'},
  136. % PUBCOMP packets missed
  137. {counter, 'packets.pubcomp.missed'},
  138. % SUBSCRIBE Packets received
  139. {counter, 'packets.subscribe.received'},
  140. % SUBSCRIBE error
  141. {counter, 'packets.subscribe.error'},
  142. % SUBSCRIBE failed for not auth
  143. {counter, 'packets.subscribe.auth_error'},
  144. % SUBACK packets sent
  145. {counter, 'packets.suback.sent'},
  146. % UNSUBSCRIBE Packets received
  147. {counter, 'packets.unsubscribe.received'},
  148. % UNSUBSCRIBE error
  149. {counter, 'packets.unsubscribe.error'},
  150. % UNSUBACK Packets sent
  151. {counter, 'packets.unsuback.sent'},
  152. % PINGREQ packets received
  153. {counter, 'packets.pingreq.received'},
  154. % PINGRESP Packets sent
  155. {counter, 'packets.pingresp.sent'},
  156. % DISCONNECT Packets received
  157. {counter, 'packets.disconnect.received'},
  158. % DISCONNECT Packets sent
  159. {counter, 'packets.disconnect.sent'},
  160. % Auth Packets received
  161. {counter, 'packets.auth.received'},
  162. % Auth Packets sent
  163. {counter, 'packets.auth.sent'}
  164. ]
  165. ).
  166. %% Messages sent/received and pubsub
  167. -define(MESSAGE_METRICS,
  168. % All Messages received
  169. [
  170. {counter, 'messages.received'},
  171. % All Messages sent
  172. {counter, 'messages.sent'},
  173. % QoS0 Messages received
  174. {counter, 'messages.qos0.received'},
  175. % QoS0 Messages sent
  176. {counter, 'messages.qos0.sent'},
  177. % QoS1 Messages received
  178. {counter, 'messages.qos1.received'},
  179. % QoS1 Messages sent
  180. {counter, 'messages.qos1.sent'},
  181. % QoS2 Messages received
  182. {counter, 'messages.qos2.received'},
  183. % QoS2 Messages sent
  184. {counter, 'messages.qos2.sent'},
  185. %% PubSub Metrics
  186. % Messages Publish
  187. {counter, 'messages.publish'},
  188. % Messages dropped due to no subscribers
  189. {counter, 'messages.dropped'},
  190. % QoS2 Messages expired
  191. {counter, 'messages.dropped.await_pubrel_timeout'},
  192. % Messages dropped
  193. {counter, 'messages.dropped.no_subscribers'},
  194. % Messages forward
  195. {counter, 'messages.forward'},
  196. % Messages delayed
  197. {counter, 'messages.delayed'},
  198. % Messages delivered
  199. {counter, 'messages.delivered'},
  200. % Messages acked
  201. {counter, 'messages.acked'}
  202. ]
  203. ).
  204. %% Delivery metrics
  205. -define(DELIVERY_METRICS, [
  206. {counter, 'delivery.dropped'},
  207. {counter, 'delivery.dropped.no_local'},
  208. {counter, 'delivery.dropped.too_large'},
  209. {counter, 'delivery.dropped.qos0_msg'},
  210. {counter, 'delivery.dropped.queue_full'},
  211. {counter, 'delivery.dropped.expired'}
  212. ]).
  213. %% Client Lifecircle metrics
  214. -define(CLIENT_METRICS, [
  215. {counter, 'client.connect'},
  216. {counter, 'client.connack'},
  217. {counter, 'client.connected'},
  218. {counter, 'client.authenticate'},
  219. {counter, 'client.auth.anonymous'},
  220. {counter, 'client.authorize'},
  221. {counter, 'client.subscribe'},
  222. {counter, 'client.unsubscribe'},
  223. {counter, 'client.disconnected'}
  224. ]).
  225. %% Session Lifecircle metrics
  226. -define(SESSION_METRICS, [
  227. {counter, 'session.created'},
  228. {counter, 'session.resumed'},
  229. {counter, 'session.takenover'},
  230. {counter, 'session.discarded'},
  231. {counter, 'session.terminated'}
  232. ]).
  233. %% Statistic metrics for ACL checking
  234. -define(STASTS_ACL_METRICS, [
  235. {counter, 'authorization.allow'},
  236. {counter, 'authorization.deny'},
  237. {counter, 'authorization.cache_hit'}
  238. ]).
  239. %% Statistic metrics for auth checking
  240. -define(STASTS_AUTHN_METRICS, [
  241. {counter, 'authentication.success'},
  242. {counter, 'authentication.success.anonymous'},
  243. {counter, 'authentication.failure'}
  244. ]).
  245. %% Overload protetion counters
  246. -define(OLP_METRICS, [
  247. {counter, 'olp.delay.ok'},
  248. {counter, 'olp.delay.timeout'},
  249. {counter, 'olp.hbn'},
  250. {counter, 'olp.gc'},
  251. {counter, 'olp.new_conn'}
  252. ]).
  253. -record(state, {next_idx = 1}).
  254. -record(metric, {name, type, idx}).
  255. %% @doc Start the metrics server.
  256. -spec start_link() -> startlink_ret().
  257. start_link() ->
  258. gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
  259. -spec stop() -> ok.
  260. stop() ->
  261. try
  262. gen_server:stop(?SERVER)
  263. catch
  264. exit:R when R =:= noproc orelse R =:= timeout ->
  265. %% pid is killed after timeout
  266. ok
  267. end.
  268. %% BACKW: v4.3.0
  269. upgrade_retained_delayed_counter_type() ->
  270. Ks = ['messages.delayed'],
  271. gen_server:call(?SERVER, {set_type_to_counter, Ks}, infinity).
  272. %%--------------------------------------------------------------------
  273. %% Metrics API
  274. %%--------------------------------------------------------------------
  275. -spec new(metric_name()) -> ok.
  276. new(Name) ->
  277. new(counter, Name).
  278. -spec new(gauge | counter, metric_name()) -> ok.
  279. new(gauge, Name) ->
  280. create(gauge, Name);
  281. new(counter, Name) ->
  282. create(counter, Name).
  283. -spec ensure(metric_name()) -> ok.
  284. ensure(Name) ->
  285. ensure(counter, Name).
  286. -spec ensure(gauge | counter, metric_name()) -> ok.
  287. ensure(Type, Name) when Type =:= gauge; Type =:= counter ->
  288. case ets:lookup(?TAB, Name) of
  289. [] -> create(Type, Name);
  290. _ -> ok
  291. end.
  292. %% @private
  293. create(Type, Name) ->
  294. case gen_server:call(?SERVER, {create, Type, Name}) of
  295. {ok, _Idx} -> ok;
  296. {error, Reason} -> error(Reason)
  297. end.
  298. %% @doc Get all metrics
  299. -spec all() -> [{metric_name(), non_neg_integer()}].
  300. all() ->
  301. CRef = persistent_term:get(?MODULE),
  302. [
  303. {Name, counters:get(CRef, Idx)}
  304. || #metric{name = Name, idx = Idx} <- ets:tab2list(?TAB)
  305. ].
  306. %% @doc Get metric value
  307. -spec val(metric_name()) -> non_neg_integer().
  308. val(Name) ->
  309. try
  310. case ets:lookup(?TAB, Name) of
  311. [#metric{idx = Idx}] ->
  312. CRef = persistent_term:get(?MODULE),
  313. counters:get(CRef, Idx);
  314. [] ->
  315. 0
  316. end
  317. %% application will restart when join cluster, then ets not exist.
  318. catch
  319. error:badarg ->
  320. 0
  321. end.
  322. %% @doc Increase counter
  323. -spec inc(metric_name()) -> ok.
  324. inc(Name) ->
  325. inc(Name, 1).
  326. %% @doc Increase metric value
  327. -spec inc(metric_name(), pos_integer()) -> ok.
  328. inc(Name, Value) ->
  329. update_counter(Name, Value).
  330. %% @doc Decrease metric value
  331. -spec dec(metric_name()) -> ok.
  332. dec(Name) ->
  333. dec(Name, 1).
  334. %% @doc Decrease metric value
  335. -spec dec(metric_name(), pos_integer()) -> ok.
  336. dec(Name, Value) ->
  337. update_counter(Name, -Value).
  338. %% @doc Set metric value
  339. -spec set(metric_name(), integer()) -> ok.
  340. set(Name, Value) ->
  341. CRef = persistent_term:get(?MODULE),
  342. Idx = ets:lookup_element(?TAB, Name, 4),
  343. counters:put(CRef, Idx, Value).
  344. -spec trans(inc | dec, metric_name()) -> ok.
  345. trans(Op, Name) when Op =:= inc; Op =:= dec ->
  346. trans(Op, Name, 1).
  347. -spec trans(inc | dec, metric_name(), pos_integer()) -> ok.
  348. trans(inc, Name, Value) ->
  349. cache(Name, Value);
  350. trans(dec, Name, Value) ->
  351. cache(Name, -Value).
  352. -spec cache(metric_name(), integer()) -> ok.
  353. cache(Name, Value) ->
  354. put(
  355. '$metrics',
  356. case get('$metrics') of
  357. undefined ->
  358. #{Name => Value};
  359. Metrics ->
  360. maps:update_with(Name, fun(Cnt) -> Cnt + Value end, Value, Metrics)
  361. end
  362. ),
  363. ok.
  364. -spec commit() -> ok.
  365. commit() ->
  366. case get('$metrics') of
  367. undefined ->
  368. ok;
  369. Metrics ->
  370. _ = erase('$metrics'),
  371. lists:foreach(fun update_counter/1, maps:to_list(Metrics))
  372. end.
  373. update_counter({Name, Value}) ->
  374. update_counter(Name, Value).
  375. update_counter(Name, Value) ->
  376. CRef = persistent_term:get(?MODULE),
  377. CIdx =
  378. case reserved_idx(Name) of
  379. Idx when is_integer(Idx) -> Idx;
  380. undefined -> ets:lookup_element(?TAB, Name, 4)
  381. end,
  382. counters:add(CRef, CIdx, Value).
  383. %%--------------------------------------------------------------------
  384. %% Inc received/sent metrics
  385. %%--------------------------------------------------------------------
  386. -spec inc_msg(emqx_types:massage()) -> ok.
  387. inc_msg(Msg) ->
  388. case Msg#message.qos of
  389. 0 -> inc('messages.qos0.received');
  390. 1 -> inc('messages.qos1.received');
  391. 2 -> inc('messages.qos2.received')
  392. end,
  393. inc('messages.received').
  394. %% @doc Inc packets received.
  395. -spec inc_recv(emqx_types:packet()) -> ok.
  396. inc_recv(Packet) ->
  397. inc('packets.received'),
  398. do_inc_recv(Packet).
  399. do_inc_recv(?PACKET(?CONNECT)) ->
  400. inc('packets.connect.received');
  401. do_inc_recv(?PUBLISH_PACKET(QoS)) ->
  402. inc('messages.received'),
  403. case QoS of
  404. ?QOS_0 -> inc('messages.qos0.received');
  405. ?QOS_1 -> inc('messages.qos1.received');
  406. ?QOS_2 -> inc('messages.qos2.received');
  407. _other -> ok
  408. end,
  409. inc('packets.publish.received');
  410. do_inc_recv(?PACKET(?PUBACK)) ->
  411. inc('packets.puback.received');
  412. do_inc_recv(?PACKET(?PUBREC)) ->
  413. inc('packets.pubrec.received');
  414. do_inc_recv(?PACKET(?PUBREL)) ->
  415. inc('packets.pubrel.received');
  416. do_inc_recv(?PACKET(?PUBCOMP)) ->
  417. inc('packets.pubcomp.received');
  418. do_inc_recv(?PACKET(?SUBSCRIBE)) ->
  419. inc('packets.subscribe.received');
  420. do_inc_recv(?PACKET(?UNSUBSCRIBE)) ->
  421. inc('packets.unsubscribe.received');
  422. do_inc_recv(?PACKET(?PINGREQ)) ->
  423. inc('packets.pingreq.received');
  424. do_inc_recv(?PACKET(?DISCONNECT)) ->
  425. inc('packets.disconnect.received');
  426. do_inc_recv(?PACKET(?AUTH)) ->
  427. inc('packets.auth.received');
  428. do_inc_recv(_Packet) ->
  429. ok.
  430. %% @doc Inc packets sent. Will not count $SYS PUBLISH.
  431. -spec inc_sent(emqx_types:packet()) -> ok.
  432. inc_sent(?PUBLISH_PACKET(_QoS, <<"$SYS/", _/binary>>, _, _)) ->
  433. ok;
  434. inc_sent(Packet) ->
  435. inc('packets.sent'),
  436. do_inc_sent(Packet).
  437. do_inc_sent(?CONNACK_PACKET(ReasonCode)) ->
  438. (ReasonCode == ?RC_SUCCESS) orelse inc('packets.connack.error'),
  439. ((ReasonCode == ?RC_NOT_AUTHORIZED) orelse
  440. (ReasonCode == ?CONNACK_AUTH)) andalso
  441. inc('packets.connack.auth_error'),
  442. ((ReasonCode == ?RC_BAD_USER_NAME_OR_PASSWORD) orelse
  443. (ReasonCode == ?CONNACK_CREDENTIALS)) andalso
  444. inc('packets.connack.auth_error'),
  445. inc('packets.connack.sent');
  446. do_inc_sent(?PUBLISH_PACKET(QoS)) ->
  447. inc('messages.sent'),
  448. case QoS of
  449. ?QOS_0 -> inc('messages.qos0.sent');
  450. ?QOS_1 -> inc('messages.qos1.sent');
  451. ?QOS_2 -> inc('messages.qos2.sent');
  452. _other -> ok
  453. end,
  454. inc('packets.publish.sent');
  455. do_inc_sent(?PUBACK_PACKET(_PacketId, ReasonCode)) ->
  456. (ReasonCode >= ?RC_UNSPECIFIED_ERROR) andalso inc('packets.publish.error'),
  457. (ReasonCode == ?RC_NOT_AUTHORIZED) andalso inc('packets.publish.auth_error'),
  458. inc('packets.puback.sent');
  459. do_inc_sent(?PUBREC_PACKET(_PacketId, ReasonCode)) ->
  460. (ReasonCode >= ?RC_UNSPECIFIED_ERROR) andalso inc('packets.publish.error'),
  461. (ReasonCode == ?RC_NOT_AUTHORIZED) andalso inc('packets.publish.auth_error'),
  462. inc('packets.pubrec.sent');
  463. do_inc_sent(?PACKET(?PUBREL)) ->
  464. inc('packets.pubrel.sent');
  465. do_inc_sent(?PACKET(?PUBCOMP)) ->
  466. inc('packets.pubcomp.sent');
  467. do_inc_sent(?PACKET(?SUBACK)) ->
  468. inc('packets.suback.sent');
  469. do_inc_sent(?PACKET(?UNSUBACK)) ->
  470. inc('packets.unsuback.sent');
  471. do_inc_sent(?PACKET(?PINGRESP)) ->
  472. inc('packets.pingresp.sent');
  473. do_inc_sent(?PACKET(?DISCONNECT)) ->
  474. inc('packets.disconnect.sent');
  475. do_inc_sent(?PACKET(?AUTH)) ->
  476. inc('packets.auth.sent');
  477. do_inc_sent(_Packet) ->
  478. ok.
  479. %%--------------------------------------------------------------------
  480. %% gen_server callbacks
  481. %%--------------------------------------------------------------------
  482. init([]) ->
  483. % Create counters array
  484. CRef = counters:new(?MAX_SIZE, [write_concurrency]),
  485. ok = persistent_term:put(?MODULE, CRef),
  486. % Create index mapping table
  487. ok = emqx_utils_ets:new(?TAB, [{keypos, 2}, {read_concurrency, true}]),
  488. Metrics = lists:append([
  489. ?BYTES_METRICS,
  490. ?PACKET_METRICS,
  491. ?MESSAGE_METRICS,
  492. ?DELIVERY_METRICS,
  493. ?CLIENT_METRICS,
  494. ?SESSION_METRICS,
  495. ?STASTS_ACL_METRICS,
  496. ?STASTS_AUTHN_METRICS,
  497. ?OLP_METRICS
  498. ]),
  499. % Store reserved indices
  500. ok = lists:foreach(
  501. fun({Type, Name}) ->
  502. Idx = reserved_idx(Name),
  503. Metric = #metric{name = Name, type = Type, idx = Idx},
  504. true = ets:insert(?TAB, Metric),
  505. ok = counters:put(CRef, Idx, 0)
  506. end,
  507. Metrics
  508. ),
  509. {ok, #state{next_idx = ?RESERVED_IDX + 1}, hibernate}.
  510. handle_call({create, Type, Name}, _From, State = #state{next_idx = ?MAX_SIZE}) ->
  511. ?SLOG(error, #{
  512. msg => "failed_to_create_type_name_for_index_exceeded",
  513. type => Type,
  514. name => Name
  515. }),
  516. {reply, {error, metric_index_exceeded}, State};
  517. handle_call({create, Type, Name}, _From, State = #state{next_idx = NextIdx}) ->
  518. case ets:lookup(?TAB, Name) of
  519. [#metric{idx = Idx}] ->
  520. ?SLOG(info, #{msg => "name_already_exists", name => Name}),
  521. {reply, {ok, Idx}, State};
  522. [] ->
  523. Metric = #metric{name = Name, type = Type, idx = NextIdx},
  524. true = ets:insert(?TAB, Metric),
  525. {reply, {ok, NextIdx}, State#state{next_idx = NextIdx + 1}}
  526. end;
  527. handle_call({set_type_to_counter, Keys}, _From, State) ->
  528. lists:foreach(
  529. fun(K) ->
  530. ets:update_element(?TAB, K, {#metric.type, counter})
  531. end,
  532. Keys
  533. ),
  534. {reply, ok, State};
  535. handle_call(Req, _From, State) ->
  536. ?SLOG(error, #{msg => "unexpected_call", req => Req}),
  537. {reply, ignored, State}.
  538. handle_cast(Msg, State) ->
  539. ?SLOG(error, #{msg => "unexpected_cast", req => Msg}),
  540. {noreply, State}.
  541. handle_info(Info, State) ->
  542. ?SLOG(error, #{msg => "unexpected_info", info => Info}),
  543. {noreply, State}.
  544. terminate(_Reason, _State) ->
  545. ok.
  546. code_change(_OldVsn, State, _Extra) ->
  547. {ok, State}.
  548. %%--------------------------------------------------------------------
  549. %% Internal functions
  550. %%--------------------------------------------------------------------
  551. reserved_idx('bytes.received') -> 01;
  552. reserved_idx('bytes.sent') -> 02;
  553. %% Reserved indices of packet's metrics
  554. reserved_idx('packets.received') -> 10;
  555. reserved_idx('packets.sent') -> 11;
  556. reserved_idx('packets.connect.received') -> 12;
  557. reserved_idx('packets.connack.sent') -> 13;
  558. reserved_idx('packets.connack.error') -> 14;
  559. reserved_idx('packets.connack.auth_error') -> 15;
  560. reserved_idx('packets.publish.received') -> 16;
  561. reserved_idx('packets.publish.sent') -> 17;
  562. reserved_idx('packets.publish.inuse') -> 18;
  563. reserved_idx('packets.publish.error') -> 19;
  564. reserved_idx('packets.publish.auth_error') -> 20;
  565. reserved_idx('packets.puback.received') -> 21;
  566. reserved_idx('packets.puback.sent') -> 22;
  567. reserved_idx('packets.puback.inuse') -> 23;
  568. reserved_idx('packets.puback.missed') -> 24;
  569. reserved_idx('packets.pubrec.received') -> 25;
  570. reserved_idx('packets.pubrec.sent') -> 26;
  571. reserved_idx('packets.pubrec.inuse') -> 27;
  572. reserved_idx('packets.pubrec.missed') -> 28;
  573. reserved_idx('packets.pubrel.received') -> 29;
  574. reserved_idx('packets.pubrel.sent') -> 30;
  575. reserved_idx('packets.pubrel.missed') -> 31;
  576. reserved_idx('packets.pubcomp.received') -> 32;
  577. reserved_idx('packets.pubcomp.sent') -> 33;
  578. reserved_idx('packets.pubcomp.inuse') -> 34;
  579. reserved_idx('packets.pubcomp.missed') -> 35;
  580. reserved_idx('packets.subscribe.received') -> 36;
  581. reserved_idx('packets.subscribe.error') -> 37;
  582. reserved_idx('packets.subscribe.auth_error') -> 38;
  583. reserved_idx('packets.suback.sent') -> 39;
  584. reserved_idx('packets.unsubscribe.received') -> 40;
  585. reserved_idx('packets.unsubscribe.error') -> 41;
  586. reserved_idx('packets.unsuback.sent') -> 42;
  587. reserved_idx('packets.pingreq.received') -> 43;
  588. reserved_idx('packets.pingresp.sent') -> 44;
  589. reserved_idx('packets.disconnect.received') -> 45;
  590. reserved_idx('packets.disconnect.sent') -> 46;
  591. reserved_idx('packets.auth.received') -> 47;
  592. reserved_idx('packets.auth.sent') -> 48;
  593. reserved_idx('packets.publish.dropped') -> 49;
  594. %% Reserved indices of message's metrics
  595. reserved_idx('messages.received') -> 100;
  596. reserved_idx('messages.sent') -> 101;
  597. reserved_idx('messages.qos0.received') -> 102;
  598. reserved_idx('messages.qos0.sent') -> 103;
  599. reserved_idx('messages.qos1.received') -> 104;
  600. reserved_idx('messages.qos1.sent') -> 105;
  601. reserved_idx('messages.qos2.received') -> 106;
  602. reserved_idx('messages.qos2.sent') -> 107;
  603. reserved_idx('messages.publish') -> 108;
  604. reserved_idx('messages.dropped') -> 109;
  605. reserved_idx('messages.dropped.await_pubrel_timeout') -> 110;
  606. reserved_idx('messages.dropped.no_subscribers') -> 111;
  607. reserved_idx('messages.forward') -> 112;
  608. %%reserved_idx('messages.retained') -> 113; %% keep the index, new metrics can use this
  609. reserved_idx('messages.delayed') -> 114;
  610. reserved_idx('messages.delivered') -> 115;
  611. reserved_idx('messages.acked') -> 116;
  612. reserved_idx('delivery.expired') -> 117;
  613. reserved_idx('delivery.dropped') -> 118;
  614. reserved_idx('delivery.dropped.no_local') -> 119;
  615. reserved_idx('delivery.dropped.too_large') -> 120;
  616. reserved_idx('delivery.dropped.qos0_msg') -> 121;
  617. reserved_idx('delivery.dropped.queue_full') -> 122;
  618. reserved_idx('delivery.dropped.expired') -> 123;
  619. reserved_idx('client.connect') -> 200;
  620. reserved_idx('client.connack') -> 201;
  621. reserved_idx('client.connected') -> 202;
  622. reserved_idx('client.authenticate') -> 203;
  623. reserved_idx('client.enhanced_authenticate') -> 204;
  624. reserved_idx('client.auth.anonymous') -> 205;
  625. reserved_idx('client.authorize') -> 206;
  626. reserved_idx('client.subscribe') -> 207;
  627. reserved_idx('client.unsubscribe') -> 208;
  628. reserved_idx('client.disconnected') -> 209;
  629. reserved_idx('session.created') -> 220;
  630. reserved_idx('session.resumed') -> 221;
  631. reserved_idx('session.takenover') -> 222;
  632. reserved_idx('session.discarded') -> 223;
  633. reserved_idx('session.terminated') -> 224;
  634. reserved_idx('authorization.allow') -> 300;
  635. reserved_idx('authorization.deny') -> 301;
  636. reserved_idx('authorization.cache_hit') -> 302;
  637. reserved_idx('authentication.success') -> 310;
  638. reserved_idx('authentication.success.anonymous') -> 311;
  639. reserved_idx('authentication.failure') -> 312;
  640. reserved_idx('olp.delay.ok') -> 400;
  641. reserved_idx('olp.delay.timeout') -> 401;
  642. reserved_idx('olp.hbn') -> 402;
  643. reserved_idx('olp.gc') -> 403;
  644. reserved_idx('olp.new_conn') -> 404;
  645. reserved_idx(_) -> undefined.