mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-06 12:28:29 +00:00
Update the default logs directory and allow collection from elsewhere. (#4352)
* Replace deprecated URL methods. * Start putting log files in Library/Logs (moving existing files with a migration.) * Make Tracing.deleteLogFiles aware of the legacy logs location. * Allow the logs to be collected from a different directory.
This commit is contained in:
@@ -8623,7 +8623,7 @@
|
|||||||
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
|
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
|
||||||
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)";
|
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.6;
|
MACOSX_DEPLOYMENT_TARGET = 14.6;
|
||||||
MARKETING_VERSION = 25.07.3;
|
MARKETING_VERSION = 25.07.4;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCTION_APP_NAME = Element;
|
PRODUCTION_APP_NAME = Element;
|
||||||
@@ -8699,7 +8699,7 @@
|
|||||||
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
|
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
|
||||||
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)";
|
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.6;
|
MACOSX_DEPLOYMENT_TARGET = 14.6;
|
||||||
MARKETING_VERSION = 25.07.3;
|
MARKETING_VERSION = 25.07.4;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
|||||||
@@ -401,9 +401,14 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
|||||||
}
|
}
|
||||||
|
|
||||||
if oldVersion < Version(1, 6, 7) {
|
if oldVersion < Version(1, 6, 7) {
|
||||||
Tracing.deleteLogFiles()
|
Tracing.deleteLogFiles(in: Tracing.legacyLogsDirectory)
|
||||||
MXLog.info("Migrating to v1.6.7, log files have been wiped")
|
MXLog.info("Migrating to v1.6.7, log files have been wiped")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if oldVersion < Version(25, 7, 4) {
|
||||||
|
Tracing.migrateLogFiles()
|
||||||
|
MXLog.info("Migrating to version 25.07.4, log files have been moved.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This could be removed once the adoption of 25.06.x is widespread.
|
// This could be removed once the adoption of 25.06.x is widespread.
|
||||||
|
|||||||
@@ -23,10 +23,17 @@ extension URL {
|
|||||||
|
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static var appGroupLogsDirectory: URL {
|
||||||
|
appGroupContainerDirectory
|
||||||
|
.appending(component: "Library", directoryHint: .isDirectory)
|
||||||
|
.appending(component: "Logs", directoryHint: .isDirectory)
|
||||||
|
.appending(component: InfoPlistReader.main.baseBundleIdentifier, directoryHint: .isDirectory)
|
||||||
|
}
|
||||||
|
|
||||||
/// The base directory where all session data is stored.
|
/// The base directory where all session data is stored.
|
||||||
static var sessionsBaseDirectory: URL {
|
static var sessionsBaseDirectory: URL {
|
||||||
let applicationSupportSessionsURL = applicationSupportBaseDirectory.appendingPathComponent("Sessions", isDirectory: true)
|
let applicationSupportSessionsURL = applicationSupportBaseDirectory.appending(component: "Sessions", directoryHint: .isDirectory)
|
||||||
|
|
||||||
try? FileManager.default.createDirectoryIfNeeded(at: applicationSupportSessionsURL)
|
try? FileManager.default.createDirectoryIfNeeded(at: applicationSupportSessionsURL)
|
||||||
|
|
||||||
@@ -36,9 +43,9 @@ extension URL {
|
|||||||
/// The base directory where all application support data is stored.
|
/// The base directory where all application support data is stored.
|
||||||
static var applicationSupportBaseDirectory: URL {
|
static var applicationSupportBaseDirectory: URL {
|
||||||
var url = appGroupContainerDirectory
|
var url = appGroupContainerDirectory
|
||||||
.appendingPathComponent("Library", isDirectory: true)
|
.appending(component: "Library", directoryHint: .isDirectory)
|
||||||
.appendingPathComponent("Application Support", isDirectory: true)
|
.appending(component: "Application Support", directoryHint: .isDirectory)
|
||||||
.appendingPathComponent(InfoPlistReader.main.baseBundleIdentifier, isDirectory: true)
|
.appending(component: InfoPlistReader.main.baseBundleIdentifier, directoryHint: .isDirectory)
|
||||||
|
|
||||||
try? FileManager.default.createDirectoryIfNeeded(at: url)
|
try? FileManager.default.createDirectoryIfNeeded(at: url)
|
||||||
|
|
||||||
@@ -56,10 +63,10 @@ extension URL {
|
|||||||
/// The base directory where all application support data is stored.
|
/// The base directory where all application support data is stored.
|
||||||
static var sessionCachesBaseDirectory: URL {
|
static var sessionCachesBaseDirectory: URL {
|
||||||
let url = appGroupContainerDirectory
|
let url = appGroupContainerDirectory
|
||||||
.appendingPathComponent("Library", isDirectory: true)
|
.appending(component: "Library", directoryHint: .isDirectory)
|
||||||
.appendingPathComponent("Caches", isDirectory: true)
|
.appending(component: "Caches", directoryHint: .isDirectory)
|
||||||
.appendingPathComponent(InfoPlistReader.main.baseBundleIdentifier, isDirectory: true)
|
.appending(component: InfoPlistReader.main.baseBundleIdentifier, directoryHint: .isDirectory)
|
||||||
.appendingPathComponent("Sessions", isDirectory: true)
|
.appending(component: "Sessions", directoryHint: .isDirectory)
|
||||||
|
|
||||||
try? FileManager.default.createDirectoryIfNeeded(at: url)
|
try? FileManager.default.createDirectoryIfNeeded(at: url)
|
||||||
|
|
||||||
@@ -75,7 +82,7 @@ extension URL {
|
|||||||
/// Make sure to manually tidy up any files you place in here once you've transferred them from one bundle to another.
|
/// Make sure to manually tidy up any files you place in here once you've transferred them from one bundle to another.
|
||||||
static var appGroupTemporaryDirectory: URL {
|
static var appGroupTemporaryDirectory: URL {
|
||||||
let url = appGroupContainerDirectory
|
let url = appGroupContainerDirectory
|
||||||
.appendingPathComponent("tmp", isDirectory: true)
|
.appending(component: "tmp", directoryHint: .isDirectory)
|
||||||
|
|
||||||
try? FileManager.default.createDirectoryIfNeeded(at: url)
|
try? FileManager.default.createDirectoryIfNeeded(at: url)
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,16 @@ enum Tracing {
|
|||||||
if ProcessInfo.isRunningIntegrationTests {
|
if ProcessInfo.isRunningIntegrationTests {
|
||||||
"/Users/Shared"
|
"/Users/Shared"
|
||||||
} else {
|
} else {
|
||||||
.appGroupContainerDirectory
|
logsDirectoryOverride ?? .appGroupLogsDirectory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set this to temporarily override the directory from which logs will be collected.
|
||||||
|
/// This basically only affects ``logFiles``, and doesn't inform the SDK to write
|
||||||
|
/// the logs to a different directory, which should be done before setting this.
|
||||||
|
static var logsDirectoryOverride: URL?
|
||||||
|
static var legacyLogsDirectory: URL { .appGroupContainerDirectory }
|
||||||
|
|
||||||
static let fileExtension = "log"
|
static let fileExtension = "log"
|
||||||
|
|
||||||
static func buildConfiguration(logLevel: LogLevel, traceLogPacks: Set<TraceLogPack>,
|
static func buildConfiguration(logLevel: LogLevel, traceLogPacks: Set<TraceLogPack>,
|
||||||
@@ -52,13 +58,17 @@ enum Tracing {
|
|||||||
sentryDsn: sentryURL?.absoluteString)
|
sentryDsn: sentryURL?.absoluteString)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A list of all log file URLs, sorted chronologically. This is only public for testing purposes, within
|
/// A list of all log file URLs, sorted chronologically.
|
||||||
/// the app please use ``copyLogs(to:)`` so that the files are name appropriates for QuickLook.
|
static var logFiles: [URL] { logFiles(in: logsDirectory) }
|
||||||
static var logFiles: [URL] {
|
|
||||||
|
/// Collect all of the logs in the given directory, sorting them chronologically.
|
||||||
|
private static func logFiles(in directory: URL) -> [URL] {
|
||||||
var logFiles = [(url: URL, modificationDate: Date)]()
|
var logFiles = [(url: URL, modificationDate: Date)]()
|
||||||
|
|
||||||
let fileManager = FileManager.default
|
let fileManager = FileManager.default
|
||||||
let enumerator = fileManager.enumerator(at: logsDirectory, includingPropertiesForKeys: [.contentModificationDateKey])
|
let enumerator = fileManager.enumerator(at: directory,
|
||||||
|
includingPropertiesForKeys: [.contentModificationDateKey],
|
||||||
|
options: .skipsSubdirectoryDescendants)
|
||||||
|
|
||||||
// Find all *.log files and their modification dates.
|
// Find all *.log files and their modification dates.
|
||||||
while let logURL = enumerator?.nextObject() as? URL {
|
while let logURL = enumerator?.nextObject() as? URL {
|
||||||
@@ -78,10 +88,38 @@ enum Tracing {
|
|||||||
return sortedFiles
|
return sortedFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete all log files.
|
static func migrateLogFiles() {
|
||||||
static func deleteLogFiles() {
|
MXLog.info("Moving log files to \(logsDirectory)")
|
||||||
let fileManager = FileManager.default
|
let fileManager = FileManager.default
|
||||||
for logFileURL in logFiles {
|
let oldLogFiles = logFiles(in: legacyLogsDirectory)
|
||||||
|
|
||||||
|
for oldFileURL in oldLogFiles {
|
||||||
|
do {
|
||||||
|
let newFileURL = logsDirectory.appending(component: oldFileURL.lastPathComponent)
|
||||||
|
try fileManager.moveItem(at: oldFileURL, to: newFileURL)
|
||||||
|
MXLog.info("Moved \(newFileURL.lastPathComponent)")
|
||||||
|
} catch {
|
||||||
|
MXLog.error("Failed to move \(oldFileURL.lastPathComponent): \(error.localizedDescription)")
|
||||||
|
|
||||||
|
let nsError = error as NSError
|
||||||
|
if nsError.domain == NSCocoaErrorDomain, nsError.code == NSFileWriteFileExistsError {
|
||||||
|
// By now there will already be some logs in the new directory, so there is likely to be
|
||||||
|
// one log file that cannot be removed. As this is a one-off operation lets just delete it.
|
||||||
|
MXLog.error("Attempting to delete log file \(oldFileURL.lastPathComponent)")
|
||||||
|
try? fileManager.removeItem(at: oldFileURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete all log files.
|
||||||
|
static func deleteLogFiles(in directory: URL) {
|
||||||
|
let fileManager = FileManager.default
|
||||||
|
|
||||||
|
// We don't simply delete logsDirectory as once upon a time the logs
|
||||||
|
// we written to the very top-level of the app group container and
|
||||||
|
// there's a migration in place for old users of the app.
|
||||||
|
for logFileURL in logFiles(in: directory) {
|
||||||
try? fileManager.removeItem(at: logFileURL)
|
try? fileManager.removeItem(at: logFileURL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
Submodule Enterprise updated: 6db7fe89bd...7761fe61ca
@@ -17,7 +17,7 @@ class LoggingTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func setUpWithError() throws {
|
override func setUpWithError() throws {
|
||||||
Tracing.deleteLogFiles()
|
Tracing.deleteLogFiles(in: Tracing.logsDirectory)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLogging() async throws {
|
func testLogging() async throws {
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ settings:
|
|||||||
ENABLE_BITCODE: false
|
ENABLE_BITCODE: false
|
||||||
APP_NAME: ElementX
|
APP_NAME: ElementX
|
||||||
KEYCHAIN_ACCESS_GROUP_IDENTIFIER: "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)"
|
KEYCHAIN_ACCESS_GROUP_IDENTIFIER: "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)"
|
||||||
MARKETING_VERSION: 25.07.3
|
MARKETING_VERSION: 25.07.4
|
||||||
CURRENT_PROJECT_VERSION: 1
|
CURRENT_PROJECT_VERSION: 1
|
||||||
SUPPORTS_MACCATALYST: false
|
SUPPORTS_MACCATALYST: false
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user