首页 > 解决方案 > Spark 数据集显示:无法多次捕获输出

问题描述

即使我已经解决了问题(请参阅答案),我仍在问这个问题,以挽救其他人同样的痛苦。

我需要一种方法来向我的 log4j 记录器显示我的数据集。我这样做是使用: void org.apache.spark.sql.Dataset.show(int numRows, boolean truncate) 它只是记录到stdOut。为了捕获stdOut,我做了以下事情(在stackoverflow的其他地方找到了灵感):

void myMethod(Dataset<Row> data){
    // Save the old System.out
    PrintStream originalPrintStream = System.out;

    // Tell Java to use your special stream
    ByteArrayOutputStream logCollection = new ByteArrayOutputStream();
    PrintStream printStreamForCollectingLogs = new PrintStream(logCollection);
    System.setOut(printStreamForCollectingLogs);

    // Print some output: goes to your special stream
    data.show(MAX_DISPLAY_ROWS, false);

    // Put things back
    System.out.flush();
    System.setOut(originalPrintStream);

    logger.info("\n"+logCollection.toString());
    logCollection.reset();
}

这仅有效一次,对同一数据集的同一方法的后续调用将无法捕获任何内容。我在用:

      <groupId>org.apache.spark</groupId>
      <artifactId>spark-sql_2.11</artifactId>
      <version>2.4.5</version>

标签: javaapache-sparkapache-spark-sqlapache-spark-dataset

解决方案


这个问题似乎是由于数据集保留了它首先遇到的作为 stdOut 的字节流,因为我能够通过将我的替代 stdOut 流提取为类变量来解决这个问题:

private static ByteArrayOutputStream logCollection = new ByteArrayOutputStream();
private static PrintStream printStreamForCollectingLogs = new PrintStream(logCollection);

这意味着我logger.info("\n"+logCollection.toString())每次都使用相同的字节流。这使我可以根据需要随时调用 myMethod 并每次都捕获输出。


推荐阅读