[ 
https://issues.apache.org/jira/browse/LOG4J2-695?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14048511#comment-14048511
 ] 

Remko Popma edited comment on LOG4J2-695 at 7/1/14 5:03 AM:
------------------------------------------------------------

Hm... we could have a long discussion about performance, but never mind. :-)

Let me summarize your requirements to see if I understand: you are developing a 
custom logging library for use by other teams. You are using something called 
Splunk which needs logging output to be in key-value pair format. You want to 
strongly encourage production logging to use this key-value format but at the 
same time it should not be impossible for your teams to do simple logging for 
debugging purposes. 

I actually think you were on the right track with the custom/extended logger.
However, instead of _extending_, how about creating a _custom_ logger with the 
log levels you need (which may be exactly the same as Log4J2: trace, debug, 
info, warn, error, fatal)?

Get the code generator tool attached to LOG4J2-519 and use this command:
{code}
java org.apache.logging.log4j.util.Generate$CustomLogger 
com.mycomp.CustomLogger FATAL=100 ERROR=200 WARN=300 INFO=400 DEBUG=500 
TRACE=600
{code}

This will generate a lot of methods for all these log levels. Now, you can put 
a @deprecated tag on all methods that you want to _discourage_ your teams from 
using, and you can delete the methods you want to _prevent_ your teams from 
using. (I would not recommend deleting too many as it is hard to predict what 
your teams will and will not need...)

Then, add your {{CustomLogger.info(String, String, String, String, String, 
Result, String, String...)}} method. 

(By the way, you probably are already aware of this, but I noticed that in the 
attached code the error handling in {{info}} is incomplete. Also, {{if 
(transactionId != null && transactionId.isEmpty())}} should probably be {{if 
(transactionId == null || transactionId.isEmpty())}}.)

Performance tips:
* When creating a StringBuilder, it is recommended practice to specify a size 
(the default of 16 characters may result in may resizes/array copies). 
* Your {{log}} method uses UUID.randomUUID() to create unique eventIDs. This is 
fairly expensive (UUID uses SecureRandom). You can consider using the 
{{sequenceNumber}} provided by Log4j's pattern layout. This will provide a 
unique id for each log event with almost zero overhead.
* Replace {{someInt % 2 != 0}} with {{someInt & 1 == 1}} - a cheaper way to 
check if a number is odd.


was (Author: rem...@yahoo.com):
Hm... we could have a long discussion about performance, but never mind. :-)

Let me summarize your requirements to see if I understand: you are developing a 
custom logging library for use by other teams. You are using something called 
Splunk which needs logging output to be in key-value pair format. You want to 
strongly encourage production logging to use this key-value format but at the 
same time it should not be impossible for your teams to do simple logging for 
debugging purposes. 

I actually think you were on the right track with the custom/extended logger.
However, how about instead of _extending_, create a _custom_ logger with the 
log levels you need (which may be exactly the same as Log4J2: trace, debug, 
info, warn, error, fatal).

You can use the generator tool attached to LOG4J2-519. This will generate a lot 
of methods for all these log levels. Now, you can put a @deprecated tag on all 
methods that you want to _discourage_ your teams from using, and you can delete 
the methods you want to _prevent_ your teams from using. (I would not recommend 
deleting too many as it is hard to predict what your teams will and will not 
need...)

Then, add your {{CustomeLogger.info(String, String, String, String, String, 
Result, String, String...)}} method. 

(By the way, you probably are already aware of this, but I noticed that the 
error handling in {{info}} is incomplete. Also, {{if (transactionId != null && 
transactionId.isEmpty())}} should probably be {{if (transactionId == null || 
transactionId.isEmpty())}}.)

Performance tips:
* When creating a StringBuilder, it is recommended practice to specify a size 
(the default of 16 characters may result in may resizes/array copies). 
* The {{log}} method uses UUID.randomUUID() to create unique eventIDs. This is 
fairly expensive (UUID uses SecureRandom). You can consider using the 
{{sequenceNumber}} provided by Log4j's pattern layout. This will provide a 
unique id for each log event with almost zero overhead.
* Replace {{someInt % 2 != 0}} with {{someInt & 1 == 1}} - a cheaper way to 
check if a number is odd.

> Custom Logger with restrictions on existing methods
> ---------------------------------------------------
>
>                 Key: LOG4J2-695
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-695
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: API
>            Reporter: SIBISH BASHEER
>              Labels: customlogger
>         Attachments: CustomLogger.java
>
>
> I have been looking at the Custom/Extended logger discussions. But none of 
> them seems to fulfil what i am looking for.
> 1) I want custom methods as below:
> {code}
>     private static CustomLogger logger = 
> CustomLogger.getLogger(AppAsyncMain.class);
>    
>     logger.info( transaction_id, app_name + event_name +
>                                       "inside the loop" + "inside the loop of 
> the sample app" +
>                                       "success" + "looped in" + "loop_count" +
>                                       String.valueOf(i));
> {code}
>                                       
>       log:
> {code}
> 2014-06-30 16:09:28,268 log_level="INFO" thread_name="main" 
> class_name="com.custom.samplelog4j.AppAsyncMain" 
> transaction_id="79ea1071-9565-405a-aa18-75d271694bf2" 
> event_id="dd5c69c0-4400-41fd-8a2e-5d538d8e8c9b" app="Sample Logging SDK App" 
> event_name="Sample Event" action="start of sample app" desc="start of api" 
> result="success" reason="start" token="abcdefg" alias="a...@gmail.com" 
> {code}
>       
> 2) I want to show warning in existing logger methods so the teams using the 
> custom logger doesn't use these methods other than for testing:
> {code}
>    logger.info("start of statement");
> {code}
>    
>    log:
> {code}
>    2014-06-30 16:12:31,065 log_level="INFO" thread_name="main" 
> class_name="com.custom.samplelog4j2.AppAsyncMain" start of statement  
> customlogger_warning="method not recommended for production use" 
> {code}
>    
> 3) Custom validations for the fields:
> {code}
>       private static String validateFields(String app_name, String event_name,
>                       String action, String desc, Result result, String 
> reason) {
>               String validateStatus = "";
>               if (!ValidateAppName(app_name)) {
>                       validateStatus = "app_name";
>               } else if (!ValidateEventName(event_name)) {
>                       validateStatus = "event_name";
>               } else if (!ValidateAction(action)) {
>                       validateStatus = "action";
>               } else if (!ValidateDesc(desc)) {
>                       validateStatus = "desc";
>               } else if (!ValidateReason(result, reason)) {
>                       validateStatus = "reason";
>               }
>               return validateStatus;
>       }
> {code}
> Options tried:
> 1.
> * extended ExtendedLoggerWrapper
> * created the map of the Custom logger
> * This option was failing because of "writing to a closed appender"
> * Attached is the code "CustomLogger.java"
>    
> 2. Modified the AbstractLogger in Trunk and added the below methods:
> {code}
>       @Override
>     public void info(final String message) {
>     String updtMessage = message + " amexlogger_error=\"Incorrect method 
> used\"";
>         logIfEnabled(FQCN, Level.INFO, null, updtMessage, (Throwable) null);
>     }
>  public void info(final String transactionId, final String app_name, final 
> String event_name, final String action, final String desc, final String 
> result, final String reason, final String... moreFields) { 
>        String message = "transaction_id=" + transactionId + " " + "app_name=" 
> + app_name + " " + "event_name=" + event_name + " " + "action=" + action;
>  
>         logIfEnabled(FQCN, Level.INFO, null, message, (Throwable) null);
>     }
> {code}
>       I don't want to modify the methods inside the log4j-api. 
>       
> Please help me with the correct approach on how to use log4j2 for this 
> usecase.
> Thanks
> Sibish



--
This message was sent by Atlassian JIRA
(v6.2#6252)

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-dev-h...@logging.apache.org

Reply via email to