I would prefer a solution that is reusable for all ThreadLocals, not just the 
one we are considering putting in PatternConverter. 
Are there any drawbacks with the registry idea?

Sent from my iPhone

> On 2015/07/04, at 16:45, Gary Gregory <[email protected]> wrote:
> 
> So the simplest thing to so would for PatternConverter to implement a stop() 
> method to clear the ThreadLocal (extending AbstractLifeCycle might be too 
> heavy for now)
> 
> The tricky part is how to connect the dots from an appender stopping all the 
> way to the PatternConverter. Unless we go the route of the registry.
> 
> Gary
> 
>> On Thu, Jul 2, 2015 at 10:34 AM, Gary Gregory <[email protected]> wrote:
>> Or the org.apache.logging.log4j.core.pattern.AbstractPatternConverter could 
>> extend org.apache.logging.log4j.core.AbstractLifeCycle and clearing the 
>> ThreadLocale would be done in stop(). The stop would have to be called at 
>> the right time of course.
>> 
>> Gary
>> 
>>> On Thu, Jul 2, 2015 at 6:18 AM, Remko Popma <[email protected]> wrote:
>>> Yes, that could still work: We could use a ThreadLocal containing a custom 
>>> class which holds the lastTimestamp, cachedDateString as well as a 
>>> SimpleDateFormat instance. 
>>> 
>>> As Jess pointed out, we would also need a way to clear the ThreadLocal when 
>>> the LoggerContext is stopped (to prevent memory leaks in web apps). This 
>>> may be the third usage of ThreadLocals in log4j2 now, so it may be worth 
>>> creating a reusable mechanism for this. 
>>> One idea would be to have a ThreadLocal registry in the LoggerContext, 
>>> where the LoggerContext is responsible for cleaning up all registered 
>>> ThreadLocals in its stop() method. 
>>> 
>>> Thoughts?
>>> 
>>> Remko..
>>> Sent from my iPhone
>>> 
>>>> On 2015/07/02, at 22:00, Gary Gregory <[email protected]> wrote:
>>>> 
>>>> What about storing a SimpleDateFormat in a ThreadLocal? 
>>>> 
>>>> But, more importantly and aside from SimpleDateFormat not being 
>>>> thread-safe [1], I thought we used synchronized to keep the lastTimestamp 
>>>> and cachedDateString ivar perfectly matched up:
>>>> 
>>>>     public void format(final LogEvent event, final StringBuilder output) {
>>>>         final long timestamp = event.getTimeMillis();
>>>> 
>>>>         synchronized (this) {
>>>>             if (timestamp != lastTimestamp) {
>>>>                 lastTimestamp = timestamp;
>>>>                 cachedDateString = formatter.format(timestamp);
>>>>             }
>>>>         }
>>>>         output.append(cachedDateString);
>>>>     }
>>>> 
>>>> But #2, lastTimestamp and cachedDateString are not volatile, so do we 
>>>> really care?
>>>> 
>>>> Gary
>>>> 
>>>> [1] Javadoc: Date formats are not synchronized.
>>>>  * It is recommended to create separate format instances for each thread.
>>>>  * If multiple threads access a format concurrently, it must be 
>>>> synchronized
>>>>  * externally.
>>>> 
>>>> 
>>>>> On Thu, Jul 2, 2015 at 5:34 AM, Ralph Goers <[email protected]> 
>>>>> wrote:
>>>>> The date pattern converter will be locking because it uses 
>>>>> SimpleDateFormat to format the date.  This can be changed in Java 8, but 
>>>>> the only alternative until then is to use the Joda Time library and we 
>>>>> have been reluctant to be reliant on third party libraries for such core 
>>>>> components. 
>>>>> 
>>>>> Sent from my iPad
>>>>> 
>>>>>> On Jul 2, 2015, at 3:44 AM, "[email protected]" <[email protected]> wrote:
>>>>>> 
>>>>>> Thanks Gary.
>>>>>> 
>>>>>> Limit number of threads can help alleviate the problem, but can't make 
>>>>>> it disappear. Especially when it happens during midnight when the 
>>>>>> workload will far below the average than the day,but we have no such 
>>>>>> problems happens during day.
>>>>>> 
>>>>>> I didn't dive into the code to see what it is doing within the 
>>>>>> synchronized block,which takes so much time.
>>>>>> 
>>>>>> I still think there should be something that is problematic in log4j.
>>>>>> 
>>>>>> [email protected]
>>>>>>  
>>>>>> From: Gary Gregory
>>>>>> Date: 2015-07-02 17:35
>>>>>> To: Log4J Developers List
>>>>>> Subject: Re: Re: Log4j2 RollingFileAppender deadlock issue
>>>>>> and let's be clear, unlike the subject of this thread, there is no 
>>>>>> deadlock here, at least not in the thread dump you shared; the 
>>>>>> application appears hung but is in fact slowed down to a crawl. IMO that 
>>>>>> is ;-)
>>>>>> 
>>>>>> Gary
>>>>>> 
>>>>>>> On Thu, Jul 2, 2015 at 2:34 AM, Gary Gregory <[email protected]> 
>>>>>>> wrote:
>>>>>>> The more threads you run to service additional requests is making the 
>>>>>>> problem worse IMO. This likely causes swapping out the wazoo. I would 
>>>>>>> bind the thread pool to try to avoid 
>>>>>>> 
>>>>>>> 
>>>>>>> in service.
>>>>>>> 
>>>>>>> Gary
>>>>>>> 
>>>>>>>> On Thu, Jul 2, 2015 at 2:25 AM, [email protected] <[email protected]> 
>>>>>>>> wrote:
>>>>>>> 
>>>>>>>> Thanks Gary. 
>>>>>>>> So, it's abnormal for so many (2000+)threads to wait for the lock. The 
>>>>>>>> workload of our application is not very high. So, It is kind of too 
>>>>>>>> long for the <0x0000000772fe2860> owner thread to unlock it.
>>>>>>>> 
>>>>>>>> 6k threads in total is abnormal, as we are using *unlimited* thread 
>>>>>>>> pool in our code to do HTTP requests to other services when responding 
>>>>>>>> user's request. Since the threads of the thread pool is waiting for 
>>>>>>>> the lock, so the thread pool has to kick off new threads when we throw 
>>>>>>>> tasks to it.
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> [email protected]
>>>>>>>>  
>>>>>>>> From: Gary Gregory
>>>>>>>> Date: 2015-07-02 16:55
>>>>>>>> To: Log4J Developers List
>>>>>>>> Subject: Re: Re: Log4j2 RollingFileAppender deadlock issue
>>>>>>>> Wow, > 6k threads? Is that normal for your application?
>>>>>>>> 
>>>>>>>> I do see two locks on two DatePatternConverter instances, and both are 
>>>>>>>> working:
>>>>>>>> 
>>>>>>>> "resin-port-7280-7309" daemon prio=10 tid=0x00002ba94d16e000 
>>>>>>>> nid=0x69e6 runnable [0x00002bab56be5000]
>>>>>>>>    java.lang.Thread.State: RUNNABLE
>>>>>>>>        at 
>>>>>>>> java.lang.AbstractStringBuilder.<init>(AbstractStringBuilder.java:64)
>>>>>>>>        at java.lang.StringBuffer.<init>(StringBuffer.java:96)
>>>>>>>>        at java.text.Format.format(Format.java:157)
>>>>>>>>        at 
>>>>>>>> org.apache.logging.log4j.core.pattern.DatePatternConverter$PatternFormatter.format(DatePatternConverter.java:50)
>>>>>>>>        at 
>>>>>>>> org.apache.logging.log4j.core.pattern.DatePatternConverter.format(DatePatternConverter.java:251)
>>>>>>>>        - locked <0x00000007a2cecaa0> (a 
>>>>>>>> org.apache.logging.log4j.core.pattern.DatePatternConverter)
>>>>>>>>        at 
>>>>>>>> org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:36)
>>>>>>>>        at 
>>>>>>>> org.apache.logging.log4j.core.layout.PatternLayout.toSerializable(PatternLayout.java:189)
>>>>>>>> ...
>>>>>>>> "DataChannel-1-thread-802" prio=10 tid=0x00002ba8c0022800 nid=0x1fbc 
>>>>>>>> runnable [0x00002ba983230000]
>>>>>>>>    java.lang.Thread.State: RUNNABLE
>>>>>>>>        at java.lang.StringBuffer.toString(StringBuffer.java:561)
>>>>>>>>        - locked <0x0000000772fe2860> (a java.lang.StringBuffer)
>>>>>>>>        at java.text.Format.format(Format.java:157)
>>>>>>>>        at 
>>>>>>>> org.apache.logging.log4j.core.pattern.DatePatternConverter$PatternFormatter.format(DatePatternConverter.java:50)
>>>>>>>>        at 
>>>>>>>> org.apache.logging.log4j.core.pattern.DatePatternConverter.format(DatePatternConverter.java:251)
>>>>>>>>        - locked <0x00000007a2cecc08> (a 
>>>>>>>> org.apache.logging.log4j.core.pattern.DatePatternConverter)
>>>>>>>>        at 
>>>>>>>> org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:36)
>>>>>>>>        at 
>>>>>>>> org.apache.logging.log4j.core.layout.PatternLayout.toSerializable(PatternLayout.java:189)
>>>>>>>> 
>>>>>>>> Lots (> 2k) of threads are waiting on these two locks.
>>>>>>>> 
>>>>>>>> So that is all 'normal' in the sense that I do not see a deadlock, 
>>>>>>>> this is more of a starvation scenario.
>>>>>>>> 
>>>>>>>> --
>>>>>>>> 
>>>>>>>> Tangent for us Log4j devs:
>>>>>>>> 
>>>>>>>> It sure is lame that java.text.Format still uses a StringBuffer 
>>>>>>>> internally instead of a StringBuilder, which would be faster.
>>>>>>>> 
>>>>>>>> Looking at reusing Commons Lang's FastDateParser would not help since 
>>>>>>>> it does not add StringBuilder version of the StringBuffer APIs.
>>>>>>>> 
>>>>>>>> Gary
>>>>>>>> 
>>>>>>>> 
>>>>>>>>> On Thu, Jul 2, 2015 at 1:26 AM, [email protected] <[email protected]> 
>>>>>>>>> wrote:
>>>>>>>>> Sorry, looks that I forgot to attach the thread dump file. 
>>>>>>>>> 
>>>>>>>>> [email protected]
>>>>>>>>>  
>>>>>>>>> From: [email protected]
>>>>>>>>> Date: 2015-07-02 16:25
>>>>>>>>> To: log4j-dev
>>>>>>>>> Subject: Re: Re: Log4j2 RollingFileAppender deadlock issue
>>>>>>>>> Thanks Gary for the reply.
>>>>>>>>> The log related stuff is:
>>>>>>>>> 
>>>>>>>>> <log4j2.version>2.0.2</log4j2.version> 
>>>>>>>>> <log4j.version>1.2.16</log4j.version>
>>>>>>>>> <slf4j.version>1.7.7</slf4j.version>
>>>>>>>>> 
>>>>>>>>> I have the thread dump in question ,and attach it in the attachment.
>>>>>>>>> 
>>>>>>>>> Thanks you!
>>>>>>>>> 
>>>>>>>>> [email protected]
>>>>>>>>>  
>>>>>>>>> From: Gary Gregory
>>>>>>>>> Date: 2015-07-02 15:57
>>>>>>>>> To: Log4J Developers List
>>>>>>>>> Subject: Re: Log4j2 RollingFileAppender deadlock issue
>>>>>>>>> Hello,
>>>>>>>>> 
>>>>>>>>> What version of Log4j are you using?
>>>>>>>>> 
>>>>>>>>> Can you post the whole thread dump? You can capture it from VisualVM 
>>>>>>>>> (jvisualvm) which ships with the JDK).
>>>>>>>>> 
>>>>>>>>> Gary
>>>>>>>>> 
>>>>>>>>>> On Wed, Jul 1, 2015 at 10:36 PM, [email protected] <[email protected]> 
>>>>>>>>>> wrote:
>>>>>>>>>> 
>>>>>>>>>> Hi,log4j developers,
>>>>>>>>>> 
>>>>>>>>>> I am using log4j2 to do log. Recently I have encountered an 
>>>>>>>>>> RollingFileAppender deadlock issue from time to time which happens 
>>>>>>>>>> around 12:00 am ~03:00am. 
>>>>>>>>>> When I dump the thread, there are lots of BLOCKED threads that 
>>>>>>>>>> waiting for the lock 0x00000007a2cecaa0.
>>>>>>>>>> 
>>>>>>>>>> Following is my log4j configuration in log4j2.xml:
>>>>>>>>>> 
>>>>>>>>>> <RollingFile name="rolling" fileName="/data/logs/app/server.log" 
>>>>>>>>>> filePattern="/data/logs/app/server.log.%d{yyyy-MM-dd}"> 
>>>>>>>>>> <PatternLayout pattern="[%-5level] [%d{yyyy-MM-dd HH:mm:ss}] 
>>>>>>>>>> [%C{1}:%M:%L] %m%n" /> 
>>>>>>>>>> <Policies> 
>>>>>>>>>> <TimeBasedTriggeringPolicy /> 
>>>>>>>>>> </Policies> 
>>>>>>>>>> <DefaultRolloverStrategy max="30"/> 
>>>>>>>>>> </RollingFile>
>>>>>>>>>> 
>>>>>>>>>> Is this a bug or there is some misconfiguration in my configuration. 
>>>>>>>>>> Is there a way that I can work around this? It happens in our 
>>>>>>>>>> production environment.
>>>>>>>>>> 
>>>>>>>>>> <Catch(07-02-13-3(07-02-17-52-37).jpg>
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> [email protected]
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> -- 
>>>>>>>>> E-Mail: [email protected] | [email protected] 
>>>>>>>>> Java Persistence with Hibernate, Second Edition
>>>>>>>>> JUnit in Action, Second Edition
>>>>>>>>> Spring Batch in Action
>>>>>>>>> Blog: http://garygregory.wordpress.com 
>>>>>>>>> Home: http://garygregory.com/
>>>>>>>>> Tweet! http://twitter.com/GaryGregory
>>>>>>>>>  邮件带有附件预览链接,若您转发或回复此邮件时不希望对方预览附件,建议您手动删除链接。
>>>>>>>>> 共有 1 个附件
>>>>>>>>> Catch(07-02-13-34-56).jpg(1M)
>>>>>>>>> 极速下载 在线预览
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>> To unsubscribe, e-mail: [email protected]
>>>>>>>>> For additional commands, e-mail: [email protected]
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> -- 
>>>>>>>> E-Mail: [email protected] | [email protected] 
>>>>>>>> Java Persistence with Hibernate, Second Edition
>>>>>>>> JUnit in Action, Second Edition
>>>>>>>> Spring Batch in Action
>>>>>>>> Blog: http://garygregory.wordpress.com 
>>>>>>>> Home: http://garygregory.com/
>>>>>>>> Tweet! http://twitter.com/GaryGregory
>>>>>>>>  邮件带有附件预览链接,若您转发或回复此邮件时不希望对方预览附件,建议您手动删除链接。
>>>>>>>> 共有 1 个附件
>>>>>>>> Catch(07-02-13-3(07-02-16-25-44).jpg(1M)
>>>>>>>> 极速下载 在线预览
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> -- 
>>>>>>> E-Mail: [email protected] | [email protected] 
>>>>>>> Java Persistence with Hibernate, Second Edition
>>>>>>> JUnit in Action, Second Edition
>>>>>>> Spring Batch in Action
>>>>>>> Blog: http://garygregory.wordpress.com 
>>>>>>> Home: http://garygregory.com/
>>>>>>> Tweet! http://twitter.com/GaryGregory
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> -- 
>>>>>> E-Mail: [email protected] | [email protected] 
>>>>>> Java Persistence with Hibernate, Second Edition
>>>>>> JUnit in Action, Second Edition
>>>>>> Spring Batch in Action
>>>>>> Blog: http://garygregory.wordpress.com 
>>>>>> Home: http://garygregory.com/
>>>>>> Tweet! http://twitter.com/GaryGregory
>>>>>>  邮件带有附件预览链接,若您转发或回复此邮件时不希望对方预览附件,建议您手动删除链接。
>>>>>> 共有 1 个附件
>>>>>> Catch(07-02-13-3(07-02-17-13-37).jpg(1M)
>>>>>> 极速下载 在线预览
>>>> 
>>>> 
>>>> 
>>>> -- 
>>>> E-Mail: [email protected] | [email protected] 
>>>> Java Persistence with Hibernate, Second Edition
>>>> JUnit in Action, Second Edition
>>>> Spring Batch in Action
>>>> Blog: http://garygregory.wordpress.com 
>>>> Home: http://garygregory.com/
>>>> Tweet! http://twitter.com/GaryGregory
>> 
>> 
>> 
>> -- 
>> E-Mail: [email protected] | [email protected] 
>> Java Persistence with Hibernate, Second Edition
>> JUnit in Action, Second Edition
>> Spring Batch in Action
>> Blog: http://garygregory.wordpress.com 
>> Home: http://garygregory.com/
>> Tweet! http://twitter.com/GaryGregory
> 
> 
> 
> -- 
> E-Mail: [email protected] | [email protected] 
> Java Persistence with Hibernate, Second Edition
> JUnit in Action, Second Edition
> Spring Batch in Action
> Blog: http://garygregory.wordpress.com 
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory

Reply via email to