summaryrefslogtreecommitdiffstats
path: root/doc/developer-guide/logging-guidelines.md
blob: 0e6b258853599a76dcef2cba872769e0651b8854 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
Guidelines on using the logging framework within a component
============================================================
Gluster library libglusterfs.so provides message logging abstractions that
are intended to be used across all code/components within gluster.

There could be potentially 2 major cases how the logging infrastructure is
used,
  - A new gluster service daemon or end point is created
    - The service daemon infrastructure itself initlializes the logging
    infrastructure (i.e calling gf_log_init and related set functions)
      - See, glusterfsd.c:logging_init
    - Alternatively there could be a case where an end point service (say
    gfapi) may need to do the required initialization
    - This document does not (yet?) cover guidelines for these cases. Best
    bet would be to look at code in glusterfsd.c:logging_init (or equivalent)
    in case a need arises and you reach this document.
  - A new xlator or subcomponent is written as a part of the stack
    - Primarily in this case, the consumer of the logging APIs would only
    invoke an API to *log* a particular message at a certain severity
    - This document elaborates on this use of the message logging framework
    in this context

There are 2 interfaces provided to log messages,
1. The older gf_log* interface
2. The newer gf_msg* interface

1. Older _to_be_deprecated_ gf_log* interface
  - Not much documentation is provided for this interface here, as these are
  meant to be deprecated and all code should be moved to the newer gf_msg*
  interface

2. New gf_msg* interface
  - The set of interfaces provided by gf_msg are,
    - NOTE: It is best to consult logging.h for the latest interfaces, as
    this document may get out of sync with the code

    *gf_msg(dom, levl, errnum, msgid, fmt...)*
      - Used predominantly to log a message above TRACE and DEBUG levels
      - See further guidelines below

    *gf_msg_debug(dom, errnum, fmt...)*
    *gf_msg_trace(dom, errnum, fmt...)*
      - Above are handy shortcuts for TRACE and DEBUG level messages
      - See further guidelines below

    *gf_msg_callingfn(dom, levl, errnum, msgid, fmt...)*
      - Useful function when a backtrace to detect calling routines that
      reached this execution point needs to be logged in addition to the
      message
      - This is very handy for framework libraries or code, as there could
      be many callers to the same, and the real failure would need the call
      stack to determine who the caller actually was
      - A good example is the dict interfaces using this function to log who
      called, when a particular error/warning needs to be displayed
      - See further guidelines below

    *gf_msg_plain(levl, fmt...)*
    *gf_msg_plain_nomem(levl, msg)*
    *gf_msg_vplain(levl, fmt, va)*
    *gf_msg_backtrace_nomem*
      - The above interfaces are provided to log messages without any typical
      headers (like the time stamp, dom, errnum etc.). The primary users of
      the above interfaces are, when printing the final graph, or printing
      the configuration when a process is about dump core or abort, or
      printing the backtrace when a process receives a critical signal
      - These interfaces should not be used outside the scope of the users
      above, unless you know what you are doing

    *gf_msg_nomem(dom, levl, size)*
      - Very crisp messages, throwing out file, function, line numbers, in
      addition to the passed in size
      - These are used in the memory allocation abstractions interfaces in
      gluster, when the allocation fails (hence a no-mem log message, so that
      further allocation is not attempted by the logging infrastructure)
      - If you are contemplating using these, then you know why and how

  - Guidelines for the various arguments to the interfaces
    **dom**
      - The domain from which this message appears, IOW for xlators it should
      be the name of the xlator (as in this->name)

      - The intention of this string is to distinguish from which
      component/xlator the message is being printed

      - This information can also be gleaned from the FILE:LINE:FUNCTION
      information printed in the message anyway, but is retained to provide
      backward compatability to the messages as seen by admins earlier

    **levl**
      - Consult logging.h:gf_loglevel_t for logging levels (they pretty much
      map to syslog levels)

    **errnum**
      - errno should be passed in here, if available, 0 otherwise. This auto
      enables the logging infrastructure to print (man 3) strerror form of the
      same at the end of the message in a consistent format

      - If any message is already adding the strerror as a parameter to the
      message, it is suggested/encouraged to remove the same and pass it as
      errnum

      - The intention is that, if all messages did this using errnum and not
      as a part of their own argument list, the output would look consistent
      for the admin and cross component developers when reading logs

    **msgid**
      - This is a unique message ID per message (which now is more a message
      ID per group of messages in the implementation)

      - Rules for generating this ID can be found in dht-messages.h (it used
      to be template-common-messages.h, but that template is not updated,
      this comment should be changed once that is done) and glfs-message-id.h

      - Every message that is *above* TRACE and DEBUG should get a message
      ID, as this helps generating message catalogs that can help admins to
      understand the context of messages better. Another intention is that
      automated message parsers could detect a class of message IDs and send
      out notifications on the same, rather than parse the message string
      itself (which if it changes, the input to the parser has to change, etc.
      and hence is better to retain message IDs)

      - Ok so if intention is not yet clear, look at journald MESSAGE ID
      motivation, as that coupled with ident/dom above is expected to provide
      us with similar advantages

      - Bottomline: Every message gets its own ID, in case a message is
      *not* DEBUG or TRACE and still is developer centric, a generic message
      ID per component *maybe* assigned to the same to provide ease of use
      of the API

    **fmt**
      - As in format argument of (man 3) printf