blob: 4beba183b191127b6e79ca1cf89d3249544dfa9d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal.monitoring.executor;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import org.apache.logging.log4j.Logger;
import org.apache.geode.internal.monitoring.ThreadsMonitoring;
import org.apache.geode.logging.internal.log4j.api.LogService;
public abstract class AbstractExecutor {
private static final int THREAD_DUMP_DEPTH = 40;
private static final Logger logger = LogService.getLogger();
public static final String LOCK_OWNER_THREAD_STACK = "Lock owner thread stack";
private long threadID;
private String groupName;
private short numIterationsStuck;
private long startTime;
public AbstractExecutor(ThreadsMonitoring tMonitoring) {
this.startTime = System.currentTimeMillis();
this.numIterationsStuck = 0;
this.threadID = Thread.currentThread().getId();
}
public AbstractExecutor(ThreadsMonitoring tMonitoring, long threadID) {
this.startTime = System.currentTimeMillis();
this.numIterationsStuck = 0;
this.threadID = threadID;
}
public void handleExpiry(long stuckTime) {
this.incNumIterationsStuck();
logger.warn(createThreadReport(stuckTime));
}
String createThreadReport(long stuckTime) {
DateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy HH:mm:ss zzz");
ThreadInfo thread =
ManagementFactory.getThreadMXBean().getThreadInfo(this.threadID, THREAD_DUMP_DEPTH);
boolean logThreadDetails = (thread != null);
StringBuilder stringBuilder = new StringBuilder();
final String lineSeparator = System.lineSeparator();
stringBuilder.append("Thread <").append(this.threadID).append("> (0x")
.append(Long.toHexString(this.threadID)).append(") that was executed at <")
.append(dateFormat.format(this.getStartTime())).append("> has been stuck for <")
.append((float) stuckTime / 1000)
.append(" seconds> and number of thread monitor iteration <")
.append(this.numIterationsStuck).append("> ").append(lineSeparator);
if (logThreadDetails) {
stringBuilder.append("Thread Name <").append(thread.getThreadName()).append(">")
.append(" state <").append(thread.getThreadState())
.append(">").append(lineSeparator);
if (thread.getLockName() != null)
stringBuilder.append("Waiting on <").append(thread.getLockName()).append(">")
.append(lineSeparator);
if (thread.getLockOwnerName() != null)
stringBuilder.append("Owned By <").append(thread.getLockOwnerName()).append("> with ID <")
.append(thread.getLockOwnerId()).append(">").append(lineSeparator);
}
stringBuilder.append("Executor Group <").append(groupName).append(">").append(
lineSeparator)
.append("Monitored metric <ResourceManagerStats.numThreadsStuck>")
.append(lineSeparator);
if (logThreadDetails) {
writeThreadStack(thread, "Thread stack:", stringBuilder);
}
if (logThreadDetails && thread.getLockOwnerName() != null) {
ThreadInfo lockOwnerThread = ManagementFactory.getThreadMXBean()
.getThreadInfo(thread.getLockOwnerId(), THREAD_DUMP_DEPTH);
if (lockOwnerThread != null) {
writeThreadStack(lockOwnerThread, LOCK_OWNER_THREAD_STACK, stringBuilder);
}
}
return stringBuilder.toString();
}
private void writeThreadStack(ThreadInfo thread, String header, StringBuilder strb) {
final String lineSeparator = System.lineSeparator();
strb.append(header).append(lineSeparator);
for (int i = 0; i < thread.getStackTrace().length; i++) {
String row = thread.getStackTrace()[i].toString();
strb.append(row).append(lineSeparator);
}
}
public long getStartTime() {
return this.startTime;
}
public void setStartTime(long newTime) {
this.startTime = newTime;
}
public short getNumIterationsStuck() {
return this.numIterationsStuck;
}
public void incNumIterationsStuck() {
this.numIterationsStuck++;
}
public String getGroupName() {
return this.groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public long getThreadID() {
return this.threadID;
}
}