Custom Log4j rollover script to automatically delete logs once the filesystem usage exceeds a specific threshold

Utilizing log4j for logging in my application has been beneficial. I am now exploring the option to automatically delete compressed files when the filesystem reaches 80 percent usage. While log4j lacks a built-in appender for this task, it does offer the ScriptCondition feature as a workaround. Although the official log4j documentation suggests using Groovy scripts (which we currently do not have installed), it also mentions that JavaScript and Nashorn can be viable alternatives. To experiment, I created a simple test script.

<configuration status="trace" name="REST Servlet Logging Configuration">
        <Properties>
                <Property name="xx">xx</Property>
        </Properties>
        <appenders>
                <RollingFile name="xx"
                        fileName="xx"
                        filePattern="xx.log.%i.gz" append="true"
                        bufferedIO="true" immediateFlush="false" fileOwner="xx"
                        fileGroup="xx" filePermissions="rw-r-----">
                        <Policies>
                                <SizeBasedTriggeringPolicy size="4 MB" />
                        </Policies>
                        <DefaultRolloverStrategy max="100" fileIndex="min">
                        <Delete basePath="${xx}" maxDepth="1">
                        <ScriptCondition>
                        <Script name="superstitious" language="javascript"><![CDATA[
                             var  exec  = require('child_process');
                                exec("df -h / | tail -1 | tr -s ' ' | cut -d' ' -f4", (error, stdout, stderr) => {
                                        if(error) {
                                                 console.log('error: ${error.message}');
                                                 return;
                                         }
                                        if(stderr) {
                                                console.log('stderr: ${stderr}');
                                                return;
                                        }
                                         console.log('stdout: ${stdout}');
                                        statusLogger.trace("stdout in trace :${stdout}");
                                });
                            statusLogger.trace("running javascript");
                            result;
                        ]]>
                        </Script>
                    </ScriptCondition>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

While the logs confirm the mention of JavaScript, an error occurs relating to Nashorn instead.

05:58:46 UTC 2021 DEBUG createScript(name="superstitious", language="javascript", scriptText="var  exec  = require('child_process');
2021-11-02T05:58:47.197Z exec("df -h / | tail -1 | tr -s ' ' | cut -d' ' -f4", (error, stdout, stderr) => {
...
...

The issue persists with the compilation of Nashorn scripts despite specifying JavaScript. The difference between both scripting languages perplexes me as a beginner.

In response to suggestions, changing => to function triggers another exception.

2021-12-02T06:56:30.192Z 2021-02-12 06:56:30,185 Log4j2-TF-1-RollingFileManager-2 ERROR Error running script superstitious javax.script.ScriptException: ReferenceError: "require" is not defined in <eval> at line number 1
...
...

Answer №1

It appears that the issue arises from attempting to utilize arrow functions, a feature of ECMAScript 6, while Nashorn defaults to ECMAScript 5.1.

To address this, consider using

function (error, stdout, stderr) { … }
in place of
(error, stdout, stderr) => { … }
, which should resolve the problem.

In Summary:

Nashorn does have some support for ES6, but it requires enabling through a flag not typically supported in embeddings. This involves stepping outside the standard javax.script API and utilizing Nashorn's own API, specifically

NashornScriptEngineFactory.getScriptEngine(String...)
. You can pass necessary flags to this method as follows:

ScriptEngine engine = NashornScriptEngineFactory.getScriptEngine("--language=es6");
...

For future reference, it may be beneficial for us to offer an engine that defaults to ES6 if requested with a language parameter like "ecmascript-6". This is something worth considering further.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Convert an array into a JSON object for an API by serializing it

Currently, I am working with Angular 12 within my TS file and have encountered an array response from a file upload that looks like this- [ { "id": "7", "name": "xyz", "job": "doctor" ...

Using ReactJS to send formData to an Express API and retrieving a JSON response

Attempting to have the ReactJS frontend send a username and password from a form to my express API via a proxy, with the intention of having the API return a JSON file containing a user id. While the proxy connection is working as expected, the issue arise ...

Launch Internet Explorer and input variable values (such as ScriptEngineMinorVersion)

I am looking to create a script that can open a file and inject values into it. Here is a basic example: Set WshShell = WScript.CreateObject("WScript.Shell") Return = WshShell.Run("iexplore.exe google.com", 1) However, I also need to modify some variab ...

Navigating through the drupal module directory using JavaScript

Is there a way to retrieve the module path in Drupal 7 from which a .js file was loaded? Although JS is primarily a front-end language, is it possible that Drupal includes this information within the Drupal object? Essentially, I am trying to achieve so ...

React project automatically refreshing when local server generates new files

I have developed a tool for developers that allows them to retrieve device data from a database for a specific time period, generate plots using matplotlib, save the plots locally, and display them on a webpage. The frontend is built using create-react-app ...

Using preventDefault in the compositionend event does not make any difference

var inputNode = document.getElementById('view_1'); inputNode.addEventListener('compositionend', function(e) { console.log(e.cancelable); // true e.preventDefault(); }); <div id="view_1" class="view" contenteditable="true> &l ...

Guide on utilizing personalized fonts with Handlebars and Puppeteer

I have a Handlebar template that I am converting to PDF using Puppeteer. My question is how can I incorporate custom fonts? Currently, I have a static folder declared in my app.js file like this: app.use(express.static(path.join(__dirname, 'assets&ap ...

arranging a collection of images based on their values in increasing order

cardShop is a container with various images, each with its own unique ID and value attribute. These values consist of two numbers separated by a comma, such as 2000,500 or 1500,200. My goal is to sort these images in ascending order based on the first numb ...

Comparing elements in one array to elements in another array

In AngularJS, the $scope.categories array is populated from a multi-select element. $scope.categories = ["Adventure", "Strategy"] To compare this array with the categories in the items array below: $scope.items = [ { title: "Star Wars", ...

The Dockerfile for Next13 is unable to locate the server.js file

When using the official Dockerfile from Next with the examples provided, I encounter an error while trying to build the app using a Dockerfile and docker-compose. b78-client-1 | node:internal/modules/cjs/loader:1078 b78-client-1 | throw err; b78-client ...

"Concealing specific routes in Vue Router depending on a certain condition - what's the

I need to determine which routes to hide based on a condition that evaluates to true or false. I have a collection of routes, such as: - Products - Clients For instance, if a user logs in but does not have the permission to edit products, then the updated ...

Remix is throwing a Hydration Error while trying to process data mapping

While working on my Remix project locally, I encountered a React hydration error. One thing I noticed is that the HTML rendered by the server does not match the HTML generated by the client. This issue seems to be related to the Material UI library usage. ...

Guide on hosting two html pages on a NodeJS server

Currently, I am in the process of learning NodeJS and Javascript with a goal to construct a basic server that can host 2 HTML pages. One page should be accessible via localhost:3000/index, while the other can be reached through localhost:3000/about. While ...

Disabling the intellisense feature for locale suggestions in Monaco is recommended

Switch the keyboard language to a different one (in this case Japanese using alt + shift), and when typing in Monaco editor, an intellisense menu appears with options to remove and search. Monaco Editor Version: V0.33.0 https://i.stack.imgur.com/SIyeV.pn ...

Unusual marking on the navigation bar

Currently, I am making updates to a website that was created by a previous employee long before I joined the team. One of the requested changes is to eliminate the orange box surrounding the navigation links. The navigation appears to be generated using Ja ...

Having trouble accessing variables using the put method in Laravel with XMLHttpRequest

I am struggling to save my image data using XMLHttpRequest. Although I can send json data and see them in the developer console, I am unable to access them on the server side as the $request appears to be null. Below are snippets of my JavaScript code: ...

I need to know how to send a "put" request using JavaScript and Ajax

My task involves programmatically updating a spreadsheet using my code. I am able to write to a specific cell within the spreadsheet with the following function: function update(){ jQuery.ajax({ type: 'PUT', ...

Images that adjust to different screen sizes within a grid layout

I have four images that need to be aligned in the following layout: ____________ |1 |4 | |_____| | |2 |3| | |__|__|______| They must be flush against each other, occupy 100% of the viewport's width, and most importantly, be respon ...

Incorporate a Variety of Elements onto Your Webpage

I have developed a custom tooltip plugin using JQuery, and I am implementing it on multiple A tags. Each A tag should have a unique tooltip associated with it, so I have the following code: var $tooltip = $("<div>").attr("id", tooltip.id).attr("cla ...

Enhancing the building matrix with JavaScript (or jQuery)

I have created a custom Javascript function for extracting specific data from a matrix. The main purpose of the function is to retrieve data based on dates within a given range. Here's how it works: The matrix[0][i] stores date values I need to extr ...