From ab6f4940c40aadb976bf738ade21b6daa11a8156 Mon Sep 17 00:00:00 2001 From: Irek Fakhrutdinov Date: Wed, 20 Apr 2022 13:37:52 +0200 Subject: [PATCH] POC of formatting Fixes: zowe/zowe-common-c#167 and zowe/zss#437 --- c/logging.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++- h/logging.h | 28 ++++++++ 2 files changed, 208 insertions(+), 1 deletion(-) diff --git a/c/logging.c b/c/logging.c index 82561a5a9..b5aa42f48 100644 --- a/c/logging.c +++ b/c/logging.c @@ -26,7 +26,7 @@ #include #include #include - +#include #endif #include "zowetypes.h" @@ -36,6 +36,7 @@ #include "utils.h" #include "logging.h" #include "printables_for_dump.h" +#include "zos.h" #ifdef __ZOWE_OS_ZOS #include "le.h" @@ -455,6 +456,51 @@ LoggingDestination *logConfigureDestination2(LoggingContext *context, return destination; } +static LoggingDestination *getDestination(LoggingContext *context, + unsigned int id) { + + if (context == NULL) { + context = getLoggingContext(); + } + + LoggingDestination *destination = NULL; + int destinationID = id & 0xFFFF; + if (destinationID >= MAX_LOGGING_DESTINATIONS) { + return NULL; + } + + unsigned int vendorID = (id >> 16) & 0xFFFF; + if (vendorID == LOG_ZOWE_VENDOR_ID) { + destination = &context->zoweAnchor->destinations[destinationID]; + } else { + LoggingVendor *vendor = htUIntGet(context->vendorTable, vendorID); + if (vendor == NULL) { + vendor = makeVendor(vendorID); + htUIntPut(context->vendorTable, vendorID, vendor); + } + destination = &vendor->destinations[destinationID]; + } + + // TODO maybe handle the other states + if (destination->state == LOG_DESTINATION_STATE_INIT) { + return destination; + } + + return NULL; +} + +int logSetLogHandler2(LoggingContext *context, + unsigned int destinationID, + LogHandler2 handler2) { + LoggingDestination *destination = getDestination(context, destinationID); + if (destination == NULL) { + return -1; + } + + destination->handler2 = handler2; + return 0; +} + void printStdout(LoggingContext *context, LoggingComponent *component, void *data, char *formatString, va_list argList){ #ifdef METTLE printf("broken printf in logging.c\n"); @@ -471,6 +517,79 @@ void printStderr(LoggingContext *context, LoggingComponent *component, void *dat #endif } +static const char *getLogLevelName(int level) { + switch (level) { + case ZOWE_LOG_SEVERE: + return "SEVERE"; + // TODO what to do with ZOWE_LOG_ALWAYS? + case ZOWE_LOG_WARNING: + return "WARN"; + case ZOWE_LOG_INFO: + return "INFO"; + case ZOWE_LOG_DEBUG: + return "DEBUG"; + case ZOWE_LOG_DEBUG2: + return "DEBUG2"; + case ZOWE_LOG_DEBUG3: + return "DEBUG3"; + default: + return "N/A"; + } +} + +static char *printx(FILE *fd, + int level, + void *siteData, + char *formatString, + va_list argList) { +#ifdef METTLE + printf("broken printf in logging.c\n"); +#else + + LoggingSiteContext *siteContext = siteData; + + // TODO check for errors + time_t localTime; + struct tm gmt; + char workBuffer[50]; + time(&localTime); + char *timeStr = asctime_r(gmtime_r(&localTime, &gmt), workBuffer); + size_t timeStrLen = strlen(timeStr); + if (timeStrLen > 0) { + timeStr[timeStrLen - 1] = '\0'; + } + + TCB *tcb = getTCB(); + const char *user = &getCurrentACEE()->aceeuser[1]; + unsigned char userLen = getCurrentACEE()->aceeuser[0]; + const char *logLevel = getLogLevelName(level); + + fprintf(fd, "%s %.*s %s ", timeStr, tcb, userLen, user, logLevel); + vfprintf(fd, formatString, argList); + +#endif +}; + +void printStdoutx(LoggingContext *context, + LoggingComponent *component, + int level, + void *componentData, + void *userData, + char *formatString, + va_list argList) { + printx(stdout, level, userData, formatString, argList); +} + +void printStderrx(LoggingContext *context, + LoggingComponent *component, + int level, + void *componentData, + void *userData, + char *formatString, + va_list argList) { + printx(stderr, level, userData, formatString, argList); +} + void logConfigureStandardDestinations(LoggingContext *context){ if (context == NULL) { context = getLoggingContext(); @@ -478,6 +597,8 @@ void logConfigureStandardDestinations(LoggingContext *context){ logConfigureDestination(context,LOG_DEST_DEV_NULL,"/dev/null",NULL,NULL); logConfigureDestination(context,LOG_DEST_PRINTF_STDOUT,"printf(stdout)",NULL,printStdout); logConfigureDestination(context,LOG_DEST_PRINTF_STDERR,"printf(stderr)",NULL,printStderr); + logSetLogHandler2(context, LOG_DEST_PRINTF_STDOUT, printStdoutx); + logSetLogHandler2(context, LOG_DEST_PRINTF_STDERR, printStderrx); } void logConfigureComponent(LoggingContext *context, uint64 compID, char *compName, int destination, int level){ @@ -695,6 +816,64 @@ void zowelog(LoggingContext *context, uint64 compID, int level, char *formatStri } +void zowelog2(LoggingContext *context, uint64 compID, int level, void *userData, + char *formatString, ...) { + + if (logShouldTrace(context, compID, level) == FALSE) { + return; + } + + if (context == NULL) { + context = getLoggingContext(); + } + + int maxDetailLevel = 0; + LoggingComponent *component = getComponent(context, compID, &maxDetailLevel); + if (component == NULL) { + return; + } + + if (maxDetailLevel >= level) { + + LoggingDestination *destination = + &getDestinationTable(context, compID)[component->destination]; + if (component->destination >= MAX_LOGGING_DESTINATIONS) { + char message[128]; + sprintf(message, "Destination %d is out of range (log)\n", + component->destination); + lastResortLog(message); + return; + } else if (component->destination == 0 && + destination->state != LOG_DESTINATION_STATE_UNINITIALIZED) { + /* silently do nothing, /dev/null is always destination 0 and always does nothing */ + printf("dev/null case\n"); + return; + } + + if (destination->state == LOG_DESTINATION_STATE_UNINITIALIZED) { + char message[128]; + sprintf(message, "Destination %d is not initialized for logging\n", + component->destination); + lastResortLog(message); + return; + } + + /* here, pass to a var-args handler */ + va_list argPointer; + va_start(argPointer, formatString); + if (destination->handler2) { + destination->handler2(context, component, level, destination->data, + userData, formatString, argPointer); + } else { + destination->handler(context, component, destination->data, formatString, + argPointer); + } + va_end(argPointer); + + } + +} + static void printToDestination(LoggingDestination *destination, struct LoggingContext_tag *context, LoggingComponent *component, diff --git a/h/logging.h b/h/logging.h index 3d4f71c26..703e09a62 100644 --- a/h/logging.h +++ b/h/logging.h @@ -138,6 +138,14 @@ typedef void (*LogHandler)(struct LoggingContext_tag *context, va_list argList); typedef char *(*DataDumper)(char *workBuffer, int workBufferSize, void *data, int dataSize, int lineNumber); +typedef void (*LogHandler2)(struct LoggingContext_tag *context, + LoggingComponent *component, + int level, + void *componentData, // IF: set in existing logConfigureDestination or logConfigureDestination2 + void *userData, // IF: set in the new function logConfigureDestination3 + char *formatString, + va_list argList); + ZOWE_PRAGMA_PACK typedef struct LoggingDestination_tag{ @@ -148,6 +156,7 @@ typedef struct LoggingDestination_tag{ void *data; /* used by destination to hold internal state */ LogHandler handler; DataDumper dumper; + LogHandler2 handler2; } LoggingDestination; #define MAX_LOGGING_COMPONENTS 256 @@ -256,6 +265,7 @@ extern LoggingContext *theLoggingContext; #define setLoggingContext STLOGCTX #define logConfigureDestination LGCFGDST #define logConfigureDestination2 LGCFGDS2 +#define logSetLogHandler2 LGSETHD2 #define logConfigureStandardDestinations LGCFGSTD #define logConfigureComponent LGCFGCMP #define logShouldTraceInternal LGSHTRCE @@ -333,6 +343,20 @@ bool logShouldTraceInternal(LoggingContext *context, uint64 componentID, int lev void zowelog(LoggingContext *context, uint64 compID, int level, char *formatString, ...); void zowedump(LoggingContext *context, uint64 compID, int level, void *data, int dataSize); +void zowelog2(LoggingContext *context, uint64 compID, int level, void *userData, + char *formatString, ...); + +typedef struct LoggingSiteContext_tag { + char *fileName; + int lineNumber; +} LoggingSiteContext; + +#define zowelogx(context, compID, level, formatString, ...) \ + do { \ + zowelog2(context, compID, level, &(LoggingSiteContext){__FILE__, __LINE__}, \ + formatString, ##__VA_ARGS__); \ + } while (0) + #define LOGCHECK(context,component,level) \ ((component > MAX_LOGGING_COMPONENTS) ? \ (context->applicationComponents[component].level >= level) : \ @@ -351,6 +375,10 @@ LoggingDestination *logConfigureDestination2(LoggingContext *context, LogHandler handler, DataDumper dumper); +int logSetLogHandler2(LoggingContext *context, + unsigned int destinationID, + LogHandler2 handler2); + void logConfigureStandardDestinations(LoggingContext *context); void logConfigureComponent(LoggingContext *context, uint64 compID,