No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

527 líneas
18 KiB

hace 11 años
  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/basho/lager) :: ![Travis-CI](https://secure.travis-ci.org/basho/lager.png)
  8. Features
  9. --------
  10. * Finer grained log levels (debug, info, notice, warning, error, critical,
  11. alert, emergency)
  12. * Logger calls are transformed using a parse transform to allow capturing
  13. Module/Function/Line/Pid information
  14. * When no handler is consuming a log level (eg. debug) no event is sent
  15. to the log handler
  16. * Supports multiple backends, including console and file.
  17. * Supports multiple sinks
  18. * Rewrites common OTP error messages into more readable messages
  19. * Support for pretty printing records encountered at compile time
  20. * Tolerant in the face of large or many log messages, won't out of memory the node
  21. * Supports internal time and date based rotation, as well as external rotation tools
  22. * Syslog style log level comparison flags
  23. * Colored terminal output (requires R16+)
  24. * Map support (requires 17+)
  25. Usage
  26. -----
  27. To use lager in your application, you need to define it as a rebar dep or have
  28. some other way of including it in Erlang's path. You can then add the
  29. following option to the erlang compiler flags:
  30. ```erlang
  31. {parse_transform, lager_transform}
  32. ```
  33. Alternately, you can add it to the module you wish to compile with logging
  34. enabled:
  35. ```erlang
  36. -compile([{parse_transform, lager_transform}]).
  37. ```
  38. Before logging any messages, you'll need to start the lager application. The
  39. lager module's `start` function takes care of loading and starting any dependencies
  40. lager requires.
  41. ```erlang
  42. lager:start().
  43. ```
  44. You can also start lager on startup with a switch to `erl`:
  45. ```erlang
  46. erl -pa path/to/lager/ebin -s lager
  47. ```
  48. Once you have built your code with lager and started the lager application,
  49. you can then generate log messages by doing the following:
  50. ```erlang
  51. lager:error("Some message")
  52. ```
  53. Or:
  54. ```erlang
  55. lager:warning("Some message with a term: ~p", [Term])
  56. ```
  57. The general form is `lager:Severity()` where `Severity` is one of the log levels
  58. mentioned above.
  59. Configuration
  60. -------------
  61. To configure lager's backends, you use an application variable (probably in
  62. your app.config):
  63. ```erlang
  64. {lager, [
  65. {log_root, "/var/log/hello"},
  66. {handlers, [
  67. {lager_console_backend, info},
  68. {lager_file_backend, [{file, "error.log"}, {level, error}]},
  69. {lager_file_backend, [{file, "console.log"}, {level, info}]}
  70. ]}
  71. ]}.
  72. ```
  73. ```log_root``` variable is optional, by default file paths are relative to CWD.
  74. The available configuration options for each backend are listed in their
  75. module's documentation.
  76. Sinks
  77. -----
  78. Lager has traditionally supported a single sink (implemented as a
  79. `gen_event` manager) named `lager_event` to which all backends were
  80. connected.
  81. Lager now supports extra sinks; each sink can have different
  82. sync/async message thresholds and different backends.
  83. ### Sink configuration
  84. To use multiple sinks (beyond the built-in sink of lager and lager_event), you
  85. need to:
  86. 1. Setup rebar.config
  87. 2. Configure the backends in app.config
  88. #### Names
  89. Each sink has two names: one atom to be used like a module name for
  90. sending messages, and that atom with `_event` appended for backend
  91. configuration.
  92. This reflects the legacy behavior: `lager:info` (or `critical`, or
  93. `debug`, etc) is a way of sending a message to a sink named
  94. `lager_event`. Now developers can invoke `audit:info` or
  95. `myCompanyName:debug` so long as the corresponding `audit_event` or
  96. `myCompanyName_event` sinks are configured.
  97. #### rebar.config
  98. In `rebar.config` for the project that requires lager, include a list
  99. of sink names (without the `_event` suffix) in `erl_opts`:
  100. `{lager_extra_sinks, [audit]}`
  101. #### Runtime requirements
  102. To be useful, sinks must be configured at runtime with backends.
  103. In `app.config` for the project that requires lager, for example,
  104. extend the lager configuration to include an `extra_sinks` tuple with
  105. backends (aka "handlers") and optionally `async_threshold` and
  106. `async_threshold_window` values (see **Overload Protection**
  107. below). If async values are not configured, no overload protection
  108. will be applied on that sink.
  109. ```erlang
  110. [{lager, [
  111. {log_root, "/tmp"},
  112. %% Default handlers for lager/lager_event
  113. {handlers, [
  114. {lager_console_backend, info},
  115. {lager_file_backend, [{file, "error.log"}, {level, error}]},
  116. {lager_file_backend, [{file, "console.log"}, {level, info}]}
  117. ]},
  118. %% Any other sinks
  119. {extra_sinks,
  120. [
  121. {audit_event,
  122. [{handlers,
  123. [{lager_file_backend,
  124. [{file, "sink1.log"},
  125. {level, info}
  126. ]
  127. }]
  128. },
  129. {async_threshold, 500},
  130. {async_threshold_window, 50}]
  131. }]
  132. }
  133. ]
  134. }
  135. ].
  136. ```
  137. Custom Formatting
  138. -----------------
  139. All loggers have a default formatting that can be overriden. A formatter is any module that
  140. exports `format(#lager_log_message{},Config#any())`. It is specified as part of the configuration
  141. for the backend:
  142. ```erlang
  143. {lager, [
  144. {handlers, [
  145. {lager_console_backend, [info, {lager_default_formatter, [time," [",severity,"] ", message, "\n"]}]},
  146. {lager_file_backend, [{file, "error.log"}, {level, error}, {formatter, lager_default_formatter},
  147. {formatter_config, [date, " ", time," [",severity,"] ",pid, " ", message, "\n"]}]},
  148. {lager_file_backend, [{file, "console.log"}, {level, info}]}
  149. ]}
  150. ]}.
  151. ```
  152. Included is `lager_default_formatter`. This provides a generic, default formatting for log messages using a structure similar to Erlang's [iolist](http://learnyousomeerlang.com/buckets-of-sockets#io-lists) which we call "semi-iolist":
  153. * Any traditional iolist elements in the configuration are printed verbatim.
  154. * Atoms in the configuration are treated as placeholders for lager metadata and extracted from the log message.
  155. * The placeholders `date`, `time`, `message`, `sev` and `severity` will always exist.
  156. * `sev` is an abbreviated severity which is interpreted as a capitalized single letter encoding of the severity level
  157. (e.g. `'debug'` -> `$D`)
  158. * The placeholders `pid`, `file`, `line`, `module`, `function`, and `node` will always exist if the parse transform is used.
  159. * Applications can define their own metadata placeholder.
  160. * A tuple of `{atom(), semi-iolist()}` allows for a fallback for
  161. the atom placeholder. If the value represented by the atom
  162. cannot be found, the semi-iolist will be interpreted instead.
  163. * A tuple of `{atom(), semi-iolist(), semi-iolist()}` represents a
  164. conditional operator: if a value for the atom placeholder can be
  165. found, the first semi-iolist will be output; otherwise, the
  166. second will be used.
  167. Examples:
  168. ```
  169. ["Foo"] -> "Foo", regardless of message content.
  170. [message] -> The content of the logged message, alone.
  171. [{pid,"Unknown Pid"}] -> "<?.?.?>" if pid is in the metadata, "Unknown Pid" if not.
  172. [{pid, ["My pid is ", pid], ["Unknown Pid"]}] -> if pid is in the metadata print "My pid is <?.?.?>", otherwise print "Unknown Pid"
  173. [{server,{pid, ["(", pid, ")"], ["(Unknown Server)"]}}] -> user provided server metadata, otherwise "(<?.?.?>)", otherwise "(Unknown Server)"
  174. ```
  175. Error logger integration
  176. ------------------------
  177. Lager is also supplied with a `error_logger` handler module that translates
  178. traditional erlang error messages into a friendlier format and sends them into
  179. lager itself to be treated like a regular lager log call. To disable this, set
  180. the lager application variable `error_logger_redirect` to `false`.
  181. The `error_logger` handler will also log more complete error messages (protected
  182. with use of `trunc_io`) to a "crash log" which can be referred to for further
  183. information. The location of the crash log can be specified by the crash_log
  184. application variable. If set to `undefined` it is not written at all.
  185. Messages in the crash log are subject to a maximum message size which can be
  186. specified via the `crash_log_msg_size` application variable.
  187. Overload Protection
  188. -------------------
  189. Prior to lager 2.0, the `gen_event` at the core of lager operated purely in
  190. synchronous mode. Asynchronous mode is faster, but has no protection against
  191. message queue overload. In lager 2.0, the `gen_event` takes a hybrid approach. it
  192. polls its own mailbox size and toggles the messaging between synchronous and
  193. asynchronous depending on mailbox size.
  194. ```erlang
  195. {async_threshold, 20},
  196. {async_threshold_window, 5}
  197. ```
  198. This will use async messaging until the mailbox exceeds 20 messages, at which
  199. point synchronous messaging will be used, and switch back to asynchronous, when
  200. size reduces to `20 - 5 = 15`.
  201. If you wish to disable this behaviour, simply set it to `undefined`. It defaults
  202. to a low number to prevent the mailbox growing rapidly beyond the limit and causing
  203. problems. In general, lager should process messages as fast as they come in, so getting
  204. 20 behind should be relatively exceptional anyway.
  205. If you want to limit the number of messages per second allowed from `error_logger`,
  206. which is a good idea if you want to weather a flood of messages when lots of
  207. related processes crash, you can set a limit:
  208. ```erlang
  209. {error_logger_hwm, 50}
  210. ```
  211. It is probably best to keep this number small.
  212. Runtime loglevel changes
  213. ------------------------
  214. You can change the log level of any lager backend at runtime by doing the
  215. following:
  216. ```erlang
  217. lager:set_loglevel(lager_console_backend, debug).
  218. ```
  219. Or, for the backend with multiple handles (files, mainly):
  220. ```erlang
  221. lager:set_loglevel(lager_file_backend, "console.log", debug).
  222. ```
  223. Lager keeps track of the minimum log level being used by any backend and
  224. suppresses generation of messages lower than that level. This means that debug
  225. log messages, when no backend is consuming debug messages, are effectively
  226. free. A simple benchmark of doing 1 million debug log messages while the
  227. minimum threshold was above that takes less than half a second.
  228. Syslog style loglevel comparison flags
  229. --------------------------------------
  230. In addition to the regular log level names, you can also do finer grained masking
  231. of what you want to log:
  232. ```
  233. info - info and higher (>= is implicit)
  234. =debug - only the debug level
  235. !=info - everything but the info level
  236. <=notice - notice and below
  237. <warning - anything less than warning
  238. ```
  239. These can be used anywhere a loglevel is supplied, although they need to be either
  240. a quoted atom or a string.
  241. Internal log rotation
  242. ---------------------
  243. Lager can rotate its own logs or have it done via an external process. To
  244. use internal rotation, use the `size`, `date` and `count` values in the file
  245. backend's config:
  246. ```erlang
  247. [{file, "error.log"}, {level, error}, {size, 10485760}, {date, "$D0"}, {count, 5}]
  248. ```
  249. This tells lager to log error and above messages to `error.log` and to
  250. rotate the file at midnight or when it reaches 10mb, whichever comes first,
  251. and to keep 5 rotated logs in addition to the current one. Setting the
  252. count to 0 does not disable rotation, it instead rotates the file and keeps
  253. no previous versions around. To disable rotation set the size to 0 and the
  254. date to "".
  255. The `$D0` syntax is taken from the syntax newsyslog uses in newsyslog.conf.
  256. The relevant extract follows:
  257. ```
  258. Day, week and month time format: The lead-in character
  259. for day, week and month specification is a `$'-sign.
  260. The particular format of day, week and month
  261. specification is: [Dhh], [Ww[Dhh]] and [Mdd[Dhh]],
  262. respectively. Optional time fields default to
  263. midnight. The ranges for day and hour specifications
  264. are:
  265. hh hours, range 0 ... 23
  266. w day of week, range 0 ... 6, 0 = Sunday
  267. dd day of month, range 1 ... 31, or the
  268. letter L or l to specify the last day of
  269. the month.
  270. Some examples:
  271. $D0 rotate every night at midnight
  272. $D23 rotate every day at 23:00 hr
  273. $W0D23 rotate every week on Sunday at 23:00 hr
  274. $W5D16 rotate every week on Friday at 16:00 hr
  275. $M1D0 rotate on the first day of every month at
  276. midnight (i.e., the start of the day)
  277. $M5D6 rotate on every 5th day of the month at
  278. 6:00 hr
  279. ```
  280. To configure the crash log rotation, the following application variables are
  281. used:
  282. * `crash_log_size`
  283. * `crash_log_date`
  284. * `crash_log_count`
  285. See the `.app.src` file for further details.
  286. Syslog Support
  287. --------------
  288. Lager syslog output is provided as a separate application:
  289. [lager_syslog](https://github.com/basho/lager_syslog). It is packaged as a
  290. separate application so lager itself doesn't have an indirect dependency on a
  291. port driver. Please see the `lager_syslog` README for configuration information.
  292. Older Backends
  293. --------------
  294. Lager 2.0 changed the backend API, there are various 3rd party backends for
  295. lager available, but they may not have been updated to the new API. As they
  296. are updated, links to them can be re-added here.
  297. Record Pretty Printing
  298. ----------------------
  299. Lager's parse transform will keep track of any record definitions it encounters
  300. and store them in the module's attributes. You can then, at runtime, print any
  301. record a module compiled with the lager parse transform knows about by using the
  302. `lager:pr/2` function, which takes the record and the module that knows about the record:
  303. ```erlang
  304. lager:info("My state is ~p", [lager:pr(State, ?MODULE)])
  305. ```
  306. Often, `?MODULE` is sufficent, but you can obviously substitute that for a literal module name.
  307. `lager:pr` also works from the shell.
  308. Colored terminal output
  309. -----------------------
  310. If you have Erlang R16 or higher, you can tell lager's console backend to be colored. Simply
  311. add to lager's application environment config:
  312. ```erlang
  313. {colored, true}
  314. ```
  315. If you don't like the default colors, they are also configurable; see
  316. the `.app.src` file for more details.
  317. The output will be colored from the first occurrence of the atom color
  318. in the formatting configuration. For example:
  319. ```erlang
  320. {lager_console_backend, [info, {lager_default_formatter, [time, color, " [",severity,"] ", message, "\e[0m\r\n"]}]}
  321. ```
  322. This will make the entire log message, except time, colored. The
  323. escape sequence before the line break is needed in order to reset the
  324. color after each log message.
  325. Tracing
  326. -------
  327. Lager supports basic support for redirecting log messages based on log message
  328. attributes. Lager automatically captures the pid, module, function and line at the
  329. log message callsite. However, you can add any additional attributes you wish:
  330. ```erlang
  331. lager:warning([{request, RequestID},{vhost, Vhost}], "Permission denied to ~s", [User])
  332. ```
  333. Then, in addition to the default trace attributes, you'll be able to trace
  334. based on request or vhost:
  335. ```erlang
  336. lager:trace_file("logs/example.com.error", [{vhost, "example.com"}], error)
  337. ```
  338. To persist metadata for the life of a process, you can use `lager:md/1` to store metadata
  339. in the process dictionary:
  340. ```erlang
  341. lager:md([{zone, forbidden}])
  342. ```
  343. Note that `lager:md` will *only* accept a list of key/value pairs keyed by atoms.
  344. You can also omit the final argument, and the loglevel will default to
  345. `debug`.
  346. Tracing to the console is similar:
  347. ```erlang
  348. lager:trace_console([{request, 117}])
  349. ```
  350. In the above example, the loglevel is omitted, but it can be specified as the
  351. second argument if desired.
  352. You can also specify multiple expressions in a filter, or use the `*` atom as
  353. a wildcard to match any message that has that attribute, regardless of its
  354. value.
  355. Tracing to an existing logfile is also supported (but see **Multiple
  356. sink support** below):
  357. ```erlang
  358. lager:trace_file("log/error.log", [{module, mymodule}, {function, myfunction}], warning)
  359. ```
  360. To view the active log backends and traces, you can use the `lager:status()`
  361. function. To clear all active traces, you can use `lager:clear_all_traces()`.
  362. To delete a specific trace, store a handle for the trace when you create it,
  363. that you later pass to `lager:stop_trace/1`:
  364. ```erlang
  365. {ok, Trace} = lager:trace_file("log/error.log", [{module, mymodule}]),
  366. ...
  367. lager:stop_trace(Trace)
  368. ```
  369. Tracing to a pid is somewhat of a special case, since a pid is not a
  370. data-type that serializes well. To trace by pid, use the pid as a string:
  371. ```erlang
  372. lager:trace_console([{pid, "<0.410.0>"}])
  373. ```
  374. As of lager 2.0, you can also use a 3 tuple while tracing, where the second
  375. element is a comparison operator. The currently supported comparison operators
  376. are:
  377. * `<` - less than
  378. * `=` - equal to
  379. * `>` - greater than
  380. ```erlang
  381. lager:trace_console([{request, '>', 117}, {request, '<', 120}])
  382. ```
  383. Using `=` is equivalent to the 2-tuple form.
  384. ### Multiple sink support
  385. If using multiple sinks, there are limitations on tracing that you
  386. should be aware of.
  387. Traces are specific to a sink, which can be specified via trace
  388. filters:
  389. ```erlang
  390. lager:trace_file("log/security.log", [{sink, audit}, {function, myfunction}], warning)
  391. ```
  392. If no sink is thus specified, the default lager sink will be used.
  393. This has two ramifications:
  394. * Traces cannot intercept messages sent to a different sink.
  395. * Tracing to a file already opened via `lager:trace_file` will only be
  396. successful if the same sink is specified.
  397. The former can be ameliorated by opening multiple traces; the latter
  398. can be fixed by rearchitecting lager's file backend, but this has not
  399. been tackled.
  400. Setting the truncation limit at compile-time
  401. --------------------------------------------
  402. Lager defaults to truncating messages at 4096 bytes, you can alter this by
  403. using the `{lager_truncation_size, X}` option. In rebar, you can add it to
  404. `erl_opts`:
  405. ```erlang
  406. {erl_opts, [{parse_transform, lager_transform}, {lager_truncation_size, 1024}]}.
  407. ```
  408. You can also pass it to `erlc`, if you prefer:
  409. ```
  410. erlc -pa lager/ebin +'{parse_transform, lager_transform}' +'{lager_truncation_size, 1024}' file.erl
  411. ```