<!-- 
RSS generated by JIRA (1001.0.0-SNAPSHOT#100246-sha1:7a5c50119eb0633d306e14180817ddef5e80c75d) at Thu Feb 08 23:21:11 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary add field=key&field=summary to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>FOLIO Jira</title>
    <link>https://folio-org.atlassian.net</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>1001.0.0-SNAPSHOT</version>
        <build-number>100246</build-number>
        <build-date>07-02-2024</build-date>
    </build-info>

<item>
            <title>[FOLIO-2511] SPIKE: investigate JSON layout to Okapi and RMB logs</title>
                <link>https://folio-org.atlassian.net/browse/FOLIO-2511</link>
                <project id="10290" key="FOLIO">FOLIO</project>
                    <description>&lt;p&gt;&lt;b&gt;Goal&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Investigate if JSON format can be used to provider structured logs in FOLIO, both for Okapi and backend modules (with RMB providing default logging configuration).&lt;/p&gt;

&lt;p&gt;If successful JSON format will be used to provide structured data in the logs. The following fields are candidates for inclusion:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;tt&gt;logLevel&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;timestamp&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;message&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;stacktrace&lt;/tt&gt; - plain text joined by \n symbol (for errors)&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;tenantId&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;moduleId&lt;/tt&gt; (e.g mod-authtoken-1.2.3)&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;requestId&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;userId&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;uri&lt;/tt&gt; (e.g /inventory-storage/instances) e.g an HTTP API path&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;queryString&lt;/tt&gt; as a separate element to capture HTTP parameters&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;code&lt;/tt&gt;  (e.g 200, 400, 500) e.g an HTTP response code&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;duration&lt;/tt&gt; (e.g 1234, in msecs) time it took to complete an operation&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;sql&lt;/tt&gt; SQL Query&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;A complete set is still being discussed, see &lt;a href=&quot;https://folio-org.atlassian.net/wiki/pages/viewpage.action?pageId=1776544&quot; class=&quot;external-link&quot; rel=&quot;nofollow noreferrer&quot;&gt;https://folio-org.atlassian.net/wiki/pages/viewpage.action?pageId=1776544&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Caveats&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;FOLIO DevOps team has been experimenting with JSON logging configuration and have seen the following issues trying to enable JSON logging:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;poor performance when using the &quot;location&quot; information (like class)&lt;/li&gt;
	&lt;li&gt;disappearance of existing structured fields when adding custom fields&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;See details of this investigation below.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Implementation&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;We will put utilities (e.g FolioLoggingContext) and default log4j config in a shared project (okapi-common since it&apos;s used by RMB and will make the classes available in all RMB projects).&lt;/p&gt;

&lt;p&gt;We will let module developers know to remove their existing log4j configuration to make use of the default one. They will be also able to use the default one as a starting point and put in additional customize.&lt;/p&gt;</description>
                <environment></environment>
        <key id="81500">FOLIO-2511</key>
            <summary>SPIKE: investigate JSON layout to Okapi and RMB logs</summary>
                <type id="10003" iconUrl="https://folio-org.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium">Task</type>
                                            <priority id="10001" iconUrl="https://dev.folio.org/assets/jira-priority/jira-p2.svg">P2</priority>
                        <status id="6" iconUrl="https://folio-org.atlassian.net/images/icons/statuses/closed.png" description="The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.">Closed</status>
                    <statusCategory id="3" key="done" colorName="green"/>
                                    <resolution id="10003">Done</resolution>
                                                        <assignee accountid="70121:84bca0b8-4380-4d87-8a90-53e9133584f6">Mikhail Fokanov</assignee>
                                                                <reporter accountid="557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d">Jakub Skoczen</reporter>
                                    <labels>
                            <label>instrumentation</label>
                            <label>platform-backlog</label>
                    </labels>
                <created>Fri, 13 Mar 2020 13:57:39 +0000</created>
                <updated>Tue, 25 Aug 2020 13:32:44 +0000</updated>
                            <resolved>Tue, 25 Aug 2020 13:06:11 +0000</resolved>
                                                                        <due></due>
                            <votes>0</votes>
                                    <watches>3</watches>
                                                                <comments>
                                                            <comment id="195380" author="5c706fbb47a54a6728e59df2" created="Fri, 13 Mar 2020 14:19:52 +0000"  >&lt;p&gt;JSON logging configuration:&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-xml&quot;&gt;
    &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;Configuration status=&lt;span class=&quot;code-quote&quot;&gt;&quot;WARN&quot;&lt;/span&gt; monitorInterval=&lt;span class=&quot;code-quote&quot;&gt;&quot;30&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;Appenders&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;Console name=&lt;span class=&quot;code-quote&quot;&gt;&quot;Console&quot;&lt;/span&gt; target=&lt;span class=&quot;code-quote&quot;&gt;&quot;SYSTEM_OUT&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;JSONLayout compact=&lt;span class=&quot;code-quote&quot;&gt;&quot;true&quot;&lt;/span&gt; eventEOL=&lt;span class=&quot;code-quote&quot;&gt;&quot;true&quot;&lt;/span&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;/Console&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;/Appenders&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;Loggers&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;Root level=&lt;span class=&quot;code-quote&quot;&gt;&quot;INFO&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;AppenderRef ref=&lt;span class=&quot;code-quote&quot;&gt;&quot;Console&quot;&lt;/span&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;/Root&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;/Loggers&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;code-tag&quot;&gt;&amp;lt;/Configuration&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Okapi log output (pretty-printed for clarity):&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
  {
    &lt;span class=&quot;code-quote&quot;&gt;&quot;thread&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;vert.x-eventloop-thread-1&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;level&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;INFO&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;loggerName&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;okapi&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;message&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;X-Okapi-Request-Id: 177027/circulation;918494/configurations&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;endOfBatch&quot;&lt;/span&gt;: &lt;span class=&quot;code-keyword&quot;&gt;false&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;loggerFqcn&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;org.apache.logging.log4j.spi.AbstractLogger&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;threadId&quot;&lt;/span&gt;: 102,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;instant&quot;&lt;/span&gt;: {
      &lt;span class=&quot;code-quote&quot;&gt;&quot;epochSecond&quot;&lt;/span&gt;: 1583852446,
      &lt;span class=&quot;code-quote&quot;&gt;&quot;nanoOfSecond&quot;&lt;/span&gt;: 282000000
    },
    &lt;span class=&quot;code-quote&quot;&gt;&quot;threadPriority&quot;&lt;/span&gt;: 5
  }
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;RMB log output (mod-inventory-storage-18.2.3):&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
  {
    &lt;span class=&quot;code-quote&quot;&gt;&quot;timeMillis&quot;&lt;/span&gt;: 1583855032670,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;thread&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;main&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;level&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;INFO&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;loggerName&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;org.folio.&lt;span class=&quot;code-keyword&quot;&gt;rest&lt;/span&gt;.tools.messages.Messages&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;message&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;Loading messages from /infra-messages/APIMessages_de.properties ................................&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;endOfBatch&quot;&lt;/span&gt;: &lt;span class=&quot;code-keyword&quot;&gt;false&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;loggerFqcn&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;io.vertx.core.logging.Logger&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;threadId&quot;&lt;/span&gt;: 1,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;threadPriority&quot;&lt;/span&gt;: 5
  }
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;</comment>
                                                            <comment id="195386" author="5c706fbb47a54a6728e59df2" created="Fri, 13 Mar 2020 14:31:56 +0000"  >&lt;p&gt;Observations from testing:&lt;br/&gt;
Attempting to add location information (class name, file, method, etc.) with locationInfo=&quot;true&quot; results in a significant performance hit. See &lt;a href=&quot;https://logging.apache.org/log4j/2.x/manual/layouts.html#LocationInformation&quot; class=&quot;external-link&quot; rel=&quot;nofollow noreferrer&quot;&gt;https://logging.apache.org/log4j/2.x/manual/layouts.html#LocationInformation&lt;/a&gt; for one possible explanation. This does not explain why including the class name in a PatternLayout does not appear to affect performance.&lt;/p&gt;

&lt;p&gt;Attempting to add a custom field (either a lookup or a constant) as documented (&lt;a href=&quot;https://logging.apache.org/log4j/2.x/manual/layouts.html#JSONLayout&quot; class=&quot;external-link&quot; rel=&quot;nofollow noreferrer&quot;&gt;https://logging.apache.org/log4j/2.x/manual/layouts.html#JSONLayout&lt;/a&gt;) does not work as expected for Okapi. You end up with log entries like this:&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
  {
    &lt;span class=&quot;code-quote&quot;&gt;&quot;logEvent&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;setTimer delay 432000000&quot;&lt;/span&gt;,
    &lt;span class=&quot;code-quote&quot;&gt;&quot;customField1&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;custom value&quot;&lt;/span&gt;
  }
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Note that the log is quite a bit thinner, and structured very differently. This is quite different from the expected behavior, according to the log4j2 documentation.&lt;/p&gt;

&lt;p&gt;For RMB, attempting to add a custom field simply doesn&apos;t work &amp;#8211; the log output is not changed.&lt;/p&gt;</comment>
                    </comments>
                <issuelinks>
                            <issuelinktype id="10003">
                    <name>Relates</name>
                                            <outwardlinks description="relates to">
                                        <issuelink>
            <issuekey id="54258">OKAPI-871</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="57384">RMB-709</issuekey>
        </issuelink>
                            </outwardlinks>
                                                                <inwardlinks description="relates to">
                                        <issuelink>
            <issuekey id="54183">OKAPI-872</issuekey>
        </issuelink>
                            </inwardlinks>
                                    </issuelinktype>
                            <issuelinktype id="10007">
                    <name>Requires</name>
                                                                <inwardlinks description="is required by">
                                        <issuelink>
            <issuekey id="81675">FOLIO-2644</issuekey>
        </issuelink>
                            </inwardlinks>
                                    </issuelinktype>
                    </issuelinks>
                <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                <customfield id="customfield_10000" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummarycf">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10057" key="com.atlassian.jira.plugin.system.customfieldtypes:select">
                        <customfieldname>Development Team</customfieldname>
                        <customfieldvalues>
                                <customfieldvalue key="10144"><![CDATA[Core: Platform]]></customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        <customfield id="customfield_10019" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>0|hzx6me:vh</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_10020" key="com.pyxis.greenhopper.jira:gh-sprint">
                        <customfieldname>Sprint</customfieldname>
                        <customfieldvalues>
                                <customfieldvalue id="1168">CP: sprint 92</customfieldvalue>
    <customfieldvalue id="1169">CP: sprint 94</customfieldvalue>
    <customfieldvalue id="1170">CP: sprint 95</customfieldvalue>
    <customfieldvalue id="1108">CP: sprint 90</customfieldvalue>
    <customfieldvalue id="952">CP: sprint 91</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                            <customfield id="customfield_10044" key="com.atlassian.jira.plugin.system.customfieldtypes:float">
                        <customfieldname>Story Points</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>3.0</customfieldvalue>
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                <customfield id="customfield_10024" key="com.atlassian.jira.ext.charting:firstresponsedate">
                        <customfieldname>[CHART] Date of First Response</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>Fri, 13 Mar 2020 14:19:52 +0000</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10025" key="com.atlassian.jira.ext.charting:timeinstatus">
                        <customfieldname>[CHART] Time in Status</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                    </customfields>
    </item>
</channel>
</rss>