Skip to content

Commit

Permalink
add BIF "LogAllThreads"
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeloffner committed Dec 13, 2024
1 parent f1264c5 commit b53b0b0
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 12 deletions.
3 changes: 2 additions & 1 deletion core/src/main/java/lucee/runtime/engine/CFMLEngineImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ private CFMLEngineImpl(CFMLEngineFactory factory, BundleCollection bc) {
break;
}
// Call the dumpThreadPositions method
Controler.dumpThreadPositions(dumpPath);
Resource target = ResourcesImpl.getFileResourceProvider().getResource(dumpPath);
Controler.dumpThreadPositions(target);

// Pause for the specified interval
SystemUtil.sleep(interval);
Expand Down
8 changes: 1 addition & 7 deletions core/src/main/java/lucee/runtime/engine/Controler.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import lucee.commons.io.log.Log;
import lucee.commons.io.log.LogUtil;
import lucee.commons.io.res.Resource;
import lucee.commons.io.res.ResourcesImpl;
import lucee.commons.io.res.filter.ExtensionResourceFilter;
import lucee.commons.io.res.filter.ResourceFilter;
import lucee.commons.io.res.util.ResourceUtil;
Expand Down Expand Up @@ -198,8 +197,7 @@ else if (time > TIMEOUT) {
}
}

public static void dumpThreadPositions(String path) throws IOException {
Resource target = ResourcesImpl.getFileResourceProvider().getResource(path);
public static void dumpThreadPositions(Resource target) throws IOException {

StackTraceElement[] stes;
String line;
Expand Down Expand Up @@ -239,10 +237,6 @@ private static void dumpThreads() {

}

public static void main(String[] args) throws IOException {
dumpThreadPositions("/Users/mic/Tmp3/tmp/data.jsonl");
}

private void control(CFMLFactoryImpl[] factories, boolean firstRun, Log log) {
long now = System.currentTimeMillis();
boolean do10Seconds = last10SecondsInterval + 10000 < now;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

package lucee.runtime.functions.system;

import java.io.IOException;

import lucee.commons.io.SystemUtil;
import lucee.commons.io.res.Resource;
import lucee.commons.io.res.util.ResourceUtil;
import lucee.runtime.PageContext;
import lucee.runtime.engine.Controler;
import lucee.runtime.exp.FunctionException;
import lucee.runtime.exp.PageException;
import lucee.runtime.ext.function.Function;
import lucee.runtime.op.Caster;

public final class LogAllThreads implements Function {

private static final long serialVersionUID = -1922482127354478506L;

public static String call(PageContext pc, String path) throws PageException {
return call(pc, path, 10, 10000);
}

public static String call(PageContext pc, String path, Number interval) throws PageException {
return call(pc, path, interval, 10000);
}

public static String call(PageContext pc, String path, Number interval, Number duration) throws PageException {
Resource res = ResourceUtil.toResourceNotExisting(pc, path);
if (!res.getParentResource().isDirectory())
throw new FunctionException(pc, "LogAllThreads", 1, "path", "the directory [" + res.getParent() + "] for your log file [" + path + "] does not exist.");

int tmp = Caster.toIntValue(interval);
if (tmp < 1) tmp = 10;
final long interv = tmp;

long ltmp = Caster.toLongValue(duration);
if (ltmp < 1) ltmp = 10000;
final long dur = ltmp;

long start = System.currentTimeMillis();
// Create a new thread to run the task
Thread thread = new Thread(() -> {
while (true) {
try {
if ((start + dur) < System.currentTimeMillis()) {
break;
}
// Call the dumpThreadPositions method
Controler.dumpThreadPositions(res);

// Pause for the specified interval
SystemUtil.sleep(interv);
}
catch (IOException e) {
SystemUtil.sleep(1000);
}
}
});

// Start the thread
thread.start();
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -568,8 +568,10 @@ static Type _writeOutFirstBIF(BytecodeContext bc, BIF bif, int mode, boolean las
}
ArrayList<FunctionLibFunctionArg> list = bif.getFlf().getArg();
lucee.transformer.dynamic.meta.Method method = getMethod(clazzz, list, rtnType, bc, line);
if (method == null) throw new TransformerException(bc, "not matching method founf for function [" + bif.getName() + "]", line);

if (method == null) {
throw new TransformerException(bc, "not matching method found for function [" + bif.getName() + "] in class [" + clazzz.getDeclaringClass().getName()
+ "] with return type [" + rtnType.getClassName() + "], when developing clear dynclasses folder", line);
}
Iterator<FunctionLibFunctionArg> it = list.iterator();

argTypes = method.getArgumentTypes();
Expand Down
75 changes: 75 additions & 0 deletions core/src/main/java/resource/fld/core-base.fld
Original file line number Diff line number Diff line change
Expand Up @@ -9533,6 +9533,81 @@ The following things are considered to be empty:
<type>number</type>
</return>
</function>
<!-- LogAllThreads -->
<function>
<name>LogAllThreads</name>
<class>lucee.runtime.functions.system.LogAllThreads</class>
<keywords>system,log,debugging,threads,performance,analysis</keywords>
<description>
Creates detailed thread stack trace logs in JSONL format for performance analysis and debugging.
This function captures stack traces from all running threads at specified intervals for a given duration.
It executes asynchronously, returning immediately after starting the logging process, making it ideal
for analyzing specific code segments by initiating logging just before the target code execution.

The output format is JSONL (JSON Lines), where each line represents a separate JSON object containing:
- Timestamp offset in milliseconds from 1/1/1970 00:00:00 UTC (Unix 0)
- Complete stack trace of each thread's current location

This data can be used for:
- Performance bottleneck identification
- Thread behavior analysis
- Deadlock detection
- Resource usage patterns
</description>

<argument>
<name>path</name>
<type>string</type>
<required>true</required>
<description>
Full file path where the log will be written. The file should have a '.jsonl' extension
for proper identification as a JSON Lines format file. The function will create the file
if it doesn't exist, or append to it if it does.

Example: "/var/log/lucee/thread_analysis.jsonl"
</description>
</argument>

<argument>
<name>interval</name>
<type>number</type>
<required>false</required>
<default>10</default>
<description>
The time interval (in milliseconds) between stack trace captures. Lower values provide
more detailed analysis but generate larger log files and may impact performance.

Recommended ranges:
- 1-10ms: Very detailed analysis, higher overhead
- 10-100ms: Balanced detail and performance
- 100ms+: Lower detail, minimal performance impact
</description>
</argument>

<argument>
<name>duration</name>
<type>number</type>
<required>false</required>
<default>10000</default>
<description>
Total duration (in milliseconds) for which the function will collect thread data.
After this period, logging automatically stops.

Common durations:
- 1000-5000ms: Quick snapshots
- 10000ms: Standard analysis period
- 30000ms+: Extended analysis for complex operations
</description>
</argument>

<return>
<type>void</type>
<description>
Returns immediately without waiting for logging completion. The logging process
continues in the background for the specified duration.
</description>
</return>
</function>

<!-- lTrim -->
<function>
Expand Down
2 changes: 1 addition & 1 deletion loader/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<project default="core" basedir="." name="Lucee"
xmlns:resolver="antlib:org.apache.maven.resolver.ant">

<property name="version" value="7.0.0.80-SNAPSHOT"/>
<property name="version" value="7.0.0.81-SNAPSHOT"/>

<taskdef uri="antlib:org.apache.maven.resolver.ant" resource="org/apache/maven/resolver/ant/antlib.xml">
<classpath>
Expand Down
2 changes: 1 addition & 1 deletion loader/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.lucee</groupId>
<artifactId>lucee</artifactId>
<version>7.0.0.80-SNAPSHOT</version>
<version>7.0.0.81-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Lucee Loader Build</name>
Expand Down

0 comments on commit b53b0b0

Please sign in to comment.