You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于PySpark计算不同错误码对应的设备停机时长

用PySpark计算错误码对应的设备停机时长

针对GB级日志的停机时长计算,用Spark SQL窗口函数的方案比RDD遍历效率高得多,核心是给每个错误事件匹配后续首个恢复事件,再计算时间差并归集。

步骤实现

1. 初始化Spark并加载数据

from pyspark.sql import SparkSession
from pyspark.sql import functions as F
from pyspark.sql.window import Window

spark = SparkSession.builder.appName("DowntimeCalculation").getOrCreate()

# 加载已处理好的Parquet数据
df = spark.read.parquet("/path/to/your/parquet/dir")

2. 筛选关键事件

先拆分出两类核心记录:

  • 错误事件:Parameter ID为Error且Parameter Value>0,提取错误码
  • 恢复事件:Parameter ID为State且Parameter Value=6,标记为恢复点
# 提取错误事件,重命名Value为Error_Code
error_df = df.filter(
    (F.col("Parameter ID") == "Error") & (F.col("Parameter Value") > 0)
).select(
    "TimeStamp",
    F.col("Parameter Value").alias("Error_Code")
)

# 提取恢复事件,添加恢复标记
recovery_df = df.filter(
    (F.col("Parameter ID") == "State") & (F.col("Parameter Value") == 6)
).select(
    "TimeStamp",
    F.lit(1).alias("is_recovery")
)

3. 匹配错误与首个恢复时间

合并两类事件后,用窗口函数向前查找每个错误之后的第一个恢复时间:

# 合并事件并按时间排序,给恢复事件补全Error_Code字段为null
combined_df = error_df.unionByName(
    recovery_df.withColumn("Error_Code", F.lit(None))
).orderBy("TimeStamp")

# 定义窗口:从当前行开始,向后扫描所有行,取第一个非空的恢复时间
window_spec = Window.orderBy("TimeStamp").rowsBetween(0, Window.unboundedFollowing)

# 提取每个错误对应的首个恢复时间,只保留错误事件行
matched_df = combined_df.withColumn(
    "recovery_time",
    F.first(F.when(F.col("is_recovery") == 1, F.col("TimeStamp")), ignorenulls=True).over(window_spec)
).filter(F.col("Error_Code").isNotNull())

4. 计算时长并按错误码归集

计算时间差(精确到毫秒),然后按错误码分组收集时长列表:

# 计算停机时长(单位:秒,保留毫秒精度)
duration_df = matched_df.withColumn(
    "downtime_seconds",
    (F.unix_timestamp("recovery_time") - F.unix_timestamp("TimeStamp")) +
    (F.millisecond("recovery_time") - F.millisecond("TimeStamp")) / 1000
)

# 按错误码归集所有停机时长
result_df = duration_df.groupBy("Error_Code").agg(
    F.collect_list("downtime_seconds").alias("downtime_list")
)

# 输出结果
result_df.show(truncate=False)

性能优化点

  • 如果日志包含设备ID,一定要在窗口函数中加上partitionBy("device_id"),避免跨设备匹配恢复事件
  • 加载数据时按TimeStamp分区,减少扫描范围:df = spark.read.parquet("/path").repartition("TimeStamp")
  • 若数据量超大,可先按时间范围过滤,再处理指定时间段的日志

内容的提问来源于stack exchange,提问作者dach

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 02:55:17