提交 389dbdd9 编写于 作者: lakernote's avatar lakernote

增加stepcountertuple

上级 486a2ac6
......@@ -61,9 +61,11 @@ public class TraceContext {
trace.getTreeView().end();
if (trace.stopSpan()) {
if (current.getCost() > time) {
// 打印日志方式一
// logSpan(trace.getSpans(), StringUtils.SPACE);
// 打印日志方式二
// 打印日志方式一 每个span 一行日志
/**
* logSpan(trace.getSpans(), StringUtils.SPACE);
*/
// 打印日志方式二 整体一颗树
String draw = trace.getTreeView().draw();
log.info(draw);
}
......
......@@ -78,15 +78,19 @@ public class TracingAspect {
// do nothing
}
//@Around("controllerAspect() || serviceAspect() || mapperAspect() || remoteAspect()")
/**
* @param pjp
* @return
* @throws Throwable
* @Around("controllerAspect() || serviceAspect() || mapperAspect() || remoteAspect()")
*/
@Around("(withinAspect() || annotationAspect()) && annotationIgnoreAspect()")
public Object around(final ProceedingJoinPoint pjp) throws Throwable {
Object obj;
TraceContext.addSpan(pjp);
try {
obj = pjp.proceed();
} catch (Exception e) {
throw e;
} finally {
TraceContext.stopSpan(time);
}
......
package com.laker.admin.framework.ext.step;
import io.micrometer.core.instrument.util.NamedThreadFactory;
import io.micrometer.core.instrument.util.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import java.time.Duration;
import java.util.Collection;
import java.util.concurrent.*;
/**
* 按步长 定期存储到任意位置,例如db
* @author laker
*/
@Slf4j
public class LakerMeterRegistry {
private final Object meterMapLock = new Object();
private Duration step;
private ScheduledExecutorService scheduledExecutorService;
private final ConcurrentMap<String, StepCounterTuple> meterMap = new ConcurrentHashMap<>();
public LakerMeterRegistry() {
this(Duration.ofMillis(1));
}
public LakerMeterRegistry(Duration step) {
this(step, new NamedThreadFactory("laker-metrics-publisher"));
}
private LakerMeterRegistry(Duration step, ThreadFactory threadFactory) {
this.step = step;
start(threadFactory);
}
public StepCounterTuple counter(String videoId) {
String id = "laker:" + videoId;
StepCounterTuple multiStepCounter = meterMap.get(id);
if (multiStepCounter == null) {
synchronized (meterMapLock) {
multiStepCounter = meterMap.get(id);
if (multiStepCounter == null) {
multiStepCounter = new StepCounterTuple(id);
StepCounterTuple old = meterMap.putIfAbsent(id, multiStepCounter);
if (old != null) {
log.warn("有并发问题 拉了裤了 " + Thread.currentThread().getName() + id);
}
}
}
}
return multiStepCounter;
}
protected void publish() {
Collection<StepCounterTuple> values = meterMap.values();
log.info("---- start 当前map 容量" + values.size());
values.stream().forEach(multiStepCounter -> {
long count1 = multiStepCounter.count1();
long count2 = multiStepCounter.count2();
// if 存在无效的数据则删除掉 防止占内存,或者 这个另起一个定时任务去删除 定时时长 更久些。
if (count1 + count2 == 0) {
String id = multiStepCounter.getId();
StepCounterTuple m = meterMap.get(id);
if (m != null) {
synchronized (meterMapLock) {
m = meterMap.remove(id);
if (m != null) {
log.info(" remove " + id);
}
}
}
}
// 不要重复调用 multiStepCounter.count() 这个方法会重置 的。模拟写入db
log.info(multiStepCounter.getId() + " count1: " + count1 + " count2: " + count2);
});
log.info("---- end 结束后 map 容量 " + values.size());
}
private void publishSafely() {
try {
publish();
} catch (Throwable e) {
log.warn("Unexpected exception thrown", e);
}
}
public void start(ThreadFactory threadFactory) {
if (scheduledExecutorService != null) {
stop();
}
log.info("publishing metrics for " + this.getClass().getSimpleName() + " every " + TimeUtils.format(step));
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(threadFactory);
scheduledExecutorService.scheduleAtFixedRate(this::publishSafely, step
.toMillis(), step.toMillis(), TimeUnit.MILLISECONDS);
}
public void stop() {
if (scheduledExecutorService != null) {
scheduledExecutorService.shutdown();
scheduledExecutorService = null;
}
}
public void close() {
publishSafely();
stop();
}
}
package com.laker.admin.framework.ext.step;
import java.util.Objects;
import java.util.concurrent.atomic.LongAdder;
/**
* <pre>
* 用于内存 聚合指标,
* 例如 视频的点赞数,观看数,按照定时步长统计 例如 60m
* id:videoid 001,count1:12,count2:12
* id:videoid 002,count1:9,count2:20
* </pre>
*
* @author laker
*/
public class StepCounterTuple {
private String id;
private final LongAdder count1 = new LongAdder();
/**
* 可以 自己扩展 count n ,double n
*/
private final LongAdder count2 = new LongAdder();
public StepCounterTuple(String id) {
this.id = id;
}
public void increment1(long amount) {
count1.add(amount);
}
/**
* 调用一次就会 获取sum 然后置位 0
*
* @return
*/
public long count1() {
return count1.sumThenReset();
}
public void increment2(long amount) {
count2.add(amount);
}
public long count2() {
return count2.sumThenReset();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
StepCounterTuple that = (StepCounterTuple) o;
return Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
public String getId() {
return id;
}
}
......@@ -12,6 +12,8 @@ import java.util.LinkedList;
import java.util.List;
/**
* 长事务监控
*
* @author: laker
* @date: 2022/10/17
**/
......
package com.laker.admin.framework.ext.step;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
/**
* @author: laker
* @date: 2022/10/23
**/
@Slf4j
public class StepCounterTest {
@SneakyThrows
@Test
public void test() {
LakerMeterRegistry lakerMeterRegistry = new LakerMeterRegistry(Duration.ofSeconds(10));
for (int i = 0; i < 30; i++) {
ThreadUtil.execute(() -> {
StepCounterTuple counter = lakerMeterRegistry.counter(RandomUtil.randomString("qwertyuiopasdfghjklzxcvbnm", 1));
counter.increment1(1);
counter.increment2(2);
});
}
TimeUnit.SECONDS.sleep(30);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册