From 50893cdaa29180e77836f311c4d3f6834dc586c1 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 14 Jan 2023 21:04:02 -0600 Subject: [PATCH 1/2] Don't allow both JSON and original iocsh registrations Log/print warning or error messages to explain what's wrong. Fixes GitHub issue #14 --- caPutLogApp/caPutJsonLogShellCommands.cpp | 52 +++++++++++++++++---- caPutLogApp/caPutLogAs.c | 2 + caPutLogApp/caPutLogShellCommands.c | 55 +++++++++++++++++++---- 3 files changed, 93 insertions(+), 16 deletions(-) diff --git a/caPutLogApp/caPutJsonLogShellCommands.cpp b/caPutLogApp/caPutJsonLogShellCommands.cpp index 1f271e0..047d3b1 100644 --- a/caPutLogApp/caPutJsonLogShellCommands.cpp +++ b/caPutLogApp/caPutJsonLogShellCommands.cpp @@ -11,12 +11,19 @@ * - Initial version */ +#include #include #include #include #include "caPutJsonLogTask.h" +// Use colored ERROR/WARNING text if available +#ifndef ERL_ERROR +# define ERL_ERROR "ERROR" +# define ERL_WARNING "WARNING" +#endif + /* EPICS iocsh shell commands */ extern "C" { @@ -35,7 +42,7 @@ extern "C" &caPutJsonLogInitArg0, &caPutJsonLogInitArg1 }; - static const iocshFuncDef caPutjsonLogInitDef = {"caPutJsonLogInit", 2, caPutJsonLogInitArgs}; + static const iocshFuncDef caPutJsonLogInitDef = {"caPutJsonLogInit", 2, caPutJsonLogInitArgs}; static void caPutJsonLogInitCall(const iocshArgBuf *args) { caPutJsonLogInit(args[0].sval, static_cast(args[1].ival)); @@ -76,17 +83,46 @@ extern "C" caPutJsonLogShow(args[0].ival); } + /* Error message if caPutLogInit used */ + static const iocshFuncDef caPutLogInitDef = {"caPutLogInit", 0, NULL}; + static void caPutLogInitCall(const iocshArgBuf *args) + { + fprintf(stderr, ERL_ERROR + ": The caPutLog module is configured for JSON put-logging,\n" + " only caPutJsonLog* commands are available. To use the plain\n" + " put-log format rebuild this IOC with 'caPutLog.dbd' instead\n" + " of 'caPutJsonLog.dbd'.\n"); + #ifdef IOCSHFUNCDEF_HAS_USAGE + iocshSetError(-1); + #endif + } - /* Register IOCsh commands */ + /* Register JSON IOCsh commands */ static void caPutJsonLogRegister(void) { - static int done = FALSE; - if(done) return; - done = TRUE; + extern int caPutLogRegisterDone; + + switch (caPutLogRegisterDone) { + case 0: + iocshRegister(&caPutJsonLogInitDef,caPutJsonLogInitCall); + iocshRegister(&caPutJsonLogReconfDef,caPutJsonLogReconfCall); + iocshRegister(&caPutJsonLogShowDef,caPutJsonLogShowCall); + iocshRegister(&caPutLogInitDef,caPutLogInitCall); + caPutLogRegisterDone = 2; + break; + + case 1: + errlogPrintf(ERL_WARNING + ": Registration of caPutJsonLog commands skipped, as\n" + " the caPutLog commands have already been registered.\n" + " This IOC may have been built with both 'caPutJsonLog.dbd'\n" + " and 'caPutLog.dbd', please rebuild it using only one.\n"); + break; - iocshRegister(&caPutjsonLogInitDef,caPutJsonLogInitCall); - iocshRegister(&caPutJsonLogReconfDef,caPutJsonLogReconfCall); - iocshRegister(&caPutJsonLogShowDef,caPutJsonLogShowCall); + case 2: + // Second registration, no problem + break; + } } epicsExportRegistrar(caPutJsonLogRegister); diff --git a/caPutLogApp/caPutLogAs.c b/caPutLogApp/caPutLogAs.c index efdae46..4b4b41d 100644 --- a/caPutLogApp/caPutLogAs.c +++ b/caPutLogApp/caPutLogAs.c @@ -62,6 +62,8 @@ #include "caPutLogTask.h" #include "caPutLogAs.h" +int caPutLogRegisterDone = 0; + static asTrapWriteId listenerId = 0; static void *logDataFreeList = 0; diff --git a/caPutLogApp/caPutLogShellCommands.c b/caPutLogApp/caPutLogShellCommands.c index 010fd57..5514d48 100644 --- a/caPutLogApp/caPutLogShellCommands.c +++ b/caPutLogApp/caPutLogShellCommands.c @@ -1,9 +1,18 @@ +#include + #include +#include #include #include #include "caPutLog.h" +/* Use colored ERROR/WARNING text if available */ +#ifndef ERL_ERROR +# define ERL_ERROR "ERROR" +# define ERL_WARNING "WARNING" +#endif + static const iocshArg caPutLogInitArg0 = {"address", iocshArgString}; static const iocshArg caPutLogInitArg1 = {"config", iocshArgInt}; static const iocshArg *const caPutLogInitArgs[] = { @@ -46,15 +55,45 @@ static void caPutLogSetTimeFmtCall(const iocshArgBuf *args) caPutLogSetTimeFmt(args[0].sval); } +/* Error message if caPutJsonLogInit used */ +static const iocshFuncDef caPutJsonLogInitDef = {"caPutJsonLogInit", 0, NULL}; +static void caPutJsonLogInitCall(const iocshArgBuf *args) +{ + fprintf(stderr, ERL_ERROR + ": The caPutLog module is configured for plain put-logging,\n" + " only caPutLog* commands are available. To use the new JSON\n" + " put-log format rebuild this IOC with 'caPutJsonLog.dbd'\n" + " instead of 'caPutLog.dbd'.\n"); + #ifdef IOCSHFUNCDEF_HAS_USAGE + iocshSetError(-1); + #endif +} + static void caPutLogRegister(void) { - static int done = FALSE; - - if(done) return; - done = TRUE; - iocshRegister(&caPutLogInitDef,caPutLogInitCall); - iocshRegister(&caPutLogReconfDef,caPutLogReconfCall); - iocshRegister(&caPutLogShowDef,caPutLogShowCall); - iocshRegister(&caPutLogSetTimeFmtDef,caPutLogSetTimeFmtCall); + extern int caPutLogRegisterDone; + + switch (caPutLogRegisterDone) { + case 0: + iocshRegister(&caPutLogInitDef,caPutLogInitCall); + iocshRegister(&caPutLogReconfDef,caPutLogReconfCall); + iocshRegister(&caPutLogShowDef,caPutLogShowCall); + iocshRegister(&caPutLogSetTimeFmtDef,caPutLogSetTimeFmtCall); + iocshRegister(&caPutJsonLogInitDef,caPutJsonLogInitCall); + caPutLogRegisterDone = 1; + break; + + case 1: + /* Second registration, no problem */ + break; + + case 2: + errlogPrintf(ERL_WARNING + ": Registration of caPutLog commands skipped, as\n" + " the caPutJsonLog commands have already been registered.\n" + " This IOC may have been built with both 'caPutJsonLog.dbd'\n" + " and 'caPutLog.dbd', please rebuild it using only one.\n"); + break; + } } epicsExportRegistrar(caPutLogRegister); From 5a7ff1ae87a23527ff6727fa9ce730d8de92f1dc Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 15 Jan 2023 01:00:11 -0600 Subject: [PATCH 2/2] Substantial documentation edits --- docs/index.rst | 348 ++++++++++++++++++++++++++---------------- docs/releasenotes.rst | 7 + 2 files changed, 224 insertions(+), 131 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index f1a6700..268640b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -17,203 +17,266 @@ use a different port. On the IOC side there are three routines to be called from the iocShell. See section `Setup`_ below for details. This module will send logs of CA puts in a text format to a remote logging -server. Currently, supports two output formats, ``standard`` and ``JSON``. -The Json format is only supported with `EPICS`_ base versions 7.0.1+. +server. Currently it supports two output formats, **Original** and **JSON**. +The JSON format is only supported with `EPICS`_ base versions 7.0.1 and later. Download -------- -You can download a release from the `Github releases`_:: page or get the +You can download a release from the `Github releases`_ page or get the latest development version via `Github`_:: git clone https://github.com/epics-modules/caPutLog.git You can also `browse`_ through the latest changes in the repo. -Compatibility matrix and release notes +Compatibility Matrix and Release Notes ++++++++++++++++++++++++++++++++++++++ +---------+------------------+------------------+ | Version | EPICS Release | Release Notes | +=========+==================+==================+ -| 4.0 | 3.14.12..7 | `R4-0`_ | +| 4.1 | 3.14.12 .. 7.0.x | `R4-1`_ | +---------+------------------+------------------+ -| 3.7 | | | +| 4.0 | 3.14.12 .. 7.0.x | `R4-0`_ | +---------+------------------+------------------+ -| 3.6 | | | +| 3.5 | 3.14.12 .. 3.15 | `R3-5`_ | +---------+------------------+------------------+ -| 3.5 | 3.14.12..3.15 | `R3-5`_ | +| 3.4 | 3.14.12 | `R3-4`_ | +---------+------------------+------------------+ -| 3.4 | 3.14.12 | `R3-4`_ | +| 3.3.3 | 3.14.12 | `R3-3-3`_ | +---------+------------------+------------------+ -| 3.3.3 | 3.14.12 | `R3-3-3`_ | +| 3.3.2 | 3.14.12 | `R3-3-2`_ | +---------+------------------+------------------+ -| 3.3.2 | 3.14.12 | `R3-3-2`_ | +| 3.3.1 | 3.14.12 | `R3-3-1`_ | +---------+------------------+------------------+ -| 3.3.1 | 3.14.12 | `R3-3-1`_ | +| 3.3 | 3.14.12 | `R3-3`_ | +---------+------------------+------------------+ -| 3.3 | 3.14.12 | `R3-3`_ | +| 3.2 | 3.14.11 | `R3-2`_ | +---------+------------------+------------------+ -| 3.2 | 3.14.11 | `R3-2`_ | +| 3.1 | 3.14.8.2 | `R3-1`_ | +---------+------------------+------------------+ -| 3.1 | 3.14.8.2 | `R3-1`_ | -+---------+------------------+------------------+ -| 3.0 | 3.14.8.2 | | +| 3.0 | 3.14.8.2 | | +---------+------------------+------------------+ Setup ----- -Build -+++++ +Build caPutLog +++++++++++++++ -Change the definition of ``EPICS_BASE`` in ``configure/RELEASE`` according to -the location of epics base on the host, then (gnu-)make. +Set the definition of ``EPICS_BASE`` in ``configure/RELEASE`` to point to +the Base installation to be used, then run ``make`` or ``gmake`` as normal to +compile the module. -Include to your EPICS application -+++++++++++++++++++++++++++++++++ +Add it to an EPICS application +++++++++++++++++++++++++++++++ -To include the module to your IOC application, add the install directory to your -application's ``configure/RELEASE``, and include ``dbd`` and ``lib`` in the -``src`` Makefile: :: +To build the module into an IOC application, add the install directory to the +application's ``configure/RELEASE`` file:: - _DBD += caPutLog.dbd # For standard format - _DBD += caPutJsonLog.dbd # For JSON format (Exists only if module is compiled with supported version of base) - _LIBS += caPutLog # Required for both output formats + CAPUTLOG = /path/to/caPutLog -for libraries to link. +Then in the IOC's ``src/Makefile`` choose one (but not both) of the two +published ``.dbd`` files to pick the logging format to use:: -Configure -+++++++++ + _DBD += caPutLog.dbd # For original format + _DBD += caPutJsonLog.dbd # For JSON format + +The ``caPutJsonLog.dbd`` file will only be available if the module was compiled +with a version of Base that supports it, 7.0.1 or later. IOCs should only be +built with one of the ``.dbd`` files, if both are included a warning will be +shown at registration time and only one set of commands for either the original +or JSON format logs will be registered with the IOC shell. + +Also in the IOC's ``src/Makefile`` add the module's library which the IOC must +be linked against:: -.. note:: Only one instance of the logger is supported to run at the time. + _LIBS += caPutLog # Required for either output format -In your IOC startup file add the following command for the standard output format:: + +Configure the IOC ++++++++++++++++++ + +.. note:: Only one logger instance may be running at a time (although it can + log to more than one log server at once), and the output format is fixed by + which of the two DBD files the IOC loaded. The format cannot be changed + without restarting and possibly rebuilding the IOC. + +In your IOC startup file add this command for logging using the original output +format:: caPutLogInit "host[:port]" [config] -or for JSON output format:: +or for the JSON output format:: caPutJsonLogInit "host[:port]" [config] -where ``host`` (mandatory argument) is the IP address or host name of the log -server and ``port`` is optional (the default is 7011). -To log to multiple hosts, either call the funtion with a space separated list like -``"host1[:port] host2[:port]"`` or call the function multiple times with different -hosts. +In both cases ``host`` is the IP address or host name of the log server and +``port`` is optional (the default is 7011). + +To log to multiple hosts, either provide the ``LogInit`` command with a space +separated list inside quotes like ``"host1[:port] host2[:port]"`` or run the +``LogInit`` command multiple times with a different host/port each time. -The environment variable ``EPICS_CA_PUT_LOG_ADDR`` / ``EPICS_CA_JSON_PUT_LOG_ADDR`` -is used if the first parameter to ``caPutLogInit`` / ``caPutJsonLogInit`` is ``NULL`` -or the empty string, respectively. +The environment variable ``EPICS_CA_PUT_LOG_ADDR`` / +``EPICS_CA_JSON_PUT_LOG_ADDR`` is used if the first parameter to +``caPutLogInit`` / ``caPutJsonLogInit`` is ``NULL``, an empty string ``""``, or +blank. The second (optional, default=0) argument should be one of: - ``-1`` - No logging (disabled) -- ``0`` - Log only on value change (ignore if old and new values are equal) -- ``1`` - Log all puts with burst filter +- ``0`` - Log only value changes (ignore puts of the samr value) +- ``1`` - Log all puts with a burst filter - ``2`` - Log all puts without any filters -Make sure access security is enabled on the IOC by providing a -suitable configuration file and load it with a call to -``asSetFilename()`` before iocInit. Your configuration file -should contain a TRAPWRITE rule. The following snippet can be used to -enable read/write access and write trapping for everyone (i.e. -unrestricted access):: +Access security must be enabled in the IOC by creating a suitable configuration +file and loading it with a call to ``asSetFilename()`` before +``iocInit``. The configuration file must contain a ``TRAPWRITE`` rule that will +match all records that are to have puts logged. The following snippet can be +used as an access security file that enables read/write access and put logging +for everyone to all records that don't have their ``ASG`` field set. This gives +unrestricted access to those records, and all puts to them will be logged:: ASG(DEFAULT) { RULE(1,READ) RULE(1,WRITE,TRAPWRITE) } -.. note:: ``caPutLogInit`` or ``caPutJsonLogInit`` are expecting access security - to be already running, so they must be called *after* iocInit. +.. note:: ``caPutLogInit`` or ``caPutJsonLogInit`` expect access security to be + active when they are executed, so they must be run *after* iocInit. -Other shell commands for logger are: +Other shell commands for controlling the logger are: ``caPutLogReconf config`` / ``caPutJsonLogReconf config`` - Change configuration on-line. The argument is the same as in - ``caPutLogInit`` / ``caPutJsonLogInit``. + + Change the logger configuration while it's already active. The ``config`` + argument has the same meaning as described for ``caPutLogInit`` / + ``caPutJsonLogInit`` above. ``caPutLogShow level`` / ``caPutJsonLogShow level`` - Show information about a running caPutLog, including config parameter. - level is the usual interest level (0, 1, or 2). -Server -++++++ + Show information about an active logger, including its current ``config`` + setting. ``level`` is the usual interest level (0, 1, or 2). + + +Set up a Log Server ++++++++++++++++++++ -For the server you can use the same executable as for the regular IOC log -server. You might want to start another instance with a different port, -though. However, you can also use the same log server instance (so that caput -log messages and regular IOC log messages go into the same log file). +For the server you can use the basic IOC log server that comes with EPICS Base, +but many newer log servers can also be configured to listen for connections to a +TCP socket and then accept text messages through that. A most standard server +will probably also be more convenient for viewing the log messages. +If your IOCs are already sending their error log messages to a log server you +might want to run another instance of it on a different port number to easily +distinguish the caput log messages. However you can use a single log server +instance and have caput log messages and regular IOC log messages all go into +the same log file or database. -Standard Log Format + +Original Log Format +++++++++++++++++++ -The iocLogServer precedes each line with these data:: +The EPICS iocLogServer starts each line in its log files with these data:: -After this comes the actual log message, which has this format:: +Other log servers may handle client and timestamp identification differently. + +The actual log message sent from the IOC has this format:: -