|
| PLUGIN_EXPORT bool | sir_plugin_query (sir_plugininfo *info) |
| | Called by libsir after the plugin library object is loaded, but before any other functions are probed or called.
|
| PLUGIN_EXPORT bool | sir_plugin_init (void) |
| | Called by libsir after the plugin is queried and successfully validated.
|
| PLUGIN_EXPORT bool | sir_plugin_write (sir_level level, const char *message) |
| | Called by libsir when a message is dispatched on any level whose bit was set in the levels bitmask of the sir_plugininfo structure when sir_plugin_query was called.
|
| PLUGIN_EXPORT bool | sir_plugin_cleanup (void) |
| | Called by libsir when the plugin is about to be unloaded.
|
Intro
Using plugins, it is possible to extend libsir's reach when dispatching log messages. A simple example of this would be a plugin that only registers for emergency-level messages. Whenever it receives a message, it posts the message to a REST API endpoint which results in a push notification being sent to a mobile device.
Use your imagination; essentially anything is possible. There are some caveats, though: until the thread pool and job queue mechanisms implemented in (#121) are utilized, plugins must either only perform operations that are guaranteed to complete quickly, or perform those operations asynchronously (i.e., on another thread).
Versioning
libsir's plugin interface will be versioned; the functions appearing on this page comprise the plugin interface v1. If/when a new function export is added (or one is modified), the version number will be bumped.
When plugins are compiled, their interface version is hard-coded in. This means that as libsir continues to evolve (and the version number increases), it can still communicate with older plugins via backwards-compatible versioned interfaces.
Creating your own plugin
The following steps should be taken in order to write your own fully- functioning libsir plugin:
- Make a copy of the plugins/sample directory (within plugins).
- Rename the new directory whatever you'd like. The name of the new directory will determine the name of the plugin file that is produced.
- Study the implementation of the sample plugin. It is included below for your convenience. Modify your copy to suit your specific needs.
#include "plugin_sample.h"
#include "sir/helpers.h"
#include <stdio.h>
#if defined(__WIN__)
BOOL APIENTRY DllMain(HMODULE module, DWORD ul_reason_for_call, LPVOID reserved) {
SIR_UNUSED(module);
SIR_UNUSED(ul_reason_for_call);
SIR_UNUSED(reserved);
return TRUE;
}
#endif
static const uint8_t maj_ver = 1U;
static const uint8_t min_ver = 0U;
static const uint8_t bld_ver = 0U;
static const char* author = "libsir contributors";
static const char* desc = "Logs messages and function calls to stdout.";
static const uint64_t caps = 0ULL;
return true;
}
return true;
}
(void)printf(
"\t" SIR_DGRAY(
"plugin_sample (%s): level: %04"PRIx16
", message: %s")
SIR_EOL,
__func__, level, message);
return true;
}
return true;
}
ANSI escape sequence macros.
#define SIR_DGRAY(s)
Dark gray foreground text.
Definition ansimacros.h:131
#define SIR_EOL
The end of line sequence.
Definition config.h:91
PLUGIN_EXPORT bool sir_plugin_init(void)
Called by libsir after the plugin is queried and successfully validated.
Definition plugin_sample.c:70
PLUGIN_EXPORT bool sir_plugin_cleanup(void)
Called by libsir when the plugin is about to be unloaded.
Definition plugin_sample.c:81
PLUGIN_EXPORT bool sir_plugin_write(sir_level level, const char *message)
Called by libsir when a message is dispatched on any level whose bit was set in the levels bitmask of...
Definition plugin_sample.c:75
PLUGIN_EXPORT bool sir_plugin_query(sir_plugininfo *info)
Called by libsir after the plugin library object is loaded, but before any other functions are probed...
Definition plugin_sample.c:55
uint16_t sir_level
The sir_level type.
Definition types.h:71
#define SIRO_NOTID
Exclude thread ID/name.
Definition types.h:87
uint16_t sir_levels
sir_level bitmask type.
Definition types.h:74
#define SIRL_INFO
Informational messages.
Definition types.h:65
#define SIRL_DEBUG
Debugging/diagnostic output.
Definition types.h:66
#define SIRO_NOHOST
Exclude local hostname.
Definition types.h:83
uint32_t sir_options
sir_option bitmask type.
Definition types.h:96
The libsir-to-plugin query data structure.
Definition types.h:329
uint8_t iface_ver
Plugin interface version.
Definition types.h:330
uint8_t bld_ver
Build/patch version number.
Definition types.h:333
uint8_t min_ver
Minor version number.
Definition types.h:332
uint64_t caps
Plugin capabilities bitmask.
Definition types.h:338
const char * desc
Plugin description.
Definition types.h:337
const char * author
Plugin author information.
Definition types.h:336
sir_levels levels
Level registration bitmask.
Definition types.h:334
uint8_t maj_ver
Major version number.
Definition types.h:331
sir_options opts
Formatting options bitmask.
Definition types.h:335
- cd back into the root directory of the repository and run make clean
plugins. If everything goes smoothly, your shiny new plugin should now be located in build/lib. If you named your directory 'foo', you should see a plugin_foo.[so/dll].
- You can now move the plugin wherever you'd like, and use sir_loadplugin to load it (after you've called sir_init, of course).
If you encounter any problems, rebuild with env SIR_SELFLOG=1 SIR_DEBUG=1
make clean plugins. This will enable diagnostic output from libsir that should aid in the diagnosis of any issues you encounter. If you're still stuck, reach out and somebody will assist you within a reasonable amount of time.
◆ sir_plugin_cleanup()
| PLUGIN_EXPORT bool sir_plugin_cleanup |
( |
void | | ) |
|
Called by libsir when the plugin is about to be unloaded.
The plugin should immediately begin releasing allocated resources and resetting its internal state.
- Returns
- bool true if the plugin cleaned up successfully, false otherwise.
◆ sir_plugin_init()
| PLUGIN_EXPORT bool sir_plugin_init |
( |
void | | ) |
|
Called by libsir after the plugin is queried and successfully validated.
The plugin should only at the time of this call begin allocating resources and initializing its internal state.
- Returns
- bool true if the plugin successfully initialized its internal state, false otherwise.
◆ sir_plugin_query()
Called by libsir after the plugin library object is loaded, but before any other functions are probed or called.
The plugin must fill out the information in the info structure in a way satisfactory to libsir, or it will immediately be unloaded:
- all members of the sir_plugininfo structure are required to be set by the plugin.
- iface_ver must be set to SIR_PLUGIN_VCURRENT.
- char* members must be set to valid strings, and must point at static memory that will not go out of scope when the function exits. Do not allocate heap memory for these properties; they will be leaked.
- levels must be a valid sir_level bitmask.
- opts must be a valid sir_option bitmask.
- Note
- It is not possible to change these settings once chosen, so ensure that they are correct.
- See also
- sir_level
-
sir_option
-
Defaults
- Parameters
-
| info | Pointer to a sir_plugininfo structure to be initialized by the plugin. |
- Returns
- bool true if the info structure was successfully initialized, false otherwise. If false, the plugin will be unloaded.
◆ sir_plugin_write()
| PLUGIN_EXPORT bool sir_plugin_write |
( |
sir_level | level, |
|
|
const char * | message ) |
Called by libsir when a message is dispatched on any level whose bit was set in the levels bitmask of the sir_plugininfo structure when sir_plugin_query was called.
The message string will be pre-formatted according to the sir_option set in the opts bitmask of the sir_plugininfo structure.
- Parameters
-
| level | The sir_level of the message being dispatched. |
| message | A string containing the pre-formatted message being dispatched. |
- Returns
- bool true if the message was successfully processed, false otherwise.