On 02/07/2013 02:12 PM, Peter Schiffer wrote: > Whole new logging with following goals is here: > - more log levels. > - allow applications to log somewhere else than stdout using their custom > callback. > - provide simple stdout logger for 'lazy' applications. > > The logging is off by default, i.e. no message appears on stdout unless > application initializes the logging explicitly. But see following patches! > > Internally, nothing changes, cgroup_dbg is still working. In addition, > cgroup_err, cgroup_warn and cgroup_info appeared. Description what message > should use which log level is in doxygen info, together with new public API > incl. simple example, I won't copy it here > > Also the cgroup_log function is made public. I am not sure if it is the > right thing to do, but that's currently the simplest way how to use the > logging from our tools (which link only the public libcgroup API). > > Changelog: > - fixed typo in cgroup_log doxygen comment > > Signed-off-by: Peter Schiffer <pschi...@redhat.com> > --- > include/Makefile.am | 2 - > include/libcgroup.h | 1 > include/libcgroup/log.h | 138 > ++++++++++++++++++++++++++++++++++++++++++++++ > src/Makefile.am | 2 - > src/libcgroup-internal.h | 8 ++- > src/libcgroup.map | 4 + > src/log.c | 76 +++++++++++++++++++++++++ > 7 files changed, 228 insertions(+), 3 deletions(-) > create mode 100644 include/libcgroup/log.h > create mode 100644 src/log.c > > diff --git a/include/Makefile.am b/include/Makefile.am > index a7602a9..752a624 100644 > --- a/include/Makefile.am > +++ b/include/Makefile.am > @@ -1,2 +1,2 @@ > # Using 'nobase_', we what groups.h in /usr/include/libcgroup/ directory > -nobase_include_HEADERS = libcgroup.h libcgroup/error.h libcgroup/init.h > libcgroup/groups.h libcgroup/tasks.h libcgroup/iterators.h libcgroup/config.h > +nobase_include_HEADERS = libcgroup.h libcgroup/error.h libcgroup/init.h > libcgroup/groups.h libcgroup/tasks.h libcgroup/iterators.h libcgroup/config.h > libcgroup/log.h > diff --git a/include/libcgroup.h b/include/libcgroup.h > index 543bd13..1c7d409 100644 > --- a/include/libcgroup.h > +++ b/include/libcgroup.h > @@ -24,6 +24,7 @@ > #include <libcgroup/groups.h> > #include <libcgroup/tasks.h> > #include <libcgroup/config.h> > +#include <libcgroup/log.h> > > #undef _LIBCGROUP_H_INSIDE > > diff --git a/include/libcgroup/log.h b/include/libcgroup/log.h > new file mode 100644 > index 0000000..cd4f11d > --- /dev/null > +++ b/include/libcgroup/log.h > @@ -0,0 +1,138 @@ > +#ifndef _LIBCGROUP_LOG_H > +#define _LIBCGROUP_LOG_H > + > +#ifndef _LIBCGROUP_H_INSIDE > +#error "Only <libcgroup.h> should be included directly." > +#endif > + > +#ifndef SWIG > +#include <features.h> > +#endif > + > +#include <stdarg.h> > + > +__BEGIN_DECLS > + > +/** > + * @defgroup group_log 7. Logging > + * @{ > + * > + * @name Logging > + * @{ > + * Libcgroup allows applications to register a callback function which > + * libcgroup will call when it wants to log something. Each log message > + * has associated a log level. As described in previous chapter, most > libcgroup > + * functions return an error code, which described root cause of the failure > + * and log messages might provide further details about these failures and > other > + * notable events. > + * > + * @par > + * The logging callback can be set at any time, but setting the callback > before > + * any other libcgroup function (including cgroup_init()) is highly > recommended. > + * > + * @par Setting log level > + * Some of the functions below set the log level as integer. > + * Application can set directly a value of enum #cgroup_log_level or use > + * value <tt>-1</tt> to set the log level automatically. In this case, > libcgroup > + * inspects environment variable <tt>CGROUP_LOGLEVEL</tt> if it is set > + * and contains any of these values: <tt>ERROR</tt>, <tt>WARNING</tt>, > + * <tt>INFO</tt>, <tt>DEBUG</tt> or integer number representing value from > + * enum #cgroup_log_level. If <tt>CGROUP_LOGLEVEL</tt> is not set or its > value > + * is not valid, <tt>CGROUP_LOG_WARNING</tt> is set as default log level.
If I read the patches correctly, the default is now CGROUP_LOG_ERROR and not CGROUP_LOG_WARNING. Otherwise, Acked-By: Jan Safranek <jsafr...@redhat.com> > + * > + * @par Example: > + * Following short example shows custom libcgroup logger sending all log > + * messages to <tt>stderr</tt>: > + * @code > + * static void my_logger(void *userdata, int level, const char *fmt, va_list > ap) > + * { > + * vfprintf(stderr, fmt, ap); > + * } > + * > + * int main(int argc, char **argv) > + * { > + * int ret; > + * > + * cgroup_set_logger(my_logger, -1, NULL); > + * ret = cgroup_init(); > + * if (ret) { > + * ... > + * } > + * ... > + * @endcode > + */ > + > +/** > + * Level of importance of a log message. > + */ > +enum cgroup_log_level { > + /** > + * Something serious happened and libcgroup failed to perform requested > + * operation. > + */ > + CGROUP_LOG_ERROR = 1, > + /** > + * Something bad happened but libcgroup recovered from the error. > + */ > + CGROUP_LOG_WARNING, > + /** > + * Something interesting happened and the message might be useful to the > + * user. > + */ > + CGROUP_LOG_INFO, > + /** > + * Debugging messages useful to libcgroup developers. > + */ > + CGROUP_LOG_DEBUG, > +}; > + > +typedef void (*cgroup_logger_callback)(void *userdata, int level, > + const char *fmt, va_list ap); > + > +/** > + * Set libcgroup logging callback. All log messages with equal or lower log > + * level will be sent to the application's callback. There can be only > + * one callback logger set, the previous callback is replaced with the new > one > + * by calling this function. > + * Use NULL as the logger callback to completely disable libcgroup logging. > + * > + * @param logger The callback. > + * @param loglevel The log level. Use value -1 to automatically discover the > + * level from CGROUP_LOGLEVEL environment variable. > + * @param userdata Application's data which will be provided back to the > + * callback. > + */ > +extern void cgroup_set_logger(cgroup_logger_callback logger, int loglevel, > + void *userdata); > + > +/** > + * Set libcgroup logging to stdout. All messages with the given loglevel > + * or below will be sent to standard output. Previous logger set by > + * cgroup_set_logger() is replaced. > + * > + * @param loglevel The log level. Use value -1 to automatically discover the > + * level from CGROUP_LOGLEVEL environment variable. > + */ > +extern void cgroup_set_default_logger(int loglevel); > + > +/** > + * Change current loglevel. > + * @param loglevel The log level. Use value -1 to automatically discover the > + * level from CGROUP_LOGLEVEL environment variable. > + */ > +extern void cgroup_set_loglevel(int loglevel); > + > +/** > + * Libcgroup log function. This is for applications which are too lazy to set > + * up their own complex logging and miss-use libcgroup for that purpose. > + * I.e. this function should be used only by simple command-line tools. > + * This logging automatically benefits from CGROUP_LOGLEVEL env. variable. > + */ > +extern void cgroup_log(int loglevel, const char *fmt, ...); > +/** > + * @} > + * @} > + */ > +__END_DECLS > + > +#endif /* _LIBCGROUP_LOG_H */ > diff --git a/src/Makefile.am b/src/Makefile.am > index 18a2ef0..3a92d59 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -11,7 +11,7 @@ CLEANFILES = lex.c parse.c parse.h > > INCLUDES = -I$(top_srcdir)/include > lib_LTLIBRARIES = libcgroup.la > -libcgroup_la_SOURCES = parse.h parse.y lex.l api.c config.c > libcgroup-internal.h libcgroup.map wrapper.c > +libcgroup_la_SOURCES = parse.h parse.y lex.l api.c config.c > libcgroup-internal.h libcgroup.map wrapper.c log.c > libcgroup_la_LIBADD = -lpthread > libcgroup_la_LDFLAGS = -Wl,--version-script,$(srcdir)/libcgroup.map \ > -version-number > $(LIBRARY_VERSION_MAJOR):$(LIBRARY_VERSION_MINOR):$(LIBRARY_VERSION_RELEASE) > diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h > index dbb8e9a..47ee2ab 100644 > --- a/src/libcgroup-internal.h > +++ b/src/libcgroup-internal.h > @@ -61,12 +61,18 @@ __BEGIN_DECLS > #define CGROUP_RULE_MAXLINE (FILENAME_MAX + CGROUP_RULE_MAXKEY + \ > CG_CONTROLLER_MAX + 3) > > +#define cgroup_err(x...) cgroup_log(CGROUP_LOG_ERROR, x) > +#define cgroup_warn(x...) cgroup_log(CGROUP_LOG_WARNING, x) > +#define cgroup_info(x...) cgroup_log(CGROUP_LOG_INFO, x) > + > #ifdef CGROUP_DEBUG > -#define cgroup_dbg(x...) printf(x) > +#define cgroup_dbg(x...) cgroup_log(CGROUP_LOG_DEBUG, x) > #else > #define cgroup_dbg(x...) do {} while (0) > #endif > > +#define CGROUP_DEFAULT_LOGLEVEL CGROUP_LOG_ERROR > + > #define max(x,y) ((y)<(x)?(x):(y)) > #define min(x,y) ((y)>(x)?(x):(y)) > > diff --git a/src/libcgroup.map b/src/libcgroup.map > index b550a58..fc850b3 100644 > --- a/src/libcgroup.map > +++ b/src/libcgroup.map > @@ -110,4 +110,8 @@ CGROUP_0.39 { > cgroup_reload_cached_templates; > cgroup_init_templates_cache; > cgroup_config_create_template_group; > + cgroup_set_logger; > + cgroup_set_default_logger; > + cgroup_set_loglevel; > + cgroup_log; > } CGROUP_0.38; > diff --git a/src/log.c b/src/log.c > new file mode 100644 > index 0000000..d0a6854 > --- /dev/null > +++ b/src/log.c > @@ -0,0 +1,76 @@ > +/* > + * Copyright Red Hat, Inc. 2012 > + * > + * Author: Jan Safranek <jsafr...@redhat.com> > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of version 2.1 of the GNU Lesser General Public License > + * as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it would be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > + */ > + > +#include <libcgroup.h> > +#include <libcgroup-internal.h> > +#include <stdarg.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <errno.h> > + > +static cgroup_logger_callback cgroup_logger; > +static void *cgroup_logger_userdata; > +static int cgroup_loglevel; > + > +static void cgroup_default_logger(void *userdata, int level, const char *fmt, > + va_list ap) > +{ > + vfprintf(stdout, fmt, ap); > +} > + > +void cgroup_log(int level, const char *fmt, ...) > +{ > + va_list ap; > + > + if (!cgroup_logger) > + return; > + > + if (level > cgroup_loglevel) > + return; > + > + va_start(ap, fmt); > + cgroup_logger(cgroup_logger_userdata, level, fmt, ap); > + va_end(ap); > +} > + > +void cgroup_set_logger(cgroup_logger_callback logger, int loglevel, > + void *userdata) > +{ > + cgroup_logger = logger; > + cgroup_set_loglevel(loglevel); > + cgroup_logger_userdata = userdata; > +} > + > +void cgroup_set_default_logger(int level) > +{ > + if (!cgroup_logger) > + cgroup_set_logger(cgroup_default_logger, level, NULL); > +} > + > +void cgroup_set_loglevel(int loglevel) > +{ > + if (loglevel != -1) > + cgroup_loglevel = loglevel; > + else { > + char *level_str = getenv("CGROUP_LOGLEVEL"); > + if (level_str != NULL) > + /* > + * TODO: add better loglevel detection, e.g. strings > + * instead of plain numbers. > + */ > + cgroup_loglevel = atoi(level_str); > + else > + cgroup_loglevel = CGROUP_DEFAULT_LOGLEVEL; > + } > +} > > > ------------------------------------------------------------------------------ > Free Next-Gen Firewall Hardware Offer > Buy your Sophos next-gen firewall before the end March 2013 > and get the hardware for free! Learn more. > http://p.sf.net/sfu/sophos-d2d-feb > _______________________________________________ > Libcg-devel mailing list > Libcg-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/libcg-devel > ------------------------------------------------------------------------------ Free Next-Gen Firewall Hardware Offer Buy your Sophos next-gen firewall before the end March 2013 and get the hardware for free! Learn more. http://p.sf.net/sfu/sophos-d2d-feb _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel