Name
Date
Size
#Lines
LOC

..--

callouts/H--10374

config/H--7460

dist/H--7561

docs/H--311244

extensions/H--34,74322,596

gen/H--165134

lib/H--2,1431,398

phosphor-rsyslog-config/H--506371

subprojects/H--4936

test/H--15,72011,237

tools/H--705545

yaml/xyz/openbmc_project/Logging/Internal/H--5049

.clang-formatH A D01-Feb-20253.7 KiB137135

.gitignoreH A D30-Apr-202142 43

.lcovrcH A D05-Jun-202080 43

.shellcheckHD13-Apr-20210

LICENSEH A D20-Jul-201611.1 KiB202169

OWNERSH A D22-Jul-20221.8 KiB5752

README.mdH A D27-Jan-202517.8 KiB487376

config_main.hH A D30-Sep-2024108 53

elog_block.hppH A D16-Aug-20241.7 KiB6139

elog_entry.cppH A D30-Sep-20243.5 KiB134108

elog_entry.hppH A D11-Dec-20246.2 KiB17884

elog_meta.cppH A D21-Nov-20241.7 KiB6455

elog_meta.hppH A D21-Nov-20243 KiB10170

elog_serialize.cppH A D11-Dec-20245.8 KiB174136

elog_serialize.hppH A D30-Sep-20241.3 KiB4719

extensions.cppH A D03-Sep-20241 KiB4637

extensions.hppH A D22-Nov-20247.8 KiB25187

log_create_main.cppH A D22-Nov-20241.6 KiB7255

log_manager.cppH A D01-Feb-202520.9 KiB724589

log_manager.hppH A D22-Nov-202413.6 KiB405153

log_manager_main.cppH A D03-Oct-20241.5 KiB6041

logging_test.cppH A D17-Dec-20247.8 KiB263204

meson.buildH A D01-Feb-20255.2 KiB205185

meson.optionsH A D01-Feb-20251.1 KiB5145

paths.cppH A D30-Sep-2024340 1613

paths.hppH A D30-Sep-2024255 159

setup.cfgH A D16-Apr-202139 21

util.cppH A D21-Nov-20247.3 KiB239170

util.hppH A D21-Nov-20241.3 KiB4818

README.md

1 # phosphor-logging
2 
3 The phosphor logging repository provides mechanisms for event and journal
4 logging.
5 
6 ## Table Of Contents
7 
8 - [Building](#to-build)
9 - [Structured Logging](#structured-logging)
10 - [Event Logs](#event-logs)
11 - [Application Specific Error YAML](#adding-application-specific-error-yaml)
12 - [Event Log Extensions](#event-log-extensions)
13 - [Remote Logging](#remote-logging-via-rsyslog)
14 - [Boot Fail on Hardware Errors](#boot-fail-on-hardware-errors)
15 
16 ## To Build
17 
18 To build this package, do the following steps:
19 
20 1. meson builddir
21 2. ninja -c builddir
22 
23 ## Structured Logging
24 
25 phosphor-logging provides APIs to add program logging information to the
26 systemd-journal and it is preferred that this logging data is formatted in a
27 structured manner (using the facilities provided by the APIs).
28 
29 See [Structured Logging](./docs/structured-logging.md) for more details on this
30 API.
31 
32 ## Event Logs
33 
34 OpenBMC event logs are a collection of D-Bus interfaces owned by
35 phosphor-log-manager that reside at `/xyz/openbmc_project/logging/entry/X`,
36 where X starts at 1 and is incremented for each new log.
37 
38 The interfaces are:
39 
40 - [xyz.openbmc_project.Logging.Entry]
41   - The main event log interface.
42 - [xyz.openbmc_project.Association.Definitions]
43   - Used for specifying inventory items as the cause of the event.
44   - For more information on associations, see [here][associations-doc].
45 - [xyz.openbmc_project.Object.Delete]
46   - Provides a Delete method to delete the event.
47 - [xyz.openbmc_project.Software.Version]
48   - Stores the code version that the error occurred on.
49 
50 On platforms that make use of these event logs, the intent is that they are the
51 common event log representation that other types of event logs can be created
52 from. For example, there is code to convert these into both Redfish and IPMI
53 event logs, in addition to the event log extensions mentioned
54 [below](#event-log-extensions).
55 
56 The logging daemon has the ability to add `callout` associations to an event log
57 based on text in the AdditionalData property. A callout is a link to the
58 inventory item(s) that were the cause of the event log. See [here][callout-doc]
59 for details.
60 
61 ### Creating Event Logs In Code
62 
63 The preferred method for creating event logs is specified in the project-level
64 [event log design][event-log-design]. Events are defined using YAML in the
65 phosphor-dbus-interfaces repository, such as the
66 [Logging.Cleared][logging-cleared] event, which will generate a C++ class for
67 the event. Then a call to `lg2::commit` is made on a constructed event to add it
68 to the event log.
69 
70 ```cpp
71 lg2::commit(sdbusplus::event::xyz::openbmc_project::Logging::Cleared(
72     "NUMBER_OF_LOGS", count));
73 ```
74 
75 The above function will return the object path of the created log entry. This
76 log-entry can be resolved with the helper `lg2::resolve` fuction.
77 
78 ```cpp
79 lg2::resolve(logPath);
80 ```
81 
82 There are two other, but now deprecated, methods to creating event logs in
83 OpenBMC code. The first makes use of the systemd journal to store metadata
84 needed for the log, and the second is a plain D-Bus method call.
85 
86 [event-log-design]:
87   https://github.com/openbmc/docs/blob/master/designs/event-logging.md#phosphor-logging
88 [logging-cleared]:
89   https://github.com/openbmc/phosphor-dbus-interfaces/blob/6a8507d06e172d8d29c0459f0a0d078553d2ecc7/yaml/xyz/openbmc_project/Logging.events.yaml#L4
90 
91 #### Journal Based Event Log Creation [deprecated]
92 
93 Event logs can be created by using phosphor-logging APIs to commit sdbusplus
94 exceptions. These APIs write to the journal, and then call a `Commit` D-Bus
95 method on the logging daemon to create the event log using the information it
96 put in the journal.
97 
98 The APIs are found in `<phosphor-logging/elog.hpp>`:
99 
100 - `elog()`: Throw an sdbusplus error.
101 - `commit()`: Catch an error thrown by elog(), and commit it to create the event
102   log.
103 - `report()`: Create an event log from an sdbusplus error without throwing the
104   exception first.
105 
106 Any errors passed into these APIs must be known to phosphor-logging, usually by
107 being defined in `<phosphor-logging/elog-errors.hpp>`. The errors must also be
108 known by sdbusplus, and be defined in their corresponding error.hpp. See below
109 for details on how get errors into these headers.
110 
111 Example:
112 
113 ```cpp
114 #include <phosphor-logging/elog-errors.hpp>
115 #include <phosphor-logging/elog.hpp>
116 #include <xyz/openbmc_project/Common/error.hpp>
117 ...
118 using InternalFailure =
119     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
120 ...
121 if (somethingBadHappened)
122 {
123     phosphor::logging::report<InternalFailure>();
124 }
125 
126 ```
127 
128 Alternatively, to throw, catch, and then commit the error:
129 
130 ```cpp
131 try
132 {
133     phosphor::logging::elog<InternalFailure>();
134 }
135 catch (InternalFailure& e)
136 {
137     phosphor::logging::commit<InternalFailure>();
138 }
139 ```
140 
141 Metadata can be added to event logs to add debug data captured at the time of
142 the event. It shows up in the AdditionalData property in the
143 `xyz.openbmc_project.Logging.Entry` interface. Metadata is passed in via the
144 `elog()` or `report()` functions, which write it to the journal. The metadata
145 must be predefined for the error in the [metadata YAML](#event-log-definition)
146 so that the daemon knows to look for it in the journal when it creates the event
147 log.
148 
149 Example:
150 
151 ```cpp
152 #include <phosphor-logging/elog-errors.hpp>
153 #include <phosphor-logging/elog.hpp>
154 #include <xyz/openbmc_project/Control/Device/error.hpp>
155 ...
156 using WriteFailure =
157     sdbusplus::xyz::openbmc_project::Control::Device::Error::WriteFailure;
158 using metadata =
159     phosphor::logging::xyz::openbmc_project::Control::Device::WriteFailure;
160 ...
161 if (somethingBadHappened)
162 {
163     phosphor::logging::report<WriteFailure>(metadata::CALLOUT_ERRNO(5),
164                               metadata::CALLOUT_DEVICE_PATH("some path"));
165 }
166 ```
167 
168 In the above example, the AdditionalData property would look like:
169 
170 ```cpp
171 ["CALLOUT_ERRNO=5", "CALLOUT_DEVICE_PATH=some path"]
172 ```
173 
174 Note that the metadata fields must be all uppercase.
175 
176 ##### Event Log Definition [deprecated]
177 
178 As mentioned above, both sdbusplus and phosphor-logging must know about the
179 event logs in their header files, or the code that uses them will not even
180 compile. The standard way to do this to define the event in the appropriate
181 `<error-category>.errors.yaml` file, and define any metadata in the
182 `<error-category>.metadata.yaml` file in the appropriate `*-dbus-interfaces`
183 repository. During the build, phosphor-logging generates the elog-errors.hpp
184 file for use by the calling code.
185 
186 In much the same way, sdbusplus uses the event log definitions to generate an
187 error.hpp file that contains the specific exception. The path of the error.hpp
188 matches the path of the YAML file.
189 
190 For example, if in phosphor-dbus-interfaces there is
191 `xyz/openbmc_project/Control/Device.errors.yaml`, the errors that come from that
192 file will be in the include: `xyz/openbmc_project/Control/Device/error.hpp`.
193 
194 In rare cases, one may want one to define their errors in the same repository
195 that uses them. To do that, one must:
196 
197 1. Add the error and metadata YAML files to the repository.
198 2. Run the sdbus++ script within the makefile to create the error.hpp and .cpp
199    files from the local YAML, and include the error.cpp file in the application
200    that uses it. See [openpower-occ-control] for an example.
201 3. Tell phosphor-logging about the error. This is done by either:
202    - Following the [directions](#adding-application-specific-error-yaml) defined
203      in this README, or
204    - Running the script yourself:
205    1. Run phosphor-logging\'s `elog-gen.py` script on the local yaml to generate
206       an elog-errors.hpp file that just contains the local errors, and check
207       that into the repository and include it where the errors are needed.
208    2. Create a recipe that copies the local YAML files to a place that
209       phosphor-logging can find it during the build. See [here][led-link] for an
210       example.
211 
212 #### D-Bus Event Log Creation [deprecated]
213 
214 There is also a [D-Bus method][log-create-link] to create event logs:
215 
216 - Service: xyz.openbmc_project.Logging
217 - Object Path: /xyz/openbmc_project/logging
218 - Interface: xyz.openbmc_project.Logging.Create
219 - Method: Create
220   - Method Arguments:
221     - Message: The `Message` string property for the
222       `xyz.openbmc_project.Logging.Entry` interface.
223     - Severity: The `severity` property for the
224       `xyz.openbmc_project.Logging.Entry` interface. An
225       `xyz.openbmc_project.Logging.Entry.Level` enum value.
226     - AdditionalData: The `AdditionalData` property for the
227       `xyz.openbmc_project.Logging.Entry` interface, but in a map instead of in
228       a vector of "KEY=VALUE" strings. Example:
229 
230 ```cpp
231     std::map<std::string, std::string> additionalData;
232     additionalData["KEY"] = "VALUE";
233 ```
234 
235 Unlike the previous APIs where errors could also act as exceptions that could be
236 thrown across D-Bus, this API does not require that the error be defined in the
237 error YAML in the D-Bus interfaces repository so that sdbusplus knows about it.
238 Additionally, as this method passes in everything needed to create the event
239 log, the logging daemon doesn't have to know about it ahead of time either.
240 
241 That being said, it is recommended that users of this API still follow some
242 guidelines for the message field, which is normally generated from a combination
243 of the path to the error YAML file and the error name itself. For example, the
244 `Timeout` error in `xyz/openbmc_project/Common.errors.yaml` will have a Message
245 property of `xyz.openbmc_project.Common.Error.Timeout`.
246 
247 The guidelines are:
248 
249 1. When it makes sense, one can still use an existing error that has already
250    been defined in an error YAML file, and use the same severity and metadata
251    (AdditionalData) as in the corresponding metadata YAML file.
252 
253 2. If creating a new error, use the same naming scheme as other errors, which
254    starts with the domain, `xyz.openbmc_project`, `org.open_power`, etc,
255    followed by the capitalized category values, followed by `Error`, followed by
256    the capitalized error name itself, with everything separated by "."s. For
257    example: `xyz.openbmc_project.Some.Category.Error.Name`.
258 
259 3. If creating a new common error, still add it to the appropriate error and
260    metadata YAML files in the appropriate D-Bus interfaces repository so that
261    others can know about it and use it in the future. This can be done after the
262    fact.
263 
264 [xyz.openbmc_project.logging.entry]:
265   https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Logging/Entry.interface.yaml
266 [xyz.openbmc_project.association.definitions]:
267   https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Association/Definitions.interface.yaml
268 [associations-doc]:
269   https://github.com/openbmc/docs/blob/master/architecture/object-mapper.md#associations
270 [callout-doc]:
271   https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Common/Callout/README.md
272 [xyz.openbmc_project.object.delete]:
273   https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Object/Delete.interface.yaml
274 [xyz.openbmc_project.software.version]:
275   https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Software/Version.errors.yaml
276 [openpower-occ-control]: https://github.com/openbmc/openpower-occ-control
277 [led-link]:
278   https://github.com/openbmc/openbmc/tree/master/meta-phosphor/recipes-phosphor/leds
279 [log-create-link]:
280   https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Logging/Create.interface.yaml
281 
282 ## Event Log Extensions
283 
284 The extension concept is a way to allow code that creates other formats of error
285 logs besides phosphor-logging's event logs to still reside in the
286 phosphor-log-manager application.
287 
288 The extension code lives in the `extensions/<extension>` subdirectories, and is
289 enabled with a `--enable-<extension>` configure flag. The extension code won't
290 compile unless enabled with this flag.
291 
292 Extensions can register themselves to have functions called at the following
293 points using the REGISTER_EXTENSION_FUNCTION macro.
294 
295 - On startup
296   - Function type void(internal::Manager&)
297 - After an event log is created
298   - Function type void(args)
299   - The args are:
300     - const std::string& - The Message property
301     - uin32_t - The event log ID
302     - uint64_t - The event log timestamp
303     - Level - The event level
304     - const AdditionalDataArg& - the additional data
305     - const AssociationEndpointsArg& - Association endpoints (callouts)
306 - Before an event log is deleted, to check if it is allowed.
307   - Function type void(std::uint32_t, bool&) that takes the event ID
308 - After an event log is deleted
309   - Function type void(std::uint32_t) that takes the event ID
310 
311 Using these callback points, they can create their own event log for each
312 OpenBMC event log that is created, and delete these logs when the corresponding
313 OpenBMC event log is deleted.
314 
315 In addition, an extension has the option of disabling phosphor-logging's default
316 error log capping policy so that it can use its own. The macro
317 DISABLE_LOG_ENTRY_CAPS() is used for that.
318 
319 ### Motivation
320 
321 The reason for adding support for extensions inside the phosphor-log-manager
322 daemon as opposed to just creating new daemons that listen for D-Bus signals is
323 to allow interactions that would be complicated or expensive if just done over
324 D-Bus, such as:
325 
326 - Allowing for custom old log retention algorithms.
327 - Prohibiting manual deleting of certain logs based on an extension's
328   requirements.
329 
330 ### Creating extensions
331 
332 1. Add a new flag to configure.ac to enable the extension:
333 
334    ```autoconf
335    AC_ARG_ENABLE([foo-extension],
336                  AS_HELP_STRING([--enable-foo-extension],
337                                 [Create Foo logs]))
338    AM_CONDITIONAL([ENABLE_FOO_EXTENSION],
339                   [test "x$enable_foo_extension" == "xyes"])
340    ```
341 
342 2. Add the code in `extensions/<extension>/`.
343 3. Create a makefile include to add the new code to phosphor-log-manager:
344 
345    ```make
346    phosphor_log_manager_SOURCES += \
347            extensions/foo/foo.cpp
348    ```
349 
350 4. In `extensions/extensions.mk`, add the makefile include:
351 
352    ```make
353    if ENABLE_FOO_EXTENSION
354    include extensions/foo/foo.mk
355    endif
356    ```
357 
358 5. In the extension code, register the functions to call and optionally disable
359    log capping using the provided macros:
360 
361    ```cpp
362    DISABLE_LOG_ENTRY_CAPS();
363 
364    void fooStartup(internal::Manager& manager)
365    {
366        // Initialize
367    }
368 
369    REGISTER_EXTENSION_FUNCTION(fooStartup);
370 
371    void fooCreate(const std::string& message, uint32_t id, uint64_t timestamp,
372                    Entry::Level severity, const AdditionalDataArg& additionalData,
373                    const AssociationEndpointsArg& assocs)
374    {
375        // Create a different type of error log based on 'entry'.
376    }
377 
378    REGISTER_EXTENSION_FUNCTION(fooCreate);
379 
380    void fooRemove(uint32_t id)
381    {
382        // Delete the extension error log that corresponds to 'id'.
383    }
384 
385    REGISTER_EXTENSION_FUNCTION(fooRemove);
386    ```
387 
388 ### Extension List
389 
390 The supported extensions are:
391 
392 - OpenPower PELs
393   - Enabled with --enable-openpower-pel-extension
394   - Detailed information can be found
395     [here](extensions/openpower-pels/README.md)
396 
397 ## Remote Logging via Rsyslog
398 
399 The BMC has the ability to stream out local logs (that go to the systemd
400 journal) via rsyslog (<https://www.rsyslog.com/>).
401 
402 The BMC will send everything. Any kind of filtering and appropriate storage will
403 have to be managed on the rsyslog server. Various examples are available on the
404 internet. Here are few pointers :
405 <https://www.rsyslog.com/storing-and-forwarding-remote-messages/>
406 <https://www.rsyslog.com/doc/rsyslog%255Fconf%255Ffilter.html>
407 <https://www.thegeekdiary.com/understanding-rsyslog-filter-options/>
408 
409 ### Configuring rsyslog server for remote logging
410 
411 The BMC is an rsyslog client. To stream out logs, it needs to talk to an rsyslog
412 server, to which there's connectivity over a network. REST API can be used to
413 set the remote server's IP address and port number.
414 
415 The following presumes a user has logged on to the BMC (see
416 <https://github.com/openbmc/docs/blob/master/rest-api.md>).
417 
418 Set the IP:
419 
420 ```sh
421 curl -b cjar -k -H "Content-Type: application/json" -X PUT \
422     -d '{"data": <IP address>}' \
423     https://<BMC IP address>/xyz/openbmc_project/logging/config/remote/attr/Address
424 ```
425 
426 Set the port:
427 
428 ```sh
429 curl -b cjar -k -H "Content-Type: application/json" -X PUT \
430     -d '{"data": <port number>}' \
431     https://<BMC IP address>/xyz/openbmc_project/logging/config/remote/attr/Port
432 ```
433 
434 #### Querying the current configuration
435 
436 ```sh
437 curl -b cjar -k \
438     https://<BMC IP address>/xyz/openbmc_project/logging/config/remote
439 ```
440 
441 #### Setting the hostname
442 
443 Rsyslog can store logs separately for each host. For this reason, it's useful to
444 provide a unique hostname to each managed BMC. Here's how that can be done via a
445 REST API :
446 
447 ```sh
448 curl -b cjar -k -H "Content-Type: application/json" -X PUT \
449     -d '{"data": "myHostName"}' \
450     https://<BMC IP address>//xyz/openbmc_project/network/config/attr/HostName
451 ```
452 
453 #### Disabling remote logging
454 
455 Remote logging can be disabled by writing 0 to the port, or an empty string("")
456 to the IP.
457 
458 #### Changing the rsyslog server
459 
460 When switching to a new server from an existing one (i.e the address, or port,
461 or both change), it is recommended to disable the existing configuration first.
462 
463 ## Boot Fail on Hardware Errors
464 
465 phosphor-logging supports a setting, which when set, will result in the software
466 looking at new phosphor-logging entries being created, and if a CALLOUT\* is
467 found within the entry, ensuring the system will not power on. Entries with
468 severities of Informational or Debug will not block boots, even if they have
469 callouts.
470 
471 The full design for this can be found
472 [here](https://github.com/openbmc/docs/blob/master/designs/fail-boot-on-hw-error.md)
473 
474 To enable this function:
475 
476 ```sh
477 busctl set-property xyz.openbmc_project.Settings /xyz/openbmc_project/logging/settings xyz.openbmc_project.Logging.Settings QuiesceOnHwError b true
478 ```
479 
480 To check if an entry is blocking the boot:
481 
482 ```sh
483 obmcutil listbootblock
484 ```
485 
486 Resolve or clear the corresponding entry to allow the system to boot.
487