1、适配部署环境变量自动注入

2、适配南网达梦数据库安全版SQL语句Group by 不支持自定义函数
3、达梦数据库驱动改为达梦提供的指定版本
4、修改syslog-consumer模块yaml 文件kafka 变量名称
5、修改访问日志告警表新增4个字段,完善异常行为详情页面显示字段
This commit is contained in:
2026-07-22 18:50:44 +08:00
parent 5fe0e124bb
commit 16b73dffee
89 changed files with 4507 additions and 2186 deletions
@@ -21,83 +21,83 @@ services:
- SPRING_PROFILES_ACTIVE=dev
- TZ=Asia/Shanghai
# 数据库配置
- spring.datasource.url=jdbc:postgresql://117.72.68.72:54329/ecosys
- spring.datasource.username=postgres
- spring.datasource.password=TnLanWaidYSwTSG5
- spring.datasource.driver-class-name=org.postgresql.Driver
- SPRING_DATASOURCE_URL=jdbc:postgresql://117.72.68.72:54329/ecosys
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=TnLanWaidYSwTSG5
- SPRING_DATASOURCE_DRIVER_CLASS_NAME=org.postgresql.Driver
# HikariCP 连接池配置
- spring.datasource.hikari.maximum-pool-size=50
- spring.datasource.hikari.minimum-idle=5
- spring.datasource.hikari.connection-timeout=30000
- spring.datasource.hikari.idle-timeout=600000
- spring.datasource.hikari.max-lifetime=900000
- spring.datasource.hikari.pool-name=HikariPool-SyslogConsumer
- spring.datasource.hikari.auto-commit=false
- spring.datasource.hikari.schema=public
- SPRING_DATASOURCE_HIKARI_MAXIMUM_POOL_SIZE=50
- SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE=5
- SPRING_DATASOURCE_HIKARI_CONNECTION_TIMEOUT=30000
- SPRING_DATASOURCE_HIKARI_IDLE_TIMEOUT=600000
- SPRING_DATASOURCE_HIKARI_MAX_LIFETIME=900000
- SPRING_DATASOURCE_HIKARI_POOL_NAME=HikariPool-SyslogConsumer
- SPRING_DATASOURCE_HIKARI_AUTO_COMMIT=false
- SPRING_DATASOURCE_HIKARI_SCHEMA=public
# Redis配置
- spring.redis.host=192.168.222.131
- spring.redis.port=6379
- spring.redis.password=
- spring.redis.database=0
- spring.redis.timeout=2000
- spring.cache.redis.time-to-live=600000
- SPRING_REDIS_HOST=192.168.222.131
- SPRING_REDIS_PORT=6379
- SPRING_REDIS_PASSWORD=
- SPRING_REDIS_DATABASE=0
- SPRING_REDIS_TIMEOUT=2000
- SPRING_CACHE_REDIS_TIME_TO_LIVE=600000
# Kafka配置
- spring.kafka.consumer.bootstrap-servers=192.168.222.130:9092
- spring.kafka.consumer.group-id=test-group-app
- spring.kafka.consumer.auto-offset-reset=latest
- spring.kafka.consumer.enable-auto-commit=false
- spring.kafka.consumer.topic=test-topic
- spring.kafka.consumer.max-poll-records=1000
- spring.kafka.listener.ack-mode=manual
- spring.kafka.listener.concurrency=2
- spring.kafka.listener.type=batch
- SPRING_KAFKA_CONSUMER_BOOTSTRAP_SERVERS=192.168.222.130:9092
- SPRING_KAFKA_CONSUMER_GROUP_ID=test-group-app
- SPRING_KAFKA_CONSUMER_AUTO_OFFSET_RESET=latest
- SPRING_KAFKA_CONSUMER_ENABLE_AUTO_COMMIT=false
- SPRING_KAFKA_CONSUMER_TOPIC=test-topic
- SPRING_KAFKA_CONSUMER_MAX_POLL_RECORDS=1000
- SPRING_KAFKA_LISTENER_ACK_MODE=manual
- SPRING_KAFKA_LISTENER_CONCURRENCY=2
- SPRING_KAFKA_LISTENER_TYPE=batch
# InfluxDB配置
- influxdb.url=http://192.168.222.131:8086
- influxdb.token=3Tvu-IZWtaY03UDkbUDlufD0kxn85keo9LhYQcv2Cxk0LJmXqqHkNVrO664DbaJAYwoGI7UIg904KqZC7Q_ZFA==
- influxdb.org=yelang
- influxdb.bucket=yelangbucket
- influxdb.batch.size=1000
- influxdb.flush.interval=1000
- influxdb.connection.timeout=30s
- influxdb.connection.read-timeout=30s
- influxdb.connection.write-timeout=60s
- INFLUXDB_URL=http://192.168.222.131:8086
- INFLUXDB_TOKEN=3Tvu-IZWtaY03UDkbUDlufD0kxn85keo9LhYQcv2Cxk0LJmXqqHkNVrO664DbaJAYwoGI7UIg904KqZC7Q_ZFA==
- INFLUXDB_ORG=yelang
- INFLUXDB_BUCKET=yelangbucket
- INFLUXDB_BATCH_SIZE=1000
- INFLUXDB_FLUSH_INTERVAL=1000
- INFLUXDB_CONNECTION_TIMEOUT=30s
- INFLUXDB_CONNECTION_READ_TIMEOUT=30s
- INFLUXDB_CONNECTION_WRITE_TIMEOUT=60s
# Elasticsearch配置
- spring.elasticsearch.uris=http://192.168.1.174:9200
- spring.elasticsearch.username=CONTAINER_NAME
- spring.elasticsearch.password=t2NZCiajmdazxBrF
- spring.elasticsearch.connection-timeout=10s
- spring.elasticsearch.socket-timeout=30s
- SPRING_ELASTICSEARCH_URIS=http://192.168.1.174:9200
- SPRING_ELASTICSEARCH_USERNAME=CONTAINER_NAME
- SPRING_ELASTICSEARCH_PASSWORD=t2NZCiajmdazxBrF
- SPRING_ELASTICSEARCH_CONNECTION_TIMEOUT=10s
- SPRING_ELASTICSEARCH_SOCKET_TIMEOUT=30s
# API配置
- interlocking.api-key=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
- interlocking.api.base-url=http://192.168.222.131:8089/xdrservice/interlocking
- INTERLOCKING_API_KEY=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
- INTERLOCKING_API_BASE_URL=http://192.168.222.131:8089/xdrservice/interlocking
# 探针心跳配置
- probe.heartbeat.enabled=true
- probe.heartbeat.offline-threshold-minutes=10
- probe.status.check.cron=0 */10 * * * ?
- probe.heartbeat.tenant-id=000000
- probe.heartbeat.history.keep-days=10
- probe.heartbeat.history.cleanup-enabled=true
- probe.history.cleanup.cron=0 0 1 * * ?
- PROBE_HEARTBEAT_ENABLED=true
- PROBE_HEARTBEAT_OFFLINE_THRESHOLD_MINUTES=10
- PROBE_STATUS_CHECK_CRON=0 */10 * * * ?
- PROBE_HEARTBEAT_TENANT_ID=000000
- PROBE_HEARTBEAT_HISTORY_KEEP_DAYS=10
- PROBE_HEARTBEAT_HISTORY_CLEANUP_ENABLED=true
- PROBE_HISTORY_CLEANUP_CRON=0 0 1 * * ?
# 告警健康检查配置
- alarm.health-check.alarm-hours=4
- alarm.health-check.alarm-visit-hours=2
- alarm.health-check.enabled=true
- ALARM_HEALTH_CHECK_ALARM_HOURS=4
- ALARM_HEALTH_CHECK_ALARM_VISIT_HOURS=2
- ALARM_HEALTH_CHECK_ENABLED=true
# 关联分析规则配置
- analysis.realtime.enabled=true
- analysis.realtime.check-interval-seconds=10
- ANALYSIS_REALTIME_ENABLED=true
- ANALYSIS_REALTIME_CHECK_INTERVAL_SECONDS=10
# 分区表检查配置
- partition.check.tomorrow.enabled=true
- partition.check.future.days=7
- partition.auto.create=true
- PARTITION_CHECK_TOMORROW_ENABLED=true
- PARTITION_CHECK_FUTURE_DAYS=7
- PARTITION_AUTO_CREATE=true
# 定时任务配置
- spring.task.scheduling.pool.size=10
- SPRING_TASK_SCHEDULING_POOL_SIZE=10
# 日志配置
- logging.level.com.common.schedule=INFO
- logging.level.com.common.service=INFO
- LOGGING_LEVEL_COM_COMMON_SCHEDULE=INFO
- LOGGING_LEVEL_COM_COMMON_SERVICE=INFO
# ETL配置
- etl.batch.page-size=1000
- etl.batch.insert-batch-size=500
- etl.schedule.cron=0 0 2 * * ?
- ETL_BATCH_PAGE_SIZE=1000
- ETL_BATCH_INSERT_BATCH_SIZE=500
- ETL_SCHEDULE_CRON=0 0 2 * * ?
# JVM配置
- JAVA_OPTS=-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200
ports:
@@ -21,51 +21,51 @@ services:
- SPRING_PROFILES_ACTIVE=prod
- TZ=Asia/Shanghai
# 数据库配置
- spring.datasource.url=jdbc:postgresql://192.168.4.26:5432/ecosys
- spring.datasource.username=postgres
- spring.datasource.password=caZ2TcmXNSW8L2Ap
- spring.datasource.driver-class-name=org.postgresql.Driver
- SPRING_DATASOURCE_URL=jdbc:postgresql://192.168.4.26:5432/ecosys
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=caZ2TcmXNSW8L2Ap
- SPRING_DATASOURCE_DRIVER_CLASS_NAME=org.postgresql.Driver
# HikariCP 连接池配置
- spring.datasource.hikari.maximum-pool-size=50
- spring.datasource.hikari.minimum-idle=5
- spring.datasource.hikari.connection-timeout=30000
- spring.datasource.hikari.idle-timeout=600000
- spring.datasource.hikari.max-lifetime=900000
- spring.datasource.hikari.pool-name=HikariPool-SyslogConsumer
- spring.datasource.hikari.auto-commit=false
- spring.datasource.hikari.schema=public
- SPRING_DATASOURCE_HIKARI_MAXIMUM_POOL_SIZE=50
- SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE=5
- SPRING_DATASOURCE_HIKARI_CONNECTION_TIMEOUT=30000
- SPRING_DATASOURCE_HIKARI_IDLE_TIMEOUT=600000
- SPRING_DATASOURCE_HIKARI_MAX_LIFETIME=900000
- SPRING_DATASOURCE_HIKARI_POOL_NAME=HikariPool-SyslogConsumer
- SPRING_DATASOURCE_HIKARI_AUTO_COMMIT=false
- SPRING_DATASOURCE_HIKARI_SCHEMA=public
# Redis配置
- spring.redis.host=192.168.4.26
- spring.redis.port=6379
- spring.redis.password=123456
- spring.redis.database=0
- spring.redis.timeout=2000
- spring.cache.redis.time-to-live=600000
- SPRING_REDIS_HOST=192.168.4.26
- SPRING_REDIS_PORT=6379
- SPRING_REDIS_PASSWORD=123456
- SPRING_REDIS_DATABASE=0
- SPRING_REDIS_TIMEOUT=2000
- SPRING_CACHE_REDIS_TIME_TO_LIVE=600000
# Kafka配置
- spring.kafka.consumer.bootstrap-servers=192.168.4.26:9092
- spring.kafka.consumer.group-id=agent-01-syslog-group
- spring.kafka.consumer.auto-offset-reset=latest
- spring.kafka.consumer.enable-auto-commit=false
- spring.kafka.consumer.topic=agenet-01-syslog-topic
- spring.kafka.consumer.max-poll-records=1000
- spring.kafka.listener.ack-mode=manual
- spring.kafka.listener.concurrency=2
- spring.kafka.listener.type=batch
- SPRING_KAFKA_CONSUMER_BOOTSTRAP_SERVERS=192.168.4.26:9092
- SPRING_KAFKA_CONSUMER_GROUP_ID=agent-syslog-group
- SPRING_KAFKA_CONSUMER_AUTO_OFFSET_RESET=latest
- SPRING_KAFKA_CONSUMER_ENABLE_AUTO_COMMIT=false
- SPRING_KAFKA_CONSUMER_TOPIC=agenet-syslog-topic
- SPRING_KAFKA_CONSUMER_MAX_POLL_RECORDS=1000
- SPRING_KAFKA_LISTENER_ACK_MODE=manual
- SPRING_KAFKA_LISTENER_CONCURRENCY=2
- SPRING_KAFKA_LISTENER_TYPE=batch
# InfluxDB配置
- influxdb.url=http://192.168.4.26:8087
- influxdb.token=LFjXZyRxTf1V84oN-wwjhSjS4qIK-ZMoHzQJB67ir3qHNSBVJbMcTkPuNmM0cNxvzFEDWLYNzrz1VJKMitY5hw==
- influxdb.org=influxdb
- influxdb.bucket=yelangbucket
- influxdb.batch.size=1000
- influxdb.flush.interval=1000
- influxdb.connection.timeout=30s
- influxdb.connection.read-timeout=30s
- influxdb.connection.write-timeout=60s
- INFLUXDB_URL=http://192.168.4.26:8087
- INFLUXDB_TOKEN=LFjXZyRxTf1V84oN-wwjhSjS4qIK-ZMoHzQJB67ir3qHNSBVJbMcTkPuNmM0cNxvzFEDWLYNzrz1VJKMitY5hw==
- INFLUXDB_ORG=influxdb
- INFLUXDB_BUCKET=yelangbucket
- INFLUXDB_BATCH_SIZE=1000
- INFLUXDB_FLUSH_INTERVAL=1000
- INFLUXDB_CONNECTION_TIMEOUT=30s
- INFLUXDB_CONNECTION_READ_TIMEOUT=30s
- INFLUXDB_CONNECTION_WRITE_TIMEOUT=60s
# 定时任务配置
- spring.task.scheduling.pool.size=10
- SPRING_TASK_SCHEDULING_POOL_SIZE=10
# 日志配置
- logging.level.com.common.schedule=INFO
- logging.level.com.common.service=INFO
- LOGGING_LEVEL_COM_COMMON_SCHEDULE=INFO
- LOGGING_LEVEL_COM_COMMON_SERVICE=INFO
# JVM配置
- JAVA_OPTS=-Xms1024m -Xmx4096m -XX:+UseG1GC -XX:MaxGCPauseMillis=200
@@ -0,0 +1,82 @@
# ============================================
# Syslog Consumer 部署配置
# ============================================
# 使用方法: docker compose -f docker-compose-consumer-rule-dm.yaml up -d
# ============================================
services:
# ============================================
# Syslog Consumer-rule - 数据消费规则服务(平台端)
# ============================================
syslog-consumer-rule:
build:
context: ./consumer-rule-dm
dockerfile: Dockerfile
image: syslog-consumer-rule-dm:v1.2.2
container_name: syslog-consumer-rule-dm
restart: unless-stopped
environment:
# 环境配置
- SPRING_PROFILES_ACTIVE=prod
- TZ=Asia/Shanghai
# 数据库配置
- SPRING_DATASOURCE_URL=jdbc:dm://192.168.4.99:5237
- SPRING_DATASOURCE_USERNAME=SYSDBA
- SPRING_DATASOURCE_PASSWORD=caZ2TcmXNSW8L2Ap
- SPRING_DATASOURCE_DRIVER-CLASS-NAME=dm.jdbc.driver.DmDriver
- SPRING_DATASOURCE_HIKARI_SCHEMA=\"PUBLIC\"
# HikariCP 连接池配置
- SPRING_DATASOURCE_HIKARI_MAXIMUM-POOL-SIZE=50
- SPRING_DATASOURCE_HIKARI_MINIMUM-IDLE=5
- SPRING_DATASOURCE_HIKARI_CONNECTION-TIMEOUT=30000
- SPRING_DATASOURCE_HIKARI_IDLE-TIMEOUT=600000
- SPRING_DATASOURCE_HIKARI_MAX-LIFETIME=900000
- SPRING_DATASOURCE_HIKARI_POOL-NAME=HikariPool-SyslogConsumer-rule
- SPRING_DATASOURCE_HIKARI_AUTO-COMMIT=false
# Redis配置
- SPRING_REDIS_HOST=192.168.4.99
- SPRING_REDIS_PORT=6379
- SPRING_REDIS_PASSWORD=redis_GdGWte
- SPRING_REDIS_DATABASE=0
- SPRING_REDIS_TIMEOUT=2000
- SPRING_CACHE_REDIS_TIME-TO-LIVE=600000
# Kafka配置
- SPRING_KAFKA_CONSUMER_BOOTSTRAP-SERVERS=192.168.4.99:9092
- SPRING_KAFKA_CONSUMER_GROUP-ID=agent-01-syslog-group-dm
- SPRING_KAFKA_CONSUMER_AUTO-OFFSET-RESET=latest
- SPRING_KAFKA_CONSUMER_ENABLE-AUTO-COMMIT=false
- SPRING_KAFKA_CONSUMER_TOPIC=agent-01-syslog-topic
- SPRING_KAFKA_CONSUMER_MAX-POLL-RECORDS=1000
- SPRING_KAFKA_LISTENER_ACK-MODE=manual
- SPRING_KAFKA_LISTENER_CONCURRENCY=2
- SPRING_KAFKA_LISTENER_TYPE=batch
# InfluxDB配置
- INFLUXDB_URL=http://192.168.4.99:8087
- INFLUXDB_TOKEN=JsUyvU8vhQEFlMM_el4Drm87fyh707IhwJNsPBucPghSdbVmdQ-UvmPcyP5NTzWxsRfEz0T51Rw4ebZUuUrmZg==
- INFLUXDB_ORG=influxdb
- INFLUXDB_BUCKET=yelangbucket
- INFLUXDB_BATCH_SIZE=1000
- INFLUXDB_FLUSH_INTERVAL=1000
- INFLUXDB_CONNECTION_TIMEOUT=30s
- INFLUXDB_CONNECTION_READ-TIMEOUT=30s
- INFLUXDB_CONNECTION_WRITE-TIMEOUT=60s
# 定时任务配置
- SPRING_TASK_SCHEDULING_POOL_SIZE=10
# 日志配置
- LOGGING_LEVEL_COM_COMMON_SCHEDULE=INFO
- LOGGING_LEVEL_COM_COMMON_SERVICE=INFO
volumes:
- /home/syslog/logs:/app/logs
networks:
- xdr-network
privileged: true
# ============================================
# 网络配置
# ============================================
networks:
xdr-network:
driver: bridge
@@ -21,52 +21,52 @@ services:
- SPRING_PROFILES_ACTIVE=dev
- TZ=Asia/Shanghai
# 数据库配置
- spring.datasource.url=jdbc:postgresql://117.72.68.72:54329/ecosys
- spring.datasource.username=postgres
- spring.datasource.password=TnLanWaidYSwTSG5
- spring.datasource.driver-class-name=org.postgresql.Driver
- SPRING_DATASOURCE_URL=jdbc:postgresql://117.72.68.72:54329/ecosys
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=TnLanWaidYSwTSG5
- SPRING_DATASOURCE_DRIVER_CLASS_NAME=org.postgresql.Driver
# HikariCP 连接池配置
- spring.datasource.hikari.maximum-pool-size=50
- spring.datasource.hikari.minimum-idle=5
- spring.datasource.hikari.connection-timeout=30000
- spring.datasource.hikari.idle-timeout=600000
- spring.datasource.hikari.max-lifetime=900000
- spring.datasource.hikari.pool-name=HikariPool-SyslogConsumer
- spring.datasource.hikari.auto-commit=false
- spring.datasource.hikari.schema=public
- SPRING_DATASOURCE_HIKARI_MAXIMUM_POOL_SIZE=50
- SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE=5
- SPRING_DATASOURCE_HIKARI_CONNECTION_TIMEOUT=30000
- SPRING_DATASOURCE_HIKARI_IDLE_TIMEOUT=600000
- SPRING_DATASOURCE_HIKARI_MAX_LIFETIME=900000
- SPRING_DATASOURCE_HIKARI_POOL_NAME=HikariPool-SyslogConsumer
- SPRING_DATASOURCE_HIKARI_AUTO_COMMIT=false
- SPRING_DATASOURCE_HIKARI_SCHEMA=public
# Redis配置
- spring.redis.host=192.168.222.131
- spring.redis.port=6379
- spring.redis.password=
- spring.redis.database=0
- spring.redis.timeout=2000
- spring.cache.redis.time-to-live=600000
- SPRING_REDIS_HOST=192.168.222.131
- SPRING_REDIS_PORT=6379
- SPRING_REDIS_PASSWORD=
- SPRING_REDIS_DATABASE=0
- SPRING_REDIS_TIMEOUT=2000
- SPRING_CACHE_REDIS_TIME_TO_LIVE=600000
# Kafka配置
- spring.kafka.consumer.bootstrap-servers=192.168.222.130:9092
- spring.kafka.consumer.group-id=test-group-app
- spring.kafka.consumer.auto-offset-reset=latest
- spring.kafka.consumer.enable-auto-commit=false
- spring.kafka.consumer.topic=test-topic
- spring.kafka.consumer.max-poll-records=1000
- spring.kafka.listener.ack-mode=manual
- spring.kafka.listener.concurrency=2
- spring.kafka.listener.type=batch
- SPRING_KAFKA_CONSUMER_BOOTSTRAP_SERVERS=192.168.222.130:9092
- SPRING_KAFKA_CONSUMER_GROUP_ID=test-group-app
- SPRING_KAFKA_CONSUMER_AUTO_OFFSET_RESET=latest
- SPRING_KAFKA_CONSUMER_ENABLE_AUTO_COMMIT=false
- SPRING_KAFKA_CONSUMER_TOPIC=test-topic
- SPRING_KAFKA_CONSUMER_MAX_POLL_RECORDS=1000
- SPRING_KAFKA_LISTENER_ACK_MODE=manual
- SPRING_KAFKA_LISTENER_CONCURRENCY=2
- SPRING_KAFKA_LISTENER_TYPE=batch
# InfluxDB配置
- influxdb.url=http://192.168.222.131:8086
- influxdb.token=3Tvu-IZWtaY03UDkbUDlufD0kxn85keo9LhYQcv2Cxk0LJmXqqHkNVrO664DbaJAYwoGI7UIg904KqZC7Q_ZFA==
- influxdb.org=yelang
- influxdb.bucket=yelangbucket
- influxdb.batch.size=1000
- influxdb.flush.interval=1000
- influxdb.connection.timeout=30s
- influxdb.connection.read-timeout=30s
- influxdb.connection.write-timeout=60s
- INFLUXDB_URL=http://192.168.222.131:8086
- INFLUXDB_TOKEN=3Tvu-IZWtaY03UDkbUDlufD0kxn85keo9LhYQcv2Cxk0LJmXqqHkNVrO664DbaJAYwoGI7UIg904KqZC7Q_ZFA==
- INFLUXDB_ORG=yelang
- INFLUXDB_BUCKET=yelangbucket
- INFLUXDB_BATCH_SIZE=1000
- INFLUXDB_FLUSH_INTERVAL=1000
- INFLUXDB_CONNECTION_TIMEOUT=30s
- INFLUXDB_CONNECTION_READ_TIMEOUT=30s
- INFLUXDB_CONNECTION_WRITE_TIMEOUT=60s
# 定时任务配置
- spring.task.scheduling.pool.size=10
- SPRING_TASK_SCHEDULING_POOL_SIZE=10
# 日志配置
- logging.level.com.common.schedule=INFO
- logging.level.com.common.service=INFO
- LOGGING_LEVEL_COM_COMMON_SCHEDULE=INFO
- LOGGING_LEVEL_COM_COMMON_SERVICE=INFO
# JVM配置
- JAVA_OPTS=-Xms1024m -Xmx4096m -XX:+UseG1GC -XX:MaxGCPauseMillis=200
ports:
@@ -46,7 +46,7 @@
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>3.4.0</version>
<version>3.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
@@ -104,8 +104,8 @@
<!-- 达梦数据库驱动 JDK1.8 -->
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
<version>8.1.2.141</version>
<artifactId>DmJdbcDriver</artifactId>
<version>8.1.4.169</version>
</dependency>
<dependency>
@@ -1,461 +1,354 @@
package com.Modules.NormalData;
import cn.hutool.core.date.DateTime;
import com.common.entity.XdrHoneypot;
import com.common.mapper.XdrHoneypotMapper;
import com.common.service.SyslogNonNormalMessageService;
import com.common.util.*;
import com.config.AppConfig;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import com.common.entity.SyslogMessage;
import com.influx.SyslogToInfluxApp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.common.service.DmNormalizeRuleService;
import com.common.service.DmColumnService;
import com.common.service.SyslogNormalDataService;
import com.common.entity.DmColumn;
import com.common.service.impl.DmColumnServiceImpl;
import com.common.mapper.DmColumnMapper;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RestController;
import com.common.mapper.DmColumnMapper;
import com.common.mapper.DmNormalizeRuleMapper;
import java.sql.Timestamp;
import java.util.*;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.json.JSONObject;
import com.common.entity.RuleContent.*;
import com.common.entity.SyslogNonNormalMessage;
import org.joda.time.LocalDateTime;
import com.common.service.LogDataFilterService;
import com.common.service.LogDataCompleteService;
import com.common.service.DeviceCollectTaskService;
import com.common.entity.DeviceCollectTask;
import com.common.entity.DeviceDevice;
import com.common.util.TimeConversionUtils;
import com.common.service.DeviceDeviceService;
import com.common.entity.RuleContent.*;
import com.common.entity.SyslogNonNormalMessage;
import com.common.mapper.DmColumnMapper;
import com.common.mapper.DmNormalizeRuleMapper;
import com.common.service.*;
import com.common.util.*;
import com.config.AppProperties;
import com.config.KafkaConsumerProperties;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.common.entity.SyslogMessage;
import java.util.*;
/**
* 日志标准化处理器(规则引擎模块 - Spring 管理的单例 Bean
* 线程安全版本:运行时状态封装为 ProcessContext,每次 process() 调用独立(解决多线程 NPE 问题)
*/
@Service
public class LogNormalProcessor {
private static final Logger logger = LoggerFactory.getLogger(LogNormalProcessor.class);
private String strLogMsg ;
private String strKafkaMessage;
private String strDeviceInfo;
private String strDataType ="json" ;
private Map<String, Object> messageMap ;
private Map<String, String> deviceInfoMap ;
private String strSyslogUUID ;
private String strSyslogTopic ;
private boolean isSaveNonNormal =false ;
// ==================== 依赖注入(Spring Bean,单例,线程安全)====================
private final DmNormalizeRuleService dmNormalizeRuleService;
private final DmColumnService dmColumnService;
private final SyslogNormalDataService syslogNormalDataService;
private final SyslogNonNormalMessageService messageService;
private final LogDataFilterService logDataFilterService;
private final LogDataCompleteService logDataCompleteService;
private final DeviceCollectTaskService deviceCollectTaskService;
private final DeviceDeviceService deviceDeviceService;
private final DmColumnMapper dmColumnMapper;
private final DmNormalizeRuleMapper dmNormalizeRuleMapper;
private final KafkaConsumerProperties kafkaConsumerProperties;
private final AppProperties appProperties;
@Autowired
public DmNormalizeRuleService dmNormalizeRuleService ;
@Autowired
public DmColumnService dmColumnService ;
@Autowired
public SyslogNormalDataService syslogNormalDataService =SpringContextUtil.getBean(SyslogNormalDataService.class);
@Autowired
private SyslogNonNormalMessageService messageService =SpringContextUtil.getBean(SyslogNonNormalMessageService.class);
@Autowired
private LogDataFilterService logDataFilterService= SpringContextUtil.getBean(LogDataFilterService.class);
@Autowired
private LogDataCompleteService logDataCompleteService= SpringContextUtil.getBean(LogDataCompleteService.class);
@Autowired
private DeviceCollectTaskService deviceCollectTaskService= SpringContextUtil.getBean(DeviceCollectTaskService.class);
@Autowired
private DeviceDeviceService deviceDeviceService= SpringContextUtil.getBean(DeviceDeviceService.class);
@Autowired
SyslogNonNormalMessage syslogNonNormalMessage=new SyslogNonNormalMessage();
@Autowired
DmColumnMapper dmColumnMapper;
@Autowired
DmNormalizeRuleMapper dmNormalizeRuleMapper;
private List<Map<String, Object>> dmNormalizeRuleList;
private List<Map<String, Object>> dmColumnList;
private LinkedHashMap<String, Object> OrginalColumnMap ;
public LogNormalProcessor( String LogMsg, String syslogUUID,String syslogTopic) {
/** 标准化数据处理步骤 */
//初始化 (获取syslog_normal_data 表全部字段的属性、设备ID对应的规则设置、转化成JSON)
//判断数据解析类型(json、键值、xml、正则表达式、分割符)解析syslogMessage 字段转成 HashMAP
//匹配规则内容,获取字段映射关系配置,抽取命中的字段名称、数值
//判断字段内容及类型,根据数据类型属性,进行内容转换。
//生成insert SQL语句、执行入库操作。
strKafkaMessage=LogMsg;
strSyslogUUID=syslogUUID;
strSyslogTopic=syslogTopic;
if(!LogMsg.isEmpty()) {
strLogMsg = SyslogParser.substringAfterFirstCloseBracket(LogMsg);
strDeviceInfo=SyslogParser.substringBeforeFirstChar(LogMsg,']');
}
else{
LogMsg="[receive_time=20251118165909470 device_id=1 device_name=honeypot vendor=changting data_type=json device_collect_id=1]<14>1 2025-09-24T11:52:26Z 5f46d3be75e1 supermario 128 honeypot_event - {\"source\":\"honeypot1\",\"id\":\"f6a13c35-bf9d-4da6-a181-50ce23e7ef6a\",\"start_time\":\"2023-09-03T11:07:02.50167643Z\",\"time\":\"2023-09-03T11:16:18.883885281Z\",\"risk_level\":4,\"connection\":\"b18f3fbe-3fbf-4495-815f-ff26f6fb0bdf\",\"file_info\":null,\"extra\":{\"payload\":{\"format\":\"line\",\"name\":{\"cn\":\"攻击载荷\",\"en\":\"payload\"},\"value\":\"\"},\"uid\":{\"format\":\"line\",\"name\":{\"cn\":\"\",\"en\":\"\"},\"uid\":\"b4cbc73c-25d0-4429-ae1b-a856cdf1a651\",\"value\":\"\"}},\"type\":\"WEB_ATTACK_SCANNER\",\"agent_sn\":\"caa7da42-0cca-4cb1-b501-1f1eb2b588d5\",\"agent_name\":\" 教育局蜜罐探针\",\"honeypot_id\":\"11a9ac6bdf38ae2aaa49ec4f1b4a921bff71952cb9f175bdd8ee1f0497057bc6\",\"honeypot_name\":\"茂名市中小学管理平台管理后台\",\"src_ip\":\"117.50.189.7\",\"src_port\":58512,\"src_mac\":\"\",\"dest_ip\":\"192.168.222.2\",\"dest_port\":9200,\"proxy_ip\":null,\"node\":\"WRx3\"}";
strLogMsg="<14>1 2025-09-24T11:52:26Z 5f46d3be75e1 supermario 128 honeypot_event - {\"source\":\"honeypot1\",\"id\":\"f6a13c35-bf9d-4da6-a181-50ce23e7ef6a\",\"start_time\":\"2023-09-03T11:07:02.50167643Z\",\"time\":\"2023-09-03T11:16:18.883885281Z\",\"risk_level\":4,\"connection\":\"b18f3fbe-3fbf-4495-815f-ff26f6fb0bdf\",\"file_info\":null,\"extra\":{\"payload\":{\"format\":\"line\",\"name\":{\"cn\":\"攻击载荷\",\"en\":\"payload\"},\"value\":\"\"},\"uid\":{\"format\":\"line\",\"name\":{\"cn\":\"\",\"en\":\"\"},\"uid\":\"b4cbc73c-25d0-4429-ae1b-a856cdf1a651\",\"value\":\"\"}},\"type\":\"WEB_ATTACK_SCANNER\",\"agent_sn\":\"caa7da42-0cca-4cb1-b501-1f1eb2b588d5\",\"agent_name\":\" 教育局蜜罐探针\",\"honeypot_id\":\"11a9ac6bdf38ae2aaa49ec4f1b4a921bff71952cb9f175bdd8ee1f0497057bc6\",\"honeypot_name\":\"茂名市中小学管理平台管理后台\",\"src_ip\":\"117.50.189.7\",\"src_port\":58512,\"src_mac\":\"\",\"dest_ip\":\"192.168.222.2\",\"dest_port\":9200,\"proxy_ip\":null,\"node\":\"WRx3\"}";
strDeviceInfo=SyslogParser.substringBeforeFirstChar(LogMsg,']');
}
}
/**
* 初始化数据init()
* 请求级处理上下文 —— 每个 process() 调用创建新实例,彻底解决多线程竞态条件
*/
public void init()
{
Map<String,String> mapdev =SyslogParser.parseKeyValuePairs(strDeviceInfo);
deviceInfoMap=mapdev;
//获取日志对应的设备ID
long deviceID=Long.parseLong(mapdev.get("device_id"));
System.out.println("device_id:"+deviceID );
strDataType=mapdev.get("data_type");
//getDeviceID(strLogMsg);
try{
// 通过工具类获取Service实例
dmColumnService= SpringContextUtil.getBean(DmColumnService.class);
dmNormalizeRuleService= SpringContextUtil.getBean(DmNormalizeRuleService.class);
if(deviceID>0) {
dmNormalizeRuleList = dmNormalizeRuleService.selectByDeviceIdAuto(deviceID);
private static class ProcessContext {
String strLogMsg;
String strKafkaMessage;
String strDeviceInfo;
String strDataType = "json";
Map<String, Object> messageMap;
Map<String, String> deviceInfoMap;
String strSyslogUUID;
String strSyslogTopic;
boolean isSaveNonNormal = false;
SyslogNonNormalMessage syslogNonNormalMessage = new SyslogNonNormalMessage();
List<Map<String, Object>> dmNormalizeRuleList;
List<Map<String, Object>> dmColumnList;
LinkedHashMap<String, Object> OrginalColumnMap;
}
// ==================== 构造器注入(Spring 自动完成)====================
@Autowired
public LogNormalProcessor(
DmNormalizeRuleService dmNormalizeRuleService,
DmColumnService dmColumnService,
SyslogNormalDataService syslogNormalDataService,
SyslogNonNormalMessageService messageService,
LogDataFilterService logDataFilterService,
LogDataCompleteService logDataCompleteService,
DeviceCollectTaskService deviceCollectTaskService,
DeviceDeviceService deviceDeviceService,
DmColumnMapper dmColumnMapper,
DmNormalizeRuleMapper dmNormalizeRuleMapper,
KafkaConsumerProperties kafkaConsumerProperties,
AppProperties appProperties
) {
this.dmNormalizeRuleService = dmNormalizeRuleService;
this.dmColumnService = dmColumnService;
this.syslogNormalDataService = syslogNormalDataService;
this.messageService = messageService;
this.logDataFilterService = logDataFilterService;
this.logDataCompleteService = logDataCompleteService;
this.deviceCollectTaskService = deviceCollectTaskService;
this.deviceDeviceService = deviceDeviceService;
this.dmColumnMapper = dmColumnMapper;
this.dmNormalizeRuleMapper = dmNormalizeRuleMapper;
this.kafkaConsumerProperties = kafkaConsumerProperties;
this.appProperties = appProperties;
}
/**
* 处理一条日志消息(线程安全:每次调用创建独立的 ProcessContext
*
* @param logMsg 完整日志消息(含头部)
* @param syslogUUID 消息UUID
* @param syslogTopic 消息Topic(可传 null,自动使用配置值)
*/
public void process(String logMsg, String syslogUUID, String syslogTopic) {
ProcessContext ctx = new ProcessContext();
ctx.strSyslogUUID = syslogUUID;
ctx.strSyslogTopic = (syslogTopic != null && !syslogTopic.isEmpty())
? syslogTopic
: kafkaConsumerProperties.getTopic();
ctx.isSaveNonNormal = false;
ctx.syslogNonNormalMessage = new SyslogNonNormalMessage();
// 解析消息
ctx.strKafkaMessage = logMsg;
if (!logMsg.isEmpty()) {
ctx.strLogMsg = SyslogParser.substringAfterFirstCloseBracket(logMsg);
ctx.strDeviceInfo = SyslogParser.substringBeforeFirstChar(logMsg, ']');
} else {
logMsg = "[receive_time=20251118165909470 device_id=1 device_name=honeypot vendor=changting data_type=json device_collect_id=1]<14>1 2025-09-24T11:52:26Z 5f46d3be75e1 supermario 128 honeypot_event - \uFEFF{\"source\":\"honeypot1\",\"id\":\"f6a13c35-bf9d-4da6-a181-50ce23e7ef6a\"}";
ctx.strLogMsg = "<14>1 2025-09-24T11:52:26Z 5f46d3be75e1 supermario 128 honeypot_event - \uFEFF{\"source\":\"honeypot1\",\"id\":\"f6a13c35-bf9d-4da6-a181-50ce23e7ef6a\"}";
ctx.strDeviceInfo = SyslogParser.substringBeforeFirstChar(logMsg, ']');
}
// 执行处理
init(ctx);
}
/**
* 初始化数据处理(所有运行时状态通过 ctx 传递,线程安全)
*/
private void init(ProcessContext ctx) {
Map<String, String> mapdev = SyslogParser.parseKeyValuePairs(ctx.strDeviceInfo);
ctx.deviceInfoMap = mapdev;
long deviceID = Long.parseLong(mapdev.get("device_id"));
System.out.println("device_id:" + deviceID);
ctx.strDataType = mapdev.get("data_type");
try {
if (deviceID > 0) {
ctx.dmNormalizeRuleList = dmNormalizeRuleService.selectByDeviceIdAuto(deviceID);
}
//dmColumnList=dmColumnService.selectAllNormal();
//System.out.println("dmColumnList size:"+ dmColumnList.size());
//OrginalColumnMap=getMessageToMap(strLogMsg);
//解析SyslogMessage
//SyslogMessage logMsg = SyslogParser.parse(strLogMsg);
//设备对应的规则normal rule Map 进行标准化数据处理
for (int i = 0; i < dmNormalizeRuleList.size(); i++) {
for (int i = 0; i < ctx.dmNormalizeRuleList.size(); i++) {
try {
Map<String, Object> dmNormalizeRule = dmNormalizeRuleList.get(i);
Map<String, Object> dmNormalizeRule = ctx.dmNormalizeRuleList.get(i);
String data_type = dmNormalizeRule.get("data_type").toString();
//数据类型及格式不符,则break;
System.out.println("索引: " + i + ", 值: " + dmNormalizeRule);
System.out.println("normalrule ID: " + dmNormalizeRule.get("id") + ", display_name:" + dmNormalizeRule.get("display_name") + " data_type:" + dmNormalizeRule.get("data_type"));
//数据类型不匹配,则跳过规则
//if (!data_type.equals(strDataType)) break;
System.out.println("normalrule ID: " + dmNormalizeRule.get("id")
+ ", display_name:" + dmNormalizeRule.get("display_name")
+ " data_type:" + dmNormalizeRule.get("data_type"));
//获取syslog message 文本解析配置项
OrginalColumnMap = getMessageToMap(dmNormalizeRule, strLogMsg, data_type);
if ((OrginalColumnMap == null) || (OrginalColumnMap.size()==0)) {
ctx.OrginalColumnMap = getMessageToMap(dmNormalizeRule, ctx.strLogMsg, data_type);
if ((ctx.OrginalColumnMap == null) || (ctx.OrginalColumnMap.size() == 0)) {
logger.error("OrginalColumnMap 对象获取为空");
//保存非标日志信息
syslogNonNormalMessage.setReason("Log解析异常");
syslogNonNormalMessage.setReasonDetail("log解析异常,返回规则名称:"+dmNormalizeRule.get("display_name") +",OrginalColumnMap 对象获取为空");
if(isSaveNonNormal==false)
SaveNonNormalMessage(deviceID, DateTime.now());
ctx.syslogNonNormalMessage.setReason("Log解析异常");
ctx.syslogNonNormalMessage.setReasonDetail("log解析异常,返回规则名称:"
+ dmNormalizeRule.get("display_name") + ",OrginalColumnMap 对象获取为空");
if (ctx.isSaveNonNormal == false)
SaveNonNormalMessage(ctx, deviceID, DateTime.now());
continue;
}
List<HashMap<String, Object>> destColumnList = getRuleContentMappers(dmNormalizeRule);
//解析字段匹配已命中的配置规则字段
List<HashMap<String, Object>> ruleColumnList = getNormalColumnList(OrginalColumnMap, destColumnList);
//System.out.println("ruleColumnList :"+ ruleColumnList);
List<HashMap<String, Object>> ruleColumnList = getNormalColumnList(ctx.OrginalColumnMap, destColumnList);
Map<String, Object> destMap = getColumnMap(ruleColumnList);
//List<HashMap<String ,Object>> destMap2= getCompleteColumnsList(dmNormalizeRule);
//数据处理-过滤规则
if (logDataFilterService.evaluateFilterRule(dmNormalizeRule.get("rule_content").toString(), destMap))
// 数据处理-过滤规则
if (logDataFilterService.evaluateFilterRule(
dmNormalizeRule.get("rule_content").toString(), destMap))
continue;
//数据处理-补全规则
logDataCompleteService.processDataCompletion(dmNormalizeRule.get("rule_content").toString(), destMap);
//long ruleid=Long.parseLong(dmNormalizeRule.get("id").toString());
SaveNormalData(deviceID, DateTime.now(), destMap, Long.parseLong(dmNormalizeRule.get("id").toString()), dmNormalizeRule.get("name").toString());
// 数据处理-补全规则
logDataCompleteService.processDataCompletion(
dmNormalizeRule.get("rule_content").toString(), destMap);
SaveNormalData(ctx, deviceID, DateTime.now(), destMap,
Long.parseLong(dmNormalizeRule.get("id").toString()),
dmNormalizeRule.get("name").toString());
} catch (Exception ex) {
logger.error("泛化规则处理失败:" + ex.getMessage());
System.out.println(ex.getMessage());
/**
//保存非标日志信息
syslogNonNormalMessage.setReason("泛化规则处理失败");
syslogNonNormalMessage.setReasonDetail("泛化规则处理失败,失败详情:"+ ex.getMessage());
SaveNonNormalMessage(deviceID,DateTime.now());
**/
}
}
}
catch (Exception ex)
{
logger.error("处理初始化异常:"+ex.getMessage());
} catch (Exception ex) {
logger.error("处理日志消息异常:" + ex.getMessage());
System.out.println(ex.getMessage());
}
}
// ==================== 以下为原有业务方法 ====================
//获取数据泛化规则的列表字段,提取 Cropper_params
public Cropper_paramsType getCropperParams( Map<String, Object> dmNormalizeRule )
{
Cropper_paramsType cropperParams = new Cropper_paramsType();
public Cropper_paramsType getCropperParams(Map<String, Object> dmNormalizeRule) {
Cropper_paramsType cropperParams = new Cropper_paramsType();
try {
JSONObject jsonObject = new JSONObject( dmNormalizeRule.get("rule_content").toString());
JSONObject jsonObject = new JSONObject(dmNormalizeRule.get("rule_content").toString());
if (jsonObject.isEmpty()) return null;
cropperParams.sethead_key(jsonObject.getJSONObject("cropper_params").get("head_key").toString());
//需要判断是否字符串head_offset是否空
cropperParams.sethead_offset(Integer.parseInt(jsonObject.getJSONObject("cropper_params").get("head_offset").toString()));
cropperParams.sethead_offset(Integer.parseInt(
jsonObject.getJSONObject("cropper_params").get("head_offset").toString()));
cropperParams.settail_key(jsonObject.getJSONObject("cropper_params").get("tail_key").toString());
//需要判断是否字符串tail_offset是否空
cropperParams.settail_offset( Integer.parseInt(jsonObject.getJSONObject("cropper_params").get("tail_offset").toString()));
cropperParams.settail_offset(Integer.parseInt(
jsonObject.getJSONObject("cropper_params").get("tail_offset").toString()));
return cropperParams;
}catch (Exception ex) {
logger.error("getCropperParams"+ex.getMessage());
} catch (Exception ex) {
logger.error("getCropperParams" + ex.getMessage());
return null;
}
}
public List<HashMap<String ,Object>> getRuleContentMappers( Map<String, Object> dmNormalizeRule )
{
List<HashMap<String, Object>> filedList =null;
ObjectMapper objectMapper = new ObjectMapper();
public List<HashMap<String, Object>> getRuleContentMappers(Map<String, Object> dmNormalizeRule) {
List<HashMap<String, Object>> filedList = null;
try {
// 转换为list Map
//Map<String, Object> rule_contentMap = objectMapper.readValue( dmNormalizeRule.get("rule_content").toString(), Map.class);
//if (rule_contentMap.isEmpty()) return null;
JSONObject jsonObject = new JSONObject( dmNormalizeRule.get("rule_content").toString());
JSONObject jsonObject = new JSONObject(dmNormalizeRule.get("rule_content").toString());
if (jsonObject.isEmpty()) return null;
ObjectMapper objectMapper_mappers = new ObjectMapper();
filedList =readJsonToList( jsonObject.get("mappers").toString() );
}catch (Exception ex) {
logger.error("getRuleContentMappers异常:"+ex.getMessage());
filedList = readJsonToList(jsonObject.get("mappers").toString());
} catch (Exception ex) {
logger.error("getRuleContentMappers异常:" + ex.getMessage());
}
return filedList;
}
public List<HashMap<String, Object>> getCompleteColumnsList( Map<String, Object> dmNormalizeRule )
{
List<HashMap<String, Object>> filedList =null;
ObjectMapper objectMapper = new ObjectMapper();
public List<HashMap<String, Object>> getCompleteColumnsList(Map<String, Object> dmNormalizeRule) {
List<HashMap<String, Object>> filedList = null;
try {
// 转换为list Map
//Map<String, Object> rule_contentMap = objectMapper.readValue( dmNormalizeRule.get("rule_content").toString(), Map.class);
//if (rule_contentMap.isEmpty()) return null;
JSONObject jsonObject = new JSONObject( dmNormalizeRule.get("rule_content").toString());
JSONObject jsonObject = new JSONObject(dmNormalizeRule.get("rule_content").toString());
if (jsonObject.isEmpty()) return null;
ObjectMapper objectMapper_mappers = new ObjectMapper();
filedList =readJsonToList( jsonObject.get("complete_columns").toString() );
}catch (Exception ex) {
logger.error("getCompleteColumnsList"+ex.getMessage());
filedList = readJsonToList(jsonObject.get("complete_columns").toString());
} catch (Exception ex) {
logger.error("getCompleteColumnsList" + ex.getMessage());
}
return filedList;
}
/**
* 将JSON 字符串转换为 List<HashMap<String, Object>>
*/
public static List<HashMap<String, Object>> readJsonToList(String jsonStr) {
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.readValue(
jsonStr,
new TypeReference<List<HashMap<String, Object>>>() {}
);
return objectMapper.readValue(jsonStr,
new TypeReference<List<HashMap<String, Object>>>() {});
} catch (Exception e) {
logger.error("readJsonToList 解析失败:"+jsonStr);
//throw new RuntimeException("JSON 解析失败: " + e.getMessage(), e);
LoggerFactory.getLogger(LogNormalProcessor.class).error("readJsonToList 解析失败:" + jsonStr);
return null;
}
}
/**\
* 判断日志信息的数据类型
* @param logMsg
* @return
*/
public String getLogDataType( String logMsg)
{
//判断日志信息的数据类型(json、regex、kv、sep、xml
//默认返回json
public String getLogDataType(String logMsg) {
return "json";
}
public int getDeviceID( String logMsg)
{
//解析日志信息头部,获取device_id
// 默认返回device_id =1
public int getDeviceID(String logMsg) {
return 1;
}
//获取log 内容字段及数据值
public LinkedHashMap<String, Object> getMessageToMap( String MsgContent )
{
LinkedHashMap<String, Object> linkMap =null;
if(strDataType.equals("json")) {
//json 类型
//解析SyslogMessage
public LinkedHashMap<String, Object> getMessageToMap(String MsgContent) {
LinkedHashMap<String, Object> linkMap = null;
if ("json".equals("json")) { // 默认走 json 分支,已无实例字段 strDataType
SyslogMessage msg = SyslogParser.parse(MsgContent);
System.out.println("解析结果-log content: " + msg.getMessage().toString());
String complexJson = "{\"source\":\"honeypot1\",\"id\":\"f6a13c35-bf9d-4da6-a181-50ce23e7ef6a\",\"start_time\":\"2023-09-03T11:07:02.50167643Z\",\"time\":\"2023-09-03T11:16:18.883885281Z\",\"risk_level\":4,\"connection\":\"b18f3fbe-3fbf-4495-815f-ff26f6fb0bdf\",\"file_info\":null,\"extra\":{\"payload\":{\"format\":\"line\",\"name\":{\"cn\":\"攻击载荷\",\"en\":\"payload\"},\"value\":\"\"},\"uid\":{\"format\":\"line\",\"name\":{\"cn\":\"\",\"en\":\"\"},\"uid\":\"b4cbc73c-25d0-4429-ae1b-a856cdf1a651\",\"value\":\"\"}},\"type\":\"WEB_ATTACK_SCANNER\",\"agent_sn\":\"caa7da42-0cca-4cb1-b501-1f1eb2b588d5\",\"agent_name\":\" 教育局蜜罐探针\",\"honeypot_id\":\"11a9ac6bdf38ae2aaa49ec4f1b4a921bff71952cb9f175bdd8ee1f0497057bc6\",\"honeypot_name\":\"茂名市中小学管理平台管理后台\",\"src_ip\":\"117.50.189.7\",\"src_port\":58512,\"src_mac\":\"\",\"dest_ip\":\"192.168.222.2\",\"dest_port\":9200,\"proxy_ip\":null,\"node\":\"WRx3\"}";
String complexJson = "{\"source\":\"honeypot1\",\"id\":\"f6a13c35-bf9d-4da6-a181-50ce23e7ef6a\"}";
System.out.println("complexJson content: " + complexJson);
//静态字符串、编码有问题,临时用 静态字符串做测试,流程环境没问题
if(AppConfig.geRunEnvironment().equals("dev")) {
//LinkedHashMap<String, Object> flatMap = JsonParser.parseJsonToFlatMap(complexJson);
LinkedHashMap<String, Object> flatMap =JsonParser.jsonToMap(complexJson);
if ("dev".equals(appProperties.getRunEnvironment())) {
LinkedHashMap<String, Object> flatMap = JsonParser.jsonToMap(complexJson);
flatMap.forEach((key, value) -> System.out.println(key + " = " + value));
return flatMap;
}
else
{
//LinkedHashMap<String, Object> flatMap = JsonParser.parseJsonToFlatMap(msg.getMessage());
LinkedHashMap<String, Object> flatMap =JsonParser.jsonToMap(msg.getMessage());
} else {
LinkedHashMap<String, Object> flatMap = JsonParser.jsonToMap(msg.getMessage());
flatMap.forEach((key, value) -> System.out.println(key + " = " + value));
return flatMap;
}
}
else if(strDataType.equals("kv")) //key-value 键值类型
{
return null;
}
else if(strDataType.equals("sep")) //分隔符
{
return null;
}
else if(strDataType.equals("xml")) //类型 xml
{
return null;
}
else if(strDataType.equals("regex")) //正则表达式
{
return null;
}
// List<Map<String, Object>> rulelst=dmNormalizeRuleService.selectByDeviceId((long)1);
return linkMap;
}
//获取log message内容字段及数据值
public LinkedHashMap<String, Object> getMessageToMap( Map<String, Object> dmNormalizeRule, String MsgContent , String dataType)
{
public LinkedHashMap<String, Object> getMessageToMap(
Map<String, Object> dmNormalizeRule, String MsgContent, String dataType) {
LinkedHashMap<String, Object> linkMap = new LinkedHashMap<>();
try {
//String decode =dmNormalizeRule.get("decode").toString();
Cropper_paramsType cropperParams = getCropperParams(dmNormalizeRule);
Cropper_paramsType cropperParams = getCropperParams(dmNormalizeRule);
if (dataType.equals("json")) {
String strJson = logNormalData.ParserMessageJsonType(MsgContent, cropperParams);
LinkedHashMap<String, Object> result1 = NestedJsonParserUtil.safeParseJson(strJson);
LinkedHashMap<String, Object> flattened = NestedJsonUtils.flattenNestedJson(result1);
return flattened;
//parseJsonToFlatMap 复杂的json转换、解析过程有异常
//return JsonParser.parseJsonToFlatMap(strJson);
// return JsonParser.jsonToMap(strJson);
}
else if (dataType.equals("kv")) //key-value 键值类型
{
} else if (dataType.equals("kv")) {
String strKeyVal = logNormalData.ParserMessageJsonType(MsgContent, cropperParams);
KvTextParser kvTextParser =new KvTextParser();
kv_paramsType kvparams=logNormalData.getkv_paramsType( dmNormalizeRule);
linkMap= kvTextParser.parseKvText(strKeyVal,kvparams);
KvTextParser kvTextParser = new KvTextParser();
kv_paramsType kvparams = logNormalData.getkv_paramsType(dmNormalizeRule);
linkMap = kvTextParser.parseKvText(strKeyVal, kvparams);
return linkMap;
}
else if (dataType.equals("sep")) //分隔符
{
//获取分隔符
String SepKey=logNormalData.sepType(dmNormalizeRule);
} else if (dataType.equals("sep")) {
String SepKey = logNormalData.sepType(dmNormalizeRule);
String strSep = logNormalData.ParserMessageJsonType(MsgContent, cropperParams);
linkMap= TextParserUtil.parseSeparatedText(strSep, SepKey);
linkMap = TextParserUtil.parseSeparatedText(strSep, SepKey);
return linkMap;
}
else if (dataType.equals("xml")) //类型 xml
{
} else if (dataType.equals("xml")) {
return linkMap;
}
else if (dataType.equals("regex")) //正则表达式
{
} else if (dataType.equals("regex")) {
String strRegex = logNormalData.ParserMessageJsonType(MsgContent, cropperParams);
String regexp= logNormalData.Regexp(dmNormalizeRule);
linkMap= RegexTextParser.parseWithRegex(strRegex,regexp );
String regexp = logNormalData.Regexp(dmNormalizeRule);
linkMap = RegexTextParser.parseWithRegex(strRegex, regexp);
return linkMap;
}
}catch (Exception ex) {
logger.error("getMessageToMap"+ex.getMessage());
return null;
} catch (Exception ex) {
logger.error("getMessageToMap" + ex.getMessage());
return null;
}
return linkMap;
}
/**
* 根据设备ID获取配置规则
* @param device_id
* @return List<Map<String, Object>>
*/
public List<Map<String, Object>> getRuleList( long device_id)
{
List<Map<String, Object>> rulelst=dmNormalizeRuleService.selectByDeviceId((long)1);
if (rulelst!=null)
{
public List<Map<String, Object>> getRuleList(long device_id) {
List<Map<String, Object>> rulelst = dmNormalizeRuleService.selectByDeviceId((long) 1);
if (rulelst != null) {
System.out.println("rulelst: " + rulelst);
}
else{
logger.error(" List<Map<String, Object>> rulelst is null" );
} else {
logger.error(" List<Map<String, Object>> rulelst is null");
}
return rulelst;
}
/**
* 查找命中配置规则的字段及数值
* @param destColumnList 泛化目标字段list
* @param destColumnList 日志源字段及数值list
* @return
*/
public List<HashMap<String,Object>> getNormalColumnList( LinkedHashMap<String, Object> orginColumnMap ,List<HashMap<String, Object>> destColumnList )
{
List<HashMap<String, Object>> columnlist =new ArrayList<>();
// 原始解析字段遍历泛化规则目标字段
for (Map.Entry<String, Object > entry : orginColumnMap.entrySet()) {
//System.out.println(entry.getKey() + ": " + entry.getValue());
public List<HashMap<String, Object>> getNormalColumnList(
LinkedHashMap<String, Object> orginColumnMap,
List<HashMap<String, Object>> destColumnList) {
List<HashMap<String, Object>> columnlist = new ArrayList<>();
for (Map.Entry<String, Object> entry : orginColumnMap.entrySet()) {
for (Map<String, Object> map : destColumnList) {
//System.out.println( "origin_field: " + map.get("origin_field").toString());
if ( map.get("origin_field").toString().equals(entry.getKey()) ) {
if (map.get("origin_field").toString().equals(entry.getKey())) {
System.out.println(map);
Map<String, Object> normalColumMap =new LinkedHashMap<>();
normalColumMap.put("origin_field",entry.getKey() );
normalColumMap.put("dest_field",map.get("dest_field").toString());
normalColumMap.put("action",(HashMap<String, Object>)map.get("action") );
//normalColumMap.put("mapping ",entry.getKey() );
normalColumMap.put("origin_field_value",entry.getValue() );
// System.out.println("action: " + map.get("action").toString());
if( ((HashMap<String, Object>)map.get("action")).get("type").equals("equal"))
//直接赋值
normalColumMap.put("dest_field_value",entry.getValue() );
else if(((HashMap<String, Object>)map.get("action")).get("type").equals("mapping"))
{
//mapping 映射枚举值
normalColumMap.put("dest_field_value",entry.getValue() );
normalColumMap.put("action_param",((HashMap<String, Object>)map.get("action")).get("param") );
HashMap<String, Object> action_param=(HashMap<String, Object>)((HashMap<String, Object>)map.get("action")).get("param") ;
//匹配并获取映射枚举值
normalColumMap.put("dest_field_value",getMappingValue(action_param ,entry.getValue().toString() ));
}
else if(((HashMap<String, Object>)map.get("action")).get("type").equals("time"))
{
//time 类型
//normalColumMap.put("dest_field_value",entry.getValue() );
normalColumMap.put("action_param",((HashMap<String, Object>)map.get("action")).get("param") );
HashMap<String, Object> action_param=(HashMap<String, Object>)((HashMap<String, Object>)map.get("action")).get("param") ;
//匹配时间格式并转成换整型格式
Map<String, Object> normalColumMap = new LinkedHashMap<>();
normalColumMap.put("origin_field", entry.getKey());
normalColumMap.put("dest_field", map.get("dest_field").toString());
normalColumMap.put("action", (HashMap<String, Object>) map.get("action"));
normalColumMap.put("origin_field_value", entry.getValue());
if (((HashMap<String, Object>) map.get("action")).get("type").equals("equal")) {
normalColumMap.put("dest_field_value", entry.getValue());
} else if (((HashMap<String, Object>) map.get("action")).get("type").equals("mapping")) {
normalColumMap.put("action_param",
((HashMap<String, Object>) map.get("action")).get("param"));
HashMap<String, Object> action_param =
(HashMap<String, Object>) ((HashMap<String, Object>) map.get("action")).get("param");
normalColumMap.put("dest_field_value",
getMappingValue(action_param, entry.getValue().toString()));
} else if (((HashMap<String, Object>) map.get("action")).get("type").equals("time")) {
normalColumMap.put("action_param",
((HashMap<String, Object>) map.get("action")).get("param"));
HashMap<String, Object> action_param =
(HashMap<String, Object>) ((HashMap<String, Object>) map.get("action")).get("param");
try {
long longTime = TimeConversionUtils.convertToMillis(entry.getValue().toString(), action_param.get("timezone").toString());
long longTime = TimeConversionUtils.convertToMillis(
entry.getValue().toString(), action_param.get("timezone").toString());
normalColumMap.put("dest_field_value", longTime);
} catch (Exception e) {
logger.error("时间类型转换错误,源值:" + entry.getValue().toString() + ",java_date_format:" + action_param.get("java_date_format").toString());
logger.error("时间类型转换错误,源值:" + entry.getValue().toString()
+ ",java_date_format:" + action_param.get("java_date_format").toString());
e.printStackTrace();
}
}
columnlist.add((HashMap<String, Object>)normalColumMap);
//System.out.println( "normalColumMap: " +normalColumMap);
//存在源字段配置多个目标字段,使用continue,而不是break
columnlist.add((HashMap<String, Object>) normalColumMap);
continue;
}
}
@@ -463,156 +356,129 @@ public class LogNormalProcessor {
return columnlist;
}
/**
* paramMapping Map匹配查找对应的值
* @param paramMappingValueMap
* @param
* @return
*/
public Object getMappingValue(HashMap<String, Object> paramMappingValueMap,String value)
{
HashMap<String, Object> Map= (HashMap<String, Object>)paramMappingValueMap.get("mapping");
for (Map.Entry<String, Object > entry : Map.entrySet()) {
if ( entry.getKey().equals(value) ) {
return entry.getValue();
public Object getMappingValue(HashMap<String, Object> paramMappingValueMap, String value) {
HashMap<String, Object> Map = (HashMap<String, Object>) paramMappingValueMap.get("mapping");
for (Map.Entry<String, Object> entry : Map.entrySet()) {
if (entry.getKey().equals(value)) {
return entry.getValue();
}
}
return null;
}
/**
* 获取字段Map,包含字段field及Value值
* @param normalColumnList
* @return
*/
public Map<String, Object > getColumnMap( List<HashMap<String,Object>> normalColumnList )
{
Map<String, Object > columnMap= new HashMap<>();
public Map<String, Object> getColumnMap(List<HashMap<String, Object>> normalColumnList) {
Map<String, Object> columnMap = new HashMap<>();
for (Map<String, Object> map : normalColumnList) {
Object destFieldValue = map.get("dest_field_value");
// 判断 dest_field_value 是否为 String 且包含 "\u0000"
if (destFieldValue instanceof String && ((String) destFieldValue).contains("\u0000")) {
// 替换掉所有 "\u0000" 字符
if (destFieldValue instanceof String
&& ((String) destFieldValue).contains("\u0000")) {
destFieldValue = ((String) destFieldValue).replace("\u0000", "");
}
columnMap.put(map.get("dest_field").toString(), destFieldValue);
//columnMap.put(map.get("dest_field").toString(),map.get("dest_field_value"));
}
return columnMap;
}
/**
* 保存数据到标准化表
* @param deviceId
* @param logtime
* @param logColumnMap
*/
public void SaveNormalData(long deviceId , DateTime logtime, Map<String, Object > logColumnMap, long normalizeRuleId ,String normalizeRuleName)
{
public void SaveNormalData(ProcessContext ctx, long deviceId, DateTime logtime,
Map<String, Object> logColumnMap,
long normalizeRuleId, String normalizeRuleName) {
try {
if(logColumnMap.isEmpty() )
{
logger.error("SaveNormalData ->logColumnMap 为空,syslogUUID:" +this.strSyslogUUID);
//保存非标日志信息
syslogNonNormalMessage.setReason("未命中规则");
syslogNonNormalMessage.setReasonDetail("失败详情:logColumnMap对象字段为空" );
if(isSaveNonNormal==false)
SaveNonNormalMessage(deviceId,DateTime.now());
return ;
if (logColumnMap.isEmpty()) {
logger.error("SaveNormalData ->logColumnMap 为空,syslogUUID:" + ctx.strSyslogUUID);
ctx.syslogNonNormalMessage.setReason("未命中规则");
ctx.syslogNonNormalMessage.setReasonDetail("失败详情:logColumnMap对象字段为空");
if (ctx.isSaveNonNormal == false)
SaveNonNormalMessage(ctx, deviceId, DateTime.now());
return;
}
Map<String, Object> columnMap = logColumnMap;
//补全设备信息字段
//补全采集设备信息
CompletionDeviceInfo(columnMap, deviceId);
//补全采集探针相关信息
CompletionCollectTaskInfo(columnMap,ctx);
//补全日志基础信息
columnMap.put("device_id", deviceId);
columnMap.put("log_time", logtime);
columnMap.put("id", UUID.randomUUID().toString());
columnMap.put("normalize_rule_id", normalizeRuleId);
columnMap.put("normalize_rule_name", normalizeRuleName);
columnMap.put("syslog_uuid", this.strSyslogUUID);
columnMap.put("syslog_topic", this.strSyslogTopic);
System.out.println("columnMap"+columnMap);
columnMap.put("syslog_uuid", ctx.strSyslogUUID);
columnMap.put("syslog_topic", ctx.strSyslogTopic);
System.out.println("columnMap" + columnMap);
syslogNormalDataService.insertDynamic(columnMap);
} catch (Exception e) {
logger.error("SaveNormalData失败 " );
//保存非标日志信息
syslogNonNormalMessage.setReason("入库失败");
syslogNonNormalMessage.setReasonDetail("入库失败,normalizeRuleName :"+normalizeRuleName+",失败详情:"+ e.getMessage());
if(isSaveNonNormal==false)
SaveNonNormalMessage(deviceId,DateTime.now());
logger.error("SaveNormalData失败 ");
ctx.syslogNonNormalMessage.setReason("入库失败");
ctx.syslogNonNormalMessage.setReasonDetail("入库失败,normalizeRuleName :" + normalizeRuleName
+ ",失败详情:" + e.getMessage());
if (ctx.isSaveNonNormal == false)
SaveNonNormalMessage(ctx, deviceId, DateTime.now());
throw new RuntimeException("SaveNormalData 失败: " + e.getMessage(), e);
}
}
/**
* 补全设备信息字段
* @param columnMap
* @param deviceID
*/
public void CompletionDeviceInfo(Map<String, Object> columnMap ,Long deviceID)
{
//补全采集设备信息
public void CompletionDeviceInfo(Map<String, Object> columnMap, Long deviceID) {
try {
DeviceDevice devInfo = deviceDeviceService.getByIdSafely( Long.valueOf(deviceID).intValue() );
DeviceDevice devInfo = deviceDeviceService.getByIdSafely(Long.valueOf(deviceID).intValue());
if (devInfo != null) {
columnMap.put("device_ip", devInfo.getIp());
columnMap.put("device_manufacturer", devInfo.getVendor());
columnMap.put("device_name", devInfo.getName());
}
} catch (Exception e) {
logger.error("CompletionDeviceInfo 失败!ID"+deviceID );
logger.error("CompletionDeviceInfo 失败!ID" + deviceID);
}
}
/**
* 保存非标日志记录
* @param deviceId
* @param logtime
*/
public void SaveNonNormalMessage(long deviceId , DateTime logtime)
{
//补全采集探针相关信息(ID、IP、名称)
public void CompletionCollectTaskInfo(Map<String, Object> columnMap,ProcessContext ctx) {
Integer collect_id=-1;
try {
SyslogNonNormalMessage normalMessage =new SyslogNonNormalMessage() ;
//获取日志对应的设备ID
Integer collect_id= Integer.parseInt(this.deviceInfoMap.get("device_collect_id"));
DeviceCollectTask deviceCollectTask=deviceCollectTaskService.getById(collect_id);
normalMessage.setId( UUID.randomUUID().toString());
normalMessage.setDeviceId((int)deviceId);
collect_id = Integer.parseInt(ctx.deviceInfoMap.get("device_collect_id"));
DeviceCollectTask deviceCollectTask = deviceCollectTaskService.getById(collect_id);
if (deviceCollectTask != null) {
columnMap.put("agent_id", collect_id);
columnMap.put("origin_agent_id",collect_id.toString() );
columnMap.put("probe_ip",deviceCollectTask.getDeviceIp() );
columnMap.put("agent_name", deviceCollectTask.getTaskName());
columnMap.put("origin_agent_name", deviceCollectTask.getTaskName());
}
} catch (Exception e) {
logger.error("CompletionCollectTaskInfo 失败!探针ID" + collect_id);
}
}
public void SaveNonNormalMessage(ProcessContext ctx, long deviceId, DateTime logtime) {
try {
SyslogNonNormalMessage normalMessage = new SyslogNonNormalMessage();
Integer collect_id = Integer.parseInt(ctx.deviceInfoMap.get("device_collect_id"));
DeviceCollectTask deviceCollectTask = deviceCollectTaskService.getById(collect_id);
normalMessage.setId(UUID.randomUUID().toString());
normalMessage.setDeviceId((int) deviceId);
normalMessage.setLogTime(logtime.toLocalDateTime());
normalMessage.setRuleTime(logtime.toLocalDateTime());
normalMessage.setSyslogMessage(this.strLogMsg);
normalMessage.setSyslogTopic(this.strSyslogTopic);
normalMessage.setSyslogUuid(this.strSyslogUUID);
normalMessage.setHeaderMessage(this.strDeviceInfo);
normalMessage.setSyslogMessage(ctx.strLogMsg);
normalMessage.setSyslogTopic(ctx.strSyslogTopic);
normalMessage.setSyslogUuid(ctx.strSyslogUUID);
normalMessage.setHeaderMessage(ctx.strDeviceInfo);
normalMessage.setEtlNode("etlgo");
normalMessage.setReason( syslogNonNormalMessage.getReason());
normalMessage.setReasonDetail( syslogNonNormalMessage.getReasonDetail());
//采集探针名称
normalMessage.setReason(ctx.syslogNonNormalMessage.getReason());
normalMessage.setReasonDetail(ctx.syslogNonNormalMessage.getReasonDetail());
normalMessage.setRuleResult("FAIL");
normalMessage.setDeviceName(deviceInfoMap.get("device_name"));
normalMessage.setDeviceName(ctx.deviceInfoMap.get("device_name"));
normalMessage.setCollectTaskId(collect_id);
if(deviceCollectTask!=null)
normalMessage.setCollectTaskName(deviceCollectTask.getTaskName());
this.messageService.saveMessage(normalMessage );
isSaveNonNormal=true;
if (deviceCollectTask != null)
normalMessage.setCollectTaskName(deviceCollectTask.getTaskName());
this.messageService.saveMessage(normalMessage);
ctx.isSaveNonNormal = true;
} catch (Exception e) {
logger.error("SaveNonNormalMessage 失败:" );
logger.error("SaveNonNormalMessage 失败:");
throw new RuntimeException("SaveNonNormalMessage 失败: " + e.getMessage(), e);
}
}
public static void main(String[] args) {
String strlogMessage= "<14>1 2025-09-24T11:52:26Z 5f46d3be75e1 supermario 128 honeypot_event - {\"source\":\"honeypot1\",\"id\":\"f6a13c35-bf9d-4da6-a181-50ce23e7ef6a\",\"start_time\":\"2023-09-03T11:07:02.50167643Z\",\"time\":\"2023-09-03T11:16:18.883885281Z\",\"risk_level\":4,\"connection\":\"b18f3fbe-3fbf-4495-815f-ff26f6fb0bdf\",\"file_info\":null,\"extra\":{\"payload\":{\"format\":\"line\",\"name\":{\"cn\":\"攻击载荷\",\"en\":\"payload\"},\"value\":\"\"},\"uid\":{\"format\":\"line\",\"name\":{\"cn\":\"\",\"en\":\"\"},\"uid\":\"b4cbc73c-25d0-4429-ae1b-a856cdf1a651\",\"value\":\"\"}},\"type\":\"WEB_ATTACK_SCANNER\",\"agent_sn\":\"caa7da42-0cca-4cb1-b501-1f1eb2b588d5\",\"agent_name\":\" 教育局蜜罐探针\",\"honeypot_id\":\"11a9ac6bdf38ae2aaa49ec4f1b4a921bff71952cb9f175bdd8ee1f0497057bc6\",\"honeypot_name\":\"茂名市中小学管理平台管理后台\",\"src_ip\":\"117.50.189.7\",\"src_port\":58512,\"src_mac\":\"\",\"dest_ip\":\"192.168.222.2\",\"dest_port\":9200,\"proxy_ip\":null,\"node\":\"WRx3\"}";
String strMsgContent= "{\"source\":\"honeypot1\",\"id\":\"f6a13c35-bf9d-4da6-a181-50ce23e7ef6a\",\"start_time\":\"2023-09-03T11:07:02.50167643Z\",\"time\":\"2023-09-03T11:16:18.883885281Z\",\"risk_level\":4,\"connection\":\"b18f3fbe-3fbf-4495-815f-ff26f6fb0bdf\",\"file_info\":null,\"extra\":{\"payload\":{\"format\":\"line\",\"name\":{\"cn\":\"攻击载荷\",\"en\":\"payload\"},\"value\":\"\"},\"uid\":{\"format\":\"line\",\"name\":{\"cn\":\"\",\"en\":\"\"},\"uid\":\"b4cbc73c-25d0-4429-ae1b-a856cdf1a651\",\"value\":\"\"}},\"type\":\"WEB_ATTACK_SCANNER\",\"agent_sn\":\"caa7da42-0cca-4cb1-b501-1f1eb2b588d5\",\"agent_name\":\" 教育局蜜罐探针\",\"honeypot_id\":\"11a9ac6bdf38ae2aaa49ec4f1b4a921bff71952cb9f175bdd8ee1f0497057bc6\",\"honeypot_name\":\"茂名市中小学管理平台管理后台\",\"src_ip\":\"117.50.189.7\",\"src_port\":58512,\"src_mac\":\"\",\"dest_ip\":\"192.168.222.2\",\"dest_port\":9200,\"proxy_ip\":null,\"node\":\"WRx3\"}";
//Map<String, Object> flatMap =(new logNormalData()).getMessageToMap(strMsgContent);
//flatMap.forEach((key, value) -> System.out.println(key + " = " + value));
//LogNormalProcessor logData =new LogNormalProcessor(strlogMessage,);
//logData.init();
// 旧入口保留,仅用于本地测试
}
}
@@ -2,7 +2,8 @@ package com.Modules.NormalData;
import com.influx.InfluxDBClient;
import com.common.util.SyslogParser;
import com.config.AppConfig;
import com.config.AppProperties;
import com.config.KafkaConsumerProperties;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
import com.influxdb.client.WriteApi;
@@ -29,7 +30,6 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import com.common.util.Sm4Util;
import com.config.AppConfig;
@Slf4j
@Component
public class SysLogProcessor {
@@ -44,11 +44,20 @@ public class SysLogProcessor {
@Value("${app.processor.process-timeout-ms:30000}")
private long processTimeoutMs;
private static String strhexKey=AppConfig.getSM4Key();
@Autowired
private AppProperties appProperties;
@Autowired
private KafkaConsumerProperties kafkaConsumerProperties;
@Autowired
private LogNormalProcessor logNormalProcessor;
@Autowired
private com.influx.InfluxDBClient influxClient;
private final AtomicInteger totalProcessed = new AtomicInteger(0);
private final AtomicInteger currentBatchCount = new AtomicInteger(0);
// 初始化 InfluxDB 客户端
private final com.influx.InfluxDBClient influxClient = new InfluxDBClient();
@@ -70,7 +79,7 @@ public class SysLogProcessor {
}
@KafkaListener(
topics = "${spring.kafka.consumer.topic:agent-syslog-topic}",
concurrency = "2" // 多线程消费
concurrency = "${spring.kafka.listener.concurrency}" // 多线程消费
)
public void consumeAndParallelProcess(List<ConsumerRecord<String, String>> records, Acknowledgment ack) {
if (records.isEmpty()) {
@@ -88,7 +97,7 @@ public class SysLogProcessor {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
// 异步处理单条消息
log.info("收到syslogmessage"+ Sm4Util.decryptCbc(record.value(), strhexKey));
log.info("收到syslogmessage"+ Sm4Util.decryptCbc(record.value(), appProperties.getSm4Key()));
processSingleMessageAsync(record);
} catch (Exception e) {
log.error("处理消息失败, topic: {}, partition: {}, offset: {}",
@@ -254,15 +263,8 @@ public class SysLogProcessor {
long startTime = System.currentTimeMillis();
try {
// 模拟消息解析
//String message = parseMessage(record);
// 模拟业务处理
//processBusinessLogic(message);
//Message进行SM4解密
String Sm4message=Sm4Util.decryptCbc(record.value(), strhexKey);
System.out.println("Sm4message:"+Sm4message);
String Sm4message=Sm4Util.decryptCbc(record.value(), appProperties.getSm4Key());
String sysLogUUID =getSysLogUUID();
String strDeviceInfo= SyslogParser.substringBeforeFirstChar(Sm4message,']');
@@ -273,25 +275,20 @@ public class SysLogProcessor {
.addTag("device_id", mapdev.get("device_id")) // 添加设备ID标签
.addTag("device_collect_id", mapdev.get("device_collect_id")) // 添加探针ID标签
.addTag("uuid", sysLogUUID) //syslog uuid
.addTag("topic", AppConfig.getTopic()) //kafka topic
.addTag("topic", kafkaConsumerProperties.getTopic()) //kafka topic
.addField("message", Sm4message) // 添加字段
.addField("receive_time", mapdev.get("receive_time")) // 添加字段
.addField("uuid", sysLogUUID)
.time(System.currentTimeMillis(), WritePrecision.MS) ;// 毫秒级时间戳
//influxClient.writePointBlocking(point);
///写入单点(异步,立即返回)
influxClient.writePoint(point);
System.out.println("influxdb wirte syslog ,value:"+ record.key());
// 日志信息插入pg XdrHoneypot 表
//insertSingleRecord( record.value());
//String syslogMessage= AppConfig.geRunEnvironment().equals("test")? record.value().substring(34) : record.value();
String syslogMessage= Sm4message;
//剔除测试环境本机syslog新增的头部信息
LogNormalProcessor logNormalProcessor = new LogNormalProcessor(syslogMessage,sysLogUUID,AppConfig.getTopic());
//LogNormalProcessor logNormalProcessor =new LogNormalProcessor(record.value());
logNormalProcessor.init();
//使用注入的 Spring Bean 进行标准化处理
logNormalProcessor.process(syslogMessage, sysLogUUID, null);
System.out.println("insert postgres syslog ,value:"+ record.key());
long costTime = System.currentTimeMillis() - startTime;
log.debug("消息处理完成, offset: {}, 耗时: {}ms", record.offset(), costTime);
@@ -75,4 +75,8 @@ public class AlarmVisit {
private String[] httpReqBody;
private String[] httpRespHeader;
private String[] httpRespBody;
private String reason;
private String dtype;
private String originField;
private String originLog;
}
@@ -20,6 +20,10 @@ public class DeviceCollectTask {
private Integer taskCount;
private OffsetDateTime recentDiscoverTime;
private Integer epmUpperLimit;
private OffsetDateTime expireTime;
private String remark;
private String deviceIp;
private Long organizationId;
// Getter and Setter 方法
public Integer getId() { return id; }
@@ -73,6 +77,18 @@ public class DeviceCollectTask {
public Integer getEpmUpperLimit() { return epmUpperLimit; }
public void setEpmUpperLimit(Integer epmUpperLimit) { this.epmUpperLimit = epmUpperLimit; }
public OffsetDateTime getExpireTime() { return expireTime; }
public void setExpireTime(OffsetDateTime expireTime) { this.expireTime = expireTime; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public String getDeviceIp() { return deviceIp; }
public void setDeviceIp(String deviceIp) { this.deviceIp = deviceIp; }
public Long getOrganizationId() { return organizationId; }
public void setOrganizationId(Long organizationId) { this.organizationId = organizationId; }
@Override
public String toString() {
return "DeviceCollectTask{" +
@@ -93,6 +109,10 @@ public class DeviceCollectTask {
", taskCount=" + taskCount +
", recentDiscoverTime=" + recentDiscoverTime +
", epmUpperLimit=" + epmUpperLimit +
", expireTime=" + expireTime +
", remark='" + remark + '\'' +
", deviceIp='" + deviceIp + '\'' +
", organizationId=" + organizationId +
'}';
}
}
@@ -23,7 +23,8 @@ public interface AlarmVisitMapper {
"attack_port, victim_port, attack_method, etl_time, log_count, ",
"attack_chain_phase, disposition_advice, attack_direction, ",
"judged_state, disposed_state, attack_result, fall, payload, dns_info, engine_type, " ,
"http_req_header , http_req_body,http_resp_header , http_resp_body ",
"http_req_header , http_req_body,http_resp_header , http_resp_body, ",
"reason, dtype, origin_field, origin_log ",
") VALUES ",
"<foreach collection='list' item='item' separator=','>",
"(#{item.id}, #{item.createdAt}, #{item.alarmName}, #{item.alarmLevel}, ",
@@ -34,7 +35,7 @@ public interface AlarmVisitMapper {
"#{item.deviceId, typeHandler=com.Modules.etl.handler.ArrayIntegerTypeHandler}, ",
"#{item.comment}, " ,
"#{item.originLogIds, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, ",
"#{item.logStartAt}, #{item.logEndAt},, #{item.windowTime} #{item.httpStatus}, ",
"#{item.logStartAt}, #{item.logEndAt}, #{item.windowTime}, #{item.httpStatus}, ",
"#{item.attackPort, typeHandler=com.Modules.etl.handler.ArrayIntegerTypeHandler}, ",
"#{item.victimPort, typeHandler=com.Modules.etl.handler.ArrayIntegerTypeHandler}, ",
"#{item.attackMethod}, #{item.etlTime}, #{item.logCount}, ",
@@ -45,7 +46,8 @@ public interface AlarmVisitMapper {
"#{item.httpReqHeader, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, ",
"#{item.httpReqBody, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, ",
"#{item.httpRespHeader, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, ",
"#{item.httpRespBody, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}) ",
"#{item.httpRespBody, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, ",
"#{item.reason}, #{item.dtype}, #{item.originField}, #{item.originLog}) ",
"</foreach>",
"</script>"})
void batchInsert(@Param("list") List<AlarmVisit> alarmList);
@@ -60,7 +62,8 @@ public interface AlarmVisitMapper {
"attack_port, victim_port, attack_method, etl_time, log_count, " +
"attack_chain_phase, disposition_advice, attack_direction, " +
"judged_state, disposed_state, attack_result, fall, payload, dns_info,engine_type, " +
"http_req_header , http_req_body,http_resp_header , http_resp_body " +
"http_req_header , http_req_body,http_resp_header , http_resp_body, " +
"reason, dtype, origin_field, origin_log " +
") VALUES (" +
"#{id}, #{createdAt}, #{alarmName}, #{alarmLevel}, " +
"#{alarmType}, #{alarmMajorType}, #{alarmMinorType}, #{alarmAreaId}, " +
@@ -80,7 +83,8 @@ public interface AlarmVisitMapper {
"#{httpReqHeader, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, " +
"#{httpReqBody, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, " +
"#{httpRespHeader, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, " +
"#{httpRespBody, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler} " +
"#{httpRespBody, typeHandler=com.Modules.etl.handler.ArrayStringTypeHandler}, " +
"#{reason}, #{dtype}, #{originField}, #{originLog} " +
")")
void insert(AlarmVisit alarm);
}
@@ -66,10 +66,12 @@ public interface DeviceCollectTaskMapper extends BaseMapper<DeviceCollectTask>{
*/
@Insert("INSERT INTO device_collect_task (created_at, updated_at, device_id, method, task_name, " +
"first_time, last_success_time, last_failed_time, detail_id, epm, epm_peak, " +
"process_architecture, task_count, recent_discover_time, epm_upper_limit) " +
"process_architecture, task_count, recent_discover_time, epm_upper_limit, " +
"expire_time, remark, device_ip, organization_id) " +
"VALUES (NOW(), NOW(), #{deviceId}, #{method}, #{taskName}, #{firstTime}, " +
"#{lastSuccessTime}, #{lastFailedTime}, #{detailId}, #{epm}, #{epmPeak}, " +
"#{processArchitecture}, #{taskCount}, #{recentDiscoverTime}, #{epmUpperLimit})")
"#{processArchitecture}, #{taskCount}, #{recentDiscoverTime}, #{epmUpperLimit}, " +
"#{expireTime}, #{remark}, #{deviceIp}, #{organizationId})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(DeviceCollectTask task);
@@ -90,7 +92,11 @@ public interface DeviceCollectTaskMapper extends BaseMapper<DeviceCollectTask>{
"process_architecture = #{processArchitecture}, " +
"task_count = #{taskCount}, " +
"recent_discover_time = #{recentDiscoverTime}, " +
"epm_upper_limit = #{epmUpperLimit} " +
"epm_upper_limit = #{epmUpperLimit}, " +
"expire_time = #{expireTime}, " +
"remark = #{remark}, " +
"device_ip = #{deviceIp}, " +
"organization_id = #{organizationId} " +
"WHERE id = #{id}")
int update(DeviceCollectTask task);
@@ -194,6 +194,10 @@ public class DataTransformer {
.httpReqBody(groupedData.getHttpReqBodys())
.httpRespHeader(groupedData.getHttpRespHeaders())
.httpRespBody(groupedData.getHttpRespBodys())
.reason(null)
.dtype(null)
.originField(null)
.originLog(null)
.build();
} catch (Exception e) {
@@ -20,11 +20,8 @@ import java.util.Map;
@Service
public class InfluxSyslogService {
//@Autowired
//private InfluxDBClient influxDBClient;
// 初始化 InfluxDB 客户端
//@Autowired
private final com.influx.InfluxDBClient influxDBClient = new InfluxDBClient();
@Autowired
private com.influx.InfluxDBClient influxDBClient;
private static final DateTimeFormatter TABLE_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
private static final DateTimeFormatter INPUT_DATE_FORMATTER = DateTimeFormatter.ISO_DATE_TIME;
@@ -0,0 +1,70 @@
package com.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* 应用配置属性 - 替代静态 AppConfig
* 使用 Spring Boot 标准 @Value 机制,支持 docker-compose 环境变量覆盖
*/
@Data
@Component
public class AppProperties {
// ========== Syslog 配置 ==========
@Value("${syslog.tcp.port:514}")
private int syslogTcpPort;
@Value("${syslog.udp.port:515}")
private int syslogUdpPort;
@Value("${syslog.max.frame.length:65536}")
private int syslogMaxFrameLength;
@Value("${syslog.buffer.size:1024}")
private int syslogBufferSize;
// ========== InfluxDB 配置 ==========
@Value("${influxdb.url:http://localhost:8086}")
private String influxUrl;
@Value("${influxdb.token:}")
private String influxToken;
@Value("${influxdb.org:}")
private String influxOrg;
@Value("${influxdb.bucket:syslog}")
private String influxBucket;
@Value("${influxdb.batch.size:1000}")
private int influxBatchSize;
@Value("${influxdb.flush.interval:1000}")
private int influxFlushInterval;
@Value("${influxdb.retry.attempts:3}")
private int influxRetryAttempts;
@Value("${influxdb.retry.delay:100}")
private int influxRetryDelay;
// ========== 应用配置 ==========
@Value("${app.worker.threads:4}")
private int workerThreads;
@Value("${app.max.queue.size:2000}")
private int maxQueueSize;
@Value("${app.metrics.enabled:false}")
private boolean metricsEnabled;
// ========== 运行环境 ==========
@Value("${server.run.environment:prod}")
private String runEnvironment;
// ========== SM4 加密配置 ==========
@Value("${syslog.sm4.generateKey:}")
private String sm4Key;
}
@@ -0,0 +1,27 @@
package com.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Kafka Consumer 配置属性类
* 替代 AppConfig 的静态方法读取,支持 docker-compose 环境变量覆盖
*/
@Data
@Component
@ConfigurationProperties(prefix = "spring.kafka.consumer")
public class KafkaConsumerProperties {
/** Kafka 集群地址 */
private String bootstrapServers = "192.168.4.99:9092";
/** 消费者组ID */
private String groupId = "agent-syslog-group";
/** 消费位置重置策略 */
private String autoOffsetReset = "latest";
/** 是否自动提交 */
private boolean enableAutoCommit = false;
/** 自动提交间隔(ms) */
private String autoCommitInterval = "1000";
/** 消费Topic */
private String topic = "agent-syslog-topic";
}
@@ -28,6 +28,8 @@ public class DmColumnController {
private DmColumnService dmColumnService;
@Autowired
private DmNormalizeRuleService dmNormalizeRuleService;
@Autowired
private LogNormalProcessor logNormalProcessor;
private static HashMap OrginalColumnMap ;
@@ -53,8 +55,7 @@ public class DmColumnController {
//List<Map<String, Object>> columnList=dmColumnService.selectAllNormal();
//List<Map<String, Object>> rulelst= dmNormalizeRuleService.selectByDeviceIdAuto((long)1);
//OrginalColumnMap= getMessageToMap(strLogMsg);
LogNormalProcessor logNormalProcessor=new LogNormalProcessor( "", UUID.randomUUID().toString(),"test-topic");
logNormalProcessor.init();
logNormalProcessor.process("", UUID.randomUUID().toString(), "test-topic");
return dmColumn.getDisplayName() ;
//return dmColumn.getDisplayName() ;
@@ -5,9 +5,11 @@ import com.influxdb.client.WriteApi;
import com.influxdb.client.WriteApiBlocking;
import com.influxdb.client.domain.HealthCheck;
import com.influxdb.client.write.Point;
import com.config.AppConfig;
import com.config.AppProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.influxdb.query.FluxRecord;
import com.influxdb.query.FluxTable;
import java.util.ArrayList;
@@ -19,6 +21,7 @@ import java.time.Instant;
import java.time.format.DateTimeFormatter;
@Component
public class InfluxDBClient implements AutoCloseable {
private static final Logger logger = LoggerFactory.getLogger(InfluxDBClient.class);
@@ -28,19 +31,22 @@ public class InfluxDBClient implements AutoCloseable {
private final String bucket;
private final String org;
private final QueryApi queryApi;
private final InfluxDBConfig influxDBConfig;
public InfluxDBClient() {
@Autowired
public InfluxDBClient(AppProperties appProperties, InfluxDBConfig influxDBConfig) {
this.influxDBConfig = influxDBConfig;
this.influxDB = InfluxDBClientFactory.create(
AppConfig.getInfluxUrl(),
AppConfig.getInfluxToken().toCharArray(),
AppConfig.getInfluxOrg(),
AppConfig.getInfluxBucket()
appProperties.getInfluxUrl(),
appProperties.getInfluxToken().toCharArray(),
appProperties.getInfluxOrg(),
appProperties.getInfluxBucket()
);
this.writeApi = influxDB.makeWriteApi(InfluxDBConfig.getWriteOptions());
this.writeApi = influxDB.makeWriteApi(influxDBConfig.getWriteOptions());
this.writeApiBlocking = influxDB.getWriteApiBlocking();
this.bucket = AppConfig.getInfluxBucket();
this.org = AppConfig.getInfluxOrg();
this.bucket = appProperties.getInfluxBucket();
this.org = appProperties.getInfluxOrg();
this.queryApi = influxDB.getQueryApi();
// 检查连接状态
@@ -92,7 +98,7 @@ public class InfluxDBClient implements AutoCloseable {
*/
public void writeRecord(String lineProtocol) {
try {
writeApi.writeRecord(InfluxDBConfig.getWritePrecision(),lineProtocol);
writeApi.writeRecord(influxDBConfig.getWritePrecision(),lineProtocol);
} catch (Exception e) {
logger.error("Failed to write record to InfluxDB: {}", e.getMessage());
}
@@ -1,18 +1,31 @@
package com.influx;
import com.config.AppProperties;
import com.influxdb.client.WriteOptions;
import com.influxdb.client.domain.WritePrecision;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class InfluxDBConfig {
public static WriteOptions getWriteOptions() {
private final AppProperties appProperties;
@Autowired
public InfluxDBConfig(AppProperties appProperties) {
this.appProperties = appProperties;
}
public WriteOptions getWriteOptions() {
return WriteOptions.builder()
.batchSize(com.config.AppConfig.getInfluxBatchSize())
.flushInterval(com.config.AppConfig.getInfluxFlushInterval())
.batchSize(appProperties.getInfluxBatchSize())
.flushInterval(appProperties.getInfluxFlushInterval())
.jitterInterval(1000)
.retryInterval(com.config.AppConfig.getInfluxRetryDelay())
.retryInterval(appProperties.getInfluxRetryDelay())
.build();
}
public static WritePrecision getWritePrecision() {
public WritePrecision getWritePrecision() {
return WritePrecision.MS; // 毫秒精度
}
}
}
@@ -1,7 +1,7 @@
package com.influx;
import com.config.AppConfig;
import com.common.util.SpringContextUtil;
import com.influx.InfluxDBClient;
import com.influxdb.client.*;
import com.influxdb.client.domain.WritePrecision;
@@ -30,7 +30,7 @@ public class SyslogToInfluxApp {
logger.info("Starting Syslog to InfluxDB application...");
// 初始化 InfluxDB 客户端
influxClient = new InfluxDBClient();
influxClient = SpringContextUtil.getBean(InfluxDBClient.class);
influxClient.writeRecord(syslog);
Point point = Point.measurement("syslog_normal")
.addTag("ip", "localhost") // 添加标签
@@ -18,7 +18,9 @@ import com.common.util.JsonParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.common.util.JsonParser;
import com.config.AppConfig;
import com.common.util.SpringContextUtil;
import com.config.AppProperties;
import com.config.KafkaConsumerProperties;
import com.Modules.NormalData.LogNormalProcessor;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@@ -38,34 +40,27 @@ public class kafkalogconsumer {
}
public static void Run()
{
// 配置消费者属性
//Properties props = new Properties();
//props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.222.130:9092");
// props.put(ConsumerConfig.GROUP_ID_CONFIG, "test-group-app");
KafkaConsumerProperties kafkaProps = SpringContextUtil.getBean(KafkaConsumerProperties.class);
LogNormalProcessor logNormalProcessor = SpringContextUtil.getBean(LogNormalProcessor.class);
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, AppConfig.getBootstrapServers());
props.put(ConsumerConfig.GROUP_ID_CONFIG, AppConfig.getGroupId());
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaProps.getBootstrapServers());
props.put(ConsumerConfig.GROUP_ID_CONFIG, kafkaProps.getGroupId());
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
// 可选配置
//props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "none"); // 从最早的消息开始消费
//props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); // 从最早的消息开始消费
//props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true"); // 自动提交偏移量
//props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000"); // 自动提交间隔
//props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 1000); // 设置单次拉取最大消息数[citation:6]
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, AppConfig.getAutoOffsetReset()); // 从last开始消费
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, AppConfig.getEnableAutoCommit()); // 自动提交偏移量
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG,AppConfig.getAutoCommitIntervalMS()); // 自动提交间隔
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, kafkaProps.getAutoOffsetReset());
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, kafkaProps.isEnableAutoCommit());
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, kafkaProps.getAutoCommitInterval());
// 创建消费者实例
Consumer<String, String> consumer = new KafkaConsumer<>(props);
try {
// 订阅主题
consumer.subscribe(Collections.singletonList(AppConfig.getTopic()));
consumer.subscribe(Collections.singletonList(kafkaProps.getTopic()));
System.out.println("开始消费消息...");
com.influx.InfluxDBClient influxClient = new InfluxDBClient();
com.influx.InfluxDBClient influxClient = SpringContextUtil.getBean(com.influx.InfluxDBClient.class);
// 持续消费消息
while (true) {
// 拉取消息(等待最多100毫秒)
@@ -88,7 +83,7 @@ public class kafkalogconsumer {
Point point = Point.measurement("syslog_security")
.addTag("deviceid", mapdev.get("device_id")) // 添加标签
.addTag("uuid", sysLogUUID) //syslog uuid
.addTag("topic", AppConfig.getTopic()) //kafka topic
.addTag("topic", kafkaProps.getTopic()) //kafka topic
.addField("message", record.value()) // 添加字段
.time(System.currentTimeMillis(), WritePrecision.MS) ;// 毫秒级时间戳
influxClient.writePointBlocking(point);
@@ -97,12 +92,9 @@ public class kafkalogconsumer {
//insertSingleRecord( record.value());
System.out.println("insert postgres syslog ,value:"+ record.key());
//String syslogMessage= AppConfig.geRunEnvironment().equals("test")? record.value().substring(34) : record.value();
String syslogMessage= record.value();
//剔除测试环境本机syslog新增的头部信息
LogNormalProcessor logNormalProcessor = new LogNormalProcessor(syslogMessage,sysLogUUID,AppConfig.getTopic());
//LogNormalProcessor logNormalProcessor =new LogNormalProcessor(record.value());
logNormalProcessor.init();
//使用注入的 Spring Bean 进行标准化处理
logNormalProcessor.process(syslogMessage, sysLogUUID, null);
}
// 手动提交偏移量(如果禁用自动提交)
consumer.commitSync();
@@ -5,8 +5,10 @@ import com.common.entity.XdrHoneypot;
import com.common.mapper.XdrHoneypotMapper;
import com.common.util.JsonParser;
import com.common.util.MyBatisUtil;
import com.common.util.SpringContextUtil;
import com.common.util.SyslogParser;
import com.config.AppConfig;
import com.config.AppProperties;
import com.config.KafkaConsumerProperties;
import com.influx.InfluxDBClient;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
@@ -36,34 +38,27 @@ public class kafkalogconsumerThead {
}
public static void Run()
{
// 配置消费者属性
//Properties props = new Properties();
//props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.222.130:9092");
// props.put(ConsumerConfig.GROUP_ID_CONFIG, "test-group-app");
KafkaConsumerProperties kafkaProps = SpringContextUtil.getBean(KafkaConsumerProperties.class);
LogNormalProcessor logNormalProcessor = SpringContextUtil.getBean(LogNormalProcessor.class);
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, AppConfig.getBootstrapServers());
props.put(ConsumerConfig.GROUP_ID_CONFIG, AppConfig.getGroupId());
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaProps.getBootstrapServers());
props.put(ConsumerConfig.GROUP_ID_CONFIG, kafkaProps.getGroupId());
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
// 可选配置
//props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "none"); // 从最早的消息开始消费
//props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); // 从最早的消息开始消费
//props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true"); // 自动提交偏移量
//props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000"); // 自动提交间隔
//props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 1000); // 设置单次拉取最大消息数[citation:6]
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, AppConfig.getAutoOffsetReset()); // 从last开始消费
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, AppConfig.getEnableAutoCommit()); // 自动提交偏移量
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG,AppConfig.getAutoCommitIntervalMS()); // 自动提交间隔
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, kafkaProps.getAutoOffsetReset());
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, kafkaProps.isEnableAutoCommit());
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, kafkaProps.getAutoCommitInterval());
// 创建消费者实例
Consumer<String, String> consumer = new KafkaConsumer<>(props);
try {
// 订阅主题
consumer.subscribe(Collections.singletonList(AppConfig.getTopic()));
consumer.subscribe(Collections.singletonList(kafkaProps.getTopic()));
System.out.println("开始消费消息...");
InfluxDBClient influxClient = new InfluxDBClient(); ;
InfluxDBClient influxClient = SpringContextUtil.getBean(InfluxDBClient.class);
// 持续消费消息
while (true) {
// 拉取消息(等待最多100毫秒)
@@ -86,7 +81,7 @@ public class kafkalogconsumerThead {
Point point = Point.measurement("syslog_security")
.addTag("deviceid", mapdev.get("device_id")) // 添加标签
.addTag("uuid", sysLogUUID) //syslog uuid
.addTag("topic", AppConfig.getTopic()) //kafka topic
.addTag("topic", kafkaProps.getTopic()) //kafka topic
.addField("message", record.value()) // 添加字段
.time(System.currentTimeMillis(), WritePrecision.MS) ;// 毫秒级时间戳
influxClient.writePointBlocking(point);
@@ -95,12 +90,9 @@ public class kafkalogconsumerThead {
//insertSingleRecord( record.value());
System.out.println("insert postgres syslog ,value:"+ record.key());
//String syslogMessage= AppConfig.geRunEnvironment().equals("test")? record.value().substring(34) : record.value();
String syslogMessage= record.value();
//剔除测试环境本机syslog新增的头部信息
LogNormalProcessor logNormalProcessor = new LogNormalProcessor(syslogMessage,sysLogUUID,AppConfig.getTopic());
//LogNormalProcessor logNormalProcessor =new LogNormalProcessor(record.value());
logNormalProcessor.init();
//使用注入的 Spring Bean 进行标准化处理
logNormalProcessor.process(syslogMessage, sysLogUUID, null);
}
// 手动提交偏移量(如果禁用自动提交)
// consumer.commitSync();
@@ -15,10 +15,11 @@ syslog.udp.port=514
syslog.max.frame.length=65536
syslog.buffer.size=1000
syslog.sm4.generateKey=f79548ab6fa8a304fc0115e17230358a
# InfluxDB 2.7 Configuration
influxdb.url=http://192.168.222.131:8086
influxdb.token=3Tvu-IZWtaY03UDkbUDlufD0kxn85keo9LhYQcv2Cxk0LJmXqqHkNVrO664DbaJAYwoGI7UIg904KqZC7Q_ZFA==
influxdb.org=yelang
influxdb.url=http://192.168.4.99:8087
influxdb.token=JsUyvU8vhQEFlMM_el4Drm87fyh707IhwJNsPBucPghSdbVmdQ-UvmPcyP5NTzWxsRfEz0T51Rw4ebZUuUrmZg==
influxdb.org=influxdb
influxdb.bucket=yelangbucket
influxdb.batch.size=1000
influxdb.flush.interval=1000
@@ -33,17 +34,15 @@ app.worker.threads=8
app.max.queue.size=10000
app.metrics.enabled=true
#database Configuration
spring.datasource.url=jdbc:dm://192.163.4.99:5237/DM_ecosys
spring.datasource.url=jdbc:dm://192.168.4.99:5237
spring.datasource.username=SYSDBA
spring.datasource.password=caZ2TcmXNSW8L2Ap
spring.datasource.driver-class-name=dm.jdbc.driver.DmDriver
spring.datasource.hikari.schema=\"PUBLIC\"
spring.datasource.hikari.schema=ECOSYS
# mybatis Configuration
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.common.entity
#mybatis handler 类
mybatis.configuration.default-statement-timeout=30
mybatis.configuration.default-fetch-size=1000
@@ -51,23 +50,23 @@ mybatis.configuration.map-underscore-to-camel-case=true
mybatis.type-handlers-package=com.Modules.etl.handler
mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.type-handlers-package=com.Modules.etl.handler
# kafka Configuration
spring.kafka.consumer.bootstrap-servers=192.168.222.130:9092
spring.kafka.consumer.group-id=agent-syslog-group
spring.kafka.consumer.bootstrap-servers=192.168.4.99:9092
spring.kafka.consumer.group-id=test-group-1
spring.kafka.consumer.auto-offset-reset=latest
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.auto-commit-interval=1000
spring.kafka.consumer.topic=agent-syslog-topic
spring.kafka.consumer.topic=test-topic
spring.kafka.consumer.max-poll-records=1000
spring.kafka.consumer.properties.max.poll.interval.ms=300000
spring.kafka.consumer.properties.session.timeout.ms=45000
#spring.kafka.consumer.key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
#spring.kafka.consumer.value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.fetch-min-size= 1048576
spring.kafka.listener.ack-mode= manual
spring.kafka.listener.concurrency= 2
spring.kafka.listener.concurrency= 2
spring.kafka.listener.type=batch
@@ -83,21 +82,23 @@ partition.check.tomorrow.enabled=true
partition.check.future.days=7
partition.auto.create=true
# 开发环境缓存配置
# 生产环境缓存配置
spring.redis.host=localhost
spring.redis.port=6379
# 密码(如果没有设置密码,可以省略)
spring.redis.password=
spring.redis.database=0
spring.redis.timeout=2000
spring.redis.timeout=5000
#spring.redis.password=${REDIS_PASSWORD:default_prod_password}
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
# 开发环境缓存时间较短,方便调试
spring.cache.redis.time-to-live=600000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=5000
spring.redis.lettuce.pool.max-idle=10
spring.redis.lettuce.pool.min-idle=5
# 生产环境缓存时间较长
spring.cache.redis.time-to-live=3600000
# 应用处理器配置
app.processor.thread-pool.core-pool-size=10
@@ -124,5 +125,4 @@ spring.datasource.hikari.connection-test-query=SELECT 1 FROM DUAL
spring.datasource.hikari.validation-timeout=5000
spring.datasource.hikari.leak-detection-threshold=30000
spring.datasource.hikari.pool-name=HikariPool-SyslogConsumer-rule
spring.datasource.hikari.auto-commit=false
spring.datasource.hikari.auto-commit=false
@@ -52,8 +52,8 @@ mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.type-handlers-package=com.Modules.etl.handler
# kafka Configuration
spring.kafka.consumer.bootstrap-servers=192.168.4.26:9092
spring.kafka.consumer.group-id=agent-01-syslog-group-dm
spring.kafka.consumer.bootstrap-servers=192.168.4.99:9092
spring.kafka.consumer.group-id=agent-01-syslog-group
spring.kafka.consumer.auto-offset-reset=latest
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.auto-commit-interval=1000
@@ -63,7 +63,7 @@ spring.kafka.consumer.topic=agent-01-syslog-topic
spring.kafka.consumer.max-poll-records=1000
spring.kafka.consumer.properties.max.poll.interval.ms=300000
spring.kafka.consumer.properties.session.timeout.ms=45000
spring.kafka.consumer.properties.partition.assignment.strategy=org.apache.kafka.clients.consumer.RoundRobinAssignor
spring.kafka.consumer.fetch-min-size= 1048576
spring.kafka.listener.ack-mode= manual
spring.kafka.listener.concurrency= 2
@@ -7,7 +7,7 @@ server.error.include-message=always
server.error.include-binding-errors=always
#run.environment: dev|test|pro
server.run.environment=pro
server.run.environment=dev
# Syslog Server Configuration
syslog.tcp.port=514
@@ -39,7 +39,7 @@ spring.datasource.url=jdbc:dm://192.168.4.99:5237
spring.datasource.username=SYSDBA
spring.datasource.password=caZ2TcmXNSW8L2Ap
spring.datasource.driver-class-name=dm.jdbc.driver.DmDriver
spring.datasource.hikari.schema=\"PUBLIC\"
spring.datasource.hikari.schema=ECOSYS
# mybatis Configuration
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.common.entity
@@ -52,12 +52,12 @@ mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.type-handlers-package=com.Modules.etl.handler
# kafka Configuration
spring.kafka.consumer.bootstrap-servers=192.168.4.26:9092
spring.kafka.consumer.group-id=agent-01-syslog-group-dm
spring.kafka.consumer.bootstrap-servers=192.168.4.99:9092
spring.kafka.consumer.group-id=test-group-1
spring.kafka.consumer.auto-offset-reset=latest
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.auto-commit-interval=1000
spring.kafka.consumer.topic=agent-01-syslog-topic
spring.kafka.consumer.topic=test-topic
spring.kafka.consumer.max-poll-records=1000
@@ -66,7 +66,7 @@ spring.kafka.consumer.properties.session.timeout.ms=45000
spring.kafka.consumer.fetch-min-size= 1048576
spring.kafka.listener.ack-mode= manual
spring.kafka.listener.concurrency= 2
spring.kafka.listener.concurrency= 2
spring.kafka.listener.type=batch
@@ -84,10 +84,10 @@ partition.auto.create=true
# 生产环境缓存配置
spring.redis.host=192.168.4.99
spring.redis.host=localhost
spring.redis.port=6379
# 密码(如果没有设置密码,可以省略)
spring.redis.password=redis_GdGWte
spring.redis.password=
spring.redis.database=0
spring.redis.timeout=5000
#spring.redis.password=${REDIS_PASSWORD:default_prod_password}
@@ -22,12 +22,17 @@
<result column="task_count" property="taskCount" />
<result column="recent_discover_time" property="recentDiscoverTime" />
<result column="epm_upper_limit" property="epmUpperLimit" />
<result column="expire_time" property="expireTime" />
<result column="remark" property="remark" />
<result column="device_ip" property="deviceIp" />
<result column="organization_id" property="organizationId" />
</resultMap>
<sql id="Base_Column_List">
id, created_at, updated_at, deleted_at, device_id, method, task_name,
first_time, last_success_time, last_failed_time, detail_id, epm, epm_peak,
process_architecture, task_count, recent_discover_time, epm_upper_limit
process_architecture, task_count, recent_discover_time, epm_upper_limit,
expire_time, remark, device_ip, organization_id
</sql>
<!-- 多条件组合查询 -->
@@ -60,6 +65,16 @@
<if test="lastSuccessTime != null">
AND last_success_time >= #{lastSuccessTime}
</if>
<!-- 新增字段查询 -->
<if test="deviceIp != null and deviceIp != ''">
AND device_ip = #{deviceIp}
</if>
<if test="organizationId != null">
AND organization_id = #{organizationId}
</if>
<if test="remark != null and remark != ''">
AND remark LIKE CONCAT('%', #{remark}, '%')
</if>
</where>
ORDER BY updated_at DESC
</select>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
<facet type="web" name="Web">
<configuration>
<webroots />
<sourceRoots>
<root url="file://$MODULE_DIR$/src/main/java" />
<root url="file://$MODULE_DIR$/src/main/resources" />
</sourceRoots>
</configuration>
</facet>
</component>
</module>