Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"en-US,en;q\u003d0.5", "gen_ut":1656497616, "reponame":"libwebsockets", "desc":"libwebsockets lightweight C networking library", "owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://libwebsockets.org/repo/libwebsockets", "f":3, "items": [ {"schema":"libjg2-1", "cid":"9c93fce53d7c40e1d85acbafe49c6766", "oid":{ "oid": "a5612fbb9a63e38e2cce50880716745fadc8cb74", "alias": [ "refs/heads/main"]},"blobname": "READMEs/README.logging.md", "blob": "# lws logging\n\n# `lwsl_` logging apis\n\nLWS has traditionally provided logging arrangements that are not indirected\nthrough the lws context, because logging may be needed before and after the\ncontext existence. For that reason the original logging arrangements are\nprocesswide.\n\nBy default the logs are emitted on stdout, but this can be overridden\nusing `lws_set_log_level()` and either syslog (provided by `lwsl_emit_syslog()`)\nor custom log emission is possible if you point it to your own.\n\nCurrently the following log levels are defined\n\n|name|function|release|meaning|\n|---|---|---|---|\n|`LLL_ERR`|`lwsl_err()`|y|Serious operation errors anyone needs to know|\n|`LLL_WARN`|`lwsl_warn()`|y|Operation errors you may need to know|\n|`LLL_USER`|`lws_user()`|y|Information user code wants you to know|\n|`LLL_NOTICE`|`lwsl_notice()`|y|Information about what lws is doing useful for logging|\n|`LLL_INFO`|`lwsl_info()`|n|Detailed information about what lws is doing|\n|`LLL_DEBUG`|`lwsl_debug()`|n|Very detailed information about what lws is doing|\n|`LLL_PARSER`|`lwsl_parser()`|n|Very detailed information about parsing|\n|`LLL_HEADER`|`lwsl_header()`|n|Very detailed information about header processing|\n|`LLL_EXT`|`lwsl_ext()`|n|Very detailed information about ws extensions|\n|`LLL_CLIENT`|`lwsl_client()`|n|Very detailed information about client connections|\n|`LLL_LATENCY`|`lwsl_latency()`|n|detailed latency stats|\n|`LLL_THREAD`|`lwsl_thread()`|n|detailed threadpool information|\n\nThe first four log levels are built into lws even on Release builds, the others\nare only built in Debug builds.\n\nYou can select between Debug and Release builds using cmake `-DCMAKE_BUILD_TYPE\u003d`\n`DEBUG` or `Release`\n\n`lws_set_log_level()` is used to OR together the logging bitfields you want to\nsee emitted, only log levels that were built in can be enabled since the code for them\nis just not there otherwise.\n\n## Finegrained control of log level build\n\nYou can deviate from the default log inclusion for release / debug by overriding it\nat cmake, using `LWS_LOGGING_BITFIELD_SET` and `LWS_LOGGING_BITFIELD_CLEAR`.\n\nFor example you can set `-DLWS_LOGGING_BITFIELD_SET\u003d\u0022LLL_INFO|LLL_DEBUG\u0022`, which will\ncause those log level traces to be built in even in Release mode. Clear works\nsimilarly to defeat build of specific log levels.\n\n## Object tags in lws\n\nCommonly logging wants to refer to an object in a repeatable way, the usual way to\ndo this is with `%p` to print the object pointer. But this has a couple of drawbacks,\nfirst the same memory may be freed and reallocated for a different instance of the same\nor another object, causing confusion, and second when multiple processes are allocating\nobjects and logging, the same address may be allocated in different process also causing\nconfusion.\n\nLws has introduced unique tag strings to refer to object identity in logging instead, these\ncontain various information such as a 64-bit ordinal for the group the object belongs\nto that won't repeat even if reallocated to the same address (until 2^64 allocations,\nanyway).\n\nTags are fixed at object creation time for the whole object lifetime, although in some\ncases the tag may be appended to... accepted server wsis for example don't have much\ninformation available to form the tag until they start to indicate what they want to\ndo.\n\nAt their simplest the tags look like this (in a log indicating creation)\n\n```\n[2020/12/27 08:49:19:2956] N: ++ (4) [wsi|5|h2]\n```\n\nIt means a wsi has been created with the tag `[wsi|5|h2]`, and after that, there are 4\nactive objects in the wsi group.\n\nThe corresponding object destruction log with the tag is\n\n```\n[2020/12/27 08:49:24:4226] N: -- (3) 5.126s [wsi|5|h2]\n```\n\nit indicates the object's tag, that it lived for 5.126s and after its destruction,\nthere are 3 objects in its group left.\n\n### Compound tags\n\nIf the object has bindings, the tag can reflect that, eg\n\n```\n[2020/12/27 08:49:19:4787] N: ++ (2) [wsiSScli|6|d_h1]\n[2020/12/27 08:49:19:4793] N: ++ (2) [wsicli|6|GET/h1/httpbin.org/([wsiSScli|6|d_h1])]\n```\n\nthe first log is describing a proxied SS client connection at the proxy, and the second\nis a wsi bound to the SS object from the first log to do the outgoing client action.\n\n## Tags in user code\n\nWhen user code wants to refer to a tagged object like a wsi or vhost, there are helpers\nthat return a `const char *` containing the tag\n\n|tag accessors|\n|---|\n|`lws_wsi_tag(wsi)`|\n|`lws_vh_tag(vh)`|\n|`lws_ss_tag(h)`|\n\n# New logging context apis\n\nFrom v4.3 on lws additionally provides wrappers that issue logs into a\n\u0022log context\u0022 object, one of these is embedded in the lws_context, lws_vhost,\nwsi, ss and sspc handles. These follow the same general approach as before, but\nallow logs to be issued in \u0022the context\u0022 of any of those objects, and to fall\nback sanely if the object pointer is NULL.\n\nThe traditional process scope logs and emit management remain available as\nbefore, and if you do not set custom log contexts, the new log apis use the\nprocesswide log context emit and mask as before too.\n\nHere's a summary of the differences:\n\n|Traditional process scope logs|New log context apis|\n|---|---|\n|Single processwide log context|Defaults to processwide, but object can use custom log contexts|\n|Single processwide emit function|Emit function per log context|\n|Single processwide log mask|log mask is in log context, objects can be bound to custom log contexts at creation time|\n|Require trailing `\u005cn` in format|Trailing `\u005cn` added if not present|\n|Manual `__func__`|`__func__` added in wrapper macros automatically|\n|Manual tag addition|Object tag prepended automatically|\n|No hierarchy|Log contexts may refer to parent log contexts, which may prepend to child logs|\n|Macros per level (eg, `lwsl_err(...)`)|Macros per object type / level (eg, `lwsl_wsi_err(wsi, ...)`)|\n\nIn addition to being able to control the emit function and log level for\nindividual log contexts, eg, for a particular wsi, the log functions understand\nhow to prepend object-specific information such as tags and `__func__`\nautomatically. They also do not need a trailing `\u005cn` in the format string. So\nthe new context aware logs remove boilerplate from the logging calls while\nmaking the log information more consistent.\n\nSo comparing this kind of logging the processwide and log context aware ways:\n\n```\n[2021/06/25 09:39:34:7050] N: [669282|wsicli|4|GET/h1/libwebsockets.org|default]: _lws_generic_transaction_completed_active_conn: ...\n```\n\n|Type|Example code|\n|---|---|\n|Process scope apis|`lwsl_notice(\u0022%s: %s: mylog %d\u005cn\u0022, __func__, lws_wsi_tag(wsi), n);`|\n|New log context apis|`lwsl_wsi_notice(wsi, \u0022mylog %d\u0022, n);`|\n\nThe log context / object-aware apis do not replace the processwide logging but\naugment it, and the new apis default to use the original processwide emit\nfunction and log mask, so the behaviours are the same. The original processwide\nlog apis themselves are unchanged.\n\nAt lws_context creation time, you can set the context info `.log_cx` to a user\ndefined log context which is inherited by objects created in that lws_context by\ndefault. Vhost creation, wsi creation and ss / sspc creation all allow passing\na user log_cx to customize how logs for that object are handled.\n\n## Using the new logging apis\n\nThis table describes the different ways to issue an ERROR verbosity log, it\nworks the same for info, notice, warn, etc.\n\n|Scope|Api example|Functionality|\n|---|---|---|\n|Old, Processwide|lwsl_err(...)|Traditional processwide error log|\n|lws_context|lwsl_cx_err(context, ...)|error log bound to lws_context|\n|lws_vhost|lwsl_vhost_err(vh, ...)|error log bound to lws_vhost|\n|lws_wsi|lwsl_wsi_err(wsi, ...)|error log bound to wsi|\n|lws_ss|lwsl_ss_err(handle, ...)|error log bound to secure stream|\n\nSimilarly hexdumps can be bound to different log contexts\n\n|Scope|Api example|Functionality|\n|---|---|---|\n|Old, Processwide|lwsl_hexdump_err(...)|Traditional processwide error hexdump|\n|lws_context|lwsl_hexdump_cx_err(context, ...)|error hexdump bound to lws_context|\n|lws_vhost|lwsl_hexdump_vhost_err(vh, ...)|error hexdump bound to lws_vhost|\n|lws_wsi|lwsl_hexdump_wsi_err(wsi, ...)|error hexdump bound to wsi|\n|lws_ss|lwsl_hexdump_ss_err(handle, ...)|error hexdump bound to secure stream|\n\n## Creating and using custom log contexts\n\nThe log context object is public, in `libwebsockets/lws-logs.h`, currently it\nis like this\n\n```\ntypedef void (*lws_log_emit_t)(int level, const char *line);\ntypedef void (*lws_log_emit_cx_t)(struct lws_log_cx *cx, int level,\n\t\t\t\t const char *line, size_t len);\ntypedef void (*lws_log_prepend_cx_t)(struct lws_log_cx *cx, void *obj,\n\t\t\t\t char **p, char *e);\ntypedef void (*lws_log_use_cx_t)(struct lws_log_cx *cx, int _new);\ntypedef struct lws_log_cx {\n\tunion {\n\t\tlws_log_emit_t\t\temit; /* legacy emit function */\n\t\tlws_log_emit_cx_t\temit_cx; /* LLLF_LOG_CONTEXT_AWARE */\n\t} u;\n\tlws_log_use_cx_t\t\trefcount_cb;\n\t/**\u003c NULL, or a function called after each change to .refcount below,\n\t * this enables implementing side-effects like opening and closing\n\t * log files when the first and last object binds / unbinds */\n\tlws_log_prepend_cx_t\t\tprepend;\n\t/**\u003c NULL, or a cb to optionally prepend a string to logs we are a\n\t * parent of */\n\tstruct lws_log_cx\t\t*parent;\n\t/**\u003c NULL, or points to log ctx we are a child of */\n\tvoid\t\t\t\t*opaque;\n\t/**\u003c ignored by lws, used to pass config to emit_cx, eg, filepath */\n\tvoid\t\t\t\t*stg;\n\t/**\u003c ignored by lws, may be used a storage by refcount_cb / emit_cx */\n\tuint32_t\t\t\tlll_flags;\n\t/**\u003c mask of log levels we want to emit in this context */\n\tint32_t\t\t\t\trefcount;\n\t/**\u003c refcount of objects bound to this log context */\n} lws_log_cx_t;\n```\n\nThe emit function is a union because the traditional logs and the old emit\nfunctions are also implemented using the new log contexts internally. For\nnew log context-aware code, you would use `.u.emit_cx` and set the flag\n`LLLF_LOG_CONTEXT_AWARE` on `.lll_flags`.\n\nLws also exports some common emit and refcount functions so you don't have to\nreinvent the wheel\n\n|Dest|emit member|`.lll_flags`|emit|`.refcount_cb`|`.opaque`|\n|---|---|---|---|---|---|\n|stderr|`.u.emit`|-|`lwsl_emit_stderr`|NULL|NULL|\n|file|`.u.emit_cx`|`LLLF_LOG_CONTEXT_AWARE`|`lws_log_emit_cx_file`|`lws_log_use_cx_file`|`(const char *)filepath`|\n\nFor example, a custom log context that emits to a configurable file can be\ndeclared like this (lws exports the needed helpers already)\n\n```\nstatic lws_log_cx_t my_log_cx \u003d {\n .lll_flags \u003d LLLF_LOG_CONTEXT_AWARE |\n LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER,\n .refcount_cb \u003d lws_log_use_cx_file,\n .u.emit_cx \u003d lws_log_emit_cx_file,\n .opaque\t \u003d \u0022/tmp/mylogpath.log\u0022 /* also settable at runtime */\n};\n```\n\nTo bind the lws_context to this log context, set `log_cx` in the context\ncreation info struct\n\n```\n\tinfo.log_cx \u003d \u0026my_log_cx;\n```\n\n### Log context hierarchy\n\nLog contexts may also point to a parent log context... the top level log context\ndefines the emit function to be used, but parent log contexts are consulted by\ncalling their prepend function if any, to annotate logs with information from\nparent levels.\n\n### Log context prepend function\n\nLogs contexts may define a \u0022prepend\u0022 function callback, that knows how to\nrepresent the object in a brief string to be prepended to other logs. For\nexample the wsi-aware log context layer knows how to provide the wsi tag\nwhen called.\n\nPrepend functions should add `:\u003cspace\u003e` after their output, if any, since these\nwill appear before the start of other logs.\n\n### Log context opaque member\n\nThe `.opaque` member is available for passing in configuration to the emit and\nrefcount_cb members. Lws does not use this itself at all.\n\n### Log context refcounting\n\nAn expected use for custom log contexts is emitting to a specific file, and\nthen binding one or more objects to that log context. Since it's too expensive\nto keep opening and closing the output file per log, it means we need to know\nwhen we bind to the first object and unbind from the last, so we can keep the\nfile handle open.\n\nFor this reason the log contexts have a refcount, and an opaque `void *stg`\navailble for the emit and refounct_cb to use how they see fit, eg, for storing\nthe output log file descriptor.\n","s":{"c":1656497616,"u": 479}} ],"g": 3097,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 1, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}