Log4J2 SizeBasedT​riggeringP​olicy not working properly - log4j2

I use the latest build log4j2 beta9, it seem the RollingRandomAccessFile and RollingRandomAccessFile not working properly
Yes, it create archive after reach the specific file size limit but after that, log file's size keep increase (i.e not roll over) and that is only one achieve create even I had set the max to 3.
Here my appender setting for log4j2.xml. Any help?
<RollingRandomAccessFile name="RollingRandomAccessFile" fileName="d:/logs/mylog.log"
filePattern="d:/logs/$${date:yyyy-MM}/idmIntg-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout>
<Pattern>%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="20 KB"/>
</Policies>
<DefaultRolloverStrategy max="3"/>
</RollingRandomAccessFile>

You may have found a bug. Can you raise this issue at https://issues.apache.org/jira/browse/LOG4J2 ?
Please include your log4j2.xml and any other details that may be relevant (OS, java version).

Configuration does not work properly on tomcat-6.For 20 MB log file, after tomcat server restart on first run, it works fine and archive files but on other turns, it does not archive log file even it is bigger than 20MB.
if you configure as 10 KB, it works fine.
I just report issue to the Log4j team.

Related

Programmatically change the filename that a Log4j2 RollingFileAppender writes to at runtime

My organization is migrating from Log4j1 to Log4j2. We have a custom rolling file appender that changes the filename that it logs to at runtime when a certain event occurs in the application. This is implemented so that it's easy to find the log file in the log directory. For example the log file directory might look like this;
mylog-2021-08-02.log
mylog-2021-08-03.log
SPECIAL_EVENT_mylog-2021-08-03.log
mylog-2021-08-04.log
mylog-2021-08-05.log
Based on the research I've done it appears that Appender filenames are immutable and I'd have to create a new Appender and add it to the configuration when the event occurs, then when the triggering policy is signaled remove this Appender and add back a new Appender for the original configuration? Is there a more elegant solution than this? Do I need to write a custom appender and handle the file naming/rollover logic myself?
Update 9/2/2021
Thanks for the answer #D.B. this helped me learn quite a bit about Log4j2. The question that you reference is very similar to my situation. We have many devices, and each device needs to log to its own file. I do have some additional requirements though. We have many threads in each device which need to log to the same device log file and many devices that each need their own log file. Additionally, I need to handle the special rollover file naming requirement (original post) when a particular event occurs in the device. Finally, the name assigned to each device is not known until runtime (its defined in another configuration file we have).
I could use markers, like you suggest, but this can quickly become difficult to maintain since developers would need to know they have to pass a marker with every logging statement and the entire existing code base would need to be updated to pass the appropriate marker. I also could use a context map as you suggest but the application has many threads and again developers would need to know they have to set the context data appropriately before logging from any thread.
With Log4j1 these requirements were met by:
A custom appender class derived from RollingFileAppender that handled the special event file naming rollover logic.
A custom filter that accepted events that met the following criteria:
a. The thread name the event came from included “device name” of the device
b. The event message included “device name”
When a new device is instantiated in the system:
a. A new custom filter is created with the “device name” string to filter on.
b. A new custom appender is created that logs to a file named “device name”.log. This appender is created with the custom filter.
c. The appender is added as reference to the Root logger
This results in all log events being sent to the new appender (and every other device appender that is created) but the log events are filter based on the “device name”. This results in a device specific log file.
I could implement a custom filter and appender like we did with Log4j1 but I’d prefer not to be dependent upon the logging core classes. Any additional recommendations you have would be greatly appreciated.
You can achieve it by using ThreadContext.
My configuration file is as following
<Routes pattern="$${ctx:logName}">
<Route>
<RollingRandomAccessFile name="Rolling-Random-Access-File-Appender" fileName="${ctx:logName}.log" filePattern="${ctx:logName}.log.%d{yyyy-MM-dd-hh-mm-ss}.gz">
<PatternLayout pattern="%msg %n"/>
<Policies>
<SizeBasedTriggeringPolicy size="50 MB"/>
</Policies>
</RollingRandomAccessFile>
</Route>
</Routes>
Put some thread context where you write your log like following
ThreadContext.put("logName", fileName);
log4j2logger.log(level, logMessage);

config.xml gets overwritten everytime

I've started my first phonegap application today. I have a text input and I want the native iOS keyboard to show up when focus()
Well, the documentation says I should open the appname/platforms/ios/appname/config.xml and change
<preference name="KeyboardDisplayRequiresUserAction" value="true" />
to
<preference name="KeyboardDisplayRequiresUserAction" value="false" />
which I did. But whenever I try to run it after rebuild the value keeps change back to "true".
In fact, I can't edit the config.xml at all because after compilation it always gets overwritten with original contents.
Not sure why making the keyboard to show up is this difficult.
Can anyone help me with this problem please?
Thanks.
Now cordova maintains two config files. one at root directory and one specific to platform. if you are using CLI you should not edit platform specific files. these will be replaced when you run build or run command. You should edit root config file. Hope it will help.
I've figured it out. It was something to do with the emulator. I had to toggle keyboard from the menu in order to get it to pop up.

Service installation fails as event source already exists

I'm trying to configure a Topshelf-based Windows service to log to a custom event log using Topshelf.Log4Net and log4net. This works fine if I run the application in command-line mode. When I try to install the service with BillsTestService.exe install, I get:
INFO Topshelf v3.1.107.0, .NET Framework v4.0.30319.18052
DEBUG Attempting to install 'BillsTestService'
Running a transacted installation.
...
Service BillsTestService has been successfully installed.
Creating EventLog source BillsTestService in log Application...
An exception occurred during the Install phase.
System.ArgumentException: Source BillsTestService already exists on the local computer.
...
at System.Diagnostics.EventLog.CreateEventSource(EventSourceCreationData sourceData)
I've tried running EventLog.DeleteEventSource("BillsTestService"); in LINQPad before installing; that succeeds, but a subsequent service install still fails.
My log4net appender configuration is:
<appender name="ErrorEventLogAppender" type="log4net.Appender.EventLogAppender" >
<threshold value="ERROR" />
<logName value="MyCompanyServices" />
<applicationName value="BillsTestService" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %logger - %message%newline" />
</layout>
</appender>
What am I doing wrong?
The intent is to have multiple services log errors to the same log name (with different application names); the log would be created by Operations.
Part of the issue is that Topshelf automatically creates an eventlog source named after the service when you install. Since the log4net appender applicationName is also used as an eventlog source, that cannot be the actual application/service name. The source must be unique on the local computer. I added a "Source" suffix to the name in the log4net configuration.
The other part is that the service does not have rights to create the log. It can create a new source, but not a new log. One way to do this is in code (I used LINQPad):
EventLog.CreateEventSource("FOODEBUG", "MyCoSvc");
EventLog mylog = new EventLog("MyCoSvc");
mylog.Source = "FOODEBUG";
mylog.WriteEntry("This is a test.");
EventLog.DeleteEventSource("FOODEBUG");
I'm not positive if you actually have to write to the log to create it; after spending over two days on this, I'd rather be safe.
Also note that log names are limited to 8 characters; you can go longer, but the system only considers the first 8 characters as significant.
There's no need to move the log4net initialization as Chris Patterson suggested. Simply including
configurator.DependsOnEventLog();
configurator.UseLog4Net("MyService.exe.config");
in the HostFactory.Run delegate is sufficient. (I'm using Topshelf.Log4Net.)
Finally, I'm reasonably sure that the entire Windows event logging system is flaky. Event Viewer's refresh doesn't work in all cases, at one point my Application log entries disappeared, and I believe I've seen different results after a reboot.
Move your log4net initialization to the ConstructUsing() configuration delegate for the service instead of specifying for use during install/uninstall which doesn't require the service class to be instantiated.
Or, only use the event log appender when the actual service is running, by either adding the appender outside of the config file or modifying the configuration to eliminate the event log appender unless an ERROR or FATAL event occurs.
My guess is the DEBUG/INFO level events are trying to log to the appender, and the source does not exist yet.

Log4j2 SMTP Appender

I'm trying to log errors through email using Log4j2.
For that purpose Log4j2 defines the SMTPAppender, and an example configuration is provided to use in the XML config file, which is like:
<appenders>
<SMTP name="Mail" suppressExceptions="false" subject="Error Log" to="errors#logging.apache.org"
from="test#logging.apache.org" smtpHost="localhost" smtpPort="25" bufferSize="50">
</SMTP>
</appenders>
So everything should be fine. But when i start the application and force an error to log i receive this message:
ERROR Error processing element SMTP: CLASS_NOT_FOUND
Ok, now what to do? the documentation gives a hint, plugins, and packages should be used, both of which have little documentation, and no examples.
I got another hint in: ClassNotFoundException javax.mail.internet.AddressException when running hibernate3:hbm2ddl but this is log4j2 and not log4j.
Any help is, of course, greatly appreciated.
The answer was easy.
After reading this https://blogs.apache.org/logging/entry/apache_log4j_2_0_beta4
I downloaded the beta4 (i had the beta3) and now i have other problems, but the appender works.

Windows Service running as a logged-in user has access issues b/c of UAC

I have a Windows service that runs as a logged-in user (local admin). During start-up, I get a message along the lines: "Unable to generate a temporary class (result=1)".
So, I went to windows/temp folder and was prompted by UAC to elevate my privileges -- after I did this, the service would start up fine. So, how do I deal with this UAC prompt from the perspective of a Windows Service?
Thanks!
Regarding the original question - beyond the specific problem of event order that fixed your symptoms.When an user who is a member of the Local Administrators group logs on to a machine under UAC, two security tokens are granted - one with limited rights, and one with the higher permission set. By default, the lower permissions are used - unless the higher is actively specified. The primary means of specifying is through the UI - as you did. The other method is to use an application manifest: an XML file that specifies how the OS is to treat this application. The manifest file should be placed in the same folder as the executable, and named using the following format: "my_application_name.exe.manifest" The XML in the manifest will look something like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" name="MY_APPLICATION_NAME" type="win32"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
I'm sure you can find a bunch more specific info by googling "UAC Manifest" ...
Hope this is useful ...
I solved my problem even though I still don't know how to answer my question. Basically, my service was inheriting the temp directory from the bootstrapping process, so I changed it to use current's users' temp dir. You will need to do something along these lines:
myProcess.StartInfo.EnvironmentVariables.Add("TempPath", "C:\Temp")
Why not have the Windows Service run as LocalSystem?

Resources