如何使用 log4j 自定义附加程序在 HDFS 上创建日志?

2024-06-19

Overview

我们希望使用 log4j 记录 Spark 作业活动,并将日志文件写入 HDFS。

  • Java 8、Spark 2.4.6、Scala 2.1.2、Hadoop 3.2.1

我们无法找到本地 apache log4j 附加程序来写入 HDFS(Apache Flume 不是一个选项),因此开始编写我们自己的附加程序。

Scala 逻辑与 Java 匹配,但是,自定义附加程序的日志记录始终失败并出现堆栈溢出错误。

我们找不到任何明显的错误吗?

实施:

这是一个简单的 hello-world 项目来重现该问题:

  • Scala / Java 项目(Maven 构建),包含一个简单的主类,以及:
  • HDFSAppender 类(扩展 log4j AppenderSkeleton)
  • LoggingTest 单元测试类
  • 用于测试的 log4j 配置文件

HDFSAppender.scala - Appender 类

```
package com.obfuscated.test.spark.log4j

import java.io.BufferedOutputStream
import java.io.IOException
import java.net.URI
import java.net.URISyntaxException

import scala.beans.BeanProperty

import org.apache.hadoop.fs.FSDataOutputStream
import org.apache.hadoop.fs.FileSystem
import org.apache.hadoop.fs.Path
import org.apache.hadoop.conf.Configuration
import org.apache.log4j.AppenderSkeleton
import org.apache.log4j.Level
import org.apache.log4j.Logger
import org.apache.log4j.MDC
import org.apache.log4j.spi.LoggingEvent
import org.apache.logging.log4j.scala.Logging
import org.apache.spark.SparkContext
import org.apache.spark.sql.SparkSession

object HDFSAppender {
  def createAndRegister(): HDFSAppender = {
    val hdfsAppender: HDFSAppender = new HDFSAppender
    Logger.getRootLogger.addAppender(hdfsAppender)
    hdfsAppender
  }

  def setClassLoggerLevel(clazz: Class[_], logLevel: Level): Level = {
    val logger = Logger.getLogger(clazz)
    val previousLevel = logger.getLevel
    Logger.getLogger(clazz).setLevel(logLevel)
    previousLevel
  }

  def unregister(hdfsAppender: HDFSAppender): Unit = {
    Logger.getRootLogger.removeAppender(hdfsAppender)
  }
}


class HDFSAppender extends AppenderSkeleton with Logging {

  var sc: SparkContext = _
  
  @BeanProperty
  var file: String = null

  @BeanProperty
  var URI: String = null

  override def close(): Unit = {}

  override def requiresLayout(): Boolean = true

  override protected def append(event: LoggingEvent): Unit = {
    var success: Boolean = false
    val log: String = this.layout.format(event)
    val uri: URI = new URI(this.URI)
    
    write(this.URI, file, log)
    
  }
    
  def write(uriString: String, file: String, log: String): Unit = {
    val conf: Configuration = new Configuration()
    MDC.put("eventName", "HDFSLogWriterWrite");
    
    
    val uri: URI = new URI(uriString)
    val logPath: Path = new Path(uriString + file)
    
    val fs = getFS(uri,conf)
    var output_stream: FSDataOutputStream = null
    try {
      if ((fs.exists(logPath) && fs.getFileStatus(logPath).isFile)) {
        output_stream = fs.append(logPath, 512)
      } else {
        output_stream = fs.create(logPath, true, 512)
      }
      val buffered_output: BufferedOutputStream = new BufferedOutputStream(output_stream)
      buffered_output.write(log.getBytes("UTF-8"))
      buffered_output.close()   
      
    } catch {
      
      case e: IOException => {
            e.printStackTrace();
      }
       case e: URISyntaxException => {
            e.printStackTrace();
      }
    }
  }
    /**
   * return a FileSystem from URI
   */
  private def getFS(uri: URI, conf: Configuration): FileSystem = {
    var fs: FileSystem = null
    try {
      fs = FileSystem.get(uri, conf)
    } catch {
      case e: Exception =>
        e.printStackTrace()
    }
    fs
  }
}

测试班

```
package com.obfuscated.test.spark.log4j.test

import java.net.URI

import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.FileSystem
import org.apache.hadoop.fs.Path
import org.apache.log4j.Level
import org.apache.log4j.LogManager
import org.apache.log4j.Logger
import org.junit.Assert.assertTrue
import org.junit.BeforeClass
import org.junit.Test
import org.scalatest.junit.JUnitSuite

import com.obfuscated.test.spark.log4j.CustomJsonEventLayout
import com.obfuscated.test.spark.log4j.HDFSAppender

import LoggingTest.fsHDFS
import LoggingTest.testHDFSHost
import LoggingTest.testOutputLogPath


object LoggingTest {
  
  var fsHDFS: FileSystem = _
  
  val testHDFSHost: String = 
    "hdfs://localhost:9000"
  
  val testOutputLogPath: String =
    "/test/ut/logging/log-test-hdfs-appender_scala.txt"

  @BeforeClass
  def setupFsRemovePreviousTestFiles(): Unit = {
    
    val conf: Configuration = new Configuration()
    conf.set("fs.defaultFS", testHDFSHost)
    fsHDFS = FileSystem.get(new URI(testHDFSHost), conf)
    val outputPath: Path = new Path(testOutputLogPath)
    if (fsHDFS.exists(outputPath)) {
      fsHDFS.delete(outputPath, true)
    }
  }

}

/**
 * programmatically builds and tests logging events with log4j.test
 *
 */
class LoggingTest extends JUnitSuite {
  val conf: Configuration = new Configuration()

  @Test
  def testHDFSAppender(): Unit = {
    val hdfsAppender: HDFSAppender = new HDFSAppender()
    val rootlogger: Logger = LogManager.getRootLogger
   
    hdfsAppender.setFile(testOutputLogPath)
    hdfsAppender.setURI(testHDFSHost)
    hdfsAppender.setThreshold(Level.ALL)
    hdfsAppender.setLayout(new CustomJsonEventLayout())
    rootlogger.addAppender(hdfsAppender)
    val logger: Logger = Logger.getLogger(this.getClass)

    try {
      logger.info("Test info message")
      logger.warn("Test warn message")
      logger.error("Test error message")
      logger.debug("Test debug message")
    } finally {
     logger.removeAppender(hdfsAppender)
  }
    val logFile: Path = new Path(testHDFSHost + testOutputLogPath)
    assertTrue(fsHDFS.exists(logFile))
    // TODO: further assertions to check log contents

  }
}

log4j配置文件(运行时测试)

```
log4j.rootLogger=DEBUG, console, HDFSAppender

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.threshold=DEBUG
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5p] [%X{eventName}] %m %c%n    
log4j.appender.HDFSAppender=com.obfuscated.test.spark.log4j.HDFSAppender
log4j.appender.HDFSAppender.layout=com.obfuscated.test.spark.log4j.CustomJsonEventLayout
log4j.appender.HDFSAppender.file=/test/ut/logging/log-test-hdfs-appender_scala.json
log4j.appender.HDFSAppender.URI=hdfs://localhost:9000
log4j.appender.HDFSAppender.threshold=DEBUG

任何日志记录事件都会导致程序因堆栈溢出错误而崩溃:

java.util.concurrent.ExecutionException: java.lang.StackOverflowError
 at java.util.concurrent.FutureTask.report(FutureTask.java:122)
 at java.util.concurrent.FutureTask.get(FutureTask.java:206)
 at org.apache.hadoop.util.ShutdownHookManager.executeShutdown(ShutdownHookManager.java:124)
 at org.apache.hadoop.util.ShutdownHookManager$1.run(ShutdownHookManager.java:95)
Caused by: java.lang.StackOverflowError
 at org.apache.log4j.PatternLayout.format(PatternLayout.java:506)
 at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:310)
 at org.apache.log4j.WriterAppender.append(WriterAppender.java:162)

然后出现以下消息,暗示某种循环/竞争条件

 at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
   at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
   at org.apache.log4j.Category.callAppenders(Category.java:206)
   at org.apache.log4j.Category.forcedLog(Category.java:391)
   at org.apache.log4j.Category.log(Category.java:856)
   at org.slf4j.impl.Log4jLoggerAdapter.warn(Log4jLoggerAdapter.java:401)
   at org.apache.spark.internal.Logging.logWarning(Logging.scala:66)
   at org.apache.spark.internal.Logging.logWarning$(Logging.scala:65)
   at org.apache.spark.SparkContext$.logWarning(SparkContext.scala:2442)
   at org.apache.spark.SparkContext$.$anonfun$assertNoOtherContextIsRunning$5(SparkContext.scala:2500)
   at org.apache.spark.SparkContext$.$anonfun$assertNoOtherContextIsRunning$5$adapted(SparkContext.scala:2491)
   at scala.Option.foreach(Option.scala:274)
   at org.apache.spark.SparkContext$.assertNoOtherContextIsRunning(SparkContext.scala:2491)
   at org.apache.spark.SparkContext$.markPartiallyConstructed(SparkContext.scala:2568)
   at org.apache.spark.SparkContext.<init>(SparkContext.scala:85)
   at org.apache.spark.SparkContext$.getOrCreate(SparkContext.scala:2520)
   at org.apache.spark.sql.SparkSession$Builder.$anonfun$getOrCreate$5(SparkSession.scala:935)
   at scala.Option.getOrElse(Option.scala:138)
   at org.apache.spark.sql.SparkSession$Builder.getOrCreate(SparkSession.scala:926)
   at com.obfuscated.test.spark.log4j.HDFSLogWriter.write(HDFSLogWriter.scala:23)
   at com.obfuscated.test.spark.log4j.HDFSAppender.append(HDFSAppender.scala:63)
(repeats 48 times...)

Maven 依赖项

Downloaded from central: 

https://repo.maven.apache.org/maven2/net/alchim31/maven/scala-maven-plugin/3.2.2/scala-maven-plugin-3.2.2.jar (119 kB at 163 kB/s)
[INFO] 
[INFO] ----------< spark-hello-world-scala:spark-hello-world-scala >-----------
[INFO] Building spark-hello-world-scala 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ spark-hello-world-scala ---
[INFO] spark-hello-world-scala:spark-hello-world-scala:jar:0.0.1-SNAPSHOT
[INFO] +- org.apache.spark:spark-core_2.12:jar:3.0.0:compile
[INFO] |  +- com.thoughtworks.paranamer:paranamer:jar:2.8:compile
[INFO] |  +- org.apache.avro:avro:jar:1.8.2:compile
[INFO] |  |  +- org.codehaus.jackson:jackson-core-asl:jar:1.9.13:compile
[INFO] |  |  +- org.codehaus.jackson:jackson-mapper-asl:jar:1.9.13:compile
[INFO] |  |  +- org.apache.commons:commons-compress:jar:1.8.1:compile
[INFO] |  |  \- org.tukaani:xz:jar:1.5:compile
[INFO] |  +- org.apache.avro:avro-mapred:jar:hadoop2:1.8.2:compile
[INFO] |  |  +- org.apache.avro:avro-ipc:jar:1.8.2:compile
[INFO] |  |  \- commons-codec:commons-codec:jar:1.9:compile
[INFO] |  +- com.twitter:chill_2.12:jar:0.9.5:compile
[INFO] |  |  \- com.esotericsoftware:kryo-shaded:jar:4.0.2:compile
[INFO] |  |     +- com.esotericsoftware:minlog:jar:1.3.0:compile
[INFO] |  |     \- org.objenesis:objenesis:jar:2.5.1:compile
[INFO] |  +- com.twitter:chill-java:jar:0.9.5:compile
[INFO] |  +- org.apache.xbean:xbean-asm7-shaded:jar:4.15:compile
[INFO] |  +- org.apache.hadoop:hadoop-client:jar:2.7.4:compile
[INFO] |  |  +- org.apache.hadoop:hadoop-common:jar:2.7.4:compile
[INFO] |  |  |  +- commons-cli:commons-cli:jar:1.2:compile
[INFO] |  |  |  +- xmlenc:xmlenc:jar:0.52:compile
[INFO] |  |  |  +- commons-httpclient:commons-httpclient:jar:3.1:compile
[INFO] |  |  |  +- commons-collections:commons-collections:jar:3.2.2:compile
[INFO] |  |  |  +- org.mortbay.jetty:jetty-sslengine:jar:6.1.26:compile
[INFO] |  |  |  +- javax.servlet.jsp:jsp-api:jar:2.1:runtime
[INFO] |  |  |  +- commons-configuration:commons-configuration:jar:1.6:compile
[INFO] |  |  |  |  \- commons-digester:commons-digester:jar:1.8:compile
[INFO] |  |  |  |     \- commons-beanutils:commons-beanutils:jar:1.7.0:compile
[INFO] |  |  |  +- com.google.code.gson:gson:jar:2.2.4:compile
[INFO] |  |  |  +- org.apache.hadoop:hadoop-auth:jar:2.7.4:compile
[INFO] |  |  |  |  +- org.apache.httpcomponents:httpclient:jar:4.2.5:compile
[INFO] |  |  |  |  |  \- org.apache.httpcomponents:httpcore:jar:4.2.4:compile
[INFO] |  |  |  |  \- org.apache.directory.server:apacheds-kerberos-codec:jar:2.0.0-M15:compile
[INFO] |  |  |  |     +- org.apache.directory.server:apacheds-i18n:jar:2.0.0-M15:compile
[INFO] |  |  |  |     +- org.apache.directory.api:api-asn1-api:jar:1.0.0-M20:compile
[INFO] |  |  |  |     \- org.apache.directory.api:api-util:jar:1.0.0-M20:compile
[INFO] |  |  |  +- org.apache.curator:curator-client:jar:2.7.1:compile
[INFO] |  |  |  \- org.apache.htrace:htrace-core:jar:3.1.0-incubating:compile
[INFO] |  |  +- org.apache.hadoop:hadoop-hdfs:jar:2.7.4:compile
[INFO] |  |  |  +- org.mortbay.jetty:jetty-util:jar:6.1.26:compile
[INFO] |  |  |  \- xerces:xercesImpl:jar:2.9.1:compile
[INFO] |  |  |     \- xml-apis:xml-apis:jar:1.3.04:compile
[INFO] |  |  +- org.apache.hadoop:hadoop-mapreduce-client-app:jar:2.7.4:compile
[INFO] |  |  |  +- org.apache.hadoop:hadoop-mapreduce-client-common:jar:2.7.4:compile
[INFO] |  |  |  |  +- org.apache.hadoop:hadoop-yarn-client:jar:2.7.4:compile
[INFO] |  |  |  |  \- org.apache.hadoop:hadoop-yarn-server-common:jar:2.7.4:compile
[INFO] |  |  |  \- org.apache.hadoop:hadoop-mapreduce-client-shuffle:jar:2.7.4:compile
[INFO] |  |  +- org.apache.hadoop:hadoop-yarn-api:jar:2.7.4:compile
[INFO] |  |  +- org.apache.hadoop:hadoop-mapreduce-client-core:jar:2.7.4:compile
[INFO] |  |  |  \- org.apache.hadoop:hadoop-yarn-common:jar:2.7.4:compile
[INFO] |  |  |     +- javax.xml.bind:jaxb-api:jar:2.2.2:compile
[INFO] |  |  |     |  \- javax.xml.stream:stax-api:jar:1.0-2:compile
[INFO] |  |  |     +- org.codehaus.jackson:jackson-jaxrs:jar:1.9.13:compile
[INFO] |  |  |     \- org.codehaus.jackson:jackson-xc:jar:1.9.13:compile
[INFO] |  |  +- org.apache.hadoop:hadoop-mapreduce-client-jobclient:jar:2.7.4:compile
[INFO] |  |  \- org.apache.hadoop:hadoop-annotations:jar:2.7.4:compile
[INFO] |  +- org.apache.spark:spark-launcher_2.12:jar:3.0.0:compile
[INFO] |  +- org.apache.spark:spark-kvstore_2.12:jar:3.0.0:compile
[INFO] |  |  +- org.fusesource.leveldbjni:leveldbjni-all:jar:1.8:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-core:jar:2.10.0:compile
[INFO] |  |  \- com.fasterxml.jackson.core:jackson-annotations:jar:2.10.0:compile
[INFO] |  +- org.apache.spark:spark-network-common_2.12:jar:3.0.0:compile
[INFO] |  +- org.apache.spark:spark-network-shuffle_2.12:jar:3.0.0:compile
[INFO] |  +- org.apache.spark:spark-unsafe_2.12:jar:3.0.0:compile
[INFO] |  +- javax.activation:activation:jar:1.1.1:compile
[INFO] |  +- org.apache.curator:curator-recipes:jar:2.7.1:compile
[INFO] |  |  +- org.apache.curator:curator-framework:jar:2.7.1:compile
[INFO] |  |  \- com.google.guava:guava:jar:16.0.1:compile
[INFO] |  +- org.apache.zookeeper:zookeeper:jar:3.4.14:compile
[INFO] |  |  \- org.apache.yetus:audience-annotations:jar:0.5.0:compile
[INFO] |  +- javax.servlet:javax.servlet-api:jar:3.1.0:compile
[INFO] |  +- org.apache.commons:commons-lang3:jar:3.9:compile
[INFO] |  +- org.apache.commons:commons-math3:jar:3.4.1:compile
[INFO] |  +- org.apache.commons:commons-text:jar:1.6:compile
[INFO] |  +- com.google.code.findbugs:jsr305:jar:3.0.0:compile
[INFO] |  +- org.slf4j:slf4j-api:jar:1.7.30:compile
[INFO] |  +- org.slf4j:jul-to-slf4j:jar:1.7.30:compile
[INFO] |  +- org.slf4j:jcl-over-slf4j:jar:1.7.30:compile
[INFO] |  +- log4j:log4j:jar:1.2.17:compile
[INFO] |  +- org.slf4j:slf4j-log4j12:jar:1.7.30:compile
[INFO] |  +- com.ning:compress-lzf:jar:1.0.3:compile
[INFO] |  +- org.xerial.snappy:snappy-java:jar:1.1.7.5:compile
[INFO] |  +- org.lz4:lz4-java:jar:1.7.1:compile
[INFO] |  +- com.github.luben:zstd-jni:jar:1.4.4-3:compile
[INFO] |  +- org.roaringbitmap:RoaringBitmap:jar:0.7.45:compile
[INFO] |  |  \- org.roaringbitmap:shims:jar:0.7.45:compile
[INFO] |  +- commons-net:commons-net:jar:3.1:compile
[INFO] |  +- org.scala-lang.modules:scala-xml_2.12:jar:1.2.0:compile
[INFO] |  +- org.scala-lang:scala-reflect:jar:2.12.10:compile
[INFO] |  +- org.json4s:json4s-jackson_2.12:jar:3.6.6:compile
[INFO] |  |  \- org.json4s:json4s-core_2.12:jar:3.6.6:compile
[INFO] |  |     +- org.json4s:json4s-ast_2.12:jar:3.6.6:compile
[INFO] |  |     \- org.json4s:json4s-scalap_2.12:jar:3.6.6:compile
[INFO] |  +- org.glassfish.jersey.core:jersey-client:jar:2.30:compile
[INFO] |  |  +- jakarta.ws.rs:jakarta.ws.rs-api:jar:2.1.6:compile
[INFO] |  |  \- org.glassfish.hk2.external:jakarta.inject:jar:2.6.1:compile
[INFO] |  +- org.glassfish.jersey.core:jersey-common:jar:2.30:compile
[INFO] |  |  +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] |  |  \- org.glassfish.hk2:osgi-resource-locator:jar:1.0.3:compile
[INFO] |  +- org.glassfish.jersey.core:jersey-server:jar:2.30:compile
[INFO] |  |  +- org.glassfish.jersey.media:jersey-media-jaxb:jar:2.30:compile
[INFO] |  |  \- jakarta.validation:jakarta.validation-api:jar:2.0.2:compile
[INFO] |  +- org.glassfish.jersey.containers:jersey-container-servlet:jar:2.30:compile
[INFO] |  +- org.glassfish.jersey.containers:jersey-container-servlet-core:jar:2.30:compile
[INFO] |  +- org.glassfish.jersey.inject:jersey-hk2:jar:2.30:compile
[INFO] |  |  +- org.glassfish.hk2:hk2-locator:jar:2.6.1:compile
[INFO] |  |  |  +- org.glassfish.hk2.external:aopalliance-repackaged:jar:2.6.1:compile
[INFO] |  |  |  +- org.glassfish.hk2:hk2-api:jar:2.6.1:compile
[INFO] |  |  |  \- org.glassfish.hk2:hk2-utils:jar:2.6.1:compile
[INFO] |  |  \- org.javassist:javassist:jar:3.25.0-GA:compile
[INFO] |  +- io.netty:netty-all:jar:4.1.47.Final:compile
[INFO] |  +- com.clearspring.analytics:stream:jar:2.9.6:compile
[INFO] |  +- io.dropwizard.metrics:metrics-core:jar:4.1.1:compile
[INFO] |  +- io.dropwizard.metrics:metrics-jvm:jar:4.1.1:compile
[INFO] |  +- io.dropwizard.metrics:metrics-json:jar:4.1.1:compile
[INFO] |  +- io.dropwizard.metrics:metrics-graphite:jar:4.1.1:compile
[INFO] |  +- io.dropwizard.metrics:metrics-jmx:jar:4.1.1:compile
[INFO] |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile
[INFO] |  +- com.fasterxml.jackson.module:jackson-module-scala_2.12:jar:2.10.0:compile
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-paranamer:jar:2.10.0:compile
[INFO] |  +- org.apache.ivy:ivy:jar:2.4.0:compile
[INFO] |  +- oro:oro:jar:2.0.8:compile
[INFO] |  +- net.razorvine:pyrolite:jar:4.30:compile
[INFO] |  +- net.sf.py4j:py4j:jar:0.10.9:compile
[INFO] |  +- org.apache.spark:spark-tags_2.12:jar:3.0.0:compile
[INFO] |  +- org.apache.commons:commons-crypto:jar:1.0.0:compile
[INFO] |  \- org.spark-project.spark:unused:jar:1.0.0:compile
[INFO] +- org.apache.spark:spark-mllib_2.12:jar:3.0.0:runtime
[INFO] |  +- org.scala-lang.modules:scala-parser-combinators_2.12:jar:1.1.2:compile
[INFO] |  +- org.apache.spark:spark-streaming_2.12:jar:3.0.0:runtime
[INFO] |  +- org.apache.spark:spark-graphx_2.12:jar:3.0.0:runtime
[INFO] |  |  +- com.github.fommil.netlib:core:jar:1.1.2:runtime
[INFO] |  |  \- net.sourceforge.f2j:arpack_combined_all:jar:0.1:runtime
[INFO] |  +- org.apache.spark:spark-mllib-local_2.12:jar:3.0.0:runtime
[INFO] |  +- org.scalanlp:breeze_2.12:jar:1.0:runtime
[INFO] |  |  +- org.scalanlp:breeze-macros_2.12:jar:1.0:runtime
[INFO] |  |  +- net.sf.opencsv:opencsv:jar:2.3:runtime
[INFO] |  |  +- com.github.wendykierp:JTransforms:jar:3.1:runtime
[INFO] |  |  |  \- pl.edu.icm:JLargeArrays:jar:1.5:runtime
[INFO] |  |  +- com.chuusai:shapeless_2.12:jar:2.3.3:runtime
[INFO] |  |  |  \- org.typelevel:macro-compat_2.12:jar:1.1.1:runtime
[INFO] |  |  +- org.typelevel:spire_2.12:jar:0.17.0-M1:runtime
[INFO] |  |  |  +- org.typelevel:spire-macros_2.12:jar:0.17.0-M1:runtime
[INFO] |  |  |  +- org.typelevel:spire-platform_2.12:jar:0.17.0-M1:runtime
[INFO] |  |  |  +- org.typelevel:spire-util_2.12:jar:0.17.0-M1:runtime
[INFO] |  |  |  +- org.typelevel:machinist_2.12:jar:0.6.8:runtime
[INFO] |  |  |  \- org.typelevel:algebra_2.12:jar:2.0.0-M2:runtime
[INFO] |  |  |     \- org.typelevel:cats-kernel_2.12:jar:2.0.0-M4:runtime
[INFO] |  |  \- org.scala-lang.modules:scala-collection-compat_2.12:jar:2.1.1:runtime
[INFO] |  \- org.glassfish.jaxb:jaxb-runtime:jar:2.3.2:runtime
[INFO] |     +- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.2:runtime
[INFO] |     \- com.sun.istack:istack-commons-runtime:jar:3.0.8:runtime
[INFO] +- org.scala-lang:scala-library:jar:2.12.8:compile
[INFO] +- org.apache.spark:spark-sql_2.12:jar:3.0.0:compile
[INFO] |  +- com.univocity:univocity-parsers:jar:2.8.3:compile
[INFO] |  +- org.apache.spark:spark-sketch_2.12:jar:3.0.0:compile
[INFO] |  +- org.apache.spark:spark-catalyst_2.12:jar:3.0.0:compile
[INFO] |  |  +- org.codehaus.janino:janino:jar:3.0.16:compile
[INFO] |  |  +- org.codehaus.janino:commons-compiler:jar:3.0.16:compile
[INFO] |  |  +- org.antlr:antlr4-runtime:jar:4.7.1:compile
[INFO] |  |  \- org.apache.arrow:arrow-vector:jar:0.15.1:compile
[INFO] |  |     +- org.apache.arrow:arrow-format:jar:0.15.1:compile
[INFO] |  |     +- org.apache.arrow:arrow-memory:jar:0.15.1:compile
[INFO] |  |     \- com.google.flatbuffers:flatbuffers-java:jar:1.9.0:compile
[INFO] |  +- org.apache.orc:orc-core:jar:1.5.10:compile
[INFO] |  |  +- org.apache.orc:orc-shims:jar:1.5.10:compile
[INFO] |  |  +- com.google.protobuf:protobuf-java:jar:2.5.0:compile
[INFO] |  |  +- commons-lang:commons-lang:jar:2.6:compile
[INFO] |  |  +- io.airlift:aircompressor:jar:0.10:compile
[INFO] |  |  \- org.threeten:threeten-extra:jar:1.5.0:compile
[INFO] |  +- org.apache.orc:orc-mapreduce:jar:1.5.10:compile
[INFO] |  +- org.apache.hive:hive-storage-api:jar:2.7.1:compile
[INFO] |  +- org.apache.parquet:parquet-column:jar:1.10.1:compile
[INFO] |  |  +- org.apache.parquet:parquet-common:jar:1.10.1:compile
[INFO] |  |  \- org.apache.parquet:parquet-encoding:jar:1.10.1:compile
[INFO] |  \- org.apache.parquet:parquet-hadoop:jar:1.10.1:compile
[INFO] |     +- org.apache.parquet:parquet-format:jar:2.4.0:compile
[INFO] |     \- org.apache.parquet:parquet-jackson:jar:1.10.1:compile
[INFO] +- com.databricks:spark-xml_2.12:jar:0.9.0:compile
[INFO] |  +- commons-io:commons-io:jar:2.6:compile
[INFO] |  \- org.glassfish.jaxb:txw2:jar:2.3.2:compile
[INFO] +- org.apache.spark:spark-avro_2.12:jar:3.0.0:compile
[INFO] +- org.scalatest:scalatest_2.12:jar:3.0.5:test
[INFO] |  \- org.scalactic:scalactic_2.12:jar:3.0.5:test
[INFO] +- org.specs2:specs2-core_2.12:jar:4.2.0:test
[INFO] |  +- org.specs2:specs2-matcher_2.12:jar:4.2.0:test
[INFO] |  |  \- org.specs2:specs2-common_2.12:jar:4.2.0:test
[INFO] |  |     \- org.specs2:specs2-fp_2.12:jar:4.2.0:test
[INFO] |  \- org.scala-sbt:test-interface:jar:1.0:test
[INFO] +- org.specs2:specs2-junit_2.12:jar:4.2.0:test
[INFO] |  \- junit:junit:jar:4.12:test
[INFO] |     \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- org.apache.logging.log4j:log4j-api:jar:2.13.3:compile
[INFO] +- org.apache.logging.log4j:log4j-core:jar:2.13.3:compile
[INFO] +- org.apache.logging.log4j:log4j-api-scala_2.12:jar:12.0:compile
[INFO] +- org.apache.logging.log4j:log4j-api:test-jar:tests:2.13.3:test
[INFO] \- org.apache.logging.log4j:log4j-to-slf4j:jar:2.13.3:compile

None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 log4j 自定义附加程序在 HDFS 上创建日志? 的相关文章

  • 抽象数据类型和接口

    抽象数据类型和接口有什么区别 例如我们有一个ListADT interface MyListADT
  • 特征/类类型参数优先于方法类型参数的规则是什么

    我已经使用 scala 一段时间了 我认为我真的开始理解一切 好吧 大多数事情 但我发现自己对 Map 类中的许多方法定义感到困惑 我知道 FoldLeft 等如何工作 但我感到困惑的是 Map 函数中使用的类型参数 我们以 FoldLef
  • 如何在 Android 上将 ISO 8601 字符串解析为 Java 日期 [重复]

    这个问题在这里已经有答案了 我正在 Android 上创建一个与服务器通信的应用程序 该服务器给我返回了一个ISO 8601 http en wikipedia org wiki ISO 8601日期字符串 如下所示 2014 11 21
  • JavaFX 控制器如何访问其他服务?

    我将 JavaFX 2 与 Scala 一起使用 我有class Application extends javafx application Application它执行诸如读取应用程序配置等操作 然后它会启动主窗口 该主窗口需要连接到一
  • Unwrap 当使用 Collectors maxBy 和 groupingBy 时可选

    我有一堂课 有一个String and an int field public class Data private String name private int value private Data String name int va
  • 如何使用我的 Apple 开发者 ID 签署 .jar 文件

    我有一个java可执行文件jar我需要使用我的 Apple 开发者 ID 进行签名的文件 我不打算通过应用程序商店分发它 我将通过我的网站直接向客户分发该应用程序 我不打算绕过 Gatekeeper Signing the app和我的de
  • 从 ArrayList HashMap 中获取多个随机值

    我想从 ArrayList 中获取一些特定数字的随机值 final ArrayList
  • Groovy 2.0.1,我自己的类上有 GroovyCastException?

    我在我的网络应用程序项目中广泛使用 Groovy 类 我可以创建类型的实例 定义为 groovy 类 但以后永远不能转换回它 GroovyCastException发生 org codehaus groovy runtime typehan
  • 从命令行进行 Liquibase 回滚不起作用

    我正在 Windows 环境中执行一个 Tomcat 应用程序 部署时会在 Oracle 数据库上创建 更新数据库架构 为此 我使用 Liquibase SDK 3 3 2 所以基本上我调用 SDK 并告诉它从我的changelog xml
  • 如何同时运行两个FOR循环

    我正在使用加速度计 第一个代码是振动检测器 代码1 if sensor SensorManager SENSOR ACCELEROMETER long curTime System currentTimeMillis long now Sy
  • Android Edittext Onclick Datepickerdialog 棒棒糖中出现错误

    我正在使用日期选择器对话框 它在 kitkat 上运行正常 但是当我在棒棒糖上运行应用程序时 当我单击编辑文本时 它会打开一个日期选择器对话框 但当我选择日期时 它会不幸地给出停止错误 以下是 edittext 上日期选择器的代码 priv
  • Java:如何实现通用二叉搜索树?

    到目前为止 我一直在编写一个 Node 类 class Node private value private Node left private Node right public int getValue return value pub
  • 带句点和逗号的自定义格式数字

    有点相关这个问题 https stackoverflow com questions 4738853 java decimal format parse to return double value with specified numbe
  • 纹理映射和光照顶点着色器错误 Java OpenGL

    我正在尝试将纹理映射到 3D 立方体并尝试编写着色器以使其具有照明和纹理 我尝试过只编写纹理着色器并且它有效 我还尝试过仅将 3D 值设置为红色的照明着色器 并且该照明着色器也可以工作 但当我尝试将两者结合起来时 我遇到了问题 我在下面提供
  • JShell 如何查找变量或结果的类型

    如何在 JShell 中查找变量或表达式结果的类型 正在尝试 Java 中的按位运算符 jshell gt byte b 5 lt lt 1 Error incompatible types possible lossy conversio
  • 使用java连接到VPN后面的http服务器

    我想通过 VPN 连接到 REST Web 服务 Java 有没有办法在不使用操作系统功能的情况下建立到 VPN 网关的 pptp l2tp ipsec 连接和 HTTP 请求隧道 这很重要 因为我将从 servlet 连接到多个休息服务
  • 将任何文件读取为二进制字符串

    正如标题所示 有什么方法可以读取 Java 或任何其他语言 中给定文件 txt docx exe 等 的二进制表示形式 在java中 我知道如何按原样读取文件的内容 即 String line BufferedReader br new B
  • 客户端和服务器之间的安全连接

    我正在开发一个服务器组件 它将为嵌入式客户端的请求提供服务 这也在我的控制之下 现在一切都是测试版 安全性是这样的 客户端通过 https 发送用户名 密码 服务器返回访问令牌 客户端使用自定义标头中的访问令牌通过 http 发出进一步请求
  • 使用迭代器时无限循环

    Set key1 map keySet Iterator it1 key1 iterator int cnt 0 while it1 hasNext cnt 这段代码导致无限循环的可能性有多大 实际上这会导致无限循环 我怀疑是因为我没有服用
  • 无法声明接口:资源繁忙

    我正在使用 USB4Java 低级版本 并且基本上是根据这段代码工作的here http www mets blog com java usb communication usb4java 我在 Ubuntu 中工作 遇到了有关权限的问题

随机推荐

  • FontAwesome 与 PrimeFaces

    我一直渴望在 Primefaces 中包含 FontAwesome 图标 最后 Optimus 昨天发布了这个伟大的新图标 gt http blog primefaces org p 3004 comment 5422 http blog
  • JavaScript for...in 与 for

    您认为 for in 和 for 循环有很大区别吗 您更喜欢使用哪种 for 为什么 假设我们有一个关联数组的数组 var myArray key value key value1 所以我们可以迭代 for var i 0 i lt myA
  • 如何使用 pdf.js 从客户端设置范围标头?

    我对客户端编程很陌生 我正在尝试使用 pdf js 在我的网站上查看我的 pdf 通过遵循文档中的步骤 我尝试使用 pdf js 加载 pdf 整个 pdf 文件通过单个请求下载 现在 我想做渐进式加载 通过指定范围下载 我在客户端和服务器
  • 对于模板上的非活动用户,user.is_authenticated 始终返回 False

    在我的模板中 login html 我有 if form errors if user is authenticated div class alert alert warning div
  • Jhipster 生成器跳过 --skip-server 处的身份验证代码

    为什么当我们使用 skip server 生成项目时 哟 jhipster skip server 部分身份验证丢失 在 AJS A2 上 是吗 每次我需要粘贴部分代码 Angular 上的 AuthServerProvider 或 Ang
  • UITableView 最后一个单元格被 UITabBarController 隐藏

    我面临一个奇怪的问题 我有一个UITableView在最初的UIViewController of the UITabBarController 起初一切都很好 但是当我更改选项卡并返回到第一个选项卡时 最后一个单元格UITableView
  • Java RSA 加密

    我正在尝试来回编码一个简单的字符串 测试 public static String encode Key publicKey String data throws NoSuchAlgorithmException NoSuchPadding
  • 如何将java项目转换为Maven项目或类似项目

    我目前正在创建一个应用程序 用于一次性编译多个 java 项目以进行编程作业 由于提交 java 项目的方式有很多种 例如 作为 eclipse 项目 作为 netbeans 项目 作为 jar 文件 是否有一个类似的插件 您可以轻松地在项
  • markdown/pandoc 的全站编译? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 With Sphinx doc http sphinx doc org 您可以创建一堆 ReStruct
  • 如何让 Entity Framework 6 + Sqlite + 代码优先工作?

    我正在尝试创建一个简单的项目来探索 Entity Framework 6 Code First 与 sqlite db 提供程序如何工作 但是当我完成我的应用程序时 我收到错误 实体框架提供程序类型 System Data SQLite S
  • 了解 PDFBox 2.0 中字体的加载

    我终于成功地让 PDFBox 打印我的 unicodes 但现在 我想了解我提出的解决方案 下面的代码可以工作并打印一个 到页面 有两件事不起作用 改变PDType0Font load documentMock systemResource
  • 居中时仅在文本的最后一行下划线

    我只想在某些文本的最后一行下划线 当文本换行到更多行时 仍然只有最后一行需要加下划线 我找到了这个解决方案 https stackoverflow com questions 15180827 advanced css challenge
  • 获取函数内的 kwargs

    如果我有一个像这样的 python 函数 def some func arg1 arg2 arg3 1 arg4 2 有没有办法确定哪些参数是从函数内部通过关键字传递的 EDIT 对于那些问我为什么需要这个的人 我没有真正的理由 它是在一次
  • 包含内容的 WPF 新窗口

    我想在现有的主 Windwoe 旁边创建一个带有可滚动文本框的新窗口 我在主窗口中按下 打开新窗口 按钮 然后它应该打开一个带有可滚动文本框的新窗口 inside form2 在 WPF 中 您可以在主窗口中拖放元素 但不能在新窗口中执行此
  • PostgreSQL 中的 Long 数据类型相当于什么?

    我想知道相当于什么LongPostgreSQL 中的数据类型 根据the docs http www postgresql org docs 7 4 interactive datatype html DATATYPE INT看起来像big
  • JSF 2 和发布/重定向/获取?

    如果我错了 请纠正我 但我认为我所有的非 AJAX 提交都应该使用 Post Redirect Get PRG 方式 因为 GET 应该用于刷新 查询数据 就我而言 我能想到的应用程序页面实际上只对数据进行更新 然后刷新页面 所以我认为 P
  • 在 python 中使用 IOT 适配器和 google pub/sub api 将 MQTT 与 GCP 集成

    与 App Engine Standard 中的 Cloud Pub Sub API 集成 我正在标准 Python 环境中开发 Google 应用程序引擎应用程序 对于代码的某些部分 我需要与 Google Cloud pub sub A
  • Richfaces a4j:loadScript 清除 ajax 调用上的 jQuery 插件

    我正在加载嵌入到 RichFaces 中的 jQuery
  • 最新的反应式扩展 (Rx) 教程

    我对反应式扩展非常感兴趣 但我找不到最新的教程 我开始于使用 NET 响应式扩展消除异步忧郁症 http go microsoft com fwlink LinkId 208528但它已经过时了 我可以找出一些改变 但我无法让很多例子发挥作
  • 如何使用 log4j 自定义附加程序在 HDFS 上创建日志?

    Overview 我们希望使用 log4j 记录 Spark 作业活动 并将日志文件写入 HDFS Java 8 Spark 2 4 6 Scala 2 1 2 Hadoop 3 2 1 我们无法找到本地 apache log4j 附加程序