[PATCH 1/2] lib: add xml logging

Colin Ian King colin.king at canonical.com
Fri Jun 1 08:54:13 UTC 2012


On 01/06/12 09:21, Keng-Yu Lin wrote:
> On Fri, Jun 1, 2012 at 10:43 AM, IvanHu <ivan.hu at canonical.com> wrote:
>> On 05/28/2012 11:01 PM, Colin King wrote:
>>>
>>> From: Colin Ian King<colin.king at canonical.com>
>>>
>>> Signed-off-by: Colin Ian King<colin.king at canonical.com>
>>> ---
>>>   doc/fwts.1                   |    2 +-
>>>   src/lib/include/fwts_log.h   |    1 +
>>>   src/lib/src/Makefile.am      |    1 +
>>>   src/lib/src/fwts_framework.c |    4 +-
>>>   src/lib/src/fwts_log.c       |    3 +
>>>   src/lib/src/fwts_log_xml.c   |  186
>>> ++++++++++++++++++++++++++++++++++++++++++
>>>   6 files changed, 195 insertions(+), 2 deletions(-)
>>>   create mode 100644 src/lib/src/fwts_log_xml.c
>>>
>>> diff --git a/doc/fwts.1 b/doc/fwts.1
>>> index 0d773cd..09eee56 100644
>>> --- a/doc/fwts.1
>>> +++ b/doc/fwts.1
>>> @@ -150,7 +150,7 @@ specify the information in each log line. The
>>> following specifiers are available
>>>   e.g. \-\-log\-format="%date %time [%field] (%owner): "
>>>   .TP
>>>   .B \-\-log\-type
>>> -specify the log type. Currently plaintext and json log types are
>>> available and the
>>> +specify the log type. Currently plaintext, json and xml log types are
>>> available and the
>>>   default is plaintext.
>>>   .TP
>>>   .B \-\-lp\-tags
>>> diff --git a/src/lib/include/fwts_log.h b/src/lib/include/fwts_log.h
>>> index 8903bab..8027d41 100644
>>> --- a/src/lib/include/fwts_log.h
>>> +++ b/src/lib/include/fwts_log.h
>>> @@ -81,6 +81,7 @@ typedef struct fwts_log_ops_t {
>>>
>>>   fwts_log_ops fwts_log_plaintext_ops;
>>>   fwts_log_ops fwts_log_json_ops;
>>> +fwts_log_ops fwts_log_xml_ops;
>>>
>>>   extern fwts_log_field fwts_log_filter;
>>>   extern const char *fwts_log_format;
>>> diff --git a/src/lib/src/Makefile.am b/src/lib/src/Makefile.am
>>> index cae1f91..acea9cb 100644
>>> --- a/src/lib/src/Makefile.am
>>> +++ b/src/lib/src/Makefile.am
>>> @@ -39,6 +39,7 @@ libfwts_la_SOURCES = \
>>>         fwts_log.c \
>>>         fwts_log_plaintext.c \
>>>         fwts_log_json.c \
>>> +       fwts_log_xml.c \
>>>         fwts_memorymap.c \
>>>         fwts_microcode.c \
>>>         fwts_mmap.c \
>>> diff --git a/src/lib/src/fwts_framework.c b/src/lib/src/fwts_framework.c
>>> index 1fcd88e..2b42982 100644
>>> --- a/src/lib/src/fwts_framework.c
>>> +++ b/src/lib/src/fwts_framework.c
>>> @@ -76,7 +76,7 @@ static fwts_option fwts_framework_options[] = {
>>>         { "json-data-path",     "j:", 1, "Specify path to fwts json data
>>> files - default is /usr/share/fwts." },
>>>         { "lp-tags-log",        "",   0, "Output LaunchPad bug tags in
>>> results log." },
>>>         { "disassemble-aml",    "",   0, "Disassemble AML from DSDT and
>>> SSDT tables." },
>>> -       { "log-type",           "",   1, "Specify log type (plaintext or
>>> json)." },
>>> +       { "log-type",           "",   1, "Specify log type (plaintext,
>>> json or xml)." },
>>>         { NULL, NULL, 0, NULL }
>>>   };
>>>
>>> @@ -1040,6 +1040,8 @@ int fwts_framework_options_handler(fwts_framework
>>> *fw, int argc, char * const ar
>>>                                 fw->log_type = LOG_TYPE_PLAINTEXT;
>>>                         else if (!strcmp(optarg, "json"))
>>>                                 fw->log_type = LOG_TYPE_JSON;
>>> +                       else if (!strcmp(optarg, "xml"))
>>> +                               fw->log_type = LOG_TYPE_XML;
>>>                         else {
>>>                                 fprintf(stderr, "--log-type can be either
>>> plaintext or json.\n");
>>>                                 return FWTS_ERROR;
>>> diff --git a/src/lib/src/fwts_log.c b/src/lib/src/fwts_log.c
>>> index 5331fff..2b11441 100644
>>> --- a/src/lib/src/fwts_log.c
>>> +++ b/src/lib/src/fwts_log.c
>>> @@ -390,6 +390,9 @@ fwts_log *fwts_log_open(const char *owner, const char
>>> *name, const char *mode, f
>>>         case LOG_TYPE_PLAINTEXT:
>>>                 newlog->ops =&fwts_log_plaintext_ops;
>>>                 break;
>>> +       case LOG_TYPE_XML:
>>> +               newlog->ops =&fwts_log_xml_ops;
>>> +               break;
>>>         case LOG_TYPE_NONE:
>>>         default:
>>>                 newlog->ops =&fwts_log_plaintext_ops;
>>> diff --git a/src/lib/src/fwts_log_xml.c b/src/lib/src/fwts_log_xml.c
>>> new file mode 100644
>>> index 0000000..57b530b
>>> --- /dev/null
>>> +++ b/src/lib/src/fwts_log_xml.c
>>> @@ -0,0 +1,186 @@
>>> +/*
>>> + * Copyright (C) 2010-2012 Canonical
>>> + *
>>> + * This program is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU General Public License
>>> + * as published by the Free Software Foundation; either version 2
>>> + * of the License, or (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program; if not, write to the Free Software
>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>>> 02110-1301, USA.
>>> + *
>>> + */
>>> +
>>> +#include<stdlib.h>
>>> +#include<stdio.h>
>>> +#include<stdarg.h>
>>> +#include<string.h>
>>> +#include<unistd.h>
>>> +#include<sys/ioctl.h>
>>> +#include<time.h>
>>> +
>>> +#include "fwts.h"
>>> +
>>> +#define MAX_XML_STACK  (64)
>>> +#define XML_INDENT     (4)
>>> +
>>> +typedef struct {
>>> +       const char *name;
>>> +} fwts_log_xml_stack_t;
>>> +
>>> +static fwts_log_xml_stack_t xml_stack[MAX_XML_STACK];
>>> +static int xml_stack_index = 0;
>>> +
>>> +/*
>>> + *  fwts_log_vprintf_xml()
>>> + *     vprintf to a log
>>> + */
>>> +static int fwts_log_vprintf_xml(fwts_log *log,
>>> +       const fwts_log_field field,
>>> +       const fwts_log_level level,
>>> +       const char *status,
>>> +       const char *label,
>>> +       const char *prefix,
>>> +       const char *fmt,
>>> +       va_list args)
>>> +{
>>> +       char buffer[4096];
>>> +       struct tm tm;
>>> +       time_t now;
>>> +       char *str;
>>> +
>>> +       if (!((field&  LOG_FIELD_MASK)&  fwts_log_filter))
>>> +               return 0;
>>> +
>>> +       if (field&  (LOG_NEWLINE | LOG_SEPARATOR | LOG_DEBUG))
>>>
>>> +               return 0;
>>> +
>>> +       time(&now);
>>> +       localtime_r(&now,&tm);
>>> +
>>> +       fprintf(log->fp, "%*s<logentry>\n", xml_stack_index * XML_INDENT,
>>> "");
>>> +
>>> +       fprintf(log->fp, "%*s<line_num>%d</line_num>\n",
>>> +               (xml_stack_index + 1) * XML_INDENT,
>>> +               "", log->line_number);
>>> +
>>> +       fprintf(log->fp, "%*s<date>%2.2d/%2.2d/%-2.2d</date>\n",
>>> +               (xml_stack_index + 1) * XML_INDENT,
>>> +               "", tm.tm_mday, tm.tm_mon + 1, (tm.tm_year+1900) % 100);
>>> +
>>> +       fprintf(log->fp, "%*s<time>%2.2d:%2.2d:%2.2d</time>\n",
>>> +               (xml_stack_index + 1) * XML_INDENT,
>>> +               "", tm.tm_hour, tm.tm_min, tm.tm_sec);
>>> +
>>> +       fprintf(log->fp, "%*s<field_type>%s</field_type>\n",
>>> +               (xml_stack_index + 1) * XML_INDENT,
>>> +               "", fwts_log_field_to_str_full(field));
>>> +
>>> +       str = fwts_log_level_to_str(level);
>>> +       if (!strcmp(str, " "))
>>> +               str = "None";
>>> +
>>> +       fprintf(log->fp, "%*s<level>%s</level>\n",
>>> +               (xml_stack_index + 1) * XML_INDENT, "", str);
>>> +
>>> +       fprintf(log->fp, "%*s<status>%s</status>\n",
>>> +               (xml_stack_index + 1) * XML_INDENT,
>>> +               "", *status ? status : "None");
>>> +
>>> +       fprintf(log->fp, "%*s<failure_label>%s</failure_label>\n",
>>> +               (xml_stack_index + 1) * XML_INDENT,
>>> +               "", label&&  *label ? label : "None");
>>>
>>> +
>>> +       vsnprintf(buffer, sizeof(buffer), fmt, args);
>>> +       fprintf(log->fp, "%*s<log_text>%s</log_text>\n",
>>> +               (xml_stack_index + 1) * XML_INDENT,
>>> +               "", buffer);
>>> +
>>> +       fprintf(log->fp, "%*s</logentry>\n", xml_stack_index * XML_INDENT,
>>> "");
>>> +       fflush(log->fp);
>>> +
>>> +       log->line_number++;
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +/*
>>> + *  fwts_log_underline_xml()
>>> + *     write an underline across log, using character ch as the underline
>>> + */
>>> +static void fwts_log_underline_xml(fwts_log *log, const int ch)
>>> +{
>>> +       /* No-op for xml */
>>> +}
>>> +
>>> +/*
>>> + *  fwts_log_newline()
>>> + *     write newline to log
>>> + */
>>> +static void fwts_log_newline_xml(fwts_log *log)
>>> +{
>>> +       /* No-op for xml */
>>> +}
>>> +
>>> +static void fwts_log_section_begin_xml(fwts_log *log, const char *name)
>>> +{
>>> +       xml_stack[xml_stack_index].name = name;
>>> +
>>> +       fprintf(log->fp, "%*s<%s>\n", xml_stack_index * XML_INDENT, "",
>>> name);
>>> +       fflush(log->fp);
>>> +
>>> +       if (xml_stack_index<  MAX_XML_STACK)
>>> +               xml_stack_index++;
>>> +       else  {
>>> +               fprintf(stderr, "xml log stack overflow pushing section
>>> %s.\n", name);
>>> +               exit(EXIT_FAILURE);
>>> +       }
>>> +}
>>> +
>>> +static void fwts_log_section_end_xml(fwts_log *log)
>>> +{
>>> +       if (xml_stack_index>  0) {
>>> +               xml_stack_index--;
>>> +               fprintf(log->fp, "%*s</%s>\n", xml_stack_index *
>>> XML_INDENT,
>>> +                       "", xml_stack[xml_stack_index].name);
>>> +               fflush(log->fp);
>>> +       } else {
>>> +               fprintf(stderr, "xml log stack underflow.\n");
>>> +               exit(EXIT_FAILURE);
>>> +       }
>>> +
>>> +}
>>> +
>>> +static void fwts_log_open_xml(fwts_log *log)
>>> +{
>>> +       char *xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"
>>> ?>\n";
>>> +
>>> +       fwrite(xml_header, 1, strlen(xml_header), log->fp);
>>> +       fflush(log->fp);
>>> +
>>> +       fwts_log_section_begin_xml(log, "fwts");
>>> +}
>>> +
>>> +static void fwts_log_close_xml(fwts_log *log)
>>> +{
>>> +       fwts_log_section_end_xml(log);
>>> +
>>> +       fwrite("\n", 1, 1, log->fp);
>>> +       fflush(log->fp);
>>> +}
>>> +
>>> +fwts_log_ops fwts_log_xml_ops = {
>>> +       .vprintf =       fwts_log_vprintf_xml,
>>> +       .underline =     fwts_log_underline_xml,
>>> +       .newline =       fwts_log_newline_xml,
>>> +       .section_begin = fwts_log_section_begin_xml,
>>> +       .section_end   = fwts_log_section_end_xml,
>>> +       .open          = fwts_log_open_xml,
>>> +       .close         = fwts_log_close_xml
>>> +};
>>
>>
>> Hi Colin,
>>
>> I've checked the xml file(results.log). It seems that it doesn't close
>> properly (missing </tests> and </fwts>).
>> Except that, all looks good to me. Thanks!

Let me check why this is happening.

Colin
>>
>
> I formed another patch fixing this.
>






More information about the fwts-devel mailing list