554 lines
20 KiB
C#
554 lines
20 KiB
C#
|
using Serilog.Events;
|
|||
|
using Serilog.Sinks.PeriodicBatching;
|
|||
|
using SqlSugar;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using Microsoft.AspNetCore.Http;
|
|||
|
using System.ComponentModel.DataAnnotations;
|
|||
|
using System.ComponentModel.DataAnnotations.Schema;
|
|||
|
using IdentityServer4.Models;
|
|||
|
using Mysqlx.Crud;
|
|||
|
using Azure.Core;
|
|||
|
using Consul;
|
|||
|
using Google.Protobuf.Collections;
|
|||
|
using IdentityModel.Client;
|
|||
|
using log4net.Core;
|
|||
|
using MySqlX.XDevAPI.Common;
|
|||
|
using System.Collections.Concurrent;
|
|||
|
using System.Data;
|
|||
|
using System.Runtime.Serialization;
|
|||
|
using NPlatform.Infrastructure.IdGenerators;
|
|||
|
using BZPT.Domains.Application;
|
|||
|
using NuGet.Protocol.Core.Types;
|
|||
|
|
|||
|
namespace BZPT
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 日志记录类
|
|||
|
/// </summary>
|
|||
|
public class LoggingWithDMSink : PeriodicBatchingSink
|
|||
|
{
|
|||
|
private readonly string _connectionString;
|
|||
|
private readonly string _sysName;
|
|||
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
|||
|
private readonly SqlSugarScope _db;
|
|||
|
public LoggingWithDMSink(
|
|||
|
string connectionString,
|
|||
|
string sysName,
|
|||
|
IHttpContextAccessor httpContextAccessor,
|
|||
|
int batchSizeLimit = 200, // 增大批量大小
|
|||
|
TimeSpan period = default)
|
|||
|
: base(batchSizeLimit, period == default ? TimeSpan.FromSeconds(15) : period)
|
|||
|
{
|
|||
|
_connectionString = connectionString;
|
|||
|
_sysName = sysName;
|
|||
|
_httpContextAccessor = httpContextAccessor;
|
|||
|
|
|||
|
// 使用 SqlSugarScope 确保线程安全
|
|||
|
_db = new SqlSugarScope(new ConnectionConfig
|
|||
|
{
|
|||
|
ConnectionString = _connectionString,
|
|||
|
DbType = SqlSugar.DbType.Dm,
|
|||
|
IsAutoCloseConnection = true,
|
|||
|
InitKeyType = InitKeyType.Attribute,
|
|||
|
ConfigId= "LoggingID"
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
protected override async Task EmitBatchAsync(IEnumerable<LogEvent> events)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
// 批量分离错误日志和操作日志
|
|||
|
var errorLogs = new List<Sys_ErrorLog>();
|
|||
|
var operationLogs = new List<Sys_OperationLog>();
|
|||
|
|
|||
|
foreach (var logEvent in events)
|
|||
|
{
|
|||
|
var (errorLog, operationLog) = ParseLogEvent(logEvent);
|
|||
|
|
|||
|
if (logEvent.Level >= LogEventLevel.Error && errorLog != null)
|
|||
|
{
|
|||
|
errorLogs.Add(errorLog);
|
|||
|
MessageApplication.SendErrorMessage($"{_sysName}:{errorLog.ErrorMessage}");
|
|||
|
}
|
|||
|
else if(logEvent.Level== LogEventLevel.Warning && errorLog != null)
|
|||
|
{
|
|||
|
errorLogs.Add(errorLog);
|
|||
|
var message = errorLog.Description ?? errorLog.ErrorMessage;
|
|||
|
if (message!=null&&message.StartsWith("SqlExecutionTime"))
|
|||
|
{
|
|||
|
MessageApplication.SendErrorMessage($"{_sysName}发现慢查询:" +message);
|
|||
|
}
|
|||
|
}
|
|||
|
else if (operationLog != null && logEvent.Level == LogEventLevel.Information)
|
|||
|
operationLogs.Add(operationLog);
|
|||
|
}
|
|||
|
|
|||
|
// 并行批量写入
|
|||
|
var tasks = new List<Task>();
|
|||
|
|
|||
|
if (errorLogs.Count > 0)
|
|||
|
{
|
|||
|
tasks.Add(_db.Fastest<Sys_ErrorLog>().BulkCopyAsync(errorLogs)); // 达梦批量插入
|
|||
|
}
|
|||
|
if (operationLogs.Count > 0)
|
|||
|
{
|
|||
|
tasks.Add(_db.Fastest<Sys_OperationLog>().BulkCopyAsync(operationLogs));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
await Task.WhenAll(tasks);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
// 错误处理(可记录到本地文件)
|
|||
|
Console.WriteLine($"日志写入失败: {ex.Message}");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private (Sys_ErrorLog?, Sys_OperationLog?) ParseLogEvent(LogEvent logEvent)
|
|||
|
{
|
|||
|
var httpContext = _httpContextAccessor.HttpContext;
|
|||
|
var id = GetPropertyValue(logEvent, "RequestID");
|
|||
|
if (logEvent.Level >= LogEventLevel.Warning)
|
|||
|
{
|
|||
|
if(logEvent.RenderMessage().Contains("SameSite=None"))return (null,null);
|
|||
|
return (new Sys_ErrorLog
|
|||
|
{
|
|||
|
SysName = _sysName,
|
|||
|
OperationType = GetPropertyValue(logEvent, "OperationType"),
|
|||
|
ModuleName = GetPropertyValue(logEvent, "ModuleName"),
|
|||
|
Description = logEvent.RenderMessage(),
|
|||
|
UserID = GetPropertyValue(logEvent, "UserID"),
|
|||
|
UserName = GetPropertyValue(logEvent, "UserName"),
|
|||
|
CreateUser = GetPropertyValue(logEvent, "UserName"),
|
|||
|
CreateTime = logEvent.Timestamp.DateTime,
|
|||
|
IP = httpContext?.Connection?.RemoteIpAddress?.ToString(),
|
|||
|
UserAgent = httpContext?.Request?.Headers["User-Agent"].ToString(),
|
|||
|
RequestMethod = httpContext?.Request?.Method,
|
|||
|
RequestUri = httpContext?.Request?.Path.ToString(),
|
|||
|
Parameters = GetPropertyValue(logEvent, "Parameters"),
|
|||
|
Result = GetPropertyValue(logEvent, "Result"),
|
|||
|
Status = GetIntPropertyValue(logEvent, "Status"),
|
|||
|
ErrorCode = GetPropertyValue(logEvent, "ErrorCode"),
|
|||
|
RequestID = id,
|
|||
|
ObjID= GetPropertyValue(logEvent, "ObjID"),
|
|||
|
ObjType = GetPropertyValue(logEvent, "ObjType"),
|
|||
|
ErrorMessage = logEvent.Exception?.ToString(),
|
|||
|
CostTime = GetIntPropertyValue(logEvent, "CostTime")
|
|||
|
}, null);
|
|||
|
}
|
|||
|
else if (!string.IsNullOrEmpty(id)) //只记录请求日志
|
|||
|
{
|
|||
|
|
|||
|
return (null, new Sys_OperationLog
|
|||
|
{
|
|||
|
SysName = _sysName,
|
|||
|
OperationType = GetPropertyValue(logEvent, "OperationType"),
|
|||
|
ModuleName = GetPropertyValue(logEvent, "ModuleName"),
|
|||
|
Description = logEvent.RenderMessage(),
|
|||
|
UserID = GetPropertyValue(logEvent, "UserID"),
|
|||
|
UserName = GetPropertyValue(logEvent, "UserName"),
|
|||
|
CreateUser = GetPropertyValue(logEvent, "UserName"),
|
|||
|
CreateTime = logEvent.Timestamp.DateTime,
|
|||
|
IP = GetPropertyValue(logEvent, "IP"),
|
|||
|
UserAgent = GetPropertyValue(logEvent, "UserAgent"),
|
|||
|
RequestMethod = httpContext?.Request?.Method,
|
|||
|
RequestUri = httpContext?.Request?.Path.ToString(),
|
|||
|
Parameters = GetPropertyValue(logEvent, "Parameters"),
|
|||
|
Result = GetPropertyValue(logEvent, "Result"),
|
|||
|
Status = GetIntPropertyValue(logEvent, "Status"),
|
|||
|
ErrorCode = GetPropertyValue(logEvent, "ErrorCode"),
|
|||
|
ErrorMessage = logEvent.MessageTemplate.ToStrNoNull(),
|
|||
|
RequestID =id,
|
|||
|
ObjID = GetPropertyValue(logEvent, "ObjID"),
|
|||
|
ObjType = GetPropertyValue(logEvent, "ObjType"),
|
|||
|
CostTime = GetIntPropertyValue(logEvent, "CostTime")
|
|||
|
});
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return (null,null);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private string GetPropertyValue(LogEvent logEvent, string propertyName)
|
|||
|
{
|
|||
|
if (logEvent.Properties.TryGetValue(propertyName, out var value))
|
|||
|
{
|
|||
|
return value.ToString().Trim('"');
|
|||
|
}
|
|||
|
return string.Empty;
|
|||
|
}
|
|||
|
|
|||
|
private int? GetIntPropertyValue(LogEvent logEvent, string propertyName)
|
|||
|
{
|
|||
|
if (logEvent.Properties.TryGetValue(propertyName, out var value) && int.TryParse(value.ToString().Trim('"'), out var result))
|
|||
|
{
|
|||
|
return result;
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
///OperationLog,操作日志(一个月)
|
|||
|
/// </summary>
|
|||
|
[Serializable]
|
|||
|
[Table(name: "Sys_OperationLog")]
|
|||
|
public partial class Sys_OperationLog : EntityBase<string>
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 操作类型(如 LOGIN, CREATE, UPDATE, DELETE, EXPORT, API_CALL 等)
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "操作类型(如 LOGIN, CREATE, UPDATE, DELETE, EXPORT, API_CALL 等)")]
|
|||
|
[StringLength(200)]
|
|||
|
public string OperationType { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 系统名称
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "系统名称")]
|
|||
|
[StringLength(400)]
|
|||
|
public string SysName { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 模块名称
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "模块名称")]
|
|||
|
[StringLength(400)]
|
|||
|
public string ModuleName { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 操作描述(如 用户登录系统, 删除ID: 1001)
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "操作描述(如 用户登录系统, 删除ID: 1001)")]
|
|||
|
[StringLength(2000)]
|
|||
|
public string Description { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 操作用户ID
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "操作用户ID")]
|
|||
|
[StringLength(144)]
|
|||
|
public string UserID { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 用户名称
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "用户名称")]
|
|||
|
[StringLength(144)]
|
|||
|
public string UserName { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// IP
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "IP")]
|
|||
|
[StringLength(180)]
|
|||
|
public string IP { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 用户客户端信息(浏览器、设备等)
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "用户客户端信息(浏览器、设备等)")]
|
|||
|
[StringLength(2000)]
|
|||
|
public string UserAgent { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// HTTP请求方法(如 GET, POST, DELETE)
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "HTTP请求方法(如 GET, POST, DELETE)")]
|
|||
|
[StringLength(40)]
|
|||
|
public string RequestMethod { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 请求url
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "请求url")]
|
|||
|
[StringLength(2000)]
|
|||
|
public string RequestUri { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 请求参数或操作详情(JSON格式,记录请求体或关键参数)
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "请求参数或操作详情(JSON格式,记录请求体或关键参数)")]
|
|||
|
[StringLength(2147483647)]
|
|||
|
public string Parameters { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 操作结果
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "操作结果")]
|
|||
|
[StringLength(2147483647)]
|
|||
|
public string Result { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 操作状态
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "操作状态")]
|
|||
|
public int? Status { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 错误码
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "错误码")]
|
|||
|
[StringLength(200)]
|
|||
|
public string ErrorCode { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 错误详情
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "错误详情")]
|
|||
|
[StringLength(2147483647)]
|
|||
|
public string ErrorMessage { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 对象ID
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "对象ID")]
|
|||
|
[StringLength(144)]
|
|||
|
public string RequestID { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 耗时
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "耗时")]
|
|||
|
public int? CostTime { get; set; }
|
|||
|
|
|||
|
public string ObjID { get; set; }
|
|||
|
|
|||
|
public string ObjType { get; set; }
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///ErrorLog,异常日志
|
|||
|
/// </summary>
|
|||
|
[Serializable]
|
|||
|
[Table(name: "Sys_ErrorLog")]
|
|||
|
public partial class Sys_ErrorLog : EntityBase<string>
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 操作类型(如 LOGIN, CREATE, UPDATE, DELETE, EXPORT, API_CALL 等)
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "操作类型(如 LOGIN, CREATE, UPDATE, DELETE, EXPORT, API_CALL 等)")]
|
|||
|
[StringLength(200)]
|
|||
|
public string OperationType { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 系统名称
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "系统名称")]
|
|||
|
[StringLength(400)]
|
|||
|
public string SysName { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 模块名称
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "模块名称")]
|
|||
|
[StringLength(400)]
|
|||
|
public string ModuleName { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 操作描述(如 用户登录系统, 删除ID: 1001)
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "操作描述(如 用户登录系统, 删除ID: 1001)")]
|
|||
|
[StringLength(2000)]
|
|||
|
public string Description { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 操作用户ID
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "操作用户ID")]
|
|||
|
[StringLength(144)]
|
|||
|
public string UserID { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 用户名称
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "用户名称")]
|
|||
|
[StringLength(144)]
|
|||
|
public string UserName { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// IP
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "IP")]
|
|||
|
[StringLength(180)]
|
|||
|
public string IP { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 用户客户端信息(浏览器、设备等)
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "用户客户端信息(浏览器、设备等)")]
|
|||
|
[StringLength(2000)]
|
|||
|
public string UserAgent { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// HTTP请求方法(如 GET, POST, DELETE)
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "HTTP请求方法(如 GET, POST, DELETE)")]
|
|||
|
[StringLength(40)]
|
|||
|
public string RequestMethod { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 请求url
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "请求url")]
|
|||
|
[StringLength(2000)]
|
|||
|
public string RequestUri { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 请求参数或操作详情(JSON格式,记录请求体或关键参数)
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "请求参数或操作详情(JSON格式,记录请求体或关键参数)")]
|
|||
|
[StringLength(2147483647)]
|
|||
|
public string Parameters { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 操作结果
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "操作结果")]
|
|||
|
[StringLength(2147483647)]
|
|||
|
public string Result { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 操作状态
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "操作状态")]
|
|||
|
public int? Status { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 错误码
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "错误码")]
|
|||
|
[StringLength(200)]
|
|||
|
public string ErrorCode { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 错误详情
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "错误详情")]
|
|||
|
[StringLength(2147483647)]
|
|||
|
public string ErrorMessage { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 对象ID
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "对象ID")]
|
|||
|
[StringLength(144)]
|
|||
|
public string RequestID { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 耗时
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[Display(Name = "耗时")]
|
|||
|
public int? CostTime { get; set; }
|
|||
|
|
|||
|
public string ObjID { get; set; }
|
|||
|
|
|||
|
public string ObjType { get; set; }
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
/// CREATE TABLESPACE LOGS_DATA DATAFILE 'LOGS_DATA01.DBF' SIZE 1024 AUTOEXTEND ON;
|
|||
|
///ALTER TABLE Sys_ErrorLog MOVE TABLESPACE LOGS_DATA;
|
|||
|
/// ALTER TABLE Sys_OperationLog MOVE TABLESPACE LOGS_DATA;
|
|||
|
/// ALTER TABLE SYS_OPERATIONLOGHIS MOVE TABLESPACE LOGS_DATA;
|
|||
|
/// GRANT USE TABLESPACE LOGS_DATA TO BZPT;
|
|||
|
///-- 则需要授予对这些表的具体操作权限,例如查询、插入、更新、删除等
|
|||
|
///GRANT SELECT, INSERT, UPDATE, DELETE ON Sys_ErrorLog TO BZPT;
|
|||
|
///GRANT SELECT, INSERT, UPDATE, DELETE ON Sys_OperationLog TO BZPT;
|
|||
|
///GRANT SELECT, INSERT, UPDATE, DELETE ON SYS_OPERATIONLOGHIS TO BZPT;
|
|||
|
//--删除表和索引
|
|||
|
//DROP TABLE IF EXISTS Sys_OperationLog;
|
|||
|
//DROP INDEX IF EXISTS idx_module_type;
|
|||
|
//DROP INDEX IF EXISTS idx_resource;
|
|||
|
//DROP INDEX IF EXISTS Index_USER_TIME;
|
|||
|
//DROP INDEX IF EXISTS Index_OPTime;
|
|||
|
//DROP INDEX IF EXISTS Index_SysTimeOP;
|
|||
|
|
|||
|
//--创建表 Sys_OperationLog(修正后的分区语法)
|
|||
|
//CREATE TABLE Sys_OperationLog (
|
|||
|
// ID BIGINT NOT NULL COMMENT 'ID',
|
|||
|
// OperationType VARCHAR(50) COMMENT '操作类型',
|
|||
|
// SysName VARCHAR(100) COMMENT '系统名称',
|
|||
|
// ModuleName VARCHAR(100) COMMENT '模块名称',
|
|||
|
// Description VARCHAR(500) COMMENT '操作描述',
|
|||
|
// UserID VARCHAR(36) COMMENT '用户ID',
|
|||
|
// UserName VARCHAR(36) COMMENT '用户名称',
|
|||
|
// OperationTime TIMESTAMP COMMENT '操作时间(精确到毫秒)',
|
|||
|
// IP VARCHAR(45) COMMENT 'IP',
|
|||
|
// UserAgent VARCHAR(500) COMMENT '客户端信息',
|
|||
|
// RequestMethod VARCHAR(10) COMMENT 'HTTP方法',
|
|||
|
// RequestUri VARCHAR(500) COMMENT '请求URI',
|
|||
|
// Parameters TEXT COMMENT '请求参数',
|
|||
|
// Result1 TEXT COMMENT '操作结果',
|
|||
|
// Status INT COMMENT '状态',
|
|||
|
// ErrorCode VARCHAR(50) COMMENT '错误码',
|
|||
|
// ErrorMessage TEXT COMMENT '错误详情',
|
|||
|
// ObjType VARCHAR(200) COMMENT '对象类型',
|
|||
|
// ObjID VARCHAR(36) COMMENT '对象ID',
|
|||
|
// CostTime INT COMMENT '耗时',
|
|||
|
// PRIMARY KEY (ID)
|
|||
|
//)
|
|||
|
//TABLESPACE LOGS_DATA
|
|||
|
//PARTITION BY RANGE (OperationTime) ( -- 直接使用日期字符串
|
|||
|
// PARTITION P2025H1 VALUES LESS THAN (TO_TIMESTAMP('2025-07-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2025H2 VALUES LESS THAN (TO_TIMESTAMP('2026-01-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2026H1 VALUES LESS THAN (TO_TIMESTAMP('2026-07-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2026H2 VALUES LESS THAN (TO_TIMESTAMP('2027-01-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2027H1 VALUES LESS THAN (TO_TIMESTAMP('2027-07-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2027H2 VALUES LESS THAN (TO_TIMESTAMP('2028-01-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2028H1 VALUES LESS THAN (TO_TIMESTAMP('2028-07-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2028H2 VALUES LESS THAN (TO_TIMESTAMP('2029-01-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2029H1 VALUES LESS THAN (TO_TIMESTAMP('2029-07-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2029H2 VALUES LESS THAN (TO_TIMESTAMP('2030-01-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2030H1 VALUES LESS THAN (TO_TIMESTAMP('2030-07-01', 'YYYY-MM-DD')),
|
|||
|
// PARTITION P2030H2 VALUES LESS THAN (TO_TIMESTAMP('2031-01-01', 'YYYY-MM-DD'))
|
|||
|
//);
|
|||
|
|
|||
|
//--添加表注释
|
|||
|
//COMMENT ON TABLE Sys_OperationLog IS '操作日志(一个月)';
|
|||
|
|
|||
|
//--创建索引(保持原样)
|
|||
|
//CREATE INDEX Index_SysTimeOP ON Sys_OperationLog(SysName, OperationTime DESC);
|
|||
|
//CREATE INDEX Index_OPTime ON Sys_OperationLog(OperationTime DESC);
|
|||
|
//CREATE INDEX Index_USER_TIME ON Sys_OperationLog(UserID, OperationTime DESC);
|
|||
|
//CREATE INDEX idx_resource ON Sys_OperationLog(ObjType, ObjID);
|
|||
|
//CREATE INDEX idx_module_type ON Sys_OperationLog(ModuleName, OperationType);
|