On 05/12/2011 08:57 AM, Jan Safranek 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 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).
>
> Signed-off-by: Jan Safranek<jsafr...@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..10b1248
> --- /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.
> + *
> + * @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 mis-use libcgroup for that purpose.
mis-use -> miss-use
> + * 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 45c1ded..cdfca0e 100644
> --- a/src/libcgroup-internal.h
> +++ b/src/libcgroup-internal.h
> @@ -58,12 +58,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_WARNING
> +
>   #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 fb30801..d7e56d9 100644
> --- a/src/libcgroup.map
> +++ b/src/libcgroup.map
> @@ -101,5 +101,9 @@ CGROUP_0.38 {
>          cgroup_get_subsys_mount_point_begin;
>          cgroup_get_subsys_mount_point_next;
>          cgroup_get_subsys_mount_point_end;
> +       cgroup_set_logger;
> +       cgroup_set_default_logger;
> +       cgroup_set_loglevel;
> +       cgroup_log;
>   } CGROUP_0.37;
>
> diff --git a/src/log.c b/src/log.c
> new file mode 100644
> index 0000000..8ca756c
> --- /dev/null
> +++ b/src/log.c
> @@ -0,0 +1,76 @@
> +/*
> + * Copyright Red Hat, Inc. 2011
> + *
> + * 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;
> +     }
> +}
>
>
> ------------------------------------------------------------------------------
> Achieve unprecedented app performance and reliability
> What every C/C++ and Fortran developer should know.
> Learn how Intel has extended the reach of its next-generation tools
> to help boost performance applications - inlcuding clusters.
> http://p.sf.net/sfu/intel-dev2devmay
> _______________________________________________
> Libcg-devel mailing list
> Libcg-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/libcg-devel


------------------------------------------------------------------------------
Achieve unprecedented app performance and reliability
What every C/C++ and Fortran developer should know.
Learn how Intel has extended the reach of its next-generation tools
to help boost performance applications - inlcuding clusters.
http://p.sf.net/sfu/intel-dev2devmay
_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to