Contents

事件日志埋点

通过自定义注解和AOP实现自定义事件日志埋点

注解和aop类

  • 注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventLog {

    Action action() default Action.DEFAULT;

    boolean recordUserId() default true;

    boolean recordUserName() default true;

    boolean recordUserPhone() default true;

    boolean recordTime() default true;

}
  • aop

@Slf4j
@Aspect
@Order(1)
public class EventLogAspect {

    public EventLogAspect() {

    }

    @Pointcut("@annotation(com.xxxx.EventLog)")
    private void eventLogPoint() {
    }

    @Around("eventLogPoint() && @annotation(eventLog)")
    public Object around(ProceedingJoinPoint pjp, EventLog eventLog) throws Throwable {
        Object[] args = pjp.getArgs();
        if (args[0] instanceof Action.Param){
            Action.Param param = (Action.Param) args[0];
            Action action = Action.of(param.getType());
            RabbitTemplate bean = SpringUtils.getBean(RabbitTemplate.class);
            EventLogBO bo = buildEventBO(action,param);
            Message message = MessageBuilder.withBody(JSON.toJSONString(bo).getBytes())
                    .setContentType(MessageProperties.CONTENT_TYPE_JSON)
                    .setContentEncoding("utf-8")
                    .build();
            bean.convertAndSend(EventLogConstant.EVENTLOG_EXCHANGE, EventLogConstant.EVENTLOG_ROUTINGKEY, message);
            return pjp.proceed();
        } else {
            throw new BusinessException("埋点参数错误");
        }
    }

    private EventLogBO buildEventBO(Action action, Action.Param param) {
        String userId = Optional.ofNullable(SysUserUtil.getLoginAppUser()).map(SysUser::getId).orElse("d50a4f05-d193-4017-8b94-238297d76bb6");
        return EventLogBO.builder()
                .id(Long.valueOf(CommonUtils.getUniqueId()))
                .eventType(action.getActionType())
                .eventName(action.getActionName())
                .eventDesc(action.getActionDesc())
                .name(DictionaryUtil.getUserNameById(userId))
                .userId(userId)
                .phone(DictionaryUtil.getUserNameById(userId,"phone"))
                .eventTime(new Date())
                .build();
    }


}

公共和事件枚举类

  • 枚举

@Getter
public enum Action {

    DEFAULT(-1,"-1","-1"),

    TECH_BOOK_VISIT_COUNT(1,"xxx","xxx"),

    UNIT_COUNT_VISIT_COUNT(2,"xxx","xxx"),

    DANCE_VISIT_COUNT(3,"xxx","xxx"),

    SYLLABUS_VISIT_COUNT(4,"xxx","xxx"),

    ;

    Action(Integer actionType, String actionName, String actionDesc) {
        this.actionType = actionType;
        this.actionName = actionName;
        this.actionDesc = actionDesc;
    }

    public static Action of(Integer type) {
        if(Objects.isNull(type)){
            throw new BusinessException("类型不能为空");
        }
        return Arrays.stream(Action.values()).filter(item -> item.actionType.compareTo(type) == 0)
                .findAny().orElseThrow(() -> new BusinessException("埋点类型不存在"));

    }

    @Override
    public String toString() {
        return "Action{" +
                "actionType=" + actionType +
                ", actionName='" + actionName + '\'' +
                ", actionDesc='" + actionDesc + '\'' +
                '}';
    }

    private Integer actionType;

    private String actionName;

    private String actionDesc;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public static class Param{

        @ApiModelProperty("xxx")
        private Integer type;

    }


}
  • BO和常量类

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class EventLogBO {

    private Long id;

    private String userId;

    private String name;

    private String phone;

    private Integer eventType;

    private String eventName;

    private String eventDesc;

    @ApiModelProperty("创建时间")
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date eventTime;

}


public class EventLogConstant {

    public static final String EVENTLOG_QUEUE = "eventlog_queue";

    public static final String EVENTLOG_EXCHANGE = "eventlog_exchange";

    public static final String EVENTLOG_ROUTINGKEY = "eventlog_routingkey";

}

spring starter类

  • aop bean 配置

@Slf4j
@Configuration
public class EventLogAutoConfiguration {

    @Bean
    public EventLogAspect eventLogAspect(){
        log.info("init EventLogAspect");
        return new EventLogAspect();
    }
}
  • mq bean 配置

@Configuration
public class EventLogRabbitMqConfig {

    @Bean
    public Queue eventlogQueue() {
        return QueueBuilder.durable(EventLogConstant.EVENTLOG_QUEUE)
                .build();
    }

    @Bean
    public DirectExchange eventlogExchange() {
        return new DirectExchange(EventLogConstant.EVENTLOG_EXCHANGE);
    }

    @Bean
    public Binding eventlogBinding(Queue eventlogQueue, DirectExchange eventlogExchange) {
        return BindingBuilder.bind(eventlogQueue)
                .to(eventlogExchange)
                .with(EventLogConstant.EVENTLOG_ROUTINGKEY);
    }

}
  • resource/META-INF/spring.factories 配置

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.xxx.EventLogAutoConfiguration,com.xxx.EventLogRabbitMqConfig