using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoreAgent.ProtocolClient.Context;
using CoreAgent.ProtocolClient.Enums;
using CoreAgent.ProtocolClient.Helpers;
using CoreAgent.ProtocolClient.Models;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace CoreAgent.ProtocolClient.ProtocolEngineCore
{
///
/// 日志数据转换器
/// 负责将BuildProtocolLog转换为TransferProtocolLog,并处理IMSI等关联数据的获取
///
public class LogDataConverter
{
private readonly ProtocolClientContext _context;
private readonly ILogger _logger;
private readonly ProtocolClientConfig _config;
public LogDataConverter(ProtocolClientContext context, ProtocolClientConfig config,ILogger logger)
{
_context = context;
_logger = logger;
_config = config;
}
///
/// 将BuildProtocolLog列表转换为TransferProtocolLog列表
///
/// 协议日志列表
/// 协议日志详情列表
public List ConvertToProtocolLogDetails(IEnumerable protocolLogs)
{
var result = new List();
var tmsiMatches =new List();
var srTmsiMappings = new List();
if (_config.Model == "RAN")
{
tmsiMatches = _context.UeIdentifier.GenerateTmsiMatches();
srTmsiMappings = _context.UeIdentifier.GenerateSrTmsiMappings(tmsiMatches);
}
foreach (var log in protocolLogs)
{
try
{
var detail = ConvertSingleLog(log, tmsiMatches, srTmsiMappings);
if (detail != null)
{
result.Add(detail);
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"转换日志详情失败,Layer: {log.Layer}, Message: {log.Message}");
}
}
// 更新 cellid 为 null 的记录
UpdateNullCellIds(result);
// 统计IMSI和PLMN为null的数量
LogNullStatistics(result);
return result;
}
///
/// 更新 cellid 为 null 的记录
/// 通过先根据 ueid 不为空分组,然后检查 cellid 为 null 的 ueid 与分组 ueid 匹配修改
///
/// 协议日志详情列表
private void UpdateNullCellIds(List details)
{
if (details == null || !details.Any())
{
_logger.LogInformation("没有日志详情需要更新 cellid");
return;
}
try
{
// 1. 先根据 ueid 不为空分组,获取每个 UE ID 对应的有效 cellid
var ueIdToCellIdMapping = details
.Where(d => d.UEID.HasValue && d.CellID.HasValue)
.GroupBy(d => d.UEID.Value)
.ToDictionary(
group => group.Key,
group => group.Select(d => d.CellID.Value).Distinct().ToList()
);
if (!ueIdToCellIdMapping.Any())
{
_logger.LogInformation("没有找到有效的 UE ID 到 Cell ID 映射");
return;
}
// 2. 检查 cellid 为 null 的记录
var nullCellIdDetails = details.Where(d => d.UEID.HasValue && !d.CellID.HasValue).ToList();
if (!nullCellIdDetails.Any())
{
_logger.LogInformation("没有找到 cellid 为 null 的记录");
return;
}
_logger.LogInformation($"找到 {nullCellIdDetails.Count} 条 cellid 为 null 的记录,开始更新...");
// 3. 通过 ueid 匹配来更新这些记录的 cellid
int updatedCount = 0;
foreach (var detail in nullCellIdDetails)
{
if (detail.UEID.HasValue && ueIdToCellIdMapping.TryGetValue(detail.UEID.Value, out var cellIds))
{
// 如果该 UE ID 有多个 cellid,选择第一个(或者可以根据业务逻辑选择最合适的)
if (cellIds.Any())
{
detail.CellID = cellIds.First();
updatedCount++;
_logger.LogDebug($"更新 UE ID {detail.UEID} 的 cellid 为 {detail.CellID}");
}
}
}
_logger.LogInformation($"成功更新了 {updatedCount} 条记录的 cellid");
// 4. 统计更新结果
var remainingNullCellIds = details.Where(d => d.UEID.HasValue && !d.CellID.HasValue).Count();
if (remainingNullCellIds > 0)
{
_logger.LogWarning($"仍有 {remainingNullCellIds} 条记录的 cellid 为 null,这些 UE ID 可能没有对应的 cellid 信息");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "更新 cellid 为 null 的记录时发生异常");
}
}
///
/// 转换单个BuildProtocolLog为TransferProtocolLog
///
/// 协议日志
/// TMSI匹配结果列表
/// Service Request TMSI映射列表
/// 协议日志详情
private TransferProtocolLog? ConvertSingleLog(BuildProtocolLog log, List tmsiMatches, List srTmsiMappings)
{
if (log == null)
return null;
var detail = new TransferProtocolLog
{
Id=log.Id,
LayerType = GetProtocolLayer(log.Layer),
Direction = log.Direction,
UEID = log.UeId,
CellID = log.Cell,
//Timestamp = log.Timestamp,
TimeMs = log.Timestamp,
Message = log.Message,
Info = _context.UeIdentifier.IdToString(log.Info ?? -1),
MessageDetailJson = JsonConvert.SerializeObject(log.Data)
};
detail.Timestamp = TimeStampHelper.ConvertToFullTimestamp(log.Timestamp);
if (_config.Model == "RAN")
{
// 获取IMSI信息
detail.IMSI = GetImsiFromUeList(log.UeId, tmsiMatches, srTmsiMappings);
// 获取PLMN信息
detail.PLMN = GetPlmnFromPlmnToUeIdMapping(log.UeId, srTmsiMappings);
}
if (_config.Model == "IMS")
{
detail.IMSI = log.SIP.IMSI;
detail.PLMN = log.SIP.Plmn;
}
return detail;
}
///
/// 根据UE ID获取IMSI信息
/// 使用TmsiMatchProcessor从UE链中获取IMSI,优先从根节点获取
///
/// UE ID
/// TMSI匹配结果列表
/// Service Request TMSI映射列表
/// IMSI字符串,如果未找到则返回null
private string? GetImsiFromUeList(int? ueId, List tmsiMatches, List srTmsiMappings)
{
if (!ueId.HasValue)
return null;
// 1. 优先从TMSI匹配结果中查找IMSI
// 查找包含当前UE ID的匹配结果
var matchingResult = tmsiMatches.FirstOrDefault(match =>
match.RequestUeId == ueId.Value || match.ReceiveUeId == ueId.Value);
if (matchingResult != null && !string.IsNullOrEmpty(matchingResult.Imsi))
{
return matchingResult.Imsi;
}
// 2. 从Service Request TMSI映射中查找IMSI
var srTmsiMatch = srTmsiMappings.FirstOrDefault(mapping => mapping.UeId == ueId.Value);
if (srTmsiMatch != null && !string.IsNullOrEmpty(srTmsiMatch.Imsi))
{
return srTmsiMatch.Imsi;
}
// 3. 如果TMSI匹配中没有找到,使用TmsiMatchProcessor从UE链中查找
var processor = new TmsiMatchProcessor(
_context.UeIdentifier.TmsiToUeId,
_context.UeIdentifier.RequestTmsiToUeId,
_context.UeIdentifier.ImsiToUeId);
// 获取UE链详细信息
var ueChains = processor.GetUeChainDetails();
// 查找包含当前UE ID的链
var containingChain = ueChains.FirstOrDefault(chain => chain.UeIds.Contains(ueId.Value));
if (containingChain != null && !string.IsNullOrEmpty(containingChain.Imsi))
{
return containingChain.Imsi;
}
// 4. 如果UE链中也没有找到,回退到原有的查找逻辑
return GetImsiFromLegacySources(ueId.Value);
}
///
/// 从传统数据源获取IMSI(回退方法)
/// 查找顺序:1.直接查找UeList 2.从Caps中查找 3.从ImsiToUeId映射表查找
///
/// UE ID
/// IMSI字符串,如果未找到则返回null
private string? GetImsiFromLegacySources(int ueId)
{
// 1. 直接从UeList中查找UE信息
if (_context.UeIdentifier.UeList?.TryGetValue(ueId, out var ueInfo) == true)
{
if (!string.IsNullOrEmpty(ueInfo?.Imsi))
{
return ueInfo.Imsi;
}
}
// 2. 从其他UE的Caps中查找UE ID
if (_context.UeIdentifier.UeList != null)
{
var imsiFromCaps = _context.UeIdentifier.UeList.Values
.Where(ueInfoItem => ueInfoItem?.Caps?.UeId == ueId)
.Select(ueInfoItem => ueInfoItem.Imsi)
.FirstOrDefault(imsi => !string.IsNullOrEmpty(imsi));
if (imsiFromCaps != null)
{
return imsiFromCaps;
}
}
// 3. 从ImsiToUeId映射表中查找
if (_context.UeIdentifier.ImsiToUeId != null)
{
var imsiFromMapping = _context.UeIdentifier.ImsiToUeId
.Where(mapping => mapping.Value?.Contains(ueId) == true)
.Select(mapping => mapping.Key)
.FirstOrDefault(imsi => !string.IsNullOrEmpty(imsi));
if (imsiFromMapping != null)
{
return imsiFromMapping;
}
}
return null;
}
///
/// 根据协议层字符串获取ProtocolLayer枚举
///
/// 协议层字符串
/// ProtocolLayer枚举值
private ProtocolLayer GetProtocolLayer(string layer)
{
return layer?.ToUpperInvariant() switch
{
"RRC" => ProtocolLayer.RRC,
"NAS" => ProtocolLayer.NAS,
"PHY" => ProtocolLayer.PHY,
"MAC" => ProtocolLayer.MAC,
"RLC" => ProtocolLayer.RLC,
"PDCP" => ProtocolLayer.PDCP,
"SIP" => ProtocolLayer.SIP,
"IMS" => ProtocolLayer.IMS,
_ => ProtocolLayer.NONE
};
}
///
/// 根据UE ID从UeIdentifier.PlmnToUeId映射表中获取PLMN
/// 优先使用srTmsiMappings中的RootUeId查找PLMN,提高匹配准确性
///
/// UE ID
/// Service Request TMSI映射列表
/// PLMN字符串,如果未找到则返回null
private string? GetPlmnFromPlmnToUeIdMapping(int? ueId, List srTmsiMappings)
{
if (!ueId.HasValue)
return null;
// 1. 优先从srTmsiMappings中查找对应的RootUeId,然后根据RootUeId查找PLMN
var srTmsiMatch = srTmsiMappings.FirstOrDefault(mapping => mapping.UeId == ueId.Value);
if (srTmsiMatch != null && srTmsiMatch.RootUeId > 0)
{
// 检查PlmnToUeId映射表是否存在
if (_context.UeIdentifier.PlmnToUeId != null)
{
// 直接使用RootUeId查找PLMN映射
var plmnMapping = _context.UeIdentifier.PlmnToUeId
.FirstOrDefault(mapping => mapping.Value?.Contains(srTmsiMatch.RootUeId) == true);
if (!string.IsNullOrEmpty(plmnMapping.Key))
{
return plmnMapping.Key;
}
}
}
// 2. 如果srTmsiMappings中没有找到或RootUeId为空,回退到原有的查找逻辑
// 检查PlmnToUeId映射表是否存在
if (_context.UeIdentifier.PlmnToUeId == null)
return null;
// 直接查找包含指定UE ID的PLMN映射
var directPlmnMapping = _context.UeIdentifier.PlmnToUeId
.FirstOrDefault(mapping => mapping.Value?.Contains(ueId.Value) == true);
return directPlmnMapping.Key;
}
///
/// 统计并打印有问题的日志详情
///
/// 协议日志详情列表
private void LogNullStatistics(List details)
{
if (details == null || !details.Any())
{
_logger.LogInformation("没有日志详情需要统计");
return;
}
// 1. UE ID为空的日志
var ueIdNullLogs = details.Where(d => d.UEID == null).ToList();
if (ueIdNullLogs.Any())
{
_logger.LogWarning($"发现 {ueIdNullLogs.Count} 条UE ID为空的日志:");
foreach (var log in ueIdNullLogs)
{
_logger.LogWarning($" UE ID为空 - Layer: {log.LayerType}, Message: {log.Message}, IMSI: {log.IMSI}, PLMN: {log.PLMN}");
}
}
// 2. 只有IMSI但没有PLMN的日志
var onlyImsiLogs = details.Where(d => d.UEID.HasValue && !string.IsNullOrEmpty(d.IMSI) && string.IsNullOrEmpty(d.PLMN)).ToList();
if (onlyImsiLogs.Any())
{
_logger.LogWarning($"发现 {onlyImsiLogs.Count} 条只有IMSI但没有PLMN的日志:");
foreach (var log in onlyImsiLogs)
{
_logger.LogWarning($" 只有IMSI - UE ID: {log.UEID}, Layer: {log.LayerType}, IMSI: {log.IMSI}, PLMN: {log.PLMN}");
}
}
// 3. 只有PLMN但没有IMSI的日志
var onlyPlmnLogs = details.Where(d => d.UEID.HasValue && string.IsNullOrEmpty(d.IMSI) && !string.IsNullOrEmpty(d.PLMN)).ToList();
if (onlyPlmnLogs.Any())
{
_logger.LogWarning($"发现 {onlyPlmnLogs.Count} 条只有PLMN但没有IMSI的日志:");
foreach (var log in onlyPlmnLogs)
{
_logger.LogWarning($" 只有PLMN - UE ID: {log.UEID}, Layer: {log.LayerType}, IMSI: {log.IMSI}, PLMN: {log.PLMN}");
}
}
// 4. 同时有IMSI和PLMN的日志
var bothLogs = details.Where(d => d.UEID.HasValue && !string.IsNullOrEmpty(d.IMSI) && !string.IsNullOrEmpty(d.PLMN)).ToList();
if (bothLogs.Any())
{
_logger.LogInformation($"发现 {bothLogs.Count} 条同时有IMSI和PLMN的日志:");
foreach (var log in bothLogs)
{
_logger.LogInformation($" 完整信息 - UE ID: {log.UEID}, Layer: {log.LayerType}, IMSI: {log.IMSI}, PLMN: {log.PLMN}");
}
}
// 5. 两者都为空的日志(UE ID不为空)
var bothNullLogs = details.Where(d => d.UEID.HasValue && string.IsNullOrEmpty(d.IMSI) && string.IsNullOrEmpty(d.PLMN)).ToList();
if (bothNullLogs.Any())
{
_logger.LogWarning($"发现 {bothNullLogs.Count} 条UE ID不为空但IMSI和PLMN都为空的日志:");
foreach (var log in bothNullLogs)
{
_logger.LogWarning($" 信息缺失 - UE ID: {log.UEID}, Layer: {log.LayerType}, IMSI: {log.IMSI}, PLMN: {log.PLMN}");
}
}
// 总结统计
var totalCount = details.Count;
_logger.LogInformation($"日志详情总结 - 总数: {totalCount}, UE ID为空: {ueIdNullLogs.Count}, 只有IMSI: {onlyImsiLogs.Count}, 只有PLMN: {onlyPlmnLogs.Count}, 完整信息: {bothLogs.Count}, 信息缺失: {bothNullLogs.Count}");
}
}
}