Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

404 строки
14 KiB

11 лет назад
12 лет назад
  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 even sent
  15. to the log handler
  16. * Supports multiple backends, including console and file.
  17. * Rewrites common OTP error messages into more readable messages
  18. * Support for pretty printing records encountered at compile time
  19. * Tolerant in the face of large or many log messages, won't out of memory the node
  20. * Supports internal time and date based rotation, as well as external rotation tools
  21. * Syslog style log level comparison flags
  22. * Colored terminal output (requires R16+)
  23. Usage
  24. -----
  25. To use lager in your application, you need to define it as a rebar dep or have
  26. some other way of including it in erlang's path. You can then add the
  27. following option to the erlang compiler flags
  28. ```erlang
  29. {parse_transform, lager_transform}
  30. ```
  31. Alternately, you can add it to the module you wish to compile with logging
  32. enabled:
  33. ```erlang
  34. -compile([{parse_transform, lager_transform}]).
  35. ```
  36. Before logging any messages, you'll need to start the lager application. The
  37. lager module's start function takes care of loading and starting any dependencies
  38. lager requires.
  39. ```erlang
  40. lager:start().
  41. ```
  42. You can also start lager on startup with a switch to `erl`:
  43. ```erlang
  44. erl -pa path/to/lager/ebin -s lager
  45. ```
  46. Once you have built your code with lager and started the lager application,
  47. you can then generate log messages by doing the following:
  48. ```erlang
  49. lager:error("Some message")
  50. ```
  51. Or:
  52. ```erlang
  53. lager:warning("Some message with a term: ~p", [Term])
  54. ```
  55. The general form is lager:Severity() where Severity is one of the log levels
  56. mentioned above.
  57. Configuration
  58. -------------
  59. To configure lager's backends, you use an application variable (probably in
  60. your app.config):
  61. ```erlang
  62. {lager, [
  63. {handlers, [
  64. {lager_console_backend, info},
  65. {lager_file_backend, [{file, "error.log"}, {level, error}]},
  66. {lager_file_backend, [{file, "console.log"}, {level, info}]}
  67. ]}
  68. ]}.
  69. ```
  70. The available configuration options for each backend are listed in their
  71. module's documentation.
  72. Custom Formatting
  73. -----------------
  74. All loggers have a default formatting that can be overriden. A formatter is any module that
  75. exports format(#lager_log_message{},Config#any()). It is specified as part of the configuration
  76. for the backend:
  77. ```erlang
  78. {lager, [
  79. {handlers, [
  80. {lager_console_backend, [info, {lager_default_formatter, [time," [",severity,"] ", message, "\n"]}]},
  81. {lager_file_backend, [{file, "error.log"}, {level, error}, {formatter, lager_default_formatter},
  82. {formatter_config, [date, " ", time," [",severity,"] ",pid, " ", message, "\n"]}]},
  83. {lager_file_backend, [{file, "console.log"}, {level, info}]}
  84. ]}
  85. ]}.
  86. ```
  87. Included is lager_default_formatter. This provides a generic, default formatting for log messages using a "semi-iolist"
  88. as configuration. Any iolist allowed elements in the configuration are printed verbatim. Atoms in the configuration
  89. are treated as metadata properties and extracted from the log message.
  90. The metadata properties date,time, message, and severity will always exist.
  91. The properties pid, file, line, module, function, and node will always exist if the parser transform is used.
  92. ```
  93. ["Foo"] -> "Foo", regardless of message content.
  94. [message] -> The content of the logged message, alone.
  95. [{pid,"Unknown Pid"}] -> "<?.?.?>" if pid is in the metadata, "Unknown Pid" if not.
  96. [{pid, ["My pid is ", pid], "Unknown Pid"}] -> if pid is in the metadata print "My pid is <?.?.?>", otherwise print "Unknown Pid"
  97. ```
  98. Optionally, a tuple of {atom(),semi-iolist()}
  99. can be used. The atom will look up the property, but if not found it will use the semi-iolist() instead. These fallbacks
  100. can be nested or refer to other properties.
  101. ```
  102. [{pid,"Unknown Pid"}] -> "<?.?.?>" if pid is in the metadata, "Unknown Pid" if not.
  103. [{server,[$(,{pid,"Unknown Server"},$)]}}] -> user provided server metadata, otherwise "(<?.?.?>)", otherwise "(Unknown Server)"
  104. ```
  105. Error logger integration
  106. ------------------------
  107. Lager is also supplied with a error_logger handler module that translates
  108. traditional erlang error messages into a friendlier format and sends them into
  109. lager itself to be treated like a regular lager log call. To disable this, set
  110. the lager application variable `error_logger_redirect` to `false`.
  111. The error_logger handler will also log more complete error messages (protected
  112. with use of trunc_io) to a "crash log" which can be referred to for further
  113. information. The location of the crash log can be specified by the crash_log
  114. application variable. If set to `undefined` it is not written at all.
  115. Messages in the crash log are subject to a maximum message size which can be
  116. specified via the crash_log_msg_size application variable.
  117. Overload Protection
  118. -------------------
  119. Prior to lager 2.0, the gen_event at the core of lager operated purely in
  120. synchronous mode. Asynchronous mode is faster, but has no protection against
  121. message queue overload. In lager 2.0, the gen_event takes a hybrid approach. it
  122. polls its own mailbox size and toggles the messaging between synchronous and
  123. asynchronous depending on mailbox size.
  124. ```erlang
  125. {async_threshold, 20},
  126. {async_threshold_window, 5}
  127. ```
  128. This will use async messaging until the mailbox exceeds 20 messages, at which
  129. point synchronous messaging will be used, and switch back to asynchronous, when
  130. size reduces to `20 - 5 = 15`.
  131. If you wish to disable this behaviour, simply set it to 'undefined'. It defaults
  132. to a low number to prevent the mailbox growing rapidly beyond the limit and causing
  133. problems. In general, lager should process messages as fast as they come in, so getting
  134. 20 behind should be relatively exceptional anyway.
  135. If you want to limit the number of messages per second allowed from error_logger,
  136. which is a good idea if you want to weather a flood of messages when lots of
  137. related processes crash, you can set a limit:
  138. ```erlang
  139. {error_logger_hwm, 50}
  140. ```
  141. It is probably best to keep this number small.
  142. Runtime loglevel changes
  143. ------------------------
  144. You can change the log level of any lager backend at runtime by doing the
  145. following:
  146. ```erlang
  147. lager:set_loglevel(lager_console_backend, debug).
  148. ```
  149. Or, for the backend with multiple handles (files, mainly):
  150. ```erlang
  151. lager:set_loglevel(lager_file_backend, "console.log", debug).
  152. ```
  153. Lager keeps track of the minium log level being used by any backend and
  154. supresses generation of messages lower than that level. This means that debug
  155. log messages, when no backend is consuming debug messages, are effectively
  156. free. A simple benchmark of doing 1 million debug log messages while the
  157. minimum threshold was above that takes less than half a second.
  158. Syslog style loglevel comparison flags
  159. --------------------------------------
  160. In addition to the regular log level names, you can also do finer grained masking
  161. of what you want to log:
  162. ```
  163. info - info and higher (>= is implicit)
  164. =debug - only the debug level
  165. !=info - everything but the info level
  166. <=notice - notice and below
  167. <warning - anything less than warning
  168. ```
  169. These can be used anywhere a loglevel is supplied, although they need to be either
  170. a quoted atom or a string.
  171. Internal log rotation
  172. ---------------------
  173. Lager can rotate its own logs or have it done via an external process. To
  174. use internal rotation, use the 'size', 'date' and 'count' values in the file
  175. backend's config:
  176. ```erlang
  177. [{name, "error.log"}, {level, error}, {size, 10485760}, {date, "$D0"}, {count, 5}]
  178. ```
  179. This tells lager to log error and above messages to "error.log" and to
  180. rotate the file at midnight or when it reaches 10mb, whichever comes first
  181. and to keep 5 rotated logs, in addition to the current one. Setting the
  182. count to 0 does not disable rotation, it instead rotates the file and keeps
  183. no previous versions around. To disable rotation set the size to 0 and the
  184. date to "".
  185. The "$D0" syntax is taken from the syntax newsyslog uses in newsyslog.conf.
  186. The relevant extract follows:
  187. ```
  188. Day, week and month time format: The lead-in character
  189. for day, week and month specification is a `$'-sign.
  190. The particular format of day, week and month
  191. specification is: [Dhh], [Ww[Dhh]] and [Mdd[Dhh]],
  192. respectively. Optional time fields default to
  193. midnight. The ranges for day and hour specifications
  194. are:
  195. hh hours, range 0 ... 23
  196. w day of week, range 0 ... 6, 0 = Sunday
  197. dd day of month, range 1 ... 31, or the
  198. letter L or l to specify the last day of
  199. the month.
  200. Some examples:
  201. $D0 rotate every night at midnight
  202. $D23 rotate every day at 23:00 hr
  203. $W0D23 rotate every week on Sunday at 23:00 hr
  204. $W5D16 rotate every week on Friday at 16:00 hr
  205. $M1D0 rotate on the first day of every month at
  206. midnight (i.e., the start of the day)
  207. $M5D6 rotate on every 5th day of the month at
  208. 6:00 hr
  209. ```
  210. To configure the crash log rotation, the following application variables are
  211. used:
  212. * crash_log_size
  213. * crash_log_date
  214. * crash_log_count
  215. See the .app.src file for further details.
  216. Syslog Support
  217. --------------
  218. Lager syslog output is provided as a separate application;
  219. [lager_syslog](https://github.com/basho/lager_syslog). It is packaged as a
  220. separate application so Lager itself doesn't have an indirect dependancy on a
  221. port driver. Please see the lager_syslog README for configuration information.
  222. Older Backends
  223. --------------
  224. Lager 2.0 changed the backend API, there are various 3rd party backends for
  225. lager available, but they may not have been updated to the new API. As they
  226. are updated, links to them can be re-added here.
  227. Record Pretty Printing
  228. ----------------------
  229. Lager's parse transform will keep track of any record definitions it encounters
  230. and store them in the module's attributes. You can then, at runtime, print any
  231. record a module compiled with the lager parse transform knows about by using the
  232. lager:pr/2 function, which takes the record and the module that knows about the record:
  233. ```erlang
  234. lager:info("My state is ~p", [lager:pr(State, ?MODULE)])
  235. ```
  236. Often, ?MODULE is sufficent, but you can obviously substitute that for a literal module name.
  237. lager:pr also works from the shell.
  238. Colored terminal output
  239. -----------------------
  240. If you have erlang R16 or higher, you can tell lager's console backend to be colored. Simply
  241. add
  242. ```erlang
  243. {colored, true}
  244. ```
  245. To lager's application environment config. If you don't like the default colors, they are
  246. also configurable, see the app.src file for more details.
  247. Tracing
  248. -------
  249. Lager supports basic support for redirecting log messages based on log message
  250. attributes. Lager automatically captures the pid, module, function and line at the
  251. log message callsite. However, you can add any additional attributes you wish:
  252. ```erlang
  253. lager:warning([{request, RequestID},{vhost, Vhost}], "Permission denied to ~s", [User])
  254. ```
  255. Then, in addition to the default trace attributes, you'll be able to trace
  256. based on request or vhost:
  257. ```erlang
  258. lager:trace_file("logs/example.com.error", [{vhost, "example.com"}], error)
  259. ```
  260. To persist metadata for the life of a process, you can use lager:md/1 to store metadata
  261. in the process dictionary:
  262. ```erlang
  263. lager:md([{zone, forbidden}])
  264. ```
  265. Note that lager:md will *only* accept a list of key/value pairs keyed by atoms.
  266. You can also omit the final argument, and the loglevel will default to
  267. 'debug'.
  268. Tracing to the console is similar:
  269. ```erlang
  270. lager:trace_console([{request, 117}])
  271. ```
  272. In the above example, the loglevel is omitted, but it can be specified as the
  273. second argument if desired.
  274. You can also specify multiple expressions in a filter, or use the '*' atom as
  275. a wildcard to match any message that has that attribute, regardless of its
  276. value.
  277. Tracing to an existing logfile is also supported, if you wanted to log
  278. warnings from a particular module to the default error.log:
  279. ```erlang
  280. lager:trace_file("log/error.log", [{module, mymodule}], warning)
  281. ```
  282. To view the active log backends and traces, you can use the lager:status()
  283. function. To clear all active traces, you can use lager:clear_all_traces().
  284. To delete a specific trace, store a handle for the trace when you create it,
  285. that you later pass to lager:stop_trace/1:
  286. ```erlang
  287. {ok, Trace} = lager:trace_file("log/error.log", [{module, mymodule}]),
  288. ...
  289. lager:stop_trace(Trace)
  290. ```
  291. Tracing to a pid is somewhat of a special case, since a pid is not a
  292. data-type that serializes well. To trace by pid, use the pid as a string:
  293. ```erlang
  294. lager:trace_console([{pid, "<0.410.0>"}])
  295. ```
  296. As of lager 2.0, you can also use a 3 tuple while tracing, where the second
  297. element is a comparison operator. The currently supported comparison operators
  298. are:
  299. * '<' - less than
  300. * '=' - equal to
  301. * '>' - greater than
  302. ```erlang
  303. lager:trace_console([{request, '>', 117}, {request, '<', 120}])
  304. ```
  305. Using '=' is equivalent to the 2-tuple form.
  306. Setting the truncation limit at compile-time
  307. --------------------------------------------
  308. Lager defaults to truncating messages at 4096 bytes, you can alter this by
  309. using the {lager_truncation_size, X} option. In rebar, you can add it to
  310. erl_opts:
  311. ```erlang
  312. {erl_opts, [{parse_transform, lager_transform}, {lager_truncation_size, 1024}]}.
  313. ```
  314. You can also pass it to erlc, if you prefer:
  315. ```
  316. erlc -pa lager/ebin +'{parse_transform, lager_transform}' +'{lager_truncation_size, 1024}' file.erl
  317. ```