You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Chris Cheshire <ya...@gmail.com> on 2022/04/21 21:07:27 UTC

Conditional access logs

Tomcat 9.

I wanted to separate out access logs for external api calls to log different info than the standard access log line. For example, the api key used which is set as a request header.

Adding that to the pattern was easy. 

However the conditional logging was clunky. I found the ‘conditionIf’ and ‘conditionUnless’ attributes for the access log valve, but these only work on request attributes, not headers (at least that’s what the documentation says).

I have created a filter that copies the values from the request headers to equivalent  attributes, just so the condition can work. This is where it feels  clunky, especially since the access log valve has replacement parameters for logging request headers.

Is there a technical reason why the condition checking can’t work on request headers in the valve? If not, can this be considered as a feature request please?

Thanks
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Conditional access logs

Posted by Chris Cheshire <ya...@gmail.com>.

> On Apr 22, 2022, at 7:21 PM, Aleks <al...@none.at> wrote:
> 
> Hi.
> 
>> On Thu, 21 Apr 2022 17:07:27 -0400
>> Chris Cheshire <ya...@gmail.com> wrote:
>> 
>> Tomcat 9.
>> 
>> I wanted to separate out access logs for external api calls to log different
>> info than the standard access log line. For example, the api key used which
>> is set as a request header.
>> 
>> Adding that to the pattern was easy. 
>> 
>> However the conditional logging was clunky. I found the ‘conditionIf’ and
>> ‘conditionUnless’ attributes for the access log valve, but these only work on
>> request attributes, not headers (at least that’s what the documentation says).
>> 
>> I have created a filter that copies the values from the request headers to
>> equivalent  attributes, just so the condition can work. This is where it
>> feels  clunky, especially since the access log valve has replacement
>> parameters for logging request headers.
> 
> I have solved a similar issue with https://logback.qos.ch/access.html and
> https://logback.qos.ch/manual/loggingSeparation.html
> 
> That's the relevant snipplet for logback-access.xml. It uses the powerful
> filter feature from logback https://logback.qos.ch/manual/filters.html .
> 
> I attach the configmap definition which shows the whole config.
> 
> ```
>      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
>        <!--
>          Don't log the probs request from OpenShift
>        -->
>        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
>          <evaluator name="DontLogHealth">
>            <expression>
>              if(event.getRequestURI().contains("/health"))
>                return true;
>              return false;
>            </expression>
>          </evaluator>
>          <onMatch>DENY</onMatch>
>        </filter>
> ```
> 
> The log back access filter can be used to filter based on some AccessEvent like
> a request header.
> 
> https://logback.qos.ch/manual/filters.html#access_EvalutorFilter
> https://logback.qos.ch/xref/ch/qos/logback/access/spi/AccessEvent.html
> 
> I think that you can also define based on the request header which logger
> should be used but I never had such a requirement .
> 
> Just replace the tomcat access valve with the logback one.
> 
> ```
> <Valve className="ch.qos.logback.access.tomcat.LogbackValve"
>            quiet="false" filename="conf/logback-access.xml"/>
> ```
> 
> It was required to add this lib to the ext dir of tomcat.
> Maybe there are some newer versions available.
> 
> ```
> ls -1 /opt/apache/tomcat/base/lib/ext/
> commons-compiler-3.1.3.jar
> jackson-annotations-2.9.9.jar
> jackson-core-2.9.9.jar
> jackson-databind-2.9.9.3.jar
> janino-3.1.3.jar
> logback-access-1.2.3.jar
> logback-core-1.2.3.jar
> logstash-logback-encoder-6.6.jar
> 
> ```
> 
>> Is there a technical reason why the condition checking can’t work on request
>> headers in the valve? If not, can this be considered as a feature request
>> please?
>> 
>> Thanks
> 
> 
> Regards
> Alex


Thanks, I’ll take a look at this. I already use logback for the app logging so this is familiar. I forgot they even had an access logger.

Chris
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Conditional access logs

Posted by Aleks <al...@none.at>.
Hi.

On Thu, 21 Apr 2022 17:07:27 -0400
Chris Cheshire <ya...@gmail.com> wrote:

> Tomcat 9.
> 
> I wanted to separate out access logs for external api calls to log different
> info than the standard access log line. For example, the api key used which
> is set as a request header.
> 
> Adding that to the pattern was easy. 
> 
> However the conditional logging was clunky. I found the ‘conditionIf’ and
> ‘conditionUnless’ attributes for the access log valve, but these only work on
> request attributes, not headers (at least that’s what the documentation says).
> 
> I have created a filter that copies the values from the request headers to
> equivalent  attributes, just so the condition can work. This is where it
> feels  clunky, especially since the access log valve has replacement
> parameters for logging request headers.

I have solved a similar issue with https://logback.qos.ch/access.html and
https://logback.qos.ch/manual/loggingSeparation.html

That's the relevant snipplet for logback-access.xml. It uses the powerful
filter feature from logback https://logback.qos.ch/manual/filters.html .

I attach the configmap definition which shows the whole config.

```
      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!--
          Don't log the probs request from OpenShift
        -->
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
          <evaluator name="DontLogHealth">
            <expression>
              if(event.getRequestURI().contains("/health"))
                return true;
              return false;
            </expression>
          </evaluator>
          <onMatch>DENY</onMatch>
        </filter>
```

The log back access filter can be used to filter based on some AccessEvent like
a request header.

https://logback.qos.ch/manual/filters.html#access_EvalutorFilter
https://logback.qos.ch/xref/ch/qos/logback/access/spi/AccessEvent.html

I think that you can also define based on the request header which logger
should be used but I never had such a requirement .

Just replace the tomcat access valve with the logback one.

```
<Valve className="ch.qos.logback.access.tomcat.LogbackValve"
            quiet="false" filename="conf/logback-access.xml"/>
```

It was required to add this lib to the ext dir of tomcat.
Maybe there are some newer versions available.

```
ls -1 /opt/apache/tomcat/base/lib/ext/
commons-compiler-3.1.3.jar
jackson-annotations-2.9.9.jar
jackson-core-2.9.9.jar
jackson-databind-2.9.9.3.jar
janino-3.1.3.jar
logback-access-1.2.3.jar
logback-core-1.2.3.jar
logstash-logback-encoder-6.6.jar

```

> Is there a technical reason why the condition checking can’t work on request
> headers in the valve? If not, can this be considered as a feature request
> please?
> 
> Thanks


Regards
Alex

Re: Conditional access logs

Posted by Chris Cheshire <ya...@gmail.com>.

> On Apr 22, 2022, at 1:32 PM, Tim Funk <fu...@apache.org> wrote:
> 
> I don't think there is a technical reason why it couldn't be added. I think
> the hard part is getting the config wording/naming correct
> 
> Alternatively, I think an out of the box workaround could also be Tomcat's
> RewriteValve where the condition matches on header and sets the
> "environment variable"
> https://tomcat.apache.org/tomcat-9.0-doc/rewrite.html
> 
> You can submit a feature enhancement request in the bug database
> https://tomcat.apache.org/bugreport.html#How_to_submit_patches_and_enhancement_requests
> 
> -Tim


Good to know. I’m going to try the logback route first - if that fails I’ll look at an enhancement request or patch.

Chris


> 
> 
>> On Thu, Apr 21, 2022 at 5:08 PM Chris Cheshire <ya...@gmail.com> wrote:
>> 
>> Tomcat 9.
>> 
>> I wanted to separate out access logs for external api calls to log
>> different info than the standard access log line. For example, the api key
>> used which is set as a request header.
>> 
>> Adding that to the pattern was easy.
>> 
>> However the conditional logging was clunky. I found the ‘conditionIf’ and
>> ‘conditionUnless’ attributes for the access log valve, but these only work
>> on request attributes, not headers (at least that’s what the documentation
>> says).
>> 
>> I have created a filter that copies the values from the request headers to
>> equivalent  attributes, just so the condition can work. This is where it
>> feels  clunky, especially since the access log valve has replacement
>> parameters for logging request headers.
>> 
>> Is there a technical reason why the condition checking can’t work on
>> request headers in the valve? If not, can this be considered as a feature
>> request please?
>> 
>> 
>> 

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Conditional access logs

Posted by Tim Funk <fu...@apache.org>.
I don't think there is a technical reason why it couldn't be added. I think
the hard part is getting the config wording/naming correct

Alternatively, I think an out of the box workaround could also be Tomcat's
RewriteValve where the condition matches on header and sets the
"environment variable"
https://tomcat.apache.org/tomcat-9.0-doc/rewrite.html

You can submit a feature enhancement request in the bug database
https://tomcat.apache.org/bugreport.html#How_to_submit_patches_and_enhancement_requests

-Tim


On Thu, Apr 21, 2022 at 5:08 PM Chris Cheshire <ya...@gmail.com> wrote:

> Tomcat 9.
>
> I wanted to separate out access logs for external api calls to log
> different info than the standard access log line. For example, the api key
> used which is set as a request header.
>
> Adding that to the pattern was easy.
>
> However the conditional logging was clunky. I found the ‘conditionIf’ and
> ‘conditionUnless’ attributes for the access log valve, but these only work
> on request attributes, not headers (at least that’s what the documentation
> says).
>
> I have created a filter that copies the values from the request headers to
> equivalent  attributes, just so the condition can work. This is where it
> feels  clunky, especially since the access log valve has replacement
> parameters for logging request headers.
>
> Is there a technical reason why the condition checking can’t work on
> request headers in the valve? If not, can this be considered as a feature
> request please?
>
>
>