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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
Example of libnslog in use
==========================
Since some people work better from an example, the following is an example of
both a library using libnslog, and a client application using that library.
The source is only inlined here, and not directly tested, but it should be
moderately complete and thus functional. It was taken, in part, from the test
suite so that you can be reasonably confident it works.
The library
===========
First we need a public header:
```{.c}
/* Example Library Header, include/libexample.h */
#ifndef LIBEXAMPLE_H
#define LIBEXAMPLE_H
#include "nslog/nslog.h"
/* All logging in libexample comes underneath this category */
NSLOG_DECLARE_CATEGORY(libexample);
/* This function does what the library does */
extern void example_do_stuff(void);
#endif
```
Next we need a private header, because libexample has some more categories...
```{.c}
/* Example Library Header, src/hidden.h */
#ifndef LIBEXAMPLE__HIDDEN_H
#define LIBEXAMPLE__HIDDEN_H
#include "libexample.h"
/* When logging some stuff, we use this subcategory */
NSLOG_DECLARE_CATEGORY(interesting);
/* And when logging some other stuff, we use this subcategory */
NSLOG_DECLARE_CATEGORY(boring);
void libexample__hidden_func();
#endif
```
Finally let's have some libexample code:
```{.c}
/* Example Library source, src/libexample.c */
#include "hidden.h"
/* First up, lets realise the main category */
NSLOG_DEFINE_CATEGORY(libexample, "The example library for nslog");
void example_do_stuff(void)
{
/* Despite not having realised the categories here, we can use them */
NSLOG(interesting, INFO, "Did you know? Categories can be realised anywhere!");
libexample__hidden_func();
/* We can also log with the main category, despite it having subs */
NSLOG(libexample, INFO, "All done, good bye %s", "Mr Bond");
}
```
And because functionality may be spread among files:
```{.c}
/* Example Library source, src/hidden.c */
#include "hidden.h"
/* Lets define the subcategories, even though the main is elsewhere */
NSLOG_DEFINE_SUBCATEGORY(libexample, interesting, "Interesting things");
NSLOG_DEFINE_SUBCATEGORY(libexample, boring, "Boring stuff");
void libexample__hidden_func(void)
{
/* And here we can log with the main or sub categories at our leisure */
NSLOG(libexample, INFO, "Yay, top level stuff");
NSLOG(boring, DEBUG, "Boring debug number: %d", 18);
}
```
The above, compiled together with libnslog's headers, will result in a library.
The client application
======================
Since it's easy enough to do, we'll show a client application in a single file.
It ought to be well enough commented to be of use...
```{.c}
/* Example client application, main.c */
/* We use nslog */
#include "nslog/nslog.h"
/* As the client, we only get to see the public API of our library */
#include "libexample.h"
/* And we're using printf and friends */
#include <stdio.h>
#include <stdarg.h>
/* All client applications *MUST* have a render function.
* Ours is deliberately obnoxious in order to make things clear.
*/
static void
exampleapp__render_function(void *_ctx, nslog_entry_context_t *ctx,
const char *fmt, va_list args)
{
UNUSED(_ctx);
/* All the metadata about the log entry */
fprintf(stderr,
"EXAMPLE LOG MESSAGE:\n"
"Category name: %.*s\n",
"Category description: %s\n",
"Logging level: %s\n",
"Source location: %.*s (line %d function %.*s)\n",
ctx->category->namelen, ctx->category->name, ctx->category->description,
nslog_level_name(ctx->level),
ctx->filenamelen, ctx->filename, ctx->lineno, ctx->funcnamelen, ctx->funcname);
/* The log entry itself */
vfprintf(stderr, fmt, args);
/* Log entries aren't newline terminated, let's put a couple here for clarity */
fprintf(stderr, "\n\n");
}
/* All that's left is to cause code to run... */
int
main(int argc, char **argv)
{
UNUSED(argc);
UNUSED(argv);
/* One beauty of libnslog is that it allows logging before the client
* is nominally ready...
*/
example_do_stuff();
/* To make the client ready, we need to register our callback */
if (nslog_set_render_callback(exampleapp__render_function, NULL) != NSLOG_NO_ERROR) {
fprintf(stderr, "Unable to set render callback\n");
return 1;
}
/* Next we can uncork the log. This causes all previously logged
* messages to make their way out of our render function
*/
fprintf(stderr, "Before uncork...\n");
if (nslog_uncork() != NSLOG_NO_ERROR) {
fprintf(stderr, "Unable to uncork!\n");
return 2;
}
fprintf(stderr, "After uncork.\n");
/* And of course, we can log again... */
example_do_stuff();
/* We can set a filter, and since nslog knows all the categories, we
* are permitted to set filters on categories we can't directly access
* ourselves.
*/
nslog_filter_t *filter;
if (nslog_filter_from_text("cat:libexample/interesting", &filter) != NSLOG_NO_ERROR) {
fprintf(stderr, "Giving up, unable to parse filter.\n");
return 3;
}
/* We need to set that filter as the active filter to engage it */
if (nslog_filter_set_active(filter, NULL) != NSLOG_NO_ERROR) {
fprintf(stderr, "Unable to set active filter, stopping.\n");
return 4;
}
/* We don't need to hold on to our filter handle any longer */
filter = nslog_filter_unref(filter);
/* This time, only "interesting" log messages come through */
example_do_stuff();
/* We can remove the filter... */
if (nslog_filter_set_active(NULL, NULL) != NSLOG_NO_ERROR) {
fprintf(stderr, "Unable to clear active filter, stopping.\n");
return 4;
}
/* Finally, all log messages come through once more */
example_do_stuff();
/* and we're done */
return 0;
}
```
|