Java实现埋点(自定义注解 + AOP + @Async)

 埋点?什么是埋点?一觉醒来感觉天塌了,听到这个需求的时候脑子一片空白,后来网上搜索了一下才知道,埋点按照我的理解就是记录用户的行为,以方便后续处理分析用户的访问数据喜好。埋点业务尽可能是异步解耦,即对主流程业务无影响。

埋点的设计思路:

        代码埋点、可视化埋点、无埋点(全埋点)

        代码埋点:每一个埋点都需要手动去添加代码,要是更新埋点方案,可能都需要改代码,技术人员的累趴下(成本比较大,而且代码容易堆积)

·      可视化埋点:这个就是前端的活了,在页面上设计点击事件,比如:按钮、页面滚动......(我一个java后端不是很了解,大家可以上网搜一下)

        无埋点(全埋点):本篇文章就是采用的无埋点的设计,这个设计方案不会修改原始业务代码,采用自定义注解 + AOP + @Async进行实现。

多的不说少的不唠咱们直接怼代码(本人亲自设计,保证能实现埋点功能):

自定义一个注解接口:

/**
 * @author YanChengHao
 * @data 2024/09/11
 * 自定义注解 作用:事件追踪【埋点】
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventTracking {

    /**
     * 事件
     */
    public String event() default "";
    /**
     * 每次访问的次数
     */
    public int count() default 1;
}

实现AOP切面拦截:

package com.zhiwei.rent.config.eventTracking;

import com.zhiwei.rent.service.eventTracking.EventTrackingService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author YanChengHao
 * @data 2024/09/11
 */
@Aspect
@Component
public class EventTrackingAspect {

    @Autowired
    private EventTrackingService eventTrackingService;

    @Around("@annotation(eventTracking)")
    public Object jointPotin(ProceedingJoinPoint joinPoint, EventTracking eventTracking) throws Throwable {
        // 统计方法耗时
        long begin = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long duration = System.currentTimeMillis() - begin;
        // 耗时:大于等于 1000ms 为 s 单位 ,小于 1000ms 还是为 ms 单位
        String timeConsuming = logExecutionTime(duration);
        // 进行业务处理 将 eventTracking 信息添入数据库进行记录
        eventTrackingService.insertEventTracking(eventTracking.event(),eventTracking.count(),timeConsuming);
        return result;
    }

    // 耗时单位
    private String logExecutionTime(long duration) {
        if (duration >= 1000) {
            double seconds = duration / 1000.0;
            return String.format("%.2f s", seconds);
        } else {
            return String.format("%d ms", duration);
        }
    }
}

切面类里面有一行代码是插入数据库进行记录的

异步:

    @Async("ThreadEventPoolExecutor")
    public void insertEventTracking(String event,int count, String timeConsuming) {
        // 是否存在事件 如果不存在则插入 如果存在则记录次数加1
        EventTracking eventTracking = eventTrackingMapper.findByEvent(event);
        if(ObjectUtil.isEmpty(eventTracking)){
            // 不存在则去添加数据
            int result =eventTrackingMapper.insertEventTracking(event, count, timeConsuming);
            log.info(result > 0 ? "事件追踪信息添加成功" : "事件追踪信息添加失败");
        }else {
            // 存在则去修改数据
            int result = eventTrackingMapper.updateEventTracking(count, timeConsuming, eventTracking.getId());
            log.info(result > 0 ? "事件追踪信息更新成功" : "事件追踪信息更新失败");
        }
    }

注解: @Async("ThreadEventPoolExecutor")  ThreadEventPoolExecutor是配置的线程池

    @Bean(name = "ThreadEventPoolExecutor", destroyMethod = "shutdown")
    public ThreadPoolExecutor systemCheckPoolExecutorService() {

        return new ThreadPoolExecutor(1, 4, 60, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(10),
                new ThreadFactoryBuilder().setNameFormat("default-executor-%d").build(),
                (r, executor) -> log.error("system pool is full! "));
    }

1:核心线程数

4:最大线程数

new LinkedBlockingQueue<Runnable>(10):阻塞队列的线程数

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

到这里的话已经接近尾声了 最后一步:在对应的方法上添加该注解:

    @EventTracking(event = "浏览商品详情页", count = 1)
    public ResData<ProductVo> detail(@RequestParam("id") String idTxt)

数据库展示:

注:本人使用jmeter测试,一秒10000访问量数据是不会丢失的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值