Initial commit
This commit is contained in:
13
src/main/java/com/noblelift/ota/common/annotation/Log.java
Normal file
13
src/main/java/com/noblelift/ota/common/annotation/Log.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.noblelift.ota.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Log {
|
||||
|
||||
String value() default "";
|
||||
}
|
||||
61
src/main/java/com/noblelift/ota/common/aspect/LogAspect.java
Normal file
61
src/main/java/com/noblelift/ota/common/aspect/LogAspect.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package com.noblelift.ota.common.aspect;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.noblelift.ota.common.annotation.Log;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class LogAspect {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@Around("@annotation(logAnnotation)")
|
||||
public Object around(ProceedingJoinPoint joinPoint, Log logAnnotation) throws Throwable {
|
||||
long start = System.currentTimeMillis();
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = requestAttributes instanceof ServletRequestAttributes servletRequestAttributes
|
||||
? servletRequestAttributes.getRequest()
|
||||
: null;
|
||||
String requestUri = request == null ? "N/A" : request.getRequestURI();
|
||||
String requestMethod = request == null ? "N/A" : request.getMethod();
|
||||
String params = serializeArgs(joinPoint.getArgs());
|
||||
String operation = logAnnotation.value().isBlank() ? signature.getMethod().getName() : logAnnotation.value();
|
||||
log.info("[API-REQUEST] operation={}, method={}, uri={}, params={}", operation, requestMethod, requestUri, params);
|
||||
try {
|
||||
Object result = joinPoint.proceed();
|
||||
log.info("[API-RESPONSE] operation={}, duration={}ms", operation, System.currentTimeMillis() - start);
|
||||
return result;
|
||||
} catch (Throwable ex) {
|
||||
log.error("[API-ERROR] operation={}, duration={}ms, message={}", operation, System.currentTimeMillis() - start, ex.getMessage(), ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private String serializeArgs(Object[] args) {
|
||||
Object[] filtered = Arrays.stream(args)
|
||||
.filter(arg -> !(arg instanceof HttpServletRequest))
|
||||
.toArray();
|
||||
try {
|
||||
return objectMapper.writeValueAsString(filtered);
|
||||
} catch (JsonProcessingException e) {
|
||||
return Arrays.toString(filtered);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/main/java/com/noblelift/ota/common/dto/ApiMessage.java
Normal file
19
src/main/java/com/noblelift/ota/common/dto/ApiMessage.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.noblelift.ota.common.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ApiMessage {
|
||||
|
||||
private String code;
|
||||
private String message;
|
||||
private Instant timestamp;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.noblelift.ota.common.model;
|
||||
|
||||
import com.noblelift.ota.domain.UpgradeMode;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ReleaseManifest {
|
||||
|
||||
private String releaseVersion;
|
||||
private String releaseNotes;
|
||||
private UpgradeMode upgradeMode;
|
||||
private Instant publishedAt;
|
||||
private Boolean parkingRequired;
|
||||
private Map<String, Object> components;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.noblelift.ota.common.model;
|
||||
|
||||
import com.noblelift.ota.domain.TaskStatus;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VehicleAssignment {
|
||||
|
||||
private String vehicleId;
|
||||
private String releaseVersion;
|
||||
private TaskStatus taskStatus;
|
||||
private Instant promptedAt;
|
||||
private Instant confirmedAt;
|
||||
private Instant startedAt;
|
||||
private Instant finishedAt;
|
||||
private Integer postponeCount;
|
||||
private String lastMessage;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.noblelift.ota.common.model;
|
||||
|
||||
import com.noblelift.ota.domain.AgentStatus;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VehicleInfo {
|
||||
|
||||
private String vehicleId;
|
||||
private String vin;
|
||||
private String currentRelease;
|
||||
private String currentBackendVersion;
|
||||
private String currentFrontendVersion;
|
||||
private String currentRosVersion;
|
||||
private Instant lastSeenAt;
|
||||
private AgentStatus agentStatus;
|
||||
private String targetRelease;
|
||||
private String lastResult;
|
||||
private Map<String, String> images;
|
||||
private String backupFile;
|
||||
private Boolean online;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.noblelift.ota.common.util;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class ReleaseVersionComparator {
|
||||
|
||||
private static final Pattern TOKEN_PATTERN = Pattern.compile("\\d+");
|
||||
|
||||
private ReleaseVersionComparator() {
|
||||
}
|
||||
|
||||
public static int compare(String left, String right) {
|
||||
List<String> leftTokens = tokenize(left);
|
||||
List<String> rightTokens = tokenize(right);
|
||||
int size = Math.max(leftTokens.size(), rightTokens.size());
|
||||
for (int i = 0; i < size; i++) {
|
||||
String leftToken = i < leftTokens.size() ? leftTokens.get(i) : "0";
|
||||
String rightToken = i < rightTokens.size() ? rightTokens.get(i) : "0";
|
||||
int result = new BigInteger(leftToken).compareTo(new BigInteger(rightToken));
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static List<String> tokenize(String value) {
|
||||
List<String> tokens = new ArrayList<>();
|
||||
if (value == null || value.isBlank()) {
|
||||
return tokens;
|
||||
}
|
||||
Matcher matcher = TOKEN_PATTERN.matcher(value);
|
||||
while (matcher.find()) {
|
||||
tokens.add(matcher.group());
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user