|
|
@@ -0,0 +1,204 @@
|
|
|
+package cn.reghao.tnb.search.app.ws.handler;
|
|
|
+
|
|
|
+import cn.reghao.bnt.log.AppLog;
|
|
|
+import cn.reghao.bnt.log.GatewayLog;
|
|
|
+import cn.reghao.jutil.jdk.converter.DateTimeConverter;
|
|
|
+import cn.reghao.jutil.jdk.serializer.JdkSerializer;
|
|
|
+import cn.reghao.jutil.jdk.serializer.JsonConverter;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.web.socket.*;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author reghao
|
|
|
+ * @date 2022-03-11 16:45:52
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Component
|
|
|
+public class LogHandler implements WebSocketHandler {
|
|
|
+ private final Map<String, String> appMap = new HashMap<>();
|
|
|
+ private final Map<String, WebSocketSession> pullRuntimeMap = new ConcurrentHashMap<>();
|
|
|
+ private final Map<String, WebSocketSession> pullAccessMap = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
+ public List<String> getApps() {
|
|
|
+ return new ArrayList<>(appMap.values());
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<String> getApp(String app) {
|
|
|
+ return appMap.values().stream()
|
|
|
+ .filter(appKey -> appKey.startsWith(app))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void afterConnectionEstablished(WebSocketSession webSocketSession) throws IOException {
|
|
|
+ String sessionId = webSocketSession.getId();
|
|
|
+ String query = webSocketSession.getUri().getQuery();
|
|
|
+ Map<String, String> map = parseParams(query);
|
|
|
+ String app = map.get("app");
|
|
|
+ String host = map.get("host");
|
|
|
+ if (app == null || host == null) {
|
|
|
+ if (webSocketSession.isOpen()) {
|
|
|
+ webSocketSession.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String appKey = String.format("%s@%s", app, host);
|
|
|
+ String path = webSocketSession.getUri().getPath();
|
|
|
+ if (path.equals("/logws/pull/runtime")) {
|
|
|
+ appMap.put(sessionId, appKey);
|
|
|
+ pullRuntimeMap.put(appKey, webSocketSession);
|
|
|
+ } else if (path.equals("/logws/pull/access")) {
|
|
|
+ pullAccessMap.put(appKey, webSocketSession);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("WebSocket 建立连接");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void removeSession(WebSocketSession webSocketSession) {
|
|
|
+ String sessionId = webSocketSession.getId();
|
|
|
+ String appKey = appMap.get(sessionId);
|
|
|
+ if (appKey == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ String path = webSocketSession.getUri().getPath();
|
|
|
+ if (path.equals("/logws/pull/runtime")) {
|
|
|
+ pullRuntimeMap.remove(appKey);
|
|
|
+ } else if (path.equals("/logws/pull/access")) {
|
|
|
+ pullAccessMap.remove(appKey);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void pushAppLog(AppLog appLog) {
|
|
|
+ String app = appLog.getApp();
|
|
|
+ String host = appLog.getHost();
|
|
|
+ WebSocketSession pullSession = getPullRuntimeSession(app, host);
|
|
|
+ if (pullSession != null) {
|
|
|
+ String jsonData = JsonConverter.objectToJson(appLog);
|
|
|
+ WebSocketMessage<String> message1 = new TextMessage(jsonData);
|
|
|
+ try {
|
|
|
+ pullSession.sendMessage(message1);
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void pushGatewayLog(GatewayLog gatewayLog) {
|
|
|
+ WebSocketSession pullSession = getPullAccessSession("tnb", "localhost");
|
|
|
+ if (pullSession != null) {
|
|
|
+ String jsonData = JsonConverter.objectToJson(gatewayLog);
|
|
|
+ WebSocketMessage<String> message1 = new TextMessage(jsonData);
|
|
|
+ try {
|
|
|
+ pullSession.sendMessage(message1);
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, String> parseParams(String query) {
|
|
|
+ String[] params = query.split("&");
|
|
|
+ Map<String, String> map = new HashMap<>();
|
|
|
+ for (String param : params) {
|
|
|
+ String[] arr = param.split("=");
|
|
|
+ map.put(arr[0], arr[1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<Long, Integer> ngxLogMap = new TreeMap<>();
|
|
|
+ @Override
|
|
|
+ public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage)
|
|
|
+ throws IOException {
|
|
|
+ try {
|
|
|
+ String appKey = appMap.get(webSocketSession.getId());
|
|
|
+ if (webSocketMessage instanceof TextMessage) {
|
|
|
+ String payload = (String) webSocketMessage.getPayload();
|
|
|
+ } else if (webSocketMessage instanceof BinaryMessage) {
|
|
|
+ BinaryMessage binaryMessage = (BinaryMessage) webSocketMessage;
|
|
|
+ Object object = JdkSerializer.deserialize(binaryMessage.getPayload().array());
|
|
|
+ if (object instanceof String) {
|
|
|
+ //log.info("{} -> {}", appKey, object);
|
|
|
+ } else if (object instanceof AppLog) {
|
|
|
+ AppLog appLog = (AppLog) object;
|
|
|
+ String dateTimeStr = DateTimeConverter.format(appLog.getTimestamp());
|
|
|
+ //appLog.setDateTimeStr(dateTimeStr);
|
|
|
+ //pushAppLog(appLog);
|
|
|
+ //runtimeLogService.addAppLog(appLog);
|
|
|
+ } /*else if (object instanceof NginxLog) {
|
|
|
+ NginxLog nginxLog = (NginxLog) object;
|
|
|
+ String date = nginxLog.getTimeIso8601();
|
|
|
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss+08:00")
|
|
|
+ .withZone(ZoneId.of("UTC"));
|
|
|
+ LocalDateTime localDateTime = LocalDateTime.parse(date, formatter);
|
|
|
+ Long timestamp = localDateTime.toEpochSecond(ZoneOffset.of("+8"));
|
|
|
+ Long key = timestamp;
|
|
|
+ Integer count = ngxLogMap.get(key);
|
|
|
+ if (count == null) {
|
|
|
+ ngxLogMap.put(key, 1);
|
|
|
+ } else {
|
|
|
+ int count1 = ngxLogMap.get(key) + 1;
|
|
|
+ ngxLogMap.put(key, count1);
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+ } else if (webSocketMessage instanceof PingMessage) {
|
|
|
+ log.info("接收到 WebSocket PingMessage");
|
|
|
+ } else if (webSocketMessage instanceof PongMessage) {
|
|
|
+ log.info("接收到 WebSocket PongMessage");
|
|
|
+ } else {
|
|
|
+ log.error("接收到未知类型的 WebSocket 消息");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) {
|
|
|
+ log.error("WebSocket 数据传输错误");
|
|
|
+ removeSession(webSocketSession);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) {
|
|
|
+ log.info("WebSocket 断开连接");
|
|
|
+ removeSession(webSocketSession);
|
|
|
+ }
|
|
|
+
|
|
|
+ private WebSocketSession getPullRuntimeSession(String app, String host) {
|
|
|
+ String suffix = String.format("%s@%s", app, host);
|
|
|
+ Set<String> keys = pullRuntimeMap.keySet();
|
|
|
+ for (String key : keys) {
|
|
|
+ if (key.endsWith(suffix)) {
|
|
|
+ return pullRuntimeMap.get(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private WebSocketSession getPullAccessSession(String app, String host) {
|
|
|
+ String suffix = String.format("%s@%s", app, host);
|
|
|
+ Set<String> keys = pullAccessMap.keySet();
|
|
|
+ for (String key : keys) {
|
|
|
+ if (key.endsWith(suffix)) {
|
|
|
+ return pullAccessMap.get(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean supportsPartialMessages() {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|