帆软报表设计器源代码。
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.
 
 
 
 

159 lines
5.5 KiB

package com.fr.design.carton.latency;
import com.fanruan.third.v2.org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
import com.fr.concurrent.FineExecutors;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.config.MarketConfig;
import com.fr.design.DesignerEnvManager;
import com.fr.design.carton.SwitchForSwingChecker;
import com.fr.design.mainframe.SiteCenterToken;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONObject;
import com.fr.stable.ProductConstants;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import com.fr.workspace.WorkspaceEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static com.fr.design.carton.CartonConstants.APPID;
import static com.fr.design.carton.CartonConstants.DESIGNER_ID;
import static com.fr.design.carton.CartonConstants.DESIGNER_VERSION;
import static com.fr.design.carton.CartonConstants.DESIGN_METHOD;
import static com.fr.design.carton.CartonConstants.LOCAL;
import static com.fr.design.carton.CartonConstants.OPERANDS_NUM;
import static com.fr.design.carton.CartonConstants.REMOTE;
import static com.fr.design.carton.CartonConstants.TIME;
import static com.fr.design.carton.CartonConstants.USERID;
/**
* 设计器延迟时间记录Metric
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/07/01
*/
public class DesignerLatencyMetric {
private ExecutorService executorService;
private ScheduledExecutorService scheduler;
private static final Map<LatencyLevel, AtomicInteger> LATENCY_CONTAINER = new ConcurrentHashMap<>();
private static final String LATENCY_INFO_URL = "https://cloud.fanruan.com/api/monitor/record_of_deisgner_latency/single";
private final static class InstanceHolder {
static final DesignerLatencyMetric INSTANCE = new DesignerLatencyMetric();
}
/**
* 获取单例
*/
public static DesignerLatencyMetric getInstance() {
return DesignerLatencyMetric.InstanceHolder.INSTANCE;
}
private DesignerLatencyMetric() {
}
/**
* 启动
*/
public void start() {
if (SwitchForSwingChecker.isLatencyMonitoring()) {
// 初始化容器
initializeContainer();
// 启动异步性能记录线程池
executorService = FineExecutors.newCachedThreadPool(
new NamedThreadFactory(DesignerLatencyMetric.class));
// 启动定时埋点
this.scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("LatencyMetricWorker"));
this.scheduler.scheduleWithFixedDelay(this::collectAndSubmit, 60, 60, TimeUnit.SECONDS);
// 注册设计器工作目录切换事件监听
EventDispatcher.listen(WorkspaceEvent.AfterSwitch, new Listener<Workspace>() {
@Override
public void on(Event event, Workspace param) {
collectAndSubmit();
}
});
}
}
/**
* 关闭
*/
public void stop() {
if (SwitchForSwingChecker.isLatencyMonitoring()) {
if (this.executorService != null) {
this.executorService.shutdown();
}
if (this.scheduler != null) {
this.scheduler.shutdown();
}
collectAndSubmit();
}
}
private void initializeContainer() {
for (LatencyLevel level : LatencyLevel.values()) {
LATENCY_CONTAINER.put(level, new AtomicInteger());
}
}
private void resetContainer() {
LATENCY_CONTAINER.values().forEach(count -> count.set(0));
}
/**
* 记录性能信息
*/
public void record(long cost) {
executorService.submit(() -> {
try {
LatencyLevel level = LatencyLevel.measure(cost);
LATENCY_CONTAINER.computeIfAbsent(level, k -> new AtomicInteger()).incrementAndGet();
} catch (Throwable ignore) {
// 记录失败不影响业务
}
});
}
/**
* 汇总并提交性能监控埋点
*/
public void collectAndSubmit() {
Map<String, Object> para = new HashMap<>();
para.put("token", SiteCenterToken.generateToken());
para.put("content", collect());
try {
HttpToolbox.post(LATENCY_INFO_URL, para);
} catch (Throwable ignore) {
// doNothing
}
resetContainer();
}
private JSONObject collect() {
JSONObject info = new JSONObject();
info.put(TIME, System.currentTimeMillis());
info.put(APPID, MarketConfig.getInstance().getCloudOperationMaintenanceId());
info.put(USERID, MarketConfig.getInstance().getBbsUid());
info.put(DESIGNER_ID, DesignerEnvManager.getEnvManager().getUUID());
info.put(DESIGNER_VERSION, ProductConstants.DESIGNER_VERSION);
info.put(DESIGN_METHOD, WorkContext.getCurrent().isLocal() ? LOCAL : REMOTE);
info.put(OPERANDS_NUM, LATENCY_CONTAINER.values().stream().mapToInt(AtomicInteger::get).sum());
for (Map.Entry<LatencyLevel, AtomicInteger> entry : LATENCY_CONTAINER.entrySet()) {
info.put(entry.getKey().getMark(), entry.getValue().get());
}
return info;
}
}