帆软报表设计器源代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

319 lines
13 KiB

package com.fr.design.carton;
import com.fr.design.i18n.Toolkit;
import com.fr.general.GeneralUtils;
import com.fr.json.JSON;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLWriter;
import com.fr.stable.xml.XMLableReader;
import sun.awt.AppContext;
import javax.swing.SwingWorker;
import java.io.IOException;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Date;
import java.util.Calendar;
import static com.fr.design.carton.CartonConstants.DEBUG_MAIN_CLASS_NAME;
import static com.fr.design.carton.CartonConstants.EASY_CHECKER_FILE_NAME;
import static com.fr.design.carton.CartonConstants.JOURNAL_FILE_PATH;
import static com.fr.design.carton.CartonConstants.TIMER_CHECKER_FILE_NAME;
public class SwitchForSwingChecker implements XMLReadable, XMLWriter {
/**
* XML标签
*/
public static final String XML_TAG = "SwitchForSwingChecker";
/**
* 定时任务的开关
*/
private static boolean checkerTimerSwitch = false;
/**
* 简单记录事件执行时间的开关
*/
private static boolean easyChecker = false;
/**
* UI性能监控埋点的开关
*/
private static boolean latencyMonitor = true;
/**
* 一个标识位用于区分耗时任务时长检测(简单检测)和timer检测
*/
public static final int TIMER_CHECK_FLAG = 0;
public static final int EASY_CHECK_FLAG = 1;
public static boolean isCheckerTimerSwitch() {
return checkerTimerSwitch;
}
public static boolean isEasyChecker() {
return easyChecker;
}
/**
* 是否开启UI性能检测
*/
public static boolean isLatencyMonitoring() {
return latencyMonitor;
}
public static volatile SwitchForSwingChecker switchForSwingChecker = new SwitchForSwingChecker();
public static SwitchForSwingChecker getInstance() {
return switchForSwingChecker;
}
public static void startTimerChecker() {
if (!checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.initTimer();
CartonThreadExecutorPool.getTimerThreadExecutorPool().initTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(true);
checkerTimerSwitch = true;
if (!easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.startFilterModalWindow();
}
}
}
public static void stopTimerChecker() {
if (checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.stopTimer();
CartonThreadExecutorPool.getTimerThreadExecutorPool().stopTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(false);
checkerTimerSwitch = false;
if (!easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.stopFilterModalWindow();
}
}
}
public static void startEasyChecker() {
if (!easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(true);
CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(true);
easyChecker = true;
if (!checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.startFilterModalWindow();
}
}
}
public static void stopEasyChecker() {
if (easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(false);
CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(false);
easyChecker = false;
if (!checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.stopFilterModalWindow();
}
}
}
/**
* 获取文件名字以及判断文件是否存在
*/
private static CartonFiles getFiles(String date) {
String[] split = date.split("-");
int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]);
String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date);
File file1 = new File(StableUtils.pathJoin(dirPath, EASY_CHECKER_FILE_NAME));
File file2 = new File(StableUtils.pathJoin(dirPath, TIMER_CHECKER_FILE_NAME));
File[] files = new File[2];
files[0] = file1;
files[1] = file2;
CartonFiles cartonFiles = new CartonFiles();
cartonFiles.setEasyCheckerFile(file1);
cartonFiles.setTimerCheckerFile(file2);
return cartonFiles;
}
/**
* 处理文件
* 一共四种情况,
* 两个文件都不存在
* 文件一存在,文件二不存在
* 文件二存在,文件一不存在
* 两个文件都存在
*/
private static List<CartonUploadMessage> getCartonLog(File easyFile, File timerFile) {
List<CartonUploadMessage> res = new ArrayList<>();
List<CartonUploadMessage> easyFileCartonLog = getEasyFileCartonLog(easyFile);
List<CartonUploadMessage> timerFileCartonLog = getTimerFileCartonLog(timerFile);
Map<String, CartonUploadMessage> easyFileMap = new HashMap<>();
for (CartonUploadMessage cartonUploadMessage : easyFileCartonLog) {
easyFileMap.put(cartonUploadMessage.getHangCount(), cartonUploadMessage);
res.add(cartonUploadMessage);
}
for (CartonUploadMessage cartonUploadMessage : timerFileCartonLog) {
String hangCount = cartonUploadMessage.getHangCount();
if (easyFileMap.containsKey(hangCount)) {
cartonUploadMessage.setThreadTime(easyFileMap.get(hangCount).getThreadTime());
}
res.add(cartonUploadMessage);
}
return res;
}
private static List<CartonUploadMessage> getTimerFileCartonLog(File file) {
List<CartonUploadMessage> res = new ArrayList<>();
try {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[");
BufferedReader bufferedReader1 = new BufferedReader(new FileReader(file));
String line1;
while ((line1 = bufferedReader1.readLine()) != null) {
stringBuilder.append(line1);
}
bufferedReader1.close();
stringBuilder.append("]");
JSONArray easyCheckerJSON = JSON.ARRAY.createJSON(GeneralUtils.objectToString(stringBuilder));
for (Object jsonObject : easyCheckerJSON) {
CartonUploadMessage cartonUploadMessage = new CartonUploadMessage();
JSONObject x = (JSONObject) jsonObject;
cartonUploadMessage.setHangCount(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number")));
cartonUploadMessage.setSlowTime(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time")));
cartonUploadMessage.setThreadTime("undefined");
//这个跟输出到文件中的格式匹配,参考EventDis里的stackTraceToString方法
String indentation = " ";
String logMessage = x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info")).replaceAll(indentation, "\r\n ");
cartonUploadMessage.setInfo(logMessage);
res.add(cartonUploadMessage);
}
} catch (IOException e) {
FineLoggerFactory.getLogger().error("upload fail", e);
}
return res;
}
private static List<CartonUploadMessage> getEasyFileCartonLog(File file) {
List<CartonUploadMessage> res = new ArrayList<>();
try {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[");
BufferedReader bufferedReader1 = new BufferedReader(new FileReader(file));
String line1;
while ((line1 = bufferedReader1.readLine()) != null) {
stringBuilder.append(line1);
}
bufferedReader1.close();
stringBuilder.append("]");
JSONArray timerCheckerJSON = JSON.ARRAY.createJSON(GeneralUtils.objectToString(stringBuilder));
for (Object jsonObject : timerCheckerJSON) {
JSONObject x = (JSONObject) jsonObject;
CartonUploadMessage cartonUploadMessage = new CartonUploadMessage();
cartonUploadMessage.setHangCount(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number")));
cartonUploadMessage.setSlowTime(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time")));
cartonUploadMessage.setThreadTime(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time")));
cartonUploadMessage.setInfo("undefined");
res.add(cartonUploadMessage);
}
} catch (IOException e) {
FineLoggerFactory.getLogger().error("upload fail", e);
}
return res;
}
/**
* /埋点方法上传卡顿信息入口
* date为 2022-09-08的格式
*/
public static List<CartonUploadMessage> uploadJournalLog(Date dateTime) {
List<CartonUploadMessage> res = new ArrayList<>();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
CartonFiles files = getFiles(simpleDateFormat.format(dateTime));
File easyCheckerFile = files.getEasyCheckerFile();
File timerCheckerFile = files.getTimerCheckerFile();
if (easyCheckerFile.exists() && timerCheckerFile.exists()) {
return getCartonLog(easyCheckerFile, timerCheckerFile);
} else if (easyCheckerFile.exists()) {
return getEasyFileCartonLog(easyCheckerFile);
} else if (timerCheckerFile.exists()) {
return getTimerFileCartonLog(timerCheckerFile);
} else {
return res;
}
}
/**
* 初始化监控任务,主要是替换EventQueue以及SwingWorker执行任务的线程池
*/
public static void initThreadMonitoring() {
String mainClass = System.getProperty("sun.java.command");
//判断一下,如果是以Designer4Debug启动,就不注册代码,不然会覆盖掉SwingExplorer,导致其无法使用
if (!StringUtils.equals(mainClass, DEBUG_MAIN_CLASS_NAME)) {
EventDispatchThreadHangMonitor.initMonitoring();
AppContext.getAppContext().put(SwingWorker.class, CartonThreadExecutorPool.getTimerThreadExecutorPool());
}
}
/**
* 判断是否有指定日期的卡顿日志,没有就返回false
*/
public static boolean isCartonExists(Date date) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String format = simpleDateFormat.format(date);
Calendar calendar = Calendar.getInstance();
int month = calendar.get(Calendar.MONTH) + 1;
int year = calendar.get(Calendar.YEAR);
File file = new File(StableUtils.pathJoin(JOURNAL_FILE_PATH, String.valueOf(year), "month-" + month, format));
return file.exists();
}
public static boolean isCartonExists() {
return isCartonExists(new Date());
}
private void initSwitchChecker() {
if (easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(true);
CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(true);
}
if (checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.initTimer();
CartonThreadExecutorPool.getTimerThreadExecutorPool().initTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(true);
}
if (easyChecker || checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.startFilterModalWindow();
}
}
@Override
public void readXML(XMLableReader reader) {
if (reader.isAttr()) {
checkerTimerSwitch = reader.getAttrAsBoolean("checkerTimerSwitch", false);
easyChecker = reader.getAttrAsBoolean("easyChecker", false);
latencyMonitor = reader.getAttrAsBoolean("latencyMonitor", true);
}
try {
initSwitchChecker();
} catch (Throwable t) {
FineLoggerFactory.getLogger().error("read checker attr fail", t);
}
}
@Override
public void writeXML(XMLPrintWriter writer) {
writer.startTAG(XML_TAG);
writer.attr("checkerTimerSwitch", checkerTimerSwitch);
writer.attr("easyChecker", easyChecker);
writer.attr("latencyMonitor", latencyMonitor);
writer.end();
}
}