Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

1379 righe
49 KiB

4 anni fa
8 anni fa
8 anni fa
4 anni fa
4 anni fa
9 anni fa
6 anni fa
7 anni fa
7 anni fa
7 anni fa
8 anni fa
6 anni fa
4 anni fa
5 anni fa
5 anni fa
5 anni fa
6 anni fa
6 anni fa
6 anni fa
6 anni fa
6 anni fa
6 anni fa
6 anni fa
6 anni fa
6 anni fa
6 anni fa
7 anni fa
7 anni fa
7 anni fa
7 anni fa
7 anni fa
8 anni fa
8 anni fa
8 anni fa
8 anni fa
8 anni fa
9 anni fa
9 anni fa
  1. Overview
  2. --------
  3. Lager (as in the beer) is a logging framework for Erlang. Its purpose is
  4. to provide a more traditional way to perform logging in an erlang application
  5. that plays nicely with traditional UNIX logging tools like logrotate and
  6. syslog.
  7. [Travis-CI](http://travis-ci.org/erlang-lager/lager) :: [![Build Status](https://travis-ci.org/erlang-lager/lager.svg?branch=master)]
  8. [![Hex pm](https://img.shields.io/hexpm/v/lager)](https://hex.pm/packages/lager)
  9. Features
  10. --------
  11. * Finer grained log levels (debug, info, notice, warning, error, critical,
  12. alert, emergency)
  13. * Logger calls are transformed using a parse transform to allow capturing
  14. Module/Function/Line/Pid information
  15. * When no handler is consuming a log level (eg. debug) no event is sent
  16. to the log handler
  17. * Supports multiple backends, including console and file.
  18. * Supports multiple sinks
  19. * Rewrites common OTP error messages into more readable messages
  20. * Support for pretty printing records encountered at compile time
  21. * Tolerant in the face of large or many log messages, won't out of memory the node
  22. * Optional feature to bypass log size truncation ("unsafe")
  23. * Supports internal time and date based rotation, as well as external rotation tools
  24. * Syslog style log level comparison flags
  25. * Colored terminal output (requires R16+)
  26. * Map support (requires 17+)
  27. * Optional load shedding by setting a high water mark to kill (and reinstall)
  28. a sink after a configurable cool down timer
  29. Contributing
  30. ------------
  31. We welcome contributions from the community. We are always excited to get ideas
  32. for improving lager.
  33. If you are looking for an idea to help out, please take a look at our open
  34. issues - a number of them are tagged with [Help Wanted](https://github.com/erlang-lager/lager/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22)
  35. and [Easy](https://github.com/erlang-lager/lager/issues?q=is%3Aopen+is%3Aissue+label%3AEasy) - some
  36. of them are tagged as both! We are happy to mentor people get started with any
  37. of these issues, and they don't need prior discussion.
  38. That being said, before you send large changes please open an issue first to
  39. discuss the change you'd like to make along with an idea of your proposal to
  40. implement that change.
  41. ### PR guidelines ###
  42. * Large changes without prior discussion are likely to be rejected.
  43. * Changes without test cases are likely to be rejected.
  44. * Please use the style of the existing codebase when submitting PRs.
  45. We review PRs and issues at least once a month as described below.
  46. OTP Support Policy
  47. ------------------
  48. The lager maintainers intend to support the past three OTP releases from
  49. current on the main 3.x branch of the project. As of August 2019 that includes
  50. 22, 21 20
  51. Lager may or may not run on older OTP releases but it will only be guaranteed
  52. tested on the previous three OTP releases. If you need a version of lager
  53. which runs on older OTP releases, we recommend you use either the 3.4.0 release
  54. or the 2.x branch.
  55. Monthly triage cadence
  56. ----------------------
  57. We have (at least) monthly issue and PR triage for lager in the #lager room on the
  58. [freenode](https://freenode.net) IRC network every third Thursday at 2 pm US/Pacific,
  59. 10 pm UTC. You are welcome to join us there to ask questions about lager or
  60. participate in the triage.
  61. Usage
  62. -----
  63. To use lager in your application, you need to define it as a rebar dep or have
  64. some other way of including it in Erlang's path. You can then add the
  65. following option to the erlang compiler flags:
  66. ```erlang
  67. {parse_transform, lager_transform}
  68. ```
  69. Alternately, you can add it to the module you wish to compile with logging
  70. enabled:
  71. ```erlang
  72. -compile([{parse_transform, lager_transform}]).
  73. ```
  74. Before logging any messages, you'll need to start the lager application. The
  75. lager module's `start` function takes care of loading and starting any dependencies
  76. lager requires.
  77. ```erlang
  78. lager:start().
  79. ```
  80. You can also start lager on startup with a switch to `erl`:
  81. ```erlang
  82. erl -pa path/to/lager/ebin -s lager
  83. ```
  84. Once you have built your code with lager and started the lager application,
  85. you can then generate log messages by doing the following:
  86. ```erlang
  87. lager:error("Some message")
  88. ```
  89. Or:
  90. ```erlang
  91. lager:warning("Some message with a term: ~p", [Term])
  92. ```
  93. The general form is `lager:Severity()` where `Severity` is one of the log levels
  94. mentioned above.
  95. Configuration
  96. -------------
  97. To configure lager's backends, you use an application variable (probably in
  98. your app.config):
  99. ```erlang
  100. {lager, [
  101. {log_root, "/var/log/hello"},
  102. {handlers, [
  103. {lager_console_backend, [{level, info}]},
  104. {lager_file_backend, [{file, "error.log"}, {level, error}]},
  105. {lager_file_backend, [{file, "console.log"}, {level, info}]}
  106. ]}
  107. ]}.
  108. ```
  109. ```log_root``` variable is optional, by default file paths are relative to CWD.
  110. The available configuration options for each backend are listed in their
  111. module's documentation.
  112. Sinks
  113. -----
  114. Lager has traditionally supported a single sink (implemented as a
  115. `gen_event` manager) named `lager_event` to which all backends were
  116. connected.
  117. Lager now supports extra sinks; each sink can have different
  118. sync/async message thresholds and different backends.
  119. ### Sink configuration
  120. To use multiple sinks (beyond the built-in sink of lager and lager_event), you
  121. need to:
  122. 1. Setup rebar.config
  123. 2. Configure the backends in app.config
  124. #### Names
  125. Each sink has two names: one atom to be used like a module name for
  126. sending messages, and that atom with `_lager_event` appended for backend
  127. configuration.
  128. This reflects the legacy behavior: `lager:info` (or `critical`, or
  129. `debug`, etc) is a way of sending a message to a sink named
  130. `lager_event`. Now developers can invoke `audit:info` or
  131. `myCompanyName:debug` so long as the corresponding `audit_lager_event` or
  132. `myCompanyName_lager_event` sinks are configured.
  133. #### rebar.config
  134. In `rebar.config` for the project that requires lager, include a list
  135. of sink names (without the `_lager_event` suffix) in `erl_opts`:
  136. `{lager_extra_sinks, [audit]}`
  137. #### Runtime requirements
  138. To be useful, sinks must be configured at runtime with backends.
  139. In `app.config` for the project that requires lager, for example,
  140. extend the lager configuration to include an `extra_sinks` tuple with
  141. backends (aka "handlers") and optionally `async_threshold` and
  142. `async_threshold_window` values (see **Overload Protection**
  143. below). If async values are not configured, no overload protection
  144. will be applied on that sink.
  145. ```erlang
  146. [{lager, [
  147. {log_root, "/tmp"},
  148. %% Default handlers for lager/lager_event
  149. {handlers, [
  150. {lager_console_backend, [{level, info}]},
  151. {lager_file_backend, [{file, "error.log"}, {level, error}]},
  152. {lager_file_backend, [{file, "console.log"}, {level, info}]}
  153. ]},
  154. %% Any other sinks
  155. {extra_sinks,
  156. [
  157. {audit_lager_event,
  158. [{handlers,
  159. [{lager_file_backend,
  160. [{file, "sink1.log"},
  161. {level, info}
  162. ]
  163. }]
  164. },
  165. {async_threshold, 500},
  166. {async_threshold_window, 50}]
  167. }]
  168. }
  169. ]
  170. }
  171. ].
  172. ```
  173. Custom Formatting
  174. -----------------
  175. All loggers have a default formatting that can be overriden. A formatter is any module that
  176. exports `format(#lager_log_message{},Config#any())`. It is specified as part of the configuration
  177. for the backend:
  178. ```erlang
  179. {lager, [
  180. {handlers, [
  181. {lager_console_backend, [{level, info}, {formatter, lager_default_formatter},
  182. {formatter_config, [time," [",severity,"] ", message, "\n"]}]},
  183. {lager_file_backend, [{file, "error.log"}, {level, error}, {formatter, lager_default_formatter},
  184. {formatter_config, [date, " ", time," [",severity,"] ",pid, " ", message, "\n"]}]},
  185. {lager_file_backend, [{file, "console.log"}, {level, info}]}
  186. ]}
  187. ]}.
  188. ```
  189. Included is `lager_default_formatter`. This provides a generic, default
  190. formatting for log messages using a structure similar to Erlang's
  191. [iolist](http://learnyousomeerlang.com/buckets-of-sockets#io-lists) which we
  192. call "semi-iolist":
  193. * Any traditional iolist elements in the configuration are printed verbatim.
  194. * Atoms in the configuration are treated as placeholders for lager metadata and
  195. extracted from the log message.
  196. * The placeholders `date`, `time`, `message`, `sev` and `severity` will always exist.
  197. * `sev` is an abbreviated severity which is interpreted as a capitalized
  198. single letter encoding of the severity level (e.g. `'debug'` -> `$D`)
  199. * The placeholders `pid`, `file`, `line`, `module`, `function`, and `node`
  200. will always exist if the parse transform is used.
  201. * The placeholder `application` may exist if the parse transform is used.
  202. It is dependent on finding the applications `app.src` file.
  203. * If the error logger integration is used, the placeholder `pid`
  204. will always exist and the placeholder `name` may exist.
  205. * Applications can define their own metadata placeholder.
  206. * A tuple of `{atom(), semi-iolist()}` allows for a fallback for
  207. the atom placeholder. If the value represented by the atom
  208. cannot be found, the semi-iolist will be interpreted instead.
  209. * A tuple of `{atom(), semi-iolist(), semi-iolist()}` represents a
  210. conditional operator: if a value for the atom placeholder can be
  211. found, the first semi-iolist will be output; otherwise, the
  212. second will be used.
  213. * A tuple of `{pterm, atom()}` will attempt to lookup
  214. the value of the specified atom from the
  215. [persistent_term](http://erlang.org/doc/man/persistent_term.html)
  216. feature added in OTP 21.2. The default value is `""`. The
  217. default value will be used if the key cannot be found or
  218. if this formatting term is specified on an OTP release before
  219. OTP 21.
  220. * A tuple of `{pterm, atom(), semi-iolist()}` will attempt to
  221. lookup the value of the specified atom from the persistent_term
  222. feature added in OTP 21.2. The default value is the specified
  223. semi-iolist(). The default value will be used if the key cannot
  224. be found or the if this formatting term is specified on an OTP
  225. release before OTP 21.
  226. Examples:
  227. ```
  228. ["Foo"] -> "Foo", regardless of message content.
  229. [message] -> The content of the logged message, alone.
  230. [{pid,"Unknown Pid"}] -> "<?.?.?>" if pid is in the metadata, "Unknown Pid" if not.
  231. [{pid, ["My pid is ", pid], ["Unknown Pid"]}] -> if pid is in the metadata print "My pid is <?.?.?>", otherwise print "Unknown Pid"
  232. [{server,{pid, ["(", pid, ")"], ["(Unknown Server)"]}}] -> user provided server metadata, otherwise "(<?.?.?>)", otherwise "(Unknown Server)"
  233. [{pterm, pterm_key, <<"undefined">>}] -> if a value for 'pterm_key' is found in OTP 21 (or later) persistent_term storage it is used, otherwise "undefined"
  234. ```
  235. Universal time
  236. --------------
  237. By default, lager formats timestamps as local time for whatever computer
  238. generated the log message.
  239. To make lager use UTC timestamps, you can set the `sasl` application's
  240. `utc_log` configuration parameter to `true` in your application configuration
  241. file.
  242. Example:
  243. ```
  244. %% format log timestamps as UTC
  245. [{sasl, [{utc_log, true}]}].
  246. ```
  247. Error logger integration
  248. ------------------------
  249. Lager is also supplied with a `error_logger` handler module that translates
  250. traditional erlang error messages into a friendlier format and sends them into
  251. lager itself to be treated like a regular lager log call. To disable this, set
  252. the lager application variable `error_logger_redirect` to `false`.
  253. You can also disable reformatting for OTP and Cowboy messages by setting variable
  254. `error_logger_format_raw` to `true`.
  255. If you installed your own handler(s) into `error_logger`, you can tell
  256. lager to leave it alone by using the `error_logger_whitelist` environment
  257. variable with a list of handlers to allow.
  258. ```
  259. {error_logger_whitelist, [my_handler]}
  260. ```
  261. The `error_logger` handler will also log more complete error messages (protected
  262. with use of `trunc_io`) to a "crash log" which can be referred to for further
  263. information. The location of the crash log can be specified by the `crash_log`
  264. application variable. If set to `false` it is not written at all.
  265. Messages in the crash log are subject to a maximum message size which can be
  266. specified via the `crash_log_msg_size` application variable.
  267. Messages from `error_logger` will be redirected to `error_logger_lager_event` sink
  268. if it is defined so it can be redirected to another log file.
  269. For example:
  270. ```
  271. [{lager, [
  272. {extra_sinks,
  273. [
  274. {error_logger_lager_event,
  275. [{handlers, [
  276. {lager_file_backend, [{file, "error_logger.log"}, {level, info}]}]
  277. }]
  278. }]
  279. }]
  280. }].
  281. ```
  282. will send all `error_logger` messages to `error_logger.log` file.
  283. Overload Protection
  284. -------------------
  285. ### Asynchronous mode
  286. Prior to lager 2.0, the `gen_event` at the core of lager operated purely in
  287. synchronous mode. Asynchronous mode is faster, but has no protection against
  288. message queue overload. As of lager 2.0, the `gen_event` takes a hybrid
  289. approach. it polls its own mailbox size and toggles the messaging between
  290. synchronous and asynchronous depending on mailbox size.
  291. ```erlang
  292. {async_threshold, 20},
  293. {async_threshold_window, 5}
  294. ```
  295. This will use async messaging until the mailbox exceeds 20 messages, at which
  296. point synchronous messaging will be used, and switch back to asynchronous, when
  297. size reduces to `20 - 5 = 15`.
  298. If you wish to disable this behaviour, simply set `async_threshold` to `undefined`. It defaults
  299. to a low number to prevent the mailbox growing rapidly beyond the limit and causing
  300. problems. In general, lager should process messages as fast as they come in, so getting
  301. 20 behind should be relatively exceptional anyway.
  302. If you want to limit the number of messages per second allowed from `error_logger`,
  303. which is a good idea if you want to weather a flood of messages when lots of
  304. related processes crash, you can set a limit:
  305. ```erlang
  306. {error_logger_hwm, 50}
  307. ```
  308. It is probably best to keep this number small.
  309. ### Event queue flushing
  310. When the high-water mark is exceeded, lager can be configured to flush all
  311. event notifications in the message queue. This can have unintended consequences
  312. for other handlers in the same event manager (in e.g. the `error_logger`), as
  313. events they rely on may be wrongly discarded. By default, this behavior is enabled,
  314. but can be controlled, for the `error_logger` via:
  315. ```erlang
  316. {error_logger_flush_queue, true | false}
  317. ```
  318. or for a specific sink, using the option:
  319. ```erlang
  320. {flush_queue, true | false}
  321. ```
  322. If `flush_queue` is true, a message queue length threshold can be set, at which
  323. messages will start being discarded. The default threshold is `0`, meaning that
  324. if `flush_queue` is true, messages will be discarded if the high-water mark is
  325. exceeded, regardless of the length of the message queue. The option to control
  326. the threshold is, for `error_logger`:
  327. ```erlang
  328. {error_logger_flush_threshold, 1000}
  329. ```
  330. and for sinks:
  331. ```erlang
  332. {flush_threshold, 1000}
  333. ```
  334. ### Sink Killer
  335. In some high volume situations, it may be preferable to drop all pending log
  336. messages instead of letting them drain over time.
  337. If you prefer, you may choose to use the sink killer to shed load. In this
  338. operational mode, if the `gen_event` mailbox exceeds a configurable
  339. high water mark, the sink will be killed and reinstalled after a
  340. configurable cool down time.
  341. You can configure this behavior by using these configuration directives:
  342. ```erlang
  343. {killer_hwm, 1000},
  344. {killer_reinstall_after, 5000}
  345. ```
  346. This means if the sink's mailbox size exceeds 1000 messages, kill the
  347. entire sink and reload it after 5000 milliseconds. This behavior can
  348. also be installed into alternative sinks if desired.
  349. By default, the manager killer *is not installed* into any sink. If
  350. the `killer_reinstall_after` cool down time is not specified it defaults
  351. to 5000.
  352. "Unsafe"
  353. --------
  354. The unsafe code pathway bypasses the normal lager formatting code and uses the
  355. same code as error_logger in OTP. This provides a marginal speedup to your logging
  356. code (we measured between 0.5-1.3% improvement during our benchmarking; others have
  357. reported better improvements.)
  358. This is a **dangerous** feature. It *will not* protect you against
  359. large log messages - large messages can kill your application and even your
  360. Erlang VM dead due to memory exhaustion as large terms are copied over and
  361. over in a failure cascade. We strongly recommend that this code pathway
  362. only be used by log messages with a well bounded upper size of around 500 bytes.
  363. If there's any possibility the log messages could exceed that limit, you should
  364. use the normal lager message formatting code which will provide the appropriate
  365. size limitations and protection against memory exhaustion.
  366. If you want to format an unsafe log message, you may use the severity level (as
  367. usual) followed by `_unsafe`. Here's an example:
  368. ```erlang
  369. lager:info_unsafe("The quick brown ~s jumped over the lazy ~s", ["fox", "dog"]).
  370. ```
  371. Runtime loglevel changes
  372. ------------------------
  373. You can change the log level of any lager backend at runtime by doing the
  374. following:
  375. ```erlang
  376. lager:set_loglevel(lager_console_backend, debug).
  377. ```
  378. Or, for the backend with multiple handles (files, mainly):
  379. ```erlang
  380. lager:set_loglevel(lager_file_backend, "console.log", debug).
  381. ```
  382. Lager keeps track of the minimum log level being used by any backend and
  383. suppresses generation of messages lower than that level. This means that debug
  384. log messages, when no backend is consuming debug messages, are effectively
  385. free. A simple benchmark of doing 1 million debug log messages while the
  386. minimum threshold was above that takes less than half a second.
  387. Syslog style loglevel comparison flags
  388. --------------------------------------
  389. In addition to the regular log level names, you can also do finer grained masking
  390. of what you want to log:
  391. ```
  392. info - info and higher (>= is implicit)
  393. =debug - only the debug level
  394. !=info - everything but the info level
  395. <=notice - notice and below
  396. <warning - anything less than warning
  397. ```
  398. These can be used anywhere a loglevel is supplied, although they need to be either
  399. a quoted atom or a string.
  400. Internal log rotation
  401. ---------------------
  402. Lager can rotate its own logs or have it done via an external process. To
  403. use internal rotation, use the `size`, `date` and `count` values in the file
  404. backend's config:
  405. ```erlang
  406. [{file, "error.log"}, {level, error}, {size, 10485760}, {date, "$D0"}, {count, 5}]
  407. ```
  408. This tells lager to log error and above messages to `error.log` and to
  409. rotate the file at midnight or when it reaches 10mb, whichever comes first,
  410. and to keep 5 rotated logs in addition to the current one. Setting the
  411. count to 0 does not disable rotation, it instead rotates the file and keeps
  412. no previous versions around. To disable rotation set the size to 0 and the
  413. date to "".
  414. The `$D0` syntax is taken from the syntax newsyslog uses in newsyslog.conf.
  415. The relevant extract follows:
  416. ```
  417. Day, week and month time format: The lead-in character
  418. for day, week and month specification is a `$'-sign.
  419. The particular format of day, week and month
  420. specification is: [Dhh], [Ww[Dhh]] and [Mdd[Dhh]],
  421. respectively. Optional time fields default to
  422. midnight. The ranges for day and hour specifications
  423. are:
  424. hh hours, range 0 ... 23
  425. w day of week, range 0 ... 6, 0 = Sunday
  426. dd day of month, range 1 ... 31, or the
  427. letter L or l to specify the last day of
  428. the month.
  429. Some examples:
  430. $D0 rotate every night at midnight
  431. $D23 rotate every day at 23:00 hr
  432. $W0D23 rotate every week on Sunday at 23:00 hr
  433. $W5D16 rotate every week on Friday at 16:00 hr
  434. $M1D0 rotate on the first day of every month at
  435. midnight (i.e., the start of the day)
  436. $M5D6 rotate on every 5th day of the month at
  437. 6:00 hr
  438. ```
  439. On top of the day, week and month time format from newsyslog,
  440. hour specification is added from PR [#420](https://github.com/erlang-lager/lager/pull/420)
  441. ```
  442. Format of hour specification is : [Hmm]
  443. The range for minute specification is:
  444. mm minutes, range 0 ... 59
  445. Some examples:
  446. $H00 rotate every hour at HH:00
  447. $D12H30 rotate every day at 12:30
  448. $W0D0H0 rotate every week on Sunday at 00:00
  449. ```
  450. To configure the crash log rotation, the following application variables are
  451. used:
  452. * `crash_log_size`
  453. * `crash_log_date`
  454. * `crash_log_count`
  455. * `crash_log_rotator`
  456. See the `.app.src` file for further details.
  457. Custom Log Rotation
  458. -------------------
  459. Custom log rotator could be configured with option for `lager_file_backend`
  460. ```erlang
  461. {rotator, lager_rotator_default}
  462. ```
  463. The module should provide the following callbacks as `lager_rotator_behaviour`
  464. ```erlang
  465. %% @doc Create a log file
  466. -callback(create_logfile(Name::list(), Buffer::{integer(), integer()} | any()) ->
  467. {ok, {FD::file:io_device(), Inode::integer(), Size::integer()}} | {error, any()}).
  468. %% @doc Open a log file
  469. -callback(open_logfile(Name::list(), Buffer::{integer(), integer()} | any()) ->
  470. {ok, {FD::file:io_device(), Inode::integer(), Size::integer()}} | {error, any()}).
  471. %% @doc Ensure reference to current target, could be rotated
  472. -callback(ensure_logfile(Name::list(), FD::file:io_device(), Inode::integer(),
  473. Buffer::{integer(), integer()} | any()) ->
  474. {ok, {FD::file:io_device(), Inode::integer(), Size::integer()}} | {error, any()}).
  475. %% @doc Rotate the log file
  476. -callback(rotate_logfile(Name::list(), Count::integer()) ->
  477. ok).
  478. ```
  479. Syslog Support
  480. --------------
  481. Lager syslog output is provided as a separate application:
  482. [lager_syslog](https://github.com/erlang-lager/lager_syslog). It is packaged as a
  483. separate application so lager itself doesn't have an indirect dependency on a
  484. port driver. Please see the `lager_syslog` README for configuration information.
  485. Other Backends
  486. --------------
  487. There are lots of them! Some connect log messages to AMQP, various logging
  488. analytic services ([bunyan](https://github.com/Vagabond/lager_bunyan_formatter),
  489. [loggly](https://github.com/kivra/lager_loggly), etc), and more. [Looking on
  490. hex](https://hex.pm/packages?_utf8=✓&search=lager&sort=recent_downloads) or
  491. using "lager BACKEND" where "BACKEND" is your preferred log solution
  492. on your favorite search engine is a good starting point.
  493. Exception Pretty Printing
  494. ----------------------
  495. Up to OTP 20:
  496. ```erlang
  497. try
  498. foo()
  499. catch
  500. Class:Reason ->
  501. lager:error(
  502. "~nStacktrace:~s",
  503. [lager:pr_stacktrace(erlang:get_stacktrace(), {Class, Reason})])
  504. end.
  505. ```
  506. On OTP 21+:
  507. ```erlang
  508. try
  509. foo()
  510. catch
  511. Class:Reason:Stacktrace ->
  512. lager:error(
  513. "~nStacktrace:~s",
  514. [lager:pr_stacktrace(Stacktrace, {Class, Reason})])
  515. end.
  516. ```
  517. Record Pretty Printing
  518. ----------------------
  519. Lager's parse transform will keep track of any record definitions it encounters
  520. and store them in the module's attributes. You can then, at runtime, print any
  521. record a module compiled with the lager parse transform knows about by using the
  522. `lager:pr/2` function, which takes the record and the module that knows about the record:
  523. ```erlang
  524. lager:info("My state is ~p", [lager:pr(State, ?MODULE)])
  525. ```
  526. Often, `?MODULE` is sufficent, but you can obviously substitute that for a literal module name.
  527. `lager:pr` also works from the shell.
  528. Colored terminal output
  529. -----------------------
  530. If you have Erlang R16 or higher, you can tell lager's console backend to be colored. Simply
  531. add to lager's application environment config:
  532. ```erlang
  533. {colored, true}
  534. ```
  535. If you don't like the default colors, they are also configurable; see
  536. the `.app.src` file for more details.
  537. The output will be colored from the first occurrence of the atom color
  538. in the formatting configuration. For example:
  539. ```erlang
  540. {lager_console_backend, [{level, info}, {formatter, lager_default_formatter},
  541. {formatter_config, [time, color, " [",severity,"] ", message, "\e[0m\r\n"]}]]}
  542. ```
  543. This will make the entire log message, except time, colored. The
  544. escape sequence before the line break is needed in order to reset the
  545. color after each log message.
  546. Tracing
  547. -------
  548. Lager supports basic support for redirecting log messages based on log message
  549. attributes. Lager automatically captures the pid, module, function and line at the
  550. log message callsite. However, you can add any additional attributes you wish:
  551. ```erlang
  552. lager:warning([{request, RequestID},{vhost, Vhost}], "Permission denied to ~s", [User])
  553. ```
  554. Then, in addition to the default trace attributes, you'll be able to trace
  555. based on request or vhost:
  556. ```erlang
  557. lager:trace_file("logs/example.com.error", [{vhost, "example.com"}], error)
  558. ```
  559. To persist metadata for the life of a process, you can use `lager:md/1` to store metadata
  560. in the process dictionary:
  561. ```erlang
  562. lager:md([{zone, forbidden}])
  563. ```
  564. Note that `lager:md` will *only* accept a list of key/value pairs keyed by atoms.
  565. You can also omit the final argument, and the loglevel will default to
  566. `debug`.
  567. Tracing to the console is similar:
  568. ```erlang
  569. lager:trace_console([{request, 117}])
  570. ```
  571. In the above example, the loglevel is omitted, but it can be specified as the
  572. second argument if desired.
  573. You can also specify multiple expressions in a filter, or use the `*` atom as
  574. a wildcard to match any message that has that attribute, regardless of its
  575. value. You may also use the special value `!` to mean, only select if this
  576. key is **not** present.
  577. Tracing to an existing logfile is also supported (but see **Multiple
  578. sink support** below):
  579. ```erlang
  580. lager:trace_file("log/error.log", [{module, mymodule}, {function, myfunction}], warning)
  581. ```
  582. To view the active log backends and traces, you can use the `lager:status()`
  583. function. To clear all active traces, you can use `lager:clear_all_traces()`.
  584. To delete a specific trace, store a handle for the trace when you create it,
  585. that you later pass to `lager:stop_trace/1`:
  586. ```erlang
  587. {ok, Trace} = lager:trace_file("log/error.log", [{module, mymodule}]),
  588. ...
  589. lager:stop_trace(Trace)
  590. ```
  591. Tracing to a pid is somewhat of a special case, since a pid is not a
  592. data-type that serializes well. To trace by pid, use the pid as a string:
  593. ```erlang
  594. lager:trace_console([{pid, "<0.410.0>"}])
  595. ```
  596. ### Filter expressions
  597. As of lager 3.3.1, you can also use a 3 tuple while tracing where the second
  598. element is a comparison operator. The currently supported comparison operators
  599. are:
  600. * `<` - less than
  601. * `=<` - less than or equal
  602. * `=` - equal to
  603. * `!=` - not equal to
  604. * `>` - greater than
  605. * `>=` - greater than or equal
  606. ```erlang
  607. lager:trace_console([{request, '>', 117}, {request, '<', 120}])
  608. ```
  609. Using `=` is equivalent to the 2-tuple form.
  610. ### Filter composition
  611. As of lager 3.3.1 you may also use the special filter composition keys of
  612. `all` or `any`. For example the filter example above could be
  613. expressed as:
  614. ```erlang
  615. lager:trace_console([{all, [{request, '>', 117}, {request, '<', 120}]}])
  616. ```
  617. `any` has the effect of "OR style" logical evaluation between filters; `all`
  618. means "AND style" logical evaluation between filters. These compositional filters
  619. expect a list of additional filter expressions as their values.
  620. ### Null filters
  621. The `null` filter has a special meaning. A filter of `{null, false}` acts as
  622. a black hole; nothing is passed through. A filter of `{null, true}` means
  623. *everything* passes through. No other values for the null filter are valid and
  624. will be rejected.
  625. ### Multiple sink support
  626. If using multiple sinks, there are limitations on tracing that you
  627. should be aware of.
  628. Traces are specific to a sink, which can be specified via trace
  629. filters:
  630. ```erlang
  631. lager:trace_file("log/security.log", [{sink, audit_event}, {function, myfunction}], warning)
  632. ```
  633. If no sink is thus specified, the default lager sink will be used.
  634. This has two ramifications:
  635. * Traces cannot intercept messages sent to a different sink.
  636. * Tracing to a file already opened via `lager:trace_file` will only be
  637. successful if the same sink is specified.
  638. The former can be ameliorated by opening multiple traces; the latter
  639. can be fixed by rearchitecting lager's file backend, but this has not
  640. been tackled.
  641. ### Traces from configuration
  642. Lager supports starting traces from its configuration file. The keyword
  643. to define them is `traces`, followed by a proplist of tuples that define
  644. a backend handler and zero or more filters in a required list,
  645. followed by an optional message severity level.
  646. An example looks like this:
  647. ```erlang
  648. {lager, [
  649. {handlers, [...]},
  650. {traces, [
  651. %% handler, filter, message level (defaults to debug if not given)
  652. {lager_console_backend, [{module, foo}], info },
  653. {{lager_file_backend, "trace.log"}, [{request, '>', 120}], error},
  654. {{lager_file_backend, "event.log"}, [{module, bar}] } %% implied debug level here
  655. ]}
  656. ]}.
  657. ```
  658. In this example, we have three traces. One using the console backend, and two
  659. using the file backend. If the message severity level is left out, it defaults
  660. to `debug` as in the last file backend example.
  661. The `traces` keyword works on alternative sinks too but the same limitations
  662. and caveats noted above apply.
  663. **IMPORTANT**: You **must** define a severity level in all lager releases
  664. up to and including 3.1.0 or previous. The 2-tuple form wasn't added until
  665. 3.2.0.
  666. Setting dynamic metadata at compile-time
  667. ----------------------------------------
  668. Lager supports supplying metadata from external sources by registering a
  669. callback function. This metadata is also persistent across processes even if
  670. the process dies.
  671. In general use you won't need to use this feature. However it is useful in
  672. situations such as:
  673. * Tracing information provided by
  674. [seq_trace](http://erlang.org/doc/man/seq_trace.html)
  675. * Contextual information about your application
  676. * Persistent information which isn't provided by the default placeholders
  677. * Situations where you would have to set the metadata before every logging call
  678. You can add the callbacks by using the `{lager_parse_transform_functions, X}`
  679. option. It is only available when using `parse_transform`. In rebar, you can
  680. add it to `erl_opts` as below:
  681. ```erlang
  682. {erl_opts, [{parse_transform, lager_transform},
  683. {lager_function_transforms,
  684. [
  685. %% Placeholder Resolve type Callback tuple
  686. {metadata_placeholder, on_emit, {module_name, function_name}},
  687. {other_metadata_placeholder, on_log, {module_name, function_name}}
  688. ]}]}.
  689. ```
  690. The first atom is the placeholder atom used for the substitution in your custom
  691. formatter. See [Custom Formatting](#custom-formatting) for more information.
  692. The second atom is the resolve type. This specify the callback to resolve at
  693. the time of the message being emitted or at the time of the logging call. You
  694. have to specify either the atom `on_emit` or `on_log`. There is not a 'right'
  695. resolve type to use, so please read the uses/caveats of each and pick the option
  696. which fits your requirements best.
  697. `on_emit`:
  698. * The callback functions are not resolved until the message is emitted by the
  699. backend.
  700. * If the callback function cannot be resolved, not loaded or produces
  701. unhandled errors then `undefined` will be returned.
  702. * Since the callback function is dependent on a process, there is the
  703. chance that message will be emitted after the dependent process has died
  704. resulting in `undefined` being returned. This process can also be your own
  705. process
  706. `on_log`:
  707. * The callback functions are resolved regardless whether the message is
  708. emitted or not
  709. * If the callback function cannot be resolved or not loaded the errors are
  710. not handled by lager itself.
  711. * Any potential errors in callback should be handled in the callback function
  712. itself.
  713. * Because the function is resolved at log time there should be less chance
  714. of the dependent process dying before you can resolve it, especially if
  715. you are logging from the app which contains the callback.
  716. The third element is the callback to your function consisting of a tuple in the
  717. form `{Module Function}`. The callback should look like the following
  718. regardless if using `on_emit` or `on_log`:
  719. * It should be exported
  720. * It should takes no arguments e.g. has an arity of 0
  721. * It should return any traditional iolist elements or the atom `undefined`
  722. * For errors generated within your callback see the resolve type documentation
  723. above.
  724. If the callback returns `undefined` then it will follow the same fallback and
  725. conditional operator rules as documented in the
  726. [Custom Formatting](#custom-formatting) section.
  727. This example would work with `on_emit` but could be unsafe to use with
  728. `on_log`. If the call failed in `on_emit` it would default to `undefined`,
  729. however with `on_log` it would error.
  730. ```erlang
  731. -export([my_callback/0]).
  732. my_callback() ->
  733. my_app_serv:call('some options').
  734. ```
  735. This example would be to safe to work with both `on_emit` and `on_log`
  736. ```erlang
  737. -export([my_callback/0]).
  738. my_callback() ->
  739. try my_app_serv:call('some options') of
  740. Result ->
  741. Result
  742. catch
  743. _ ->
  744. %% You could define any traditional iolist elements you wanted here
  745. undefined
  746. end.
  747. ```
  748. Note that the callback can be any Module:Function/0. It does not have be part
  749. of your application. For example you could use `cpu_sup:avg1/0` as your
  750. callback function like so `{cpu_avg1, on_emit, {cpu_sup, avg1}}`
  751. Examples:
  752. ```erlang
  753. -export([reductions/0]).
  754. reductions() ->
  755. proplists:get_value(reductions, erlang:process_info(self())).
  756. ```
  757. ```erlang
  758. -export([seq_trace/0]).
  759. seq_trace() ->
  760. case seq_trace:get_token(label) of
  761. {label, TraceLabel} ->
  762. TraceLabel;
  763. _ ->
  764. undefined
  765. end.
  766. ```
  767. **IMPORTANT**: Since `on_emit` relies on function calls injected at the
  768. point where a log message is emitted, your logging performance (ops/sec)
  769. will be impacted by what the functions you call do and how much latency they
  770. may introduce. This impact will even greater with `on_log` since the calls
  771. are injected at the point a message is logged.
  772. Setting the truncation limit at compile-time
  773. --------------------------------------------
  774. Lager defaults to truncating messages at 4096 bytes, you can alter this by
  775. using the `{lager_truncation_size, X}` option. In rebar, you can add it to
  776. `erl_opts`:
  777. ```erlang
  778. {erl_opts, [{parse_transform, lager_transform}, {lager_truncation_size, 1024}]}.
  779. ```
  780. You can also pass it to `erlc`, if you prefer:
  781. ```
  782. erlc -pa lager/ebin +'{parse_transform, lager_transform}' +'{lager_truncation_size, 1024}' file.erl
  783. ```
  784. Suppress applications and supervisors start/stop logs
  785. -----------------------------------------------------
  786. If you don't want to see supervisors and applications start/stop logs in debug
  787. level of your application, you can use these configs to turn it off:
  788. ```erlang
  789. {lager, [{suppress_application_start_stop, true},
  790. {suppress_supervisor_start_stop, true}]}
  791. ```
  792. Sys debug functions
  793. --------------------
  794. Lager provides an integrated way to use sys 'debug functions'. You can install a debug
  795. function in a target process by doing
  796. ```erlang
  797. lager:install_trace(Pid, notice).
  798. ```
  799. You can also customize the tracing somewhat:
  800. ```erlang
  801. lager:install_trace(Pid, notice, [{count, 100}, {timeout, 5000}, {format_string, "my trace event ~p ~p"]}).
  802. ```
  803. The trace options are currently:
  804. * timeout - how long the trace stays installed: `infinity` (the default) or a millisecond timeout
  805. * count - how many trace events to log: `infinity` (default) or a positive number
  806. * format_string - the format string to log the event with. *Must* have 2 format specifiers for the 2 parameters supplied.
  807. This will, on every 'system event' for an OTP process (usually inbound messages, replies
  808. and state changes) generate a lager message at the specified log level.
  809. You can remove the trace when you're done by doing:
  810. ```erlang
  811. lager:remove_trace(Pid).
  812. ```
  813. If you want to start an OTP process with tracing enabled from the very beginning, you can do something like this:
  814. ```erlang
  815. gen_server:start_link(mymodule, [], [{debug, [{install, {fun lager:trace_func/3, lager:trace_state(undefined, notice, [])}}]}]).
  816. ```
  817. The third argument to the trace_state function is the Option list documented above.
  818. Console output to another group leader process
  819. ----------------------------------------------
  820. If you want to send your console output to another group_leader (typically on
  821. another node) you can provide a `{group_leader, Pid}` argument to the console
  822. backend. This can be combined with another console config option, `id` and
  823. gen_event's `{Module, ID}` to allow remote tracing of a node to standard out via
  824. nodetool:
  825. ```erlang
  826. GL = erlang:group_leader(),
  827. Node = node(GL),
  828. lager_app:start_handler(lager_event, {lager_console_backend, Node},
  829. [{group_leader, GL}, {level, none}, {id, {lager_console_backend, Node}}]),
  830. case lager:trace({lager_console_backend, Node}, Filter, Level) of
  831. ...
  832. ```
  833. In the above example, the code is assumed to be running via a `nodetool rpc`
  834. invocation so that the code is executing on the Erlang node, but the
  835. group_leader is that of the reltool node (eg. appname_maint_12345@127.0.0.1).
  836. If you intend to use tracing with this feature, make sure the second parameter
  837. to start_handler and the `id` parameter match. Thus when the custom group_leader
  838. process exits, lager will remove any associated traces for that handler.
  839. Elixir Support
  840. --------------
  841. There are 2 ways in which Lager can be leveraged in an Elixir project:
  842. 1. Lager Backend for Elixir Logger
  843. 2. Directly
  844. ### Lager Backend for Elixir Logger
  845. [Elixir's Logger](https://hexdocs.pm/logger/Logger.html) is the idiomatic way
  846. to add logging into elixir code. Logger has a plug-in model,
  847. allowing for different logging [Backends](https://hexdocs.pm/logger/Logger.html#module-backends)
  848. to be used without the need to change the logging code within your project.
  849. This approach will benefit from the fact that most elixir libs and frameworks
  850. are likely to use the elixir Logger and as such logging will all flow via the
  851. same logging mechanism.
  852. In [elixir 1.5 support for parse transforms was deprecated](https://github.com/elixir-lang/elixir/issues/5762).
  853. Taking the "Lager as a Logger Backend" approach is likely bypass any related
  854. regression issues that would be introduced into a project which is using lager
  855. directly when updating to elixir 1.5.
  856. There are open source elixir Logger backends for Lager available:
  857. - [LagerLogger](https://github.com/PSPDFKit-labs/lager_logger)
  858. - [LoggerLagerBackend](https://github.com/jonathanperret/logger_lager_backend)
  859. ### Directly
  860. It is fully possible prior to elixir 1.5 to use lager and all its features
  861. directly.
  862. After elixir 1.5 there is no support for parse transforms, and it is
  863. recommended to use an elixir wrapper for the lager api that provides compile time
  864. log level exclusion via elixir macros when opting for direct use of lager.
  865. Including Lager as a dependency:
  866. ``` elixir
  867. # mix.exs
  868. def application do
  869. [
  870. applications: [:lager],
  871. erl_opts: [parse_transform: "lager_transform"]
  872. ]
  873. end
  874. defp deps do
  875. [{:lager, "~> 3.2"}]
  876. end
  877. ```
  878. Example Configuration:
  879. ``` elixir
  880. # config.exs
  881. use Mix.Config
  882. # Stop lager writing a crash log
  883. config :lager, :crash_log, false
  884. config :lager,
  885. log_root: '/var/log/hello',
  886. handlers: [
  887. lager_console_backend: :info,
  888. lager_file_backend: [file: "error.log", level: :error],
  889. lager_file_backend: [file: "console.log", level: :info]
  890. ]
  891. ```
  892. There is a known issue where Elixir's Logger and Lager both contest for the
  893. Erlang `error_logger` handle if used side by side.
  894. If using both add the following to your `config.exs`:
  895. ```elixir
  896. # config.exs
  897. use Mix.Config
  898. # Stop lager redirecting :error_logger messages
  899. config :lager, :error_logger_redirect, false
  900. # Stop lager removing Logger's :error_logger handler
  901. config :lager, :error_logger_whitelist, [Logger.ErrorHandler]
  902. ```
  903. Example Usage:
  904. ``` elixir
  905. :lager.error('Some message')
  906. :lager.warning('Some message with a term: ~p', [term])
  907. ```
  908. 3.x Changelog
  909. -------------
  910. 3.8.1 - 28 August 2020
  911. * Feature: Allow metadata fields to be whitelisted in log formatting (#514)
  912. * Feature: Enable a persistent_term log formatter (#530) (#531)
  913. * Bugfix: Handle gen_statem crashes in newer OTP releases correctly (#523)
  914. * Cleanup: Add a hex badge (#525)
  915. * Cleanup: Fix Travis CI badge link
  916. * Policy: Officially ending support for OTP 20 (Support OTP 21, 22, 23)
  917. 3.8.0 - 9 August 2019
  918. * Breaking API change: Modify the `lager_rotator_behaviour` to pass in a
  919. file's creation time to `ensure_logfile/5` to be used to determine if
  920. file has changed on systems where inodes are not available (i.e.
  921. `win32`). The return value from `create_logfile/2`, `open_logfile/2` and
  922. `ensure_logfile/5` now requires ctime to be returned (#509)
  923. * Bugfix: ensure log file rotation works on `win32` (#509)
  924. * Bugfix: ensure test suite passes on `win32` (#509)
  925. * Bugfix: ensure file paths with Unicode are formatted properly (#510)
  926. 3.7.0 - 24 May 2019
  927. * Policy: Officially ending support for OTP 19 (Support OTP 20, 21, 22)
  928. * Cleanup: Fix all dialyzer errors
  929. * Bugfix: Minor changes to FSM/statem exits in OTP 22.
  930. 3.6.10 - 30 April 2019
  931. * Documentation: Fix pr_stacktrace invocation example (#494)
  932. * Bugfix: Do not count suppressed messages for message drop counts (#499)
  933. 3.6.9 - 13 March 2019
  934. * Bugfix: Fix file rotation on windows (#493)
  935. 3.6.8 - 21 December 2018
  936. * Documentation: Document the error_logger_whitelist environment variable. (#489)
  937. * Bugfix: Remove the built in handler inside of OTP 21 `logger` system. (#488)
  938. * Bugfix: Cleanup unneeded check for is_map (#486)
  939. * Bugfix: Cleanup ranch errors treated as cowboy errors (#485)
  940. * Testing: Remove OTP 18 from TravisCI testing matrix
  941. 3.6.7 - 14 October 2018
  942. * Bugfix: fix tracing to work with OTP21 #480
  943. 3.6.6 - 24 September 2018
  944. * Bugfix: When printing records, handle an improper list correctly. #478
  945. * Bugfix: Fix various tests and make some rotation code more explicit. #476
  946. * Bugfix: Make sure not to miscount messages during high-water mark check. #475
  947. 3.6.5 - 3 September 2018
  948. * Feature: Allow the console backend to redirect output to a remote node #469
  949. * Feature: is_loggble - support for severity as atom #472
  950. * Bugfix: Prevent silent dropping of messages when hwm is exceeded #467
  951. * Bugfix: rotation - default log file not deleted #474
  952. * Bugfix: Handle strange crash report from gen_statem #473
  953. * Documentation: Various markup fixes: #468 #470
  954. 3.6.4 - 11 July 2018
  955. * Bugfix: Reinstall handlers after a sink is killed #459
  956. * Bugfix: Fix platform_define matching not to break on OSX Mojave #461
  957. * Feature: Add support for installing a sys trace function #462
  958. 3.6.3 - 6 June 2018
  959. * OTP 21 support
  960. 3.6.2 - 26 April 2018
  961. * Bugfix: flush_threshold not working (#449)
  962. * Feature: Add `node` as a formatting option (#447)
  963. * Documentation: Update Elixir section with information about parse_transform (#446)
  964. * Bugfix: Correct default console configuation to use "[{level,info}]" instead (#445)
  965. * Feature: Pretty print lists of records at top level and field values with lager:pr (#442)
  966. * Bugfix: Ignore return value of lager:dispatch_log in lager.hrl (#441)
  967. 3.6.1 - 1 February 2018
  968. * Bugfix: Make a few corrections to the recent mailbox flushing changes (#436)
  969. * Bugfix: add flush options to proplist validation (#439)
  970. * Bugfix: Don't log when we dropped 0 messages (#440)
  971. 3.6.0 - 16 January 2018
  972. * Feature: Support logging with macros per level (#419)
  973. * Feature: Support custom file rotation handler; support hourly file
  974. rotation (#420)
  975. * Feature: Optionally reverse pretty stacktraces (so errors are
  976. at the top and the failed function call is at the bottom.)
  977. (#424)
  978. * Bugfix: Handle OTP 20 gen_server failure where client pid
  979. is dead. (#426)
  980. * Feature: Optionally don't flush notify messages at
  981. high water mark. (#427)
  982. * Bugfix: Handle another stacktrace format (#429)
  983. * Bugfix: Fix test failure using macros on OTP 18 (#430)
  984. * Policy: Remove all code which supports R15 (#432)
  985. 3.5.2 - 19 October 2017
  986. * Bugfix: Properly check for unicode characters in potentially deep
  987. character list. (#417)
  988. 3.5.1 - 15 June 2017
  989. * Doc fix: Missed a curly brace in an example. (#412)
  990. * Feature: Dynamic metadata functions (#392) - It is now possible to
  991. dynamically add metadata to lager messages. See the "dynamic
  992. metadata" section above for more information.
  993. * Doc fix: Add information about the "application" placeholder. (#414)
  994. 3.5.0 - 28 May 2017
  995. * Bugfix: Support OTP 20 gen_event messages (#410)
  996. * Feature: Enable console output to standard_error.
  997. Convert to proplist configuration style (like file handler)
  998. Deprecate previous configuration directives (#409)
  999. * Bugfix: Enable the event shaper to filter messages before they're
  1000. counted; do not count application/supervisor start/stops
  1001. toward high water mark. (#411)
  1002. * Docs: Add PR guidelines; add info about the #lager chat room on freenode.
  1003. 3.4.2 - 26 April 2017
  1004. * Docs: Document how to make lager use UTC timestamps (#405)
  1005. * Docs: Add a note about our triage cadence.
  1006. * Docs: Update lager_syslog URL
  1007. * Docs: Document placeholders for error_logger integration (#404)
  1008. * Feature: Add hex.pm metadata and full rebar3 support.
  1009. 3.4.1 - 28 March 2017
  1010. * Docs: Added documentation around using lager in the context of elixir applications (#398)
  1011. * Bugfix: Properly expand paths when log_root is set. (#386)
  1012. * Policy: Removed R15 from Travis configuration
  1013. 3.4.0 - 16 March 2017
  1014. * Policy: Adopt official OTP support policy. (This is the **last** lager 3.x release
  1015. that will support R15.)
  1016. * Test: Fix timeouts, R15 missing functions on possibly long-running tests in Travis. (#394, #395)
  1017. * Feature: capture and log metadata from error_logger messages (#397)
  1018. * Feature: Expose new trace filters and enable filter composition (#389)
  1019. * Feature: Log crashes from gen_fsm and gen_statem correctly (#391)
  1020. * Docs: Typo in badge URL (#390)
  1021. 3.3.0 - 16 February 2017
  1022. * Docs: Fix documentation to make 'it' unambiguous when discussing asychronous
  1023. operation. (#387)
  1024. * Test: Fix test flappiness due to insufficient sanitation between test runs (#384, #385)
  1025. * Feature: Allow metadata only logging. (#380)
  1026. * Feature: Add an upper case severity formatter (#372)
  1027. * Feature: Add support for suppressing start/stop messages from supervisors (#368)
  1028. * Bugfix: Fix ranch crash messages (#366)
  1029. * Test: Update Travis config for 18.3 and 19.0 (#365)
  1030. 3.2.4 - 11 October 2016
  1031. * Test: Fix dialyzer warnings.
  1032. 3.2.3 - 29 September 2016
  1033. * Dependency: Update to goldrush 0.19
  1034. 3.2.2 - 22 September 2016
  1035. * Bugfix: Backwards-compatibility fix for `{crash_log, undefined}` (#371)
  1036. * Fix documentation/README to reflect the preference for using `false`
  1037. as the `crash_log` setting value rather than `undefined` to indicate
  1038. that the crash log should not be written (#364)
  1039. * Bugfix: Backwards-compatibility fix for `lager_file_backend` "legacy"
  1040. configuration format (#374)
  1041. 3.2.1 - 10 June 2016
  1042. * Bugfix: Recent `get_env` changes resulted in launch failure (#355)
  1043. * OTP: Support typed records for Erlang 19.0 (#361)
  1044. 3.2.0 - 08 April 2016
  1045. * Feature: Optional sink killer to shed load when mailbox size exceeds a
  1046. configurable high water mark (#346)
  1047. * Feature: Export `configure_sink/2` so users may dynamically configure
  1048. previously setup and parse transformed sinks from their own code. (#342)
  1049. * Feature: Re-enable Travis CI and update .travis.yml (#340)
  1050. * Bugfix: Fix test race conditions for Travis CI (#344)
  1051. * Bugfix: Add the atom 'none' to the log_level() type so downstream
  1052. users won't get dialyzer failures if they use the 'none' log level. (#343)
  1053. * Bugfix: Fix typo in documentation. (#341)
  1054. * Bugfix: Fix OTP 18 test failures due to `warning_map/0` response
  1055. change. (#337)
  1056. * Bugfix: Make sure traces that use the file backend work correctly
  1057. when specified in lager configuration. (#336)
  1058. * Bugfix: Use `lager_app:get_env/3` for R15 compatibility. (#335)
  1059. * Bugfix: Make sure lager uses `id` instead of `name` when reporting
  1060. supervisor children failures. (The atom changed in OTP in 2014.) (#334)
  1061. * Bugfix: Make lager handle improper iolists (#327)
  1062. 3.1.0 - 27 January 2016
  1063. * Feature: API calls to a rotate handler, sink or all. This change
  1064. introduces a new `rotate` message for 3rd party lager backends; that's
  1065. why this is released as a new minor version number. (#311)
  1066. 3.0.3 - 27 January 2016
  1067. * Feature: Pretty printer for human readable stack traces (#298)
  1068. * Feature: Make error reformatting optional (#305)
  1069. * Feature: Optional and explicit sink for error_logger messages (#303)
  1070. * Bugfix: Always explicitly close a file after its been rotated (#316)
  1071. * Bugfix: If a relative path already contains the log root, do not add it again (#317)
  1072. * Bugfix: Configure and start extra sinks before traces are evaluated (#307)
  1073. * Bugfix: Stop and remove traces correctly (#306)
  1074. * Bugfix: A byte value of 255 is valid for Unicode (#300)
  1075. * Dependency: Bump to goldrush 0.1.8 (#313)