-
Notifications
You must be signed in to change notification settings - Fork 29.1k
[SPARK-56234][CORE] Support disabling log directory scanning by path pattern in SHS #55029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -109,6 +109,20 @@ private[history] class FsHistoryProvider(conf: SparkConf, clock: Clock) | |
| private val logDirs = conf.get(History.HISTORY_LOG_DIR) | ||
| .split(",").map(_.trim).filter(_.nonEmpty).toSeq | ||
|
|
||
| private val scanDisabledPathPatterns = conf.get(History.SCAN_DISABLED_PATH_PATTERNS) | ||
| .map(_.r) | ||
|
|
||
| /** Check if scanning is disabled for a directory by matching its path against patterns. */ | ||
| private def isScanDisabled(dir: String): Boolean = { | ||
| if (scanDisabledPathPatterns.isEmpty) return false | ||
| val qualifiedPath = { | ||
| val path = new Path(dir) | ||
| val dirFs = logDirFs(dir) | ||
| path.makeQualified(dirFs.getUri, dirFs.getWorkingDirectory).toString | ||
| } | ||
| scanDisabledPathPatterns.exists(_.pattern.matcher(qualifiedPath).matches()) | ||
| } | ||
|
|
||
| private val historyUiAclsEnable = conf.get(History.HISTORY_SERVER_UI_ACLS_ENABLE) | ||
| private val historyUiAdminAcls = conf.get(History.HISTORY_SERVER_UI_ADMIN_ACLS) | ||
| private val historyUiAdminAclsGroups = conf.get(History.HISTORY_SERVER_UI_ADMIN_ACLS_GROUPS) | ||
|
|
@@ -454,16 +468,35 @@ private[history] class FsHistoryProvider(conf: SparkConf, clock: Clock) | |
|
|
||
| private def loadFromFallbackLocation(appId: String, attemptId: Option[String], logPath: String) | ||
| : ApplicationInfoWrapper = { | ||
| val date = new Date(0) | ||
| val lastUpdate = new Date() | ||
| val (logSourceName, logSourceFullPath) = getLogDirInfo(logPath) | ||
| val info = ApplicationAttemptInfo( | ||
| attemptId, date, date, lastUpdate, 0, "spark", false, "unknown", | ||
| Some(logSourceName), Some(logSourceFullPath)) | ||
| addListing(new ApplicationInfoWrapper( | ||
| ApplicationInfo(appId, appId, None, None, None, None, List.empty), | ||
| List(new AttemptInfoWrapper(info, logPath, 0, Some(1), None, None, None, None, | ||
| logSourceName, logSourceFullPath)))) | ||
| // Resolve the full path to find which directory actually contains this log. | ||
| // logPath is a relative name (e.g., "eventlog_v2_app1"), so we look up | ||
| // all directories to find the correct one. | ||
| val (dirFs, fullPath) = resolveLogPath(logPath, "") | ||
| val dir = logDirForPath(fullPath) | ||
|
|
||
| if (isScanDisabled(dir)) { | ||
| // For scan-disabled directories, run mergeApplicationListing to populate accurate | ||
| // metadata since periodic scanning will never update the dummy entry. | ||
| try { | ||
| EventLogFileReader(dirFs, dirFs.getFileStatus(fullPath)).foreach { reader => | ||
| mergeApplicationListing(reader, clock.getTimeMillis(), enableOptimizations = true) | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this enough to load a single Spark job history correctly? If then, can we remove
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
| } catch { | ||
| case _: FileNotFoundException => | ||
| throw new NoSuchElementException(s"Log not found for appId: $appId") | ||
| } | ||
| } else { | ||
| val date = new Date(0) | ||
| val lastUpdate = new Date() | ||
| val (logSourceName, logSourceFullPath) = getLogDirInfo(logPath) | ||
| val info = ApplicationAttemptInfo( | ||
| attemptId, date, date, lastUpdate, 0, "spark", false, "unknown", | ||
| Some(logSourceName), Some(logSourceFullPath)) | ||
| addListing(new ApplicationInfoWrapper( | ||
| ApplicationInfo(appId, appId, None, None, None, None, List.empty), | ||
| List(new AttemptInfoWrapper(info, logPath, 0, Some(1), None, None, None, None, | ||
| logSourceName, logSourceFullPath)))) | ||
| } | ||
| load(appId) | ||
| } | ||
|
|
||
|
|
@@ -561,10 +594,17 @@ private[history] class FsHistoryProvider(conf: SparkConf, clock: Clock) | |
| private[history] def checkForLogs(): Unit = { | ||
| val newLastScanTime = clock.getTimeMillis() | ||
| val allNotStale = mutable.HashSet[String]() | ||
| val skippedDirs = mutable.ArrayBuffer[String]() | ||
|
|
||
| logDirs.foreach { dir => | ||
| try { | ||
| checkForLogsInDir(dir, newLastScanTime, allNotStale) | ||
| if (isScanDisabled(dir)) { | ||
| logDebug(log"Skipping scan for directory ${MDC(HISTORY_DIR, dir)}" + | ||
| log" (scan disabled for this directory)") | ||
| skippedDirs += dir | ||
| } else { | ||
| checkForLogsInDir(dir, newLastScanTime, allNotStale) | ||
| } | ||
| } catch { | ||
| case e: IOException => | ||
| logError(log"Error checking for logs in directory ${MDC(HISTORY_DIR, dir)}", e) | ||
|
|
@@ -574,13 +614,17 @@ private[history] class FsHistoryProvider(conf: SparkConf, clock: Clock) | |
| // Delete all information about applications whose log files disappeared from storage. | ||
| // This is done after scanning ALL directories to avoid incorrectly marking entries from | ||
| // other directories as stale. | ||
| // Entries from scan-disabled directories are excluded from stale detection because | ||
| // they are never scanned and their lastProcessed time is never updated. | ||
| val stale = listing.synchronized { | ||
| KVUtils.viewToSeq(listing.view(classOf[LogInfo]) | ||
| .index("lastProcessed") | ||
| .last(newLastScanTime - 1)) | ||
| } | ||
| stale.filterNot(isProcessing) | ||
| .filterNot(info => allNotStale.contains(info.logPath)) | ||
| .filterNot(info => skippedDirs.exists(dir => | ||
| logDirForPath(new Path(info.logPath)) == dir)) | ||
| .foreach { log => | ||
| log.appId.foreach { appId => | ||
| cleanAppData(appId, log.attemptId, log.logPath) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds misleading because this PR title is
Support disabling log directory scanning .... Could you revise the comment?