Fields
- reason,- class,- stacktrace: standard error catching fields.
- module,- function,- line,- timestamp,- node,- when,- pid: reserved fields (could be used by logger itself).
- When logging IQs, adding the accfield should be enough. Ifaccnot available,iqcan be used.
  Ifiqis not available,sub_elcould be logged as a last option.
- what: why we are logging. We often use the function name as the- whatfield.- 
- Suffixes: If something goes wrong, use a _failedsuffix (instead ofunable_toand_error).
  The most common suffixes are_starting,_started,_stopping,_stopped, and_result.
- Prefixes: We sometimes add prefixes to whatto signal where we are logging from.
  Such prefixes should be short. Please, don't prefix with the complete module name.
  Some examples for prefixes are:mam_,sm_,muc_,auth_,s2s_,pool_.
 
When checking the final event name, remove duplicates from it.
| Bad event names | Good event names | Why | 
| s2s_dns_error | s2s_dns_lookup_failed | Not _failedprefix | 
| s2s_dns_error | s2s_dns_lookup_timeout | More specific failure reason | 
| mod_mam_starting | mam_starting | Use mam_prefix for MAM modules | 
| mongoose_wpool_mgr_pool_starting | pool_starting | Too long and repetitive | 
Logger defaults
Timestamp should be ordered first when possible, so that sorting is automatic.
| Name | Type | Description | Examples | 
| timestamp | atom | The timestamp (with timezone information) | 2018-07-11T13:41:10+00:00 | 
| at | string | Where in code the call or log line was emitted | module:function:line | 
| level | enum | log level according to RFC 5424 | warning | 
Generally required
| Name | Type | Description | Examples | Notes | 
| what | atom | Event (or issue) name | remove_user_failed |  | 
| text | binary | Human readable description | <<"MAM failed to contact MySQL">> |  | 
| result | binary | Explanation of the whatkey | failed | Optional | 
| tags | [atom] | The subcomponent taking action and logging data. | [c2s, presence], [mam, rdbms] | This category should be chosen based on filtering needs, and may represent the domain of concern for some operations | 
HTTP requests
| Name | Type | Description | Examples | Notes | 
| path | binary | HTTP path | <<"/api/add_user">> |  | 
| code | integer | HTTP code | 200 |  | 
| ip | tuple | IP address | inet:ip_address() |  | 
| port | integer | TCP/UDP port number | 5222 |  | 
| peer | tuple | peer() :: {inet:ip_address(), inet:port_number()} | {{127,0,0,1},5222} |  | 
| req | map | Cowboy request |  | Provide when available | 
| reply_body | binary | Body reply | <<"ok">> |  | 
XMPP
| Name | Type | Description | Examples | Notes | 
| acc | map | mongoose_acc, used to extract fields | #{...} |  | 
| user | binary | Local Username | <<"alice">> | Use #jid.luserwhen available | 
| server | binary | Local Server (host) name | <<"localhost">> | Use #jid.lserverwhen available | 
| sub_host | binary | Subhost when MUC or pubsub are used | <<"muc.localhost">> | It's not the same as server | 
| remote_user | binary | Remote Username (usually who makes IQ requests) | <<"alice">> | Use #jid.luserwhen available | 
| remote_server | binary | Remote Server (usually who makes IQ requests) | <<"otherhost">> | Use #jid.lserverwhen available | 
| iq | record | MongooseIM IQ record | #iq{} | Provide when available (but it could be acc instead) | 
| sub_el | record | IQ sub element | #xmlel{} | Provide ONLY if iqnot available | 
| c2s_state | record | C2S process state, that would be used by formatter | #state{} |  | 
| from_jid | binary | Accumulator's from_jid | <<"alice@localhost">> |  | 
| to_jid | binary | Accumulator's to_jid | <<"to@localhost">> |  | 
| packet | binary | Accumulator's element | <<"<message>...">> | Encoded as XML, not erlang records | 
| exml_packet | record | Same as packet, but in #xmlel{}format | #xmlel{} | Record, formatted in formatter | 
Other requests
| Name | Type | Description | Examples | Notes | 
| duration | integer | Duration of some operation in milliseconds | 5000 | Don't use it for microseconds | 
| state_name | atom | State name in gen_fsm | wait_for_stream |  | 
| state | term | gen_serverstate | #state{} | Consider adding a formatter | 
| call_from | tuple | From argument in gen_server's handle_call | {Pid, Tag} |  | 
When logging exceptions
what key should contain en _exception suffix. Following keys should be present:
| Name | Type | Description | Examples | Notes | 
| class | enum | catch Class:Reason:Stacktrace | error |  | 
| reason | term | catch Class:Reason:Stacktrace | http_timeout |  | 
| stacktrace | term | catch Class:Reason:Stacktrace | [...] | Formatted by formatter | 
Macros for logging unexpected requests
gen_server processes sometimes receive messages they couldn't process.
We use macros to log such events (just because you would need them in each
gen_server module).
We don't need to log state or state names for such events.
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15 | %% We don't always handle unexpected calls.
handle_call(Request, From, State) ->
    ?UNEXPECTED_CALL(Request, From),
    {reply, {error, unexpected_call}, State}.
%% We don't always handle unexpected casts.
handle_cast(Msg, State) ->
    ?UNEXPECTED_CAST(Msg),
    {noreply, State}.
%% We SHOULD ignore all unexpected messages, because they could arrive in case
%% of gen_server call timeouts.
handle_info(Msg, State) ->
    ?UNEXPECTED_INFO(Msg),
    {noreply, State}.
 | 
These macros translate into warning logs with the following keys, respectively:
|  | #{what => unexpected_cast, msg => Msg}.
#{what => unexpected_info, msg => Msg}.
#{what => unexpected_call, msg => Msg, call_from => From}.
 |