-
Notifications
You must be signed in to change notification settings - Fork 50
Dynamic Log Levels
Dynamic Log Levels enable application developers to change the log level during the runtime of the application. No changes of the configuration file is required.
cf-java-logging-support supports setting a specific log level for one single request by adding a token in the request header. This feature allows to understand misbehavior of a live-system in detail for a specific request, without flooding the system with an enormous number of DEBUG level log messages emitted during the processing of all other requests. This approach has the advantage that no unnecessary log messages need to be processed that might lead to quota exceedance. To avoid abuse of this feature, the dynamic log level has to be provided within an RSA-signed JWT token that also contains an expiry date.
There is a simple extension point to enable custom implementation of different approaches to dynamic log levels. This feature is described at the end of this article.
This feature is easy to use and requires only little extra configuration of the application. It is available with version 2.1.1 of the cf-java-logging-support or higher. Depending on the logging framework in use, few additions have to be made to the logback.xml or the log4j2.xml file as described below. Regardless of the framework, the public RSA key required to verify the JWT token's signature must be provided in the application's environment variables. Furthermore an individually chosen name for the HTTPS header field can also be specified here.
-
DYN_LOG_HEADER
: a specific header name for the log level token can be defined here. If not specified, the default value (SAP-LOG-LEVEL) is used. -
DYN_LOG_LEVEL_KEY
: a public key which can be used to verify the JWT tokens that contain the dynamic log level.
In the logback.xml file, a turbofilter has to be defined by adding the following line to the configuration element:
<turboFilter class="com.sap.hcp.cf.logback.filter.CustomLoggingTurboFilter" />
In the log4j2.xml file, add the following to the configuration element:
<DynamicThresholdFilter key="dynamic_log_level"
defaultThreshold="ERROR" onMatch="ACCEPT" onMismatch="DENY">
<KeyValuePair key="TRACE" value="TRACE" />
<KeyValuePair key="DEBUG" value="DEBUG" />
<KeyValuePair key="INFO" value="INFO" />
<KeyValuePair key="WARN" value="WARN" />
<KeyValuePair key="ERROR" value="ERROR" />
</DynamicThresholdFilter>
A valid JWT token should be signed with RS256. Its payload should contain the email of the issuer, the desired log-level, a timestamp for the time at which the token has been generated and a timestamp that represents the expiry date. The Java class TokenCreator can be used to create valid tokens.
{
"alg": "RS256",
"typ": "JWT"
}
{
"issuer": "<valid e-mail address>",
"level": "TRACE",
"iat": 1506016127,
"exp": 1506188927
}
Dynamic Log Levels are managed by the MDC field "dynamic-log-level". The value of this field is checked by the configured filters of the above configuration. If present, any log messages with a level equal or above this value is emitted regardless of the logger.
To provide an alternative approach to dynamic log levels, all you have to do is to put the current log level in the MDC field "dynamic-log-level". The configuration from above will ensure, that this log level is then applied to all log messages.
Our sample app can provide an example for the Dynamic Log Levels with the JWT token. The logging configuration of this app is already complete, but the manifest is missing the DYN_LOG_LEVEL_KEY
entry. For testing purposes just execute the TokenCreator. You can customise its output by changing the variables as documented. If you leave everything as is you will get an output like this:
You successfully created a dynamic log level token with log level TRACE!
Your private key is:
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCAtT0LL5QNZOy3dV0vB4KRqUec7o8UqOMgKa3O6gCz85qtKV98icN6gG0vgzIYvYwJI/MpHSbRke93YcaYiaYETl0XngxB/05BwW9NsGkdtnpKWJPC4gH8PULCMEJoAjsuueSo6xY7LBL/eZEZ0tI7Djf5hrE/IzXbn1DgXfIvHHeG4nfZN+DwBEjJGuGi9I2ojDYuKD7FieWUnBbODgbjTiWEbmfASGU0uvks9ZEp/QqFTlbL9ZP0GeYcoI4BUa/4dwBJLDo963OYOuCTuMQonTv5Tfty6lv/kjqW1JTUI/Ai3FmngrjeFlkH2BTueb0Kfp+ijXGZBaYCU2J533X/AgMBAAECggEAZOk0VivUgXfqnKA5EiFqPrghPKpRphoQEWx8KGmRaYWKdU+l3OfKSqacdI8BXSJnw9ba1BZWFCO+Q7R2V6w8bM3f8R9qbugzvBxkHt48XB5w3Q97smUut0x0pfneZtuw+R6oZ8QBpx0UPBddK4j+aWzpeAshtuXtWScc6vzdYA9oZhvt70Lu8cBDRx9OHoY8QQLM2lLxiMI4QCCs59ICRvrGRClNfFQZEeM/2G7ZaJfSrQmrDYl57XRQdji6UgzzdfzQiev2poZAPyzxuA8XzX7R/13q9vITYqISMpjyRtNQbRubtW+kvgdXMWSDJQ4+Y7fXPVAwBlDTCC1PJ5w40QKBgQDdZzg/Jgpeaz5DCv7Kaf4X1k6UctLz97IFR5+3cuipk2rxnsj99mnD31AH45JufgwsalN3FqZPs6qC/pJlAHvEVpiqUZ3nqNW745C0HxtzAh9gmnsS0r+wri6/TnXW978zm9fN+MAPkF6aaxDG0G6XDKFqy5LOO/YYlxEcaoqGBwKBgQCU0e+kpKU3SLywzeU4esA10uIYOP67d8bxEGcZ0S30DGDoPibm9UBtvPdOonXdQe27gn5HW1QfNuSbzp5IRxAx0Rad9L5VR8Bxi1s/DI6woZLW5oOpCJuxjpzMLNuSM/4RMA2shmmwPtNYRkd4KMStlQwtwRrn9z7To1OnpsdSSQKBgB3R+D5xJjZfZWxsP7MNoZ6eS8ksygL4Gq8hXX686F9mrqHKjDHAjbBHFKVrXl6pdYRJ8eH5V/8mKNIp7ZfS/9iK/Vb7VTRNhjQfS28nPXA5GfbN98OqRQ1L+JnlvHNuvP77f46LcXrnLAbKYuEUU8Def6M9thE2/EeFmVVleDDjAoGAKNZzLHsB22naXaoifJ0yoZJ8+KirPkZgEUavBCaitZWwAgsMIdSrGXIBa1KphU3SLuJgRLSLIQWvNhI83RijGQiHbFD86eoGpSHYqDSJ825jHRWki34RO2gnHuAwYK5jydOl7PH1jqeu10px0kddsUR1UxjqiT0PwIPRMPBTQgECgYEAibPoDNWCsDIqkH18LTJwyB1KpeO7ZD3HNEoeZFBdIFPUboxqka/qlmueXAGguQEvBOYmSZc4EzZSmlH7XUvMVlnOWHl3Y1USbEWO3gjGPkFDsdSL1dy2+0qgVi1FZPWGzb0sJImi1Dhofyhfaf9F8Kp44Ap9v4zZrlaFhltdqnU=
Your public key is:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgLU9Cy+UDWTst3VdLweCkalHnO6PFKjjICmtzuoAs/OarSlffInDeoBtL4MyGL2MCSPzKR0m0ZHvd2HGmImmBE5dF54MQf9OQcFvTbBpHbZ6SliTwuIB/D1CwjBCaAI7LrnkqOsWOywS/3mRGdLSOw43+YaxPyM1259Q4F3yLxx3huJ32Tfg8ARIyRrhovSNqIw2Lig+xYnllJwWzg4G404lhG5nwEhlNLr5LPWRKf0KhU5Wy/WT9BnmHKCOAVGv+HcASSw6PetzmDrgk7jEKJ07+U37cupb/5I6ltSU1CPwItxZp4K43hZZB9gU7nm9Cn6foo1xmQWmAlNied91/wIDAQAB
Your JWT token with log level TRACE is:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJsZXZlbCI6IlRSQUNFIiwiaXNzIjoiZmlyc3RuYW1lLmxhc3RuYW1lQHNhcC5jb20iLCJleHAiOjE1OTMyNTY2OTcsImlhdCI6MTU5MzA4Mzg5N30.Yw-UwhhR1uMMmi6j4ReaFohTiKiSV_H_TPFUFMnwDbV9AUyyrGNKnsnY5YF8Rem3Wh8HHQYFI5gf11yn1A0uve3wRsxyq0TWLJ7ptbPDpG6LWSGrUFfF3YiKXt91mkL9GtUMYGUuj0Kji7W4zPBBOePYapurKr00IGg8La6cT4R5HKxhNSobjFzxGGRH_qlzdwFHM_Jsp3XIDBPMGYqtTVyt0nqqLExJAsU0S6Oew8tptNIJcSSFjF1NS8VhlYs198s_dj-7ntcM3jy3EzvqtQv8TNDo7sA7bFJ_he9lktmDdjPQ2gt2gyJAx-sUswcS5qvFY6JpXd74Xl-PbsT9sA
Please copy and save token and keys for later usage. The JWT token can now be written
to an HTTP header in order to change the corresponding request's log level to TRACE
For token validation, the public key must be added to the environment of the application.
In order to generate a new token with specific keys, the variables privateKey and publicKey
can be instantiated with these keys
Take the public key and add it as DYN_LOG_LEVEL_KEY
to the manifest.yml. The whole file should look like this:
---
applications:
#
# You may want/need to change these to avoid naming conflicts
#
- name: logging-sample-app
instances: 1
path: target/logging-sample-app-3.0.9.war
env:
RANDOM_SLEEP: true
# Set LOG_*: true to activate logging of respective field
LOG_SENSITIVE_CONNECTION_DATA: false
LOG_REMOTE_USER: false
LOG_REFERER: false
DYN_LOG_LEVEL_KEY: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgLU9Cy+UDWTst3VdLweCkalHnO6PFKjjICmtzuoAs/OarSlffInDeoBtL4MyGL2MCSPzKR0m0ZHvd2HGmImmBE5dF54MQf9OQcFvTbBpHbZ6SliTwuIB/D1CwjBCaAI7LrnkqOsWOywS/3mRGdLSOw43+YaxPyM1259Q4F3yLxx3huJ32Tfg8ARIyRrhovSNqIw2Lig+xYnllJwWzg4G404lhG5nwEhlNLr5LPWRKf0KhU5Wy/WT9BnmHKCOAVGv+HcASSw6PetzmDrgk7jEKJ07+U37cupb/5I6ltSU1CPwItxZp4K43hZZB9gU7nm9Cn6foo1xmQWmAlNied91/wIDAQAB
You can now call the app while specifying the JWT token as HTTP header:
curl -k https://logging-sample-app.<your-cf-domain> -H "SAP-LOG-LEVEL: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJsZXZlbCI6IlRSQUNFIiwiaXNzIjoiZmlyc3RuYW1lLmxhc3RuYW1lQHNhcC5jb20iLCJleHAiOjE1OTMyNTY2OTcsImlhdCI6MTU5MzA4Mzg5N30.Yw-UwhhR1uMMmi6j4ReaFohTiKiSV_H_TPFUFMnwDbV9AUyyrGNKnsnY5YF8Rem3Wh8HHQYFI5gf11yn1A0uve3wRsxyq0TWLJ7ptbPDpG6LWSGrUFfF3YiKXt91mkL9GtUMYGUuj0Kji7W4zPBBOePYapurKr00IGg8La6cT4R5HKxhNSobjFzxGGRH_qlzdwFHM_Jsp3XIDBPMGYqtTVyt0nqqLExJAsU0S6Oew8tptNIJcSSFjF1NS8VhlYs198s_dj-7ntcM3jy3EzvqtQv8TNDo7sA7bFJ_he9lktmDdjPQ2gt2gyJAx-sUswcS5qvFY6JpXd74Xl-PbsT9sA"
The app logs 5 messages in this configuration with the respective log levels:
This is a trace message with attached string TESTSTRING
This is a debug message with attached string TESTSTRING
This is a info message with attached string TESTSTRING
This is a warning message with attached string TESTSTRING
This is a error message with attached string TESTSTRING
If you leave out the JWT token, it will only log the last 3 messages.