|
|
@@ -16,6 +16,7 @@ import shop.alien.store.util.analytics.AnalyticsDateUtil;
|
|
|
import shop.alien.store.util.analytics.AnalyticsFrontHelper;
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.util.Date;
|
|
|
import java.util.UUID;
|
|
|
|
|
|
@@ -44,8 +45,9 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
public void trackFromFront(AnalyticsFrontReportDTO dto, HttpServletRequest request) {
|
|
|
AnalyticsTrackEventDTO eventDto = convertFrontReport(dto);
|
|
|
AnalyticsFrontHelper.enrichTrackEvent(eventDto, request);
|
|
|
- insertEvent(eventDto);
|
|
|
- syncContentAuditFromFront(dto, eventDto.getEventCode());
|
|
|
+ if (insertEvent(eventDto)) {
|
|
|
+ syncDetailFromFront(dto, eventDto.getEventCode());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -72,18 +74,26 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
throw new IllegalArgumentException("userId 不能为空");
|
|
|
}
|
|
|
Date heartbeatTime = new Date();
|
|
|
- AnalyticsFrontReportDTO report = new AnalyticsFrontReportDTO();
|
|
|
- report.setScene(AnalyticsScene.USER_HEARTBEAT.getScene());
|
|
|
- report.setUserId(dto.getUserId());
|
|
|
- report.setDurationMs(dto.getDurationMs());
|
|
|
- report.setDeviceType(dto.getDeviceType());
|
|
|
- report.setChannel(dto.getChannel());
|
|
|
- report.setCity(dto.getCity());
|
|
|
- trackFromFront(report, request);
|
|
|
- upsertUserHeartbeat(dto, heartbeatTime);
|
|
|
- }
|
|
|
-
|
|
|
- private void insertEvent(AnalyticsTrackEventDTO dto) {
|
|
|
+ AnalyticsTrackEventDTO eventDto = buildHeartbeatEvent(dto, heartbeatTime);
|
|
|
+ AnalyticsFrontHelper.enrichTrackEvent(eventDto, request);
|
|
|
+ if (insertEvent(eventDto)) {
|
|
|
+ upsertUserHeartbeat(dto, heartbeatTime);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private AnalyticsTrackEventDTO buildHeartbeatEvent(AnalyticsHeartbeatDTO dto, Date heartbeatTime) {
|
|
|
+ AnalyticsTrackEventDTO eventDto = new AnalyticsTrackEventDTO();
|
|
|
+ eventDto.setEventCode(AnalyticsEventCode.USER_HEARTBEAT);
|
|
|
+ eventDto.setUserId(dto.getUserId());
|
|
|
+ eventDto.setDurationMs(dto.getDurationMs());
|
|
|
+ eventDto.setDeviceType(dto.getDeviceType());
|
|
|
+ eventDto.setChannel(dto.getChannel());
|
|
|
+ eventDto.setCity(dto.getCity());
|
|
|
+ eventDto.setEventTime(heartbeatTime);
|
|
|
+ return eventDto;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean insertEvent(AnalyticsTrackEventDTO dto) {
|
|
|
AnalyticsEvent event = new AnalyticsEvent();
|
|
|
event.setEventId(StringUtils.hasText(dto.getEventId()) ? dto.getEventId() : UUID.randomUUID().toString().replace("-", ""));
|
|
|
event.setEventCode(dto.getEventCode());
|
|
|
@@ -103,8 +113,10 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
|
|
|
try {
|
|
|
eventMapper.insert(event);
|
|
|
+ return true;
|
|
|
} catch (DuplicateKeyException e) {
|
|
|
log.debug("埋点事件已存在,跳过: eventId={}", event.getEventId());
|
|
|
+ return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -225,7 +237,15 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
AnalyticsAiChatStat existing = aiChatStatMapper.selectOne(wrapper);
|
|
|
|
|
|
if (existing == null) {
|
|
|
- aiChatStatMapper.insert(buildAiChatStat(dto));
|
|
|
+ try {
|
|
|
+ aiChatStatMapper.insert(buildAiChatStat(dto));
|
|
|
+ } catch (DuplicateKeyException e) {
|
|
|
+ existing = aiChatStatMapper.selectOne(wrapper);
|
|
|
+ if (existing != null) {
|
|
|
+ mergeAiChatStat(existing, dto);
|
|
|
+ aiChatStatMapper.updateById(existing);
|
|
|
+ }
|
|
|
+ }
|
|
|
return;
|
|
|
}
|
|
|
mergeAiChatStat(existing, dto);
|
|
|
@@ -247,7 +267,9 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
eventDto.setChannel(dto.getChannel());
|
|
|
eventDto.setCity(dto.getCity());
|
|
|
eventDto.setEventTime(registerTime);
|
|
|
- insertEvent(eventDto);
|
|
|
+ if (!insertEvent(eventDto)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
Date statDate = AnalyticsDateUtil.truncateToDate(registerTime);
|
|
|
AnalyticsUserStat existing = detailStoreService.findUserStat(statDate, dto.getUserId());
|
|
|
@@ -290,7 +312,9 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
eventDto.setCity(dto.getCity());
|
|
|
eventDto.setDeviceType(dto.getDeviceName());
|
|
|
eventDto.setEventTime(activeTime);
|
|
|
- insertEvent(eventDto);
|
|
|
+ if (!insertEvent(eventDto)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
Date statDate = AnalyticsDateUtil.truncateToDate(activeTime);
|
|
|
AnalyticsUserStat existing = detailStoreService.findUserStat(statDate, dto.getUserId());
|
|
|
@@ -331,7 +355,9 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
eventDto.setDeviceType(dto.getDeviceName());
|
|
|
eventDto.setDurationMs(sessionMin > 0 ? sessionMin * 60000L : 0L);
|
|
|
eventDto.setEventTime(activeTime);
|
|
|
- insertEvent(eventDto);
|
|
|
+ if (!insertEvent(eventDto)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
Date statDate = AnalyticsDateUtil.truncateToDate(activeTime);
|
|
|
AnalyticsUserStat existing = detailStoreService.findUserStat(statDate, dto.getUserId());
|
|
|
@@ -378,7 +404,9 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
eventDto.setUserId(dto.getUserId());
|
|
|
eventDto.setDurationMs(dto.getAiResponseDurationMs());
|
|
|
eventDto.setEventTime(endTime);
|
|
|
- insertEvent(eventDto);
|
|
|
+ if (!insertEvent(eventDto)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
AnalyticsAiChatDetailDTO detail = new AnalyticsAiChatDetailDTO();
|
|
|
detail.setChatId(dto.getChatId());
|
|
|
@@ -428,7 +456,9 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
if (dto.getBusinessCategory() != null) {
|
|
|
eventDto.setBusinessCategory(dto.getBusinessCategory());
|
|
|
}
|
|
|
- insertEvent(eventDto);
|
|
|
+ if (!insertEvent(eventDto)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
AnalyticsContentDetailDTO detail = new AnalyticsContentDetailDTO();
|
|
|
detail.setContentId(dto.getContentId());
|
|
|
@@ -464,10 +494,14 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
eventDto.setUserId(dto.getUserId());
|
|
|
eventDto.setTargetId(dto.getContentId());
|
|
|
eventDto.setContentType(dto.getContentType());
|
|
|
+ eventDto.setEventSubtype(dto.getEventSubtype());
|
|
|
+ eventDto.setAmount(BigDecimal.valueOf(dto.getIncrement()));
|
|
|
eventDto.setEventTime(eventTime);
|
|
|
- insertEvent(eventDto);
|
|
|
+ if (!insertEvent(eventDto)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- addContentInteraction(dto.getContentType(), dto.getContentId(), dto.getIncrement());
|
|
|
+ addContentInteraction(dto.getContentType(), dto.getContentId(), dto.getIncrement(), dto.getEventSubtype());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -501,8 +535,11 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
eventDto.setEventCode(AnalyticsEventCode.MERCHANT_VIEW);
|
|
|
eventDto.setUserId(dto.getUserId());
|
|
|
eventDto.setMerchantId(dto.getMerchantId());
|
|
|
+ eventDto.setShopType(dto.getShopType());
|
|
|
eventDto.setEventTime(eventTime);
|
|
|
- insertEvent(eventDto);
|
|
|
+ if (!insertEvent(eventDto)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
Date statDate = AnalyticsDateUtil.truncateToDate(eventTime);
|
|
|
addMerchantVisit(statDate, dto.getMerchantId(), dto.getShopType(), dto.getVisitUv(), dto.getVisitPv());
|
|
|
@@ -538,6 +575,23 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
target.setIsNewUser(1);
|
|
|
}
|
|
|
|
|
|
+ private void syncDetailFromFront(AnalyticsFrontReportDTO dto, String eventCode) {
|
|
|
+ syncContentAuditFromFront(dto, eventCode);
|
|
|
+ if (AnalyticsEventCode.MERCHANT_VIEW.equals(eventCode)
|
|
|
+ && dto.getMerchantId() != null && dto.getShopType() != null) {
|
|
|
+ Date statDate = AnalyticsDateUtil.truncateToDate(
|
|
|
+ dto.getEventTime() != null ? dto.getEventTime() : new Date());
|
|
|
+ addMerchantVisit(statDate, dto.getMerchantId(), dto.getShopType(), 1, 1);
|
|
|
+ }
|
|
|
+ if (AnalyticsEventCode.CONTENT_INTERACT.equals(eventCode)
|
|
|
+ && dto.getTargetId() != null && dto.getContentType() != null) {
|
|
|
+ int increment = dto.getAmount() != null ? dto.getAmount().intValue() : 1;
|
|
|
+ if (increment != 0) {
|
|
|
+ addContentInteraction(dto.getContentType(), dto.getTargetId(), increment, dto.getEventSubtype());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void syncContentAuditFromFront(AnalyticsFrontReportDTO dto, String eventCode) {
|
|
|
if (dto.getTargetId() == null || dto.getContentType() == null) {
|
|
|
return;
|
|
|
@@ -685,7 +739,7 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
if (dto.getAuditTime() != null) target.setAuditTime(dto.getAuditTime());
|
|
|
}
|
|
|
|
|
|
- private void addContentInteraction(Integer contentType, Long contentId, int increment) {
|
|
|
+ private void addContentInteraction(Integer contentType, Long contentId, int increment, String eventSubtype) {
|
|
|
Date statDate = AnalyticsDateUtil.truncateToDate(new Date());
|
|
|
AnalyticsContentStat existing = detailStoreService.findContentStat(statDate, contentType, contentId);
|
|
|
if (existing == null) {
|
|
|
@@ -695,19 +749,34 @@ public class AnalyticsTrackServiceImpl implements AnalyticsTrackService {
|
|
|
stat.setAuthorType(1);
|
|
|
stat.setAuthorId(0L);
|
|
|
stat.setInteractionCount(Math.max(0, increment));
|
|
|
+ applyInteractSubtypeDelta(stat, eventSubtype, increment);
|
|
|
detailStoreService.insertContentStat(statDate, stat);
|
|
|
return;
|
|
|
}
|
|
|
int next = defaultInt(existing.getInteractionCount()) + increment;
|
|
|
existing.setInteractionCount(Math.max(0, next));
|
|
|
+ applyInteractSubtypeDelta(existing, eventSubtype, increment);
|
|
|
detailStoreService.updateContentStat(statDate, existing);
|
|
|
}
|
|
|
|
|
|
+ private void applyInteractSubtypeDelta(AnalyticsContentStat stat, String eventSubtype, int increment) {
|
|
|
+ if (!StringUtils.hasText(eventSubtype)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (AnalyticsEventSubtype.INTERACT_LIKE.equalsIgnoreCase(eventSubtype)) {
|
|
|
+ stat.setLikeCount(Math.max(0, defaultInt(stat.getLikeCount()) + increment));
|
|
|
+ } else if (AnalyticsEventSubtype.INTERACT_COMMENT.equalsIgnoreCase(eventSubtype)) {
|
|
|
+ stat.setCommentCount(Math.max(0, defaultInt(stat.getCommentCount()) + increment));
|
|
|
+ } else if (AnalyticsEventSubtype.INTERACT_SHARE.equalsIgnoreCase(eventSubtype)) {
|
|
|
+ stat.setShareCount(Math.max(0, defaultInt(stat.getShareCount()) + increment));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void upsertUserHeartbeat(AnalyticsHeartbeatDTO dto, Date heartbeatTime) {
|
|
|
Date statDate = AnalyticsDateUtil.truncateToDate(heartbeatTime);
|
|
|
int addMin = (int) (dto.getDurationMs() / 60000);
|
|
|
if (addMin <= 0) {
|
|
|
- addMin = 1;
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
AnalyticsUserStat existing = detailStoreService.findUserStat(statDate, dto.getUserId());
|