Skip to content

Extend the logging facility to include additional information in messages #167

@ifakhrutdinov

Description

@ifakhrutdinov

Overview

At the moment there is a community requirement to prefix all the log messages with additional information like timestamp, line number, severity level, etc.

Here's an example

2019-03-19 11:23:57.776 <ZWEAGW1:threadInformation> userID INFO (locationInformation) ZWEA001I Message text

The existing logging facility has the ability to use a custom formatter but the caller cannot pass the context information to it (e.g. the line number). The purpose of this ticket is to discuss how we could re-factor/extend the code in logging.c to meet the new requirements while keeping backward compatibility.

Details

The current logging function has the following signature:

void zowelog(LoggingContext *context, uint64 compID, int level, char *formatString, ...);

One possible solution would be making this a macro and changing the original zowelog to have file name and line number arguments. The issues are: making this a macro may break existing code, the formatter (or log handler) will also have to change.

Possible fix 1

  • Define a new function, let's say zowelog2
void zowelog2(LoggingContext *context, uint64 compID, int level, void *userData, char *formatString, ...);
  • Define a new handler type
typedef void (*LogHandler2)(struct LoggingContext_tag *context,
                            LoggingComponent *component, 
                            void *componentData, // IF: set in existing logConfigureDestination or logConfigureDestination2
                            void *userData,      // IF: set in the new function logConfigureDestination3
                            char *formatString,
                            va_list argList);
  • LoggingDestination will need to have a new field - handler2
typedef struct LoggingDestination_tag{
  char   eyecatcher[8]; /* RSLOGDST */
  int    id;
  int    state;
  char  *name;
  void  *data;          /* used by destination to hold internal state */
  LogHandler handler;
  DataDumper dumper;
  LogHandler2 handler2;
} LoggingDestination;
  • zowelog2 will have the same implementation as zowelog except for the handler call
if (destination->handler2) {
  destination->handler2(context, component, destination->data, userData, formatString, argPointer);
} else {
  destination->handler(context, component, destination->data, formatString, argPointer);
}
  • Add a wrapper macro for zowelog2 which will actually pass __FILE__ and __LINE__
#define zowelogx(context, compID, level, formatString, ...) \
  do { \
    struct { \
      char *fileName; \
      int lineNnumber; \
    } fileAndLine = {__FILE__, __LINE__}; \
    zowelog2(context, compID, &fileAndLine, formatString, ##__VA_ARGS__); \
  } while (0)

Drawbacks of fix 1:

  • zowelogx will have to do some work before actually testing whether we need to log (hopefully the compiler can optimize the fileAndLine initialization
  • If the code with the old version of the loggin facility calls a shared library that uses the new one, the new code will try to check handler2 which doesn't exist in the old LoggingDestination in the caller code. We may possible carve out some bytes out of the LoggingDestination->eyecatcher field and create a flag or version field which could be tested by the new version.

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

Status

New

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions