Skip to content

Commit 1f67215

Browse files
committed
Fix parsing failing due to new TaskBacktrace activity log attachment
Signed-off-by: fortmarek <marekfort@me.com>
1 parent 5facacc commit 1f67215

File tree

4 files changed

+94
-10
lines changed

4 files changed

+94
-10
lines changed

Sources/XCLogParser/activityparser/ActivityParser.swift

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -380,12 +380,27 @@ public class ActivityParser {
380380
}
381381

382382
if className == "IDEFoundation.\(String(describing: IDEActivityLogSectionAttachment.self))" {
383-
let jsonType = IDEActivityLogSectionAttachment.BuildOperationTaskMetrics.self
384-
return try IDEActivityLogSectionAttachment(identifier: try parseAsString(token: iterator.next()),
385-
majorVersion: try parseAsInt(token: iterator.next()),
386-
minorVersion: try parseAsInt(token: iterator.next()),
387-
metrics: try parseAsJson(token: iterator.next(),
388-
type: jsonType))
383+
let identifier = try parseAsString(token: iterator.next())
384+
switch identifier.components(separatedBy: "ActivityLogSectionAttachment.").last {
385+
case .some("TaskMetrics"):
386+
let jsonType = IDEActivityLogSectionAttachment.BuildOperationTaskMetrics.self
387+
return try IDEActivityLogSectionAttachment(identifier: identifier,
388+
majorVersion: try parseAsInt(token: iterator.next()),
389+
minorVersion: try parseAsInt(token: iterator.next()),
390+
metrics: try parseAsJson(token: iterator.next(),
391+
type: jsonType),
392+
backtraces: [])
393+
case .some("TaskBacktrace"):
394+
let jsonType = [IDEActivityLogSectionAttachment.BuildOperationTaskBacktrace].self
395+
return try IDEActivityLogSectionAttachment(identifier: identifier,
396+
majorVersion: try parseAsInt(token: iterator.next()),
397+
minorVersion: try parseAsInt(token: iterator.next()),
398+
metrics: nil,
399+
backtraces: try parseAsJson(token: iterator.next(),
400+
type: jsonType) ?? [])
401+
default:
402+
throw XCLogParserError.parseError("Unexpected attachment identifier \(identifier)")
403+
}
389404
}
390405
throw XCLogParserError.parseError("Unexpected className found parsing IDEConsoleItem \(className)")
391406
}

Sources/XCLogParser/activityparser/IDEActivityModel.swift

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,16 +658,77 @@ public class IDEActivityLogSectionAttachment: Encodable {
658658
public let majorVersion: UInt64
659659
public let minorVersion: UInt64
660660
public let metrics: BuildOperationTaskMetrics?
661+
public let backtraces: [BuildOperationTaskBacktrace]
661662

662663
public init(
663664
identifier: String,
664665
majorVersion: UInt64,
665666
minorVersion: UInt64,
666-
metrics: BuildOperationTaskMetrics?
667+
metrics: BuildOperationTaskMetrics?,
668+
backtraces: [BuildOperationTaskBacktrace]
667669
) throws {
668670
self.identifier = identifier
669671
self.majorVersion = majorVersion
670672
self.minorVersion = minorVersion
671673
self.metrics = metrics
674+
self.backtraces = backtraces
675+
}
676+
677+
public struct BuildOperationTaskBacktrace: Codable {
678+
public let category: BuildOperationTaskBacktraceCategory
679+
public let description: String
680+
}
681+
682+
public enum BuildOperationTaskBacktraceCategory: String, Codable {
683+
case ruleHadInvalidValue
684+
case ruleSignatureChanged
685+
case ruleNeverBuilt
686+
case ruleInputRebuilt
687+
688+
public init(from decoder: Decoder) throws {
689+
let container = try decoder.container(keyedBy: BuildOperationTaskBacktraceCategoryCodingKeys.self)
690+
691+
if container.contains(.ruleHadInvalidValue) {
692+
self = .ruleHadInvalidValue
693+
} else if container.contains(.ruleSignatureChanged) {
694+
self = .ruleSignatureChanged
695+
} else if container.contains(.ruleNeverBuilt) {
696+
self = .ruleNeverBuilt
697+
} else if container.contains(.ruleInputRebuilt) {
698+
self = .ruleInputRebuilt
699+
} else {
700+
throw DecodingError.dataCorrupted(
701+
DecodingError.Context(
702+
codingPath: decoder.codingPath,
703+
debugDescription: "Unknown task backtrace category"
704+
)
705+
)
706+
}
707+
}
708+
709+
public func encode(to encoder: Encoder) throws {
710+
var container = encoder.container(keyedBy: BuildOperationTaskBacktraceCategoryCodingKeys.self)
711+
switch self {
712+
case .ruleHadInvalidValue:
713+
try container.encode(EmptyObject(), forKey: .ruleHadInvalidValue)
714+
case .ruleSignatureChanged:
715+
try container.encode(EmptyObject(), forKey: .ruleSignatureChanged)
716+
case .ruleNeverBuilt:
717+
try container.encode(EmptyObject(), forKey: .ruleNeverBuilt)
718+
case .ruleInputRebuilt:
719+
try container.encode(EmptyObject(), forKey: .ruleInputRebuilt)
720+
}
721+
}
722+
}
723+
724+
private enum BuildOperationTaskBacktraceCategoryCodingKeys: String, CodingKey {
725+
case ruleHadInvalidValue
726+
case ruleSignatureChanged
727+
case ruleNeverBuilt
728+
case ruleInputRebuilt
729+
}
730+
731+
private struct EmptyObject: Codable {
732+
// Empty struct for objects with no properties
672733
}
673734
}

Sources/XCLogParser/logmanifest/LogManifest.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public struct LogManifest {
2525

2626
public init() {}
2727

28-
public func getWithLogOptions(_ logOptions: LogOptions) throws -> [LogManifestEntry] {
28+
public func getWithLogOptions(_ logOptions: LogOptions) throws -> [LogManifestEntry] {
2929
let logFinder = LogFinder()
3030
let logManifestURL = try logFinder.findLogManifestWithLogOptions(logOptions)
3131
let logManifestDictionary = try getDictionaryFromURL(logManifestURL)

Tests/XCLogParserTests/ActivityParserTests.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,13 @@ class ActivityParserTests: XCTestCase {
9797
Token.string("501796C4-6BE4-4F80-9F9D-3269617ECC17"),
9898
Token.string("localizedResultString"),
9999
Token.string("xcbuildSignature"),
100-
Token.list(1),
100+
Token.list(2),
101+
Token.classNameRef("IDEFoundation.IDEActivityLogSectionAttachment"),
102+
Token.string("com.apple.dt.ActivityLogSectionAttachment.TaskBacktrace"),
103+
Token.int(1),
104+
Token.int(0),
105+
// swiftlint:disable:next line_length
106+
Token.json(#"[{"description":"'Planning Swift module ConcurrencyExtras (arm64)' had never run","category":{"ruleNeverBuilt":{}},"identifier":{"storage":{"task":{"_0":[0,80,50,58,116,97,114,103,101,116,45,67,111,110,99,117,114,114,101,110,99,121,69,120,116,114,97,115,45,101,102,52,50,51,48,52,53,57,52,98,102,56,53,50,102,52,51,56,101,102,55,99,51,97,49,51,54,98,50,99,57,48,100,102,56,55,49,56,97,102,50,98,57,100,51,97,97,99,48,100,48,100,99,97,50,50,98,52,99,50,57,99,50,45,58,66,101,116,97,32,68,101,98,117,103,58,51,99,57,97,99,57,53,50,98,52,99,56,49,100,57,99,99,49,55,100,49,97,102,52,55,49,97,48,52,53,101,56]}}},"frameKind":{"genericTask":{}}}]"#),
101107
Token.classNameRef("IDEFoundation.IDEActivityLogSectionAttachment"),
102108
Token.string("com.apple.dt.ActivityLogSectionAttachment.TaskMetrics"),
103109
Token.int(1),
@@ -339,7 +345,9 @@ class ActivityParserTests: XCTestCase {
339345
XCTAssertEqual("501796C4-6BE4-4F80-9F9D-3269617ECC17", logSection.uniqueIdentifier)
340346
XCTAssertEqual("localizedResultString", logSection.localizedResultString)
341347
XCTAssertEqual("xcbuildSignature", logSection.xcbuildSignature)
342-
XCTAssertEqual(1, logSection.attachments.count)
348+
XCTAssertEqual(2, logSection.attachments.count)
349+
XCTAssertEqual(logSection.attachments[0].backtraces[0].category, .ruleNeverBuilt)
350+
XCTAssertEqual(logSection.attachments[1].metrics?.wcDuration, 1)
343351
XCTAssertEqual(0, logSection.unknown)
344352
}
345353

0 commit comments

Comments
 (0)