OmniRoam
OmniRoam 是 Omnitouch 为漫游运营商提供的全面批发收入管理解决方案。它处理漫游数据 CDR(通话详细记录)的完整生命周期,从数据摄取到计费评级,再到 TAP3 文件生成和报告。
目录
概述
OmniRoam 处理来自移动网络运营商的漫游 CDR,使用 OmniCharge 计费引擎进行评级,生成符合 GSMA 标准的 TAP3 文件用于计费,并提供全面的监控和报告能力。

CDR 导入和评级过程
TAP3 导出过程
操作指南
运行 TAP3 导出
# Export for specific partner
python3 export_TAP3.py VZW_Live
# Interactive mode (prompts for partner)
python3 export_TAP3.py
导出过程:
- 查询过去 30 天的 CDR(GSMA 要求)
- 过滤掉标记为已处理的 CDR
- 排除结束时间少于 1 小时的 CDR(防止不完整会话)
- 按漫游合作伙伴分组 CDR
- 为每个合作伙伴生成 TAP3 文件
- 在数据库中将 CDR 标记为已处理
- 增加序列计数器
- 将指标推送到 InfluxDB
监控与报告
OmniRoam 将实时指标推送到 InfluxDB 进行监控和分析。
收集的指标
原始 CDR 指标 在 CDR 导入和评级过程中推送:
- operator: 漫游合作伙伴标识符
- input_file: 源 CSV 文件名
- apn: 接入点名称(数据服务标识符)
- cellId: 基站标识符
- imsi: 用户身份
- tac: 跟踪区域代码
- sGWAddress: 服务网关 IP 地址
- pGWAddress: PDN 网关 IP 地址
- chargeableUnits: 使用的总字节数
- chargedUnits: 计算的费用
TAP 导出指标 在 TAP3 文件生成过程中推送:
- operator: 漫游合作伙伴标识符
- filename: 生成的 TAP3 文件名
- totalcharge: TAP3 文件中的总费用
- totalconsumed: TAP3 文件中的总字节数
- cdr_count: TAP3 文件中的 CDR 数量
仪表板查询
用于监控的示例 InfluxDB 查询:
按运营商收入
SELECT sum("totalcharge")
FROM "tap_cdr"
WHERE time > now() - 30d
GROUP BY "operator"
按 TAC 数据使用
SELECT sum("chargeableUnits")
FROM "raw_cdr"
WHERE time > now() - 7d
GROUP BY "tac"
按小时 CDR 量
SELECT count("chargeableUnits")
FROM "raw_cdr"
WHERE time > now() - 24h
GROUP BY time(1h)
按 APN 收入
SELECT sum("chargedUnits")
FROM "raw_cdr"
WHERE time > now() - 7d
GROUP BY "apn"
Grafana 集成
使用这些指标创建 Grafana 仪表板,用于:
- 实时收入监控
- 流量模式分析
- 合作伙伴绩效跟踪
- 网络资源利用率
- 异常检测
- 计费对账
故障排除

CDR 导入问题
检查日志 /tmp/import_CDR_Logger_Marben_*.log
常见问题:
- 无效的 IMSI 格式
- 缺少必填字段
- 时区转换错误
- 重复的计费 ID
TAP3 导出问题
检查日志 /tmp/tap3_export_*.log
常见问题:
- 最近 30 天内没有 CDR
- 缺少 TAC 配置
- 无效的序列号
- 数据库连接错误
OmniCharge 计费错误
查看 OmniCharge 日志以查找:
- 缺少费率计划
- 找不到账户
- 无效的使用值
- 货币转换错误
InfluxDB 连接问题
验证:
- InfluxDB URL 可达
- 有效的身份验证令牌
- 存在存储桶
- 网络连接
支持与维护
日志位置
- CDR 导入:
/tmp/import_CDR_Logger_Marben_*.log - TAP 导出:
/tmp/tap3_export_*.log
关键配置文件
- config.yaml - 主要配置(合作伙伴费率、网络设置、InfluxDB 连接)
- counters.yaml - TAP3 文件序列计数器
定期维护任务
- 监控序列计数器 - 确保它们不超过 99999
- 归档旧的 TAP 文件 - 移动超过保留期的文件
- 监控 InfluxDB 磁盘使用 - 配置保留策略
- 审查费率配置 - 当合作伙伴费率变化时更新
- 备份配置文件 - config.yaml 和 counters.yaml
- 监控 CDR 积压 - 确保及时处理
系统架构
高层架构
CDR 导入过程
OmniRoam 使用两阶段导入过程,使用缓存作为临时聚合层,将部分 CDR 记录组装成完整的可计费 CDR。
理解部分 CDR
移动网络元素(S-GW/P-GW)不会为数据会话生成单个 CDR。相反,它们在会话生命周期中生成 多个部分 CDR 记录:
- 开始记录:在数据会话开始时生成
- 更新记录:在会话期间定期生成(例如,每 15 分钟或每 100 MB 数据使用)
- 停止记录:在会话结束时生成
每个部分记录包含增量使用数据。为了准确计费,OmniRoam 必须:
- 识别 哪些部分记录属于同一数据会话
- 聚合 所有部分记录的使用数据
- 计算 总会话持续时间
- 组装 一个完整的 CDR,表示整个会话
为什么使用缓存进行 CDR 聚合?
缓存作为高性能的临时存储区域,部分 CDR 在会话完成之前会在此累积。缓存提供:
- 快速键值查找 - 立即找到会话的现有部分 CDR
- 内存存储 - 实时聚合的高速读写操作
- 原子操作 - 安全的并发更新来自多个导入过程
- 持久性 - CDR 在聚合窗口期间即使系统重启也能存活
两阶段导入架构
阶段 1:CSV 解析和部分 CDR 聚合
第一阶段持续读取来自 S-GW 网络元素的 CSV 文件,并在缓存中聚合部分 CDR。
如何识别和匹配部分 CDR
OmniRoam 必须确定哪些部分记录属于同一数据会话。每个会话通过一个复合 会话 ID 唯一标识,该 ID 由以下组成:
- 计费 ID:来自网络元素的唯一会话标识符
- IMSI:用户身份(移动号码标识符)
- 日期:服务网络时区的会话日期
- P-GW IP 地址:处理会话的网关
- TAC:跟踪区域代码(基站位置)
- QCI:服务质量类别
这种组合确保来自同一数据会话的所有部分记录被分组在一起,即使多个文件的到达顺序不同。
如何聚合部分 CDR
当 CSV 解析器处理每个部分 CDR 时:
- 从 CDR 字段生成会话 ID
- 检查缓存 以查看此会话是否已存在
- 如果会话存在于缓存中:
- 检索累积的 CDR 数据
- 验证此文件是否未被处理过(防止重复)
- 添加新的使用数据:传入字节 + 传出字节
- 使用最早和最新的时间戳更新会话持续时间
- 保存关于此部分记录的元数据以供审计
- 将更新的 CDR 保存回缓存
- 如果是新会话:
- 在缓存中创建新的 CDR 条目
- 初始化使用计数器和会��元数据
- 记录第一个部分记录的时间戳
审计跟踪和元数据
每个对 CDR 有贡献的部分记录都通过全面的元数据进行跟踪:
- 源文件名:包含此部分记录的 CSV 文件
- 时间戳:网络元素生成此记录的时间
- 处理时间:OmniRoam 接收和处理它的时间
- 使用贡献:此部分增加了多少数据(传入/传出字节)
- 事件类型:这是开始、更新还是停止记录
- 服务网络时区:用于准确的时间戳转换
为什么元数据对会计至关重要:
这个审计跟踪允许 OmniRoam 追踪单个费用在每个处理阶段的端到端过程,这对于:
- 争议解决:当合作伙伴质疑费用时,运营商可以准确显示哪些源文件对此做出了贡献
- 收入对账:验证所有可计费使用是否被捕获,没有遗漏或重复
- 合规性:证明对计费记录的适当处理以供审计
- 调试:通过追踪完整数据流迅速识别 CDR 聚合过程中的问题
- 财务准确性:确保每一美元的收费都可以追溯到特定的网络事件
会话持续时间计算
总会话持续时间通过查找以下内容计算:
- 所有部分记录中的最早时间戳(会话开始)
- 所有部分记录中的最新时间戳(会话结束)
- 持续时间 = 最新 - 最早
对于仅存在更新记录的会话(缺少开始/停止),持续时间默认为 24 小时。
阶段 2:CDR 组装和评级
第二阶段定期扫描缓存以查找已完成的会话,组装最终 CDR,并提交给 OmniCharge 进行评级。
如何从缓存中选择完整的 CDR
CDR 组装过程持续运行,检查缓存中存储的所有会话:
- 扫描缓存 以查找所有累积的 CDR 会话
- 每次处理 1,000 个会话 的批次
- 对于每个会话:
- 从会话 ID 中提取会话日期
- 如果太旧则跳过(> 30 天):从缓存中删除(防止过时数据积累)
- 如果太新则跳过(< 24 小时):保留在缓存中以等待更多部分记录到达
- 加载完整的 CDR,包含所有累积的数据
24 小时等待期
为什么 OmniRoam 在评级 CDR 之前等待 24 小时?
- 部分记录的到达顺序不一致:网络拥塞可能会延迟 CSV 文件的交付数小时
- 会话跨越午夜:在 11:50 PM 开始的会话会生成两个不同日期的文件。相同的计费 ID 可能跨越多天,部分记录的日期不同
- 更新记录延迟到达:定期更新记录可能在会话结束后很久才到达
- 异步文件生成:不同的网络元素在不同的时间表上导出文件
- 长时间运行的会话:数据会话可能持续数小时或数天,更新记录可能会在整个过程中逐渐到达
通过等待 24 小时,OmniRoam 确保所有部分记录都已到达,并且 CDR 在计费之前确实完整。
CDR 验证和丰富
在评级之前,每个组装的 CDR 都要经过验证和丰富:
-
验证完整性:
- 检查是否存在开始/停止记录
- 如果仅存在更新记录,则将持续时间设置为 24 小时(默认)
-
丢弃无效 CDR:
- 删除零使用会话(没有可计费活动)
-
计算最终使用:
- 汇总所有传入和传出字节
- 应用合作伙伴特定的四舍五入规则(例如,向上舍入到最近的 1 KB)
-
丰富位置信息:
- 将 TAC(跟踪区域代码)映射到服务网络位置
- 添加时区信息以确保时间戳准确
- 添加地理位置描述
-
提交给 OmniCharge:
- 将完整的、丰富的 CDR 提交进行评级
- 收回计算的费用
-
存储和清理:
- 将评级后的 CDR 保存到数据库
- 将指标推送到 InfluxDB 进行报告
- 从缓存中删除已处理的 CDR
CDR 数据结构
每个聚合的 CDR 包含:
- 用户信息:IMSI、MSISDN、IMEI
- 网络信息:服务网关(S-GW)、PDN 网关(P-GW)、基站 ID、TAC(跟踪区域代码)
- 会话详情:开始/结束时间戳、持续时间、APN(接入点名称)
- 使用数据:传入/传出数据量、总可计费单位
- 位置信息:服务 BID(网络 ID)、地理位置
- QoS 信息:QCI(服务质量类别标识符)
数据处理规则
使用四舍五入
CDR 根据合作伙伴特定配置中的 config.yaml 进行四舍五入:
partners:
Example_Live:
round_up_to: 1024 # Round usage to nearest 1KB
系统:
- 计算总使用量:
dataVolumeIncoming + dataVolumeOutgoing - 向上舍入到配置的单位(例如,1024 字节)
- 保留原始值以供审计
基于 TAC 的本地化
系统根据 TAC(跟踪区域代码)确定服务网络位置:
config:
tac_config:
Global:
tac_list: ['1101', '10000', '10100']
servingBid: 72473
servingLocationDescription: 'Smallville USA'
timezone: 'America/Smallville'
这使得:
- 时间戳的正确时区转换
- 地理位置的分配
- 服务网络的识别
OmniCharge 计费引擎
OmniRoam 将 CDR 发送到 OmniCharge,这是一个强大的计费引擎,根据可配置的费率计划计算费用。

计费过程
费率配置
费率在配置文件中按漫游合作伙伴进行配置:
partners:
Example_Live:
imsi_prefixes:
- 99901
rates:
unit_price: 0.000476800 # Price per unit
unit_bytes: 1024 # Unit size in bytes
batch_info:
sender: AUSIE
recipient: AAA00
accountingInfo:
localCurrency: 'USD'
tapCurrency: 'USD'
roundingAction: 'Simple'
tapDecimalPlaces: 5
IMSI 前缀匹配
OmniRoam 使用 IMSI 前缀匹配和最长匹配优先逻辑 将 CDR 匹配到漫游合作伙伴。这使得运营商能够为测试 SIM 创建特定配置,同时保持生产流量的一般配置。
前缀匹配的工作原理
在对 CDR 进行计费时,OmniRoam:
- 从 CDR 中提取 IMSI(例如,
310410123456789) - 按顺序评估所有合作伙伴配置
- 找到最长的匹配前缀
- 应用该合作伙伴的费率和配置
示例:测试 SIM 配置
此功能对于 TADIG/IREG 测试特别有用,其中测试 SIM 需要不同的处理:
partners:
Demo_Test:
imsi_prefixes:
- 0010112345123 # Test SIM range (9-digit prefix)
rates:
unit_price: 0.0 # No charge for test traffic
batch_info:
sender: AUSIE
recipient: AAA00TEST
Demo_Production:
imsi_prefixes:
- 001011 # Production range (6-digit prefix)
rates:
unit_price: 0.000476800
batch_info:
sender: AUSIE
recipient: AAA00
匹配行为:
- IMSI
00101123451234→ 匹配Demo_Test(9 位前缀更长) - IMSI
00101023456789→ 匹配Demo_Production(6 位前缀)
这确保测试流量进入测试 TAP 文件,使用测试 TADIG 代码,而生产流量正常计费,使用生产 TADIG 代码。
计费计算
对于每个 CDR:
- 匹配合作伙伴:通过 IMSI 前缀识别漫游合作伙伴
- 计算单位:
totalBytes / unit_bytes - 应用费率:
units × unit_price = charge - 应用四舍五入:根据
roundingAction(向上/向下/简单)进行四舍五入 - 转换为 TAP 单位:乘以 1000 以符合 TAP3 格式
示例:
使用量:52,428,800 字节(50 MB)
单位大小:1024 字节
单位:51,200
费率:每 1KB $0.000476800
费用:51,200 × $0.000476800 = $24.41
TAP 单位:24,410(24.41 × 1000)
基于 QCI 的呼叫类型分配
服务质量类别(QCI)映射到 TAP3 呼叫类型级别:
call_type_level:
qci_1: 20 # 对话(语音)
qci_2: 22 # 对话(视频)
qci_3: 23 # 实时游戏
qci_4: 24 # 缓冲流媒体
qci_5: 20 # IMS 信令
qci_6: 26 # 交互式(浏览)
qci_7: 27 # 交互式(游戏)
qci_8: 28 # 背景
qci_9: 29 # 背景(低优先级)
default: 20
TAP3 文件生成
在 CDR 被 OmniCharge 评级后,OmniRoam 生成符合 GSMA 标准的 TAP3 文件用于批发计费。
TAP3 导出流程
TAP3 文件结构
文件命名约定
TAP3 文件遵循 GSMA 命名标准:
<FileType><Sender><Recipient><SequenceNumber>
示例:
CDAUSIEAAA0000001 - 从 AUSIE 到 AAA00 的商业数据文件,序列 1
TDAUSIEAAA0000001 - 从 AUSIE 到 AAA00 的测试数据文件,序列 1
其中:
- FileType:
CD(商业)或TD(测试) - Sender: 5 字符 TADIG 代码
- Recipient: 5 字符 TADIG 代码
- SequenceNumber: 5 位序列(来自 counters.yaml)
配置指南
合作伙伴配置
在 config.yaml 中添加漫游合作伙伴:
partners:
ONS_Live:
imsi_prefixes: # 此合作伙伴的 IMSI 前缀列表
- 505057
accessPointNameOI: mnc057.mcc505.gprs
rates:
unit_price: 0.000476800 # 每单位价格(美元)
unit_bytes: 1024 # 每单位的字节数
batch_info:
sender: AUSIE # 您的 TADIG 代码
recipient: AAA00 # 合作伙伴 TADIG 代码
specificationVersionNumber: 3
releaseVersionNumber: 12
accountingInfo:
localCurrency: 'USD'
tapCurrency: 'USD'
roundingAction: 'Simple' # 向上/向下/简单
tapDecimalPlaces: 5
round_up_to: 1024 # 将使用量四舍五入到最近的 N 字节
call_type_level: # QCI 到呼叫类型级别的映射
qci_1: 20
qci_2: 22
default: 20
序列计数器配置
在 counters.yaml 中初始化序列计数器:
AAA00:
CD: 1 # 商业数据序列
TD: 1 # 测试数据序列
AAA01:
CD: 1
TD: 1
序列在��个生成的 TAP 文件中自动递增。
网络配置
配置 TAC 到位置的映射:
config:
tac_config:
LocationName:
tac_list: ['1101', '10000']
servingBid: 72473
servingLocationDescription: 'Network Location'
timezone: 'America/New_York'
InfluxDB 配置
在 config.yaml 中配置 InfluxDB 连接:
config:
influx_db:
influxDbUrl: 'http://10.3.0.135:8086'
influxDbOrg: 'omnitouch'
influxDbBucket: 'Omnicharge_TAP3'
influxDbToken: 'your-token-here'
输出路径
配置文件输出位置:
config:
tap_output_path: '/etc/pytap3/OutputFiles'
tap_human_readable_output_path: '/etc/pytap3/OutputFiles_Human'
tap_in_path: '/home/user/TAP_In/'
架构决策
为什么选择 OmniCharge?
OmniCharge 提供:
- 强大的计费引擎,具有灵活的费率计划
- 实时计费能力
- CDR 去重
- 全面的审计跟踪
- 基于 API 的集成
为什么选择 InfluxDB?
优势:
- 针对 CDR 指标优化的时间序列
- 高写入吞吐量
- 具有压缩的高效存储
- 内置降采样
- 原生 Grafana 集成
工作流程摘要
OmniRoam - 由 Omnitouch 提供的专业漫游收入管理。