{"id":153,"date":"2022-02-01T20:53:14","date_gmt":"2022-02-01T20:53:14","guid":{"rendered":"https:\/\/akicom.de\/?p=153"},"modified":"2022-02-05T12:38:35","modified_gmt":"2022-02-05T12:38:35","slug":"protokollgruesse-aus-der-datenbank-logging-aus-pl-sql","status":"publish","type":"post","link":"https:\/\/akicom.de\/?p=153","title":{"rendered":"Protokollgr\u00fcsse aus der Datenbank  &#8211; Logging aus  PL\/SQL"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"188\" src=\"https:\/\/akicom.de\/wp-content\/uploads\/2022\/01\/greetings_from_database-1024x188.jpg\" alt=\"\" class=\"wp-image-156\" srcset=\"https:\/\/akicom.de\/wp-content\/uploads\/2022\/01\/greetings_from_database-1024x188.jpg 1024w, https:\/\/akicom.de\/wp-content\/uploads\/2022\/01\/greetings_from_database-300x55.jpg 300w, https:\/\/akicom.de\/wp-content\/uploads\/2022\/01\/greetings_from_database-768x141.jpg 768w, https:\/\/akicom.de\/wp-content\/uploads\/2022\/01\/greetings_from_database.jpg 1080w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-drop-cap\">Datenbanken sind ja dazu da, Daten zu speichern. Die Daten werden in irgendeiner Form verarbeitet. Das kann sein vor dem Speichern in der Datenbank, in dem die Daten von anderen Systemen zusammengesammelt und &#8211; gestellt werden und dann in die Datenbank geladen werden. Es kann auch sein, dass die Daten innerhalb der Daten weiter verarbeitet, z.B. aggregiert, werden. Diese Verarbeitung \u00fcbernimmt ein Batch, der vorzugsweise nachts  l\u00e4uft und im Idealfall f\u00fcr vor den B\u00fcrozeiten beendet ist, so dass p\u00fcnktlich zum Arbeitsbeginn die akteullen Daten zur Verf\u00fcgung stehen.<\/p>\n\n\n\n<p class=\"has-drop-cap\">So ein Batch kann aus verschiedenen Scripten auf unterschiedlichen Servern bestehen, aber auch aus einem Script innerhalb der Datenbank. Das k\u00f6nnen SQL-Scripte sein, aber auch Programmcode, also in ORACLE&#8217;s Programmiersprache PL\/SQL geschrieben.<br>Wichtig f\u00fcr so ein Batch sind Protokolle \u00fcber den Ablauf. Darin kann der DevOps-Engineer sehen, ob alles fehlerfrei verarbeitet wurde, wie lange der Batch gedauert usw. <\/p>\n\n\n\n<p class=\"has-drop-cap\">Protokollieren ist in einem Shellscript sehr einfach, man lenkt  echo-Ausgaben zwischen den verarbeitenden Scritten in ein Logfile aus &#8211; fertig.  <br>Aber wie geht das aus der Datenbank heraus? Im Normalfall, startet man sqlplus und f\u00fcr darin entweder ein SQL-Script, also irgendwelche Insert-Update-Delete-Sequenzen, aus oder man startet ein PL\/SQL-Schnipsel, entweder als stored procedure oder function &#8211; standalone oder in einem Package hinterlegt &#8211; oder als anonymen Block. Die Ausgaben bei solchen Scripten sind nur soundsoviel Rows inserted, updated oder deleted oder &#8222;function (oder procedure) successful finished oder es gab irgendeinen Fehler. <\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"673\" height=\"517\" src=\"https:\/\/akicom.de\/wp-content\/uploads\/2022\/01\/grafik-1.png\" alt=\"\" class=\"wp-image-207\" srcset=\"https:\/\/akicom.de\/wp-content\/uploads\/2022\/01\/grafik-1.png 673w, https:\/\/akicom.de\/wp-content\/uploads\/2022\/01\/grafik-1-300x230.png 300w\" sizes=\"(max-width: 673px) 100vw, 673px\" \/><figcaption>Log-Eintr\u00e4ge beim Ausf\u00fchren eines Scripts in sqlplus<\/figcaption><\/figure>\n\n\n\n<p class=\"has-drop-cap\">F\u00fcr SQL-Scripts mag das vielleicht reichen, aber bei der Ausf\u00fchrung von etwas komplexeren PL\/SQL-Objekten m\u00f6chte man schon wissen, was gerade wie verarbeitet wurde oder wo die Verarbeitung gerade steht usw.<br>D.h. man braucht Funktionen oder Prozeduren, die im PL\/SQL-Code aufgerufen werden. <br>Man k\u00f6nnte DBMS_OUTPUT verwenden.Allerdings w\u00fcrde dann alles in der sqlplus-Session ausgegeben werden. Und nicht alle Datentypen k\u00f6nnen mit DBMS_OUTPUT  ausgegeben werden. Und wenn man nicht die richtigen Einstellungen hat, sind die Ausgaben futsch. Das Gleiche gilt f\u00fcr Ausgaben in Prozeduren, die als Job ausgef\u00fchrt werden.<\/p>\n\n\n\n<p class=\"has-drop-cap\">Deswegen musste ich mir etwas anderes \u00fcberlegen, und dabei ist der logFileMgr entstanden. Dies ist ein Package, mit dem man in definierte Logfiles, die irgendwo auf dem Datenbankserver liegen k\u00f6nnen, schreiben kann. Zus\u00e4tzlich kann man seine Ausgaben in verschiedene Log Levels unterteilen, je nach Bedeutung der Ausgabe und \u00e4hnlich den Log Levels in Linux:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Level 1 &#8211; &#8222;alert&#8220;  <\/li><li>Level 2 &#8211; &#8222;critical&#8220;<\/li><li>Level 3 &#8211; &#8222;error&#8220;<\/li><li>Level 4 &#8211; &#8222;warning&#8220;<\/li><li>Level 5 &#8211; &#8222;notice&#8220;<\/li><li>Level 6 &#8211; &#8222;information&#8220;<\/li><li>Level 7 &#8211; &#8222;debug&#8220;<\/li><\/ul>\n\n\n\n<p class=\"has-drop-cap\">Level-1-Meldungen sind also Meldungen, die schwerwiegende Fehlerzust\u00e4nde anzeigen, Level-7-Meldungen sind daf\u00fcr da, um Debugmeldungen auszugeben. <br>Nun kann man f\u00fcr einen PL\/SQL-Prozedur-Lauf in einem Konfigurationsfile ein Log Level angeben, z.B: 4 (warning). Damit werden alle Protokollausgaben gr\u00f6sser als 4 ignoriert, alle Ausgaben mit einem Log Level kleiner oder gleich 4 werden ausgegeben. Auf diese Art und Weise ist es nun m\u00f6glich, Stored Procedures zu entwickeln, die alle Ausgaben von kritisch bis Debug enthalten. Der DevOps-Engineer, der den Betrieb verantwortet, kann nun den f\u00fcr ihn im Betrieb ausreichenden Log Level in der Konfiguration setzen, z.B. 5 (notice). Sollte es beim Ausf\u00fchren der Prozedur zu Fehlern kommen, kann der Log Level einfach auf 7 (debug) gesetzt und anhand der nun ausgegebenen Debug-Informationen der Fehler gesucht werden.<\/p>\n\n\n\n<p class=\"has-drop-cap\">Die Konfigurationsdatei, in der man die Logfiles und das Ausgabeverhalten beschreibt, kann ebenfalls irgendwo auf dem Datenbankserver, egal ob UNIX\/Linux oder Windows, abgelegt werden.<\/p>\n\n\n<pre class=\"brush: plain; title: Konfigurationsdatei f\u00fcr das Logging; notranslate\" title=\"Konfigurationsdatei f\u00fcr das Logging\">###################################\n#  Description:\n#  ============\n#  Example for a Log Configuration\n#\n#   File:            logging.cfg\n#   Author:          Andy Kielhorn\n#   Company:         AkiCom\n###################################\n#\n# Logging for PL\/SQL batch TESTLOG\n#\nTESTLOG_LOGLEVEL=7\nTESTLOG_LOGFILE=\/opt\/oracle\/admin\/log\/testlog.log\nTESTLOG_LOGFORMAT=ALL\n#\n# Logging for PL\/SQL module WATCHDOG\n#\nWATCHDOG_LOGLEVEL=4\nWATCHDOG_LOGFILE=\/opt\/watchdog\/log\/watchDogDeamon.log\nWATCHDOG_LOGFORMAT=ALL<\/pre>\n\n\n\n<p>Die Datei kann mehrere Konfigurationen f\u00fcr verschiedene PL\/SQL-&#8222;Batches&#8220; enthalten. Pro &#8222;Batch&#8220; oder Modul gibt es drei Parameter, die immer mit dem Namen des Batches oder dem Modul beginnen.<\/p>\n\n\n\n<p><strong><span style=\"text-decoration: underline;\">Log Level<\/span><\/strong><\/p>\n\n\n\n<p>Mit dem Parameter der Form <strong>&lt;Modulname&gt;_LOGLEVEL= [1|2|3|4|5|6|7] <\/strong>stellt man den Log Level ein. D.h. wie schon beschrieben, es werden alle Ausgaben mit einem Log Level, der kleiner oder gleich dem hier angegebenen ist, ausgegeben. <\/p>\n\n\n\n<p><strong><span style=\"text-decoration: underline;\">Logfile<\/span><\/strong><\/p>\n\n\n\n<p>Mit dem Parameter der Form <strong>&lt;Modulname&gt;_LOGFILE=&lt;Log File mit Pfad&gt;<\/strong> gibt man den Namen und den Speicherort des Logfiles auf dem Server an.<\/p>\n\n\n\n<p><strong><span style=\"text-decoration: underline;\">Logformat<\/span><\/strong><\/p>\n\n\n\n<p>Der Parameter <br><strong>&lt;Modulname&gt;_LOGFORMAT=[ALL|NAME|TIME|HOUR|DAY|SHORT] <\/strong>gibt das Ausgabeformat f\u00fcr den Zeitstempel auf der linken Seite der Ausgabe fest<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"554\" src=\"https:\/\/akicom.de\/wp-content\/uploads\/2022\/02\/grafik-2-1024x554.png\" alt=\"\" class=\"wp-image-252\" srcset=\"https:\/\/akicom.de\/wp-content\/uploads\/2022\/02\/grafik-2-1024x554.png 1024w, https:\/\/akicom.de\/wp-content\/uploads\/2022\/02\/grafik-2-300x162.png 300w, https:\/\/akicom.de\/wp-content\/uploads\/2022\/02\/grafik-2-768x416.png 768w, https:\/\/akicom.de\/wp-content\/uploads\/2022\/02\/grafik-2.png 1205w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>Log-Ausgaben mit logFileMgr<\/figcaption><\/figure>\n\n\n\n<p>Bei Logformat NAME wird kein Zeitstempel ausgegeben, bei HOUR und SHORT wird kein Datum ausgegeben, w\u00e4hrend bei DAY die Uhrzeit fehlt.<\/p>\n\n\n\n<p class=\"has-drop-cap\">Um das Logging zu starten muss die Funktion logInit aufgerufen werden, dabei muss der Pfad zur Konfigurationsdatei, der Name der Konfigurationsdatei und der Name des Moduls, dessen Konfiguration geladen werden soll. Danach stehen verschiedene writeLog-Prozeduren zur Verf\u00fcgung, mit denen man Log-Eintr\u00e4ge in der Protokolldatei erzeugen kann. Zu dem gibt es noch eine Prozedur raiseError, die einen Log-Eintrag erzugt und danach einen Fehler &#8222;raised&#8220;.<\/p>\n\n\n\n<p>Alle Log Level sowie alle Log-Formate sind als Konstanten in der Package Spezifikation hinterlegt. <\/p>\n\n\n<pre class=\"brush: sql; collapse: false; first-line: 1; gutter: true; title: Package Spezifikation von logFileMgr; toolbar: true; notranslate\" title=\"Package Spezifikation von logFileMgr\">CREATE OR REPLACE PACKAGE logFileMgr IS\n   \/* *****************************************************************************\n   * Description\n   * ============\n   *  This package enables logging in UNIX files system\n   *\n   *   File:          pkg_akitools_logfilemgr_ph.sql\n   *   Modified at:   $Date: 2020-01-01 08:00:00 +0200 (Mi, 01 Jan 2020) $\n   *   Checked in by: $Author: AKielhorn $\n   *   Revision:      $Revision: 100 $\n   *   Author:        Andy Kielhorn\n   *   Company:       AkiCom\n   *****************************************************************************\n   *\/\n   \n   \/* ====================================================================================\n                                         Constants\n     =====================================================================================\n\n      ************************************************************************************\n                                 L O G G I N G L E V E L S                               \n       The logging system introduces different levels (logging levels) of the protocol \n       scope. These are based on the logging levels of the operating system Linux and \n       are defined in the following.\n       It applies that all messages will be written to logfile that correspond to the \n       set level and the one below it. \n       For example you set Level 4, so all messages from level 1 to level 4 will be \n       writtento logfile                   \n      ************************************************************************************\n\n      Level 1  - &quot;alert&quot;\n\n       With this logging level, a module only outputs messages that are acted upon \n       immediately otherwise the system will suffer a production standstill.\n       This message must be forwarded to the person responsible for the system \n       immediately. \n   *\/\n   c_alert CONSTANT PLS_INTEGER := 1;\n   \n   \/* Level 2 - &quot;critical&quot;\n\n      Messages of this logging level indicate a critical status.\n      Here, too, the person responsible for the system should be informed.\n   *\/\n   c_critical CONSTANT PLS_INTEGER := 2;\n   \n   \/* Level 3 - &quot;error&quot;\n\n      Messages with this logging level log errors in a module.\n   *\/\n   c_error CONSTANT PLS_INTEGER := 3;\n   \n   \/* Level 4 - &quot;warning&quot;\n\n     The messages classified by the module as warnings are logged here.\n   *\/\n   c_warning CONSTANT PLS_INTEGER := 4;\n   \n   \/* Level 5 - &quot;notice&quot;\n\n      In this level, normal but important information of the modules are logged\n   *\/\n   c_notice CONSTANT PLS_INTEGER := 5;\n   \n   \/* Level 6 - &quot;information&quot;\n\n      This level denotes simple information of no major importance, which\n      can also be ignored.\n   *\/\n   c_info CONSTANT PLS_INTEGER := 6;\n   \n   \/* Level 7 - &quot;debug&quot;\n\n      Debug messages are the least relevant messages and are the most important\n      for checking freshly written software for possible errors or for tracking down\n      exploited by errors in existing software.\n   *\/\n   c_debug CONSTANT PLS_INTEGER := 7;\n   \n   \/* Options for the left site of logging message *\/\n   \/* only module name *\/\n   logFormatName    CONSTANT VARCHAR2(10) := 'NAME';\n   \/* only day and night *\/\n   logFormatTime    CONSTANT VARCHAR2(10) := 'TIME';\n   \/* only time *\/\n   logFormatHour    CONSTANT VARCHAR2(10) := 'HOUR';\n   \/* only day *\/\n   logFormatDay     CONSTANT VARCHAR2(10) := 'DAY';\n   \/* all *\/\n   logFormatAll     CONSTANT VARCHAR2(10) := 'ALL';\n   \/* only name and time -&amp;gt; short*\/\n   logFormatShort CONSTANT VARCHAR2(10) := 'SHORT';\n   \n   \/* Errors that can occured during file operations *\/\n   logInvalidPath       CONSTANT    NUMBER := -1;\n   logInvalidMode       CONSTANT    NUMBER := -2;\n   logInvalidFileHandle CONSTANT    NUMBER := -3;\n   logInvalidOperation  CONSTANT    NUMBER := -4;\n   logReadError         CONSTANT    NUMBER := -5;\n   logWriteError        CONSTANT    NUMBER := -6;\n   logInternalError     CONSTANT    NUMBER := -7;\n   logNoCFGFile         CONSTANT    NUMBER := -8;\n   logLogConfigFound    CONSTANT    NUMBER := -9;\n   logWrongOpenMode     CONSTANT    NUMBER := -10;\n   logNoDataFound       CONSTANT    NUMBER := -100;\n   \n   \n  \/* ******************************************************************************************\n     * Function:    logInit\n     * Description: initialisation of logging,\n     *              read logging configuration\n     *\n     * Parameter:   i_moduleName    - Name of module logging is initiate for\n     *              i_logCfgPath    - Path of Logging configuration file\n     *              i_logCfgFile    - Logging configuration file\n     *\n     * Returnvalue: 0 = No errors, else Error \n     ******************************************************************************************\n   *\/\n   FUNCTION logInit( i_moduleName  IN VARCHAR2,\n                     i_logCfgPath  IN VARCHAR2 DEFAULT '\/tmp',\n                     i_logCfgFile  IN VARCHAR2 DEFAULT 'logging.cfg') RETURN NUMBER;\n\n    \/* ********************************************************************************************************\n       * Procedure:      writeLog\n       * \n       * Description:    procedure logs all given information in table message_log\n       *\n       * Parameters:     i_v_moduleName        - name of calling module\n       *                 i_n_moduleCodeLine    - line number in code of calling module\n       *                                         for messages with given parameters\n       *                 i_n_loggingLevel      - logging level of message\n       *                 i_v_messageText       - free style message\n       *                 i_b_setAppInfo        - TRUE = set application info (DBMS_APPLICATION_INFO)\n       ********************************************************************************************************\n    *\/\n   PROCEDURE writeLog (i_v_moduleName       IN VARCHAR2,\n                       i_n_moduleCodeLine   IN NUMBER,\n                       i_n_loggingLevel     IN PLS_INTEGER,\n                       i_v_messageText      IN VARCHAR2,\n                       i_b_setAppInfo       IN BOOLEAN DEFAULT FALSE);\n                       \n   \/* ********************************************************************************************************\n      * Procedure:    writeLog\n      * Description:  Procedure logs all given information in table message_log\n      *\n      * Parameters:   i_n_moduleName        -  name of calling module\n      *               i_n_moduleCodeLine    -  line number in code of calling module\n      *                                        for messages with given parameters\n      *               i_n_loggingLevel      -  logging level of message\n      *               i_v_messageText       -  free style message\n      *               i_n_dbErrorID         -  Error-ID of DB\n      *               i_v_dbErrorText       -  error message\n      ********************************************************************************************************\n    *\/\n\n   PROCEDURE writeLog (i_v_moduleName       IN VARCHAR2,\n                       i_n_moduleCodeLine   IN NUMBER,\n                       i_n_loggingLevel     IN PLS_INTEGER,\n                       i_v_messageText      IN VARCHAR2,\n                       i_n_dbErrorID        IN NUMBER,\n                       i_v_dbErrorText      IN VARCHAR2);\n                       \n    \/* ********************************************************************************************************\n       * Procedure:    raiseError\n       * Description:  Procedure logs all given information in table message_log and raise DB error\n       *\n       * Parameters:   i_n_moduleName        -  name of calling module\n       *               i_n_moduleCodeLine    -  line number in code of calling module\n       *                                        for messages with given parameters\n       *               i_n_loggingLevel      -  logging level of message\n       *               i_v_messageText       -  free style message\n       *               i_n_dbErrorID         -  Error-ID of database\n       *               i_v_dbErrorText       -  error message\n       ********************************************************************************************************\n    *\/\n   PROCEDURE raiseError (i_v_moduleName       IN VARCHAR2,\n                         i_n_moduleCodeLine   IN NUMBER,\n                         i_n_loggingLevel     IN PLS_INTEGER,\n                         i_v_messageText      IN VARCHAR2,\n                         i_n_dbErrorID        IN NUMBER,\n                         i_v_dbErrorText      IN VARCHAR2);                                           \n\nEND LogFileMgr;\n<\/pre>\n\n\n\n<p>Das Schema, das den logFileMgr enth\u00e4lt, ben\u00f6tigt SELECT-Zugriff auf die View <strong><span style=\"color:#0066cc\" class=\"tadv-color\">DBA_DIRECTORIES<\/span><\/strong>, ausserdem das Recht  <strong><span style=\"color:#0066cc\" class=\"tadv-color\">CREATE ANY DIRECTORY<\/span><\/strong>. <br>Damit das Package datenbankweit benutzt werden kann, sollte man ein public Synonym f\u00fcr das Package erzeugen und die Execute-Rechte an Public vergeben.<br>Nun kann man die Funktionen des logFileMgr in seinem eigenen PL\/SQL-Quellcode benutzen, wie z.B. hier:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nCREATE OR REPLACE PROCEDURE testLog\nIS\n\n \/* *****************************************************************************\n    * Description\n    * ============\n    *  This procedure shows how to use LogFileMgr\n    *\n    *   File:          proc_akitools_testLog.sql\n    *   Modified at:   $Date: 2020-01-01 08:00:00 +0200 (Mi, 01 Jan 2020) $\n    *   Checked in by: $Author: AKielhorn $\n    *   Revision:      $Revision: 100 $\n    *   Author:        Andy Kielhorn\n    *   Company:       AkiCom\n    *****************************************************************************\n *\/\n   \n    retCode   NUMBER;\nBEGIN\n    retCode :=\n        logFileMgr.logInit (i_moduleName   =&gt; $$PLSQL_UNIT,\n                            i_logCfgPath   =&gt; '\/opt\/oracle\/admin\/log\/config',\n                            i_logCfgFile   =&gt; 'logging.cfg');\n    logFileMgr.writeLog (\n        i_v_moduleName       =&gt; $$PLSQL_UNIT,\n        i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n        i_n_loggingLevel     =&gt; logFileMgr.c_debug,\n        i_v_messageText      =&gt; '# LogInit returncode: ' || retCode);\n    logFileMgr.writeLog (i_v_moduleName       =&gt; $$PLSQL_UNIT,\n                         i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n                         i_n_loggingLevel     =&gt; logFileMgr.c_info,\n                         i_v_messageText      =&gt; '&gt; Start Batch TestLog');\n    logFileMgr.writeLog (i_v_moduleName       =&gt; $$PLSQL_UNIT,\n                         i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n                         i_n_loggingLevel     =&gt; logFileMgr.c_alert,\n                         i_v_messageText      =&gt; '+ This is an alert message');\n    logFileMgr.writeLog (\n        i_v_moduleName       =&gt; $$PLSQL_UNIT,\n        i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n        i_n_loggingLevel     =&gt; logFileMgr.c_critical,\n        i_v_messageText      =&gt; '+ This is a critical message');\n    logFileMgr.writeLog (i_v_moduleName       =&gt; $$PLSQL_UNIT,\n                         i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n                         i_n_loggingLevel     =&gt; logFileMgr.c_error,\n                         i_v_messageText      =&gt; '! This is an error message',\n                         i_n_dbErrorID        =&gt; -1412,\n                         i_v_dbErrorText      =&gt; SQLERRM (-1412));\n    logFileMgr.writeLog (\n        i_v_moduleName       =&gt; $$PLSQL_UNIT,\n        i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n        i_n_loggingLevel     =&gt; logFileMgr.c_warning,\n        i_v_messageText      =&gt; '+ This is a warning message');\n    logFileMgr.writeLog (i_v_moduleName       =&gt; $$PLSQL_UNIT,\n                         i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n                         i_n_loggingLevel     =&gt; logFileMgr.c_notice,\n                         i_v_messageText      =&gt; '+ This is a notice message');\n    logFileMgr.writeLog (i_v_moduleName       =&gt; $$PLSQL_UNIT,\n                         i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n                         i_n_loggingLevel     =&gt; logFileMgr.c_info,\n                         i_v_messageText      =&gt; '+ This is an info message');\n    logFileMgr.writeLog (i_v_moduleName       =&gt; $$PLSQL_UNIT,\n                         i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n                         i_n_loggingLevel     =&gt; logFileMgr.c_debug,\n                         i_v_messageText      =&gt; '+ This is a debug message');\n    logFileMgr.writeLog (i_v_moduleName       =&gt; $$PLSQL_UNIT,\n                         i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n                         i_n_loggingLevel     =&gt; logFileMgr.c_info,\n                         i_v_messageText      =&gt; '&lt; End Batch TestLog');\n EXCEPTION \n   WHEN OTHERS THEN\n    logFileMgr.raiseError(i_v_moduleName       =&gt; $$PLSQL_UNIT,\n                         i_n_moduleCodeLine   =&gt; $$PLSQL_LINE,\n                         i_n_loggingLevel     =&gt; logFileMgr.c_error,\n                         i_v_messageText      =&gt; '! This is an error message',\n                         i_n_dbErrorID        =&gt; SQLCODE,\n                         i_v_dbErrorText      =&gt; SQLERRM);                 \nEND testLog;\n<\/pre><\/div>\n\n\n<p>Die Prozedur schreibt Log-Eintr\u00e4ge in das Protokoll \/opt\/oracle\/admin\/log\/testlog.log.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n01.02.2022 20:33:49 TESTLOG (26) &amp;lt;7&gt;: # LogInit returncode: 0\n01.02.2022 20:33:49 TESTLOG (30) &amp;lt;6&gt;: &gt; Start Batch TestLog\n01.02.2022 20:33:49 TESTLOG (34) &amp;lt;1&gt;: + This is an alert message\n01.02.2022 20:33:49 TESTLOG (39) &amp;lt;2&gt;: + This is a critical message\n01.02.2022 20:33:49 TESTLOG (43) &amp;lt;3&gt;: ! This is an error message\n01.02.2022 20:33:49 TESTLOG (43) &amp;lt;3&gt;: ! Error -1412: ORA-01412: L\u00e4nge gleich Null ist f\u00fcr diesen Datentyp nicht gestattet\n01.02.2022 20:33:49 TESTLOG (50) &amp;lt;4&gt;: + This is a warning message\n01.02.2022 20:33:49 TESTLOG (54) &amp;lt;5&gt;: + This is a notice message\n01.02.2022 20:33:49 TESTLOG (58) &amp;lt;6&gt;: + This is an info message\n01.02.2022 20:33:49 TESTLOG (62) &amp;lt;7&gt;: + This is a debug message\n01.02.2022 20:33:49 TESTLOG (66) &amp;lt;6&gt;: &amp;lt; End Batch TestLog\n<\/pre><\/div>\n\n\n<p>Der logFileMgr zusammen mit einem Installationsscript, der Testprozedur und einem Beispiel f\u00fcr die Log-Konfiguration k\u00f6nnen im <a rel=\"noreferrer noopener\" href=\"https:\/\/akicom.de\/?page_id=158#LogFileMgr\" data-type=\"page\" target=\"_blank\">Download-Bereich<\/a> heruntergeladen werden.<br>Ich hoffe, dass der logFileMgr an der einen oder anderen Stelle eingesetzt wird und n\u00fctzlich ist. <br>\u00dcber ein Feedback und Verbesserungsvorschl\u00e4ge w\u00fcrde ich mich freuen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This blog shows how to write a Logfile from  a PL\/SQL procedure.  <a href=\"https:\/\/akicom.de\/?p=153\">Weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":288,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-153","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle-plsql"],"jetpack_featured_media_url":"https:\/\/akicom.de\/wp-content\/uploads\/2022\/02\/greetings_from_database_blogtitle_1.jpg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/akicom.de\/index.php?rest_route=\/wp\/v2\/posts\/153"}],"collection":[{"href":"https:\/\/akicom.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/akicom.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/akicom.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/akicom.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=153"}],"version-history":[{"count":63,"href":"https:\/\/akicom.de\/index.php?rest_route=\/wp\/v2\/posts\/153\/revisions"}],"predecessor-version":[{"id":292,"href":"https:\/\/akicom.de\/index.php?rest_route=\/wp\/v2\/posts\/153\/revisions\/292"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/akicom.de\/index.php?rest_route=\/wp\/v2\/media\/288"}],"wp:attachment":[{"href":"https:\/\/akicom.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/akicom.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/akicom.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}