Friday, June 5, 2020

Custom Severity Levels with Pantheios C/C++ project

Been a bit of demand for this one, so here we go, in as few words as possible.

Stock Severity Levels

Out of the box, up to the present version (1.0.1 beta 218) the Pantheios C/C++ library comes with eight stock severity levels, as follows:


Manifest constantIntegral valueString form (1)
PANTHEIOS_SEV_EMERGENCY0"Emergency"
PANTHEIOS_SEV_ALERT1"Alert"
PANTHEIOS_SEV_CRITICAL2"Critical"
PANTHEIOS_SEV_ERROR3"Error"
PANTHEIOS_SEV_WARNING4"Warning"
PANTHEIOS_SEV_NOTICE5"Notice"
PANTHEIOS_SEV_INFORMATIONAL   6"Informational"   
PANTHEIOS_SEV_DEBUG7"Debug"

1. as obtained by pantheios_getStockSeverityString()

These are defined in the file pantheios/pantheios.h and are available for both C and C++ compilation units. Additionally, for C++ compilation units the following pseudo-constants are available:


C++ pseudo-constant (2)Integral ValueCorresponding constant
pantheios::emergency0PANTHEIOS_SEV_EMERGENCY
pantheios::alert1PANTHEIOS_SEV_ALERT
pantheios::critical2PANTHEIOS_SEV_CRITICAL
pantheios::error3PANTHEIOS_SEV_ERROR
pantheios::warning4PANTHEIOS_SEV_WARNING
pantheios::notice5PANTHEIOS_SEV_NOTICE
pantheios::informational   6PANTHEIOS_SEV_INFORMATIONAL
pantheios::debug7PANTHEIOS_SEV_DEBUG

2. these are defined 

These C++-only pseudo-constants also facilitate easily the use of extended severity information, but that's a topic for another time.

The string forms' C-style strings and string lengths are obtained, respectively, via the pantheios_getStockSeverityString() and pantheios_getStockSeverityStringLength() API functions.

Custom Severity Levels

If you want to use a different set of severities, then you must do the following:
  1. #define the preprocessor symbol PANTHEIOS_NO_STOCK_LEVELS;
  2. link to a back-end of your own that understands your custom severity levels.

Here's a C-program illustrating how to do this (with as much detail as possible elided for brevity):



#define PANTHEIOS_NO_STOCK_LEVELS /* suppress stock severity levels */

#include ⟨pantheios/pantheios.h⟩

/* some log4j-like levels */

enum CustomSeverityLevel_t
{
  CSL_Fatal = 0,
  CSL_Error = 3,
  CSL_Warn  = 4,
  CSL_Info  = 6,
  CSL_Debug = 7,
};

/* the application */

int main()
{
  int retCode = EXIT_SUCCESS;
  int res;

  res = pantheios_init();

  if(0 != res)
  {
    fprintf(stderr, "Failed to initialise the Pantheios libraries: %s\n", pantheios_getInitCodeString(res));

    retCode = EXIT_FAILURE;
  }
  else
  {
    pantheios_logputs(CSL_Info, PANTHEIOS_LITERAL_STRING("pantheios_logputs() can output a single C-style string"));


    . . . //rest of program logic, including more pantheios_logputs() / pantheios_logprintf() statements


    pantheios_uninit();
  }

  return retCode;
}

/* the custom back-end */

#include ⟨pantheios/backend.h⟩
#include ⟨pantheios/init_codes.h⟩
#include ⟨pantheios/strdup.h⟩

PANTHEIOS_CALL(int) pantheios_be_init(
  PAN_CHAR_T const* processIdentity
, void*             reserved
, void**            ptoken
)
{
  ((void)reserved);

  *ptoken = pantheios_util_strdup_nothrow(processIdentity);

  return (NULL == *ptoken) ? PANTHEIOS_INIT_RC_OUT_OF_MEMORY : PANTHEIOS_INIT_RC_SUCCESS;
}

PANTHEIOS_CALL(void) pantheios_be_uninit(void *token)
{
  pantheios_util_strfree((PAN_CHAR_T*)(token));
}

PANTHEIOS_CALL(int) pantheios_be_logEntry(  
  void*             feToken
, void*             beToken
, int               severity
, PAN_CHAR_T const* entry
, size_t            cchEntry
)
{
  PAN_CHAR_T const* sevString;
  PAN_CHAR_T const* processId = (PAN_CHAR_T const*)(beToken);

  ((void)feToken);

  switch (severity)
  {
  case CSL_Fatal:
    sevString = PANTHEIOS_LITERAL_STRING("Fatal");
    break;
  case CSL_Error:
    sevString = PANTHEIOS_LITERAL_STRING("Error");
    break;
  case CSL_Warn:
    sevString = PANTHEIOS_LITERAL_STRING("Warn");
    break;
  case CSL_Info:
    sevString = PANTHEIOS_LITERAL_STRING("Info");
    break;
  case CSL_Debug:
    sevString = PANTHEIOS_LITERAL_STRING("Debug");
    break;
  default:
    sevString = PANTHEIOS_LITERAL_STRING("");
    break;
  }

#ifdef PANTHEIOS_USE_WIDE_STRINGS
  return fwprintf(
        stderr
      , L"[%s; %s]: %.*s\n"
      , processId
      , sevString
      , (int)cchEntry, entry
      );
#else /* ? PANTHEIOS_USE_WIDE_STRINGS */
  return fprintf(
        stderr
      , "[%s; %s]: %.*s\n"
      , processId
      , sevString
      , (int)cchEntry, entry
      );
#endif /* PANTHEIOS_USE_WIDE_STRINGS */
}

No comments:

Post a Comment