Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Backtrace.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ Pod::Spec.new do |s|
s.osx.public_header_files = ["Backtrace-macOS/**/*.h*"]
s.tvos.public_header_files = ["Backtrace-tvOS/**/*.h*"]

s.ios.dependency "Cassette", '1.0.0-beta5'
Copy link
Contributor

@vlussenburg vlussenburg May 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if there's any superfluous #if os(iOS) || os(OSX) left in prod/test code. I know there were a bunch of 'm

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take a look :)

s.osx.dependency "Cassette", '1.0.0-beta5'
s.dependency "Backtrace-PLCrashReporter", '1.5.3'

s.resources = 'Sources/**/*.xcdatamodeld'
Expand Down
436 changes: 223 additions & 213 deletions Backtrace.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ end

def shared_ios_mac_pods
shared_pods
pod 'Cassette', '1.0.0-beta5'
end

def shared_test_ios_mac_pods
Expand Down
13 changes: 4 additions & 9 deletions Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
PODS:
- Backtrace (1.7.4-beta2):
- Backtrace (1.7.5):
- Backtrace-PLCrashReporter (= 1.5.3)
- Cassette (= 1.0.0-beta5)
- Backtrace-PLCrashReporter (1.5.3)
- Cassette (1.0.0-beta5)
- Nimble (10.0.0)
- Quick (5.0.1)

DEPENDENCIES:
- Backtrace (from `./Backtrace.podspec`)
- Backtrace-PLCrashReporter (= 1.5.3)
- Cassette (= 1.0.0-beta5)
- Nimble (~> 10.0.0)
- Quick (~> 5.0.1)

SPEC REPOS:
trunk:
- Backtrace-PLCrashReporter
- Cassette
- Nimble
- Quick

Expand All @@ -26,12 +22,11 @@ EXTERNAL SOURCES:
:path: "./Backtrace.podspec"

SPEC CHECKSUMS:
Backtrace: c0124ca7e1a84bc7a3b3407671fb99a90be474e9
Backtrace: 1b471570061cb4740b42663aaf3e381177a317ce
Backtrace-PLCrashReporter: 71ddeba11834d2bcc3c19f357aaec7bf87131f89
Cassette: 074c6991391733888990dba728b7ffe00299a0a6
Nimble: 5316ef81a170ce87baf72dd961f22f89a602ff84
Quick: 749aa754fd1e7d984f2000fe051e18a3a9809179

PODFILE CHECKSUM: 2045466adc5eebf2fa4652c2a2c73ec6a81b89b3
PODFILE CHECKSUM: ec560ea7bd4dba9a68a30ffbb0b25db5e3491921

COCOAPODS: 1.11.3
COCOAPODS: 1.12.1
119 changes: 119 additions & 0 deletions Sources/Features/Breadcrumb/BacktraceBreadcrumbFile.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import Foundation

enum BacktraceBreadcrumbFileError: Error {
case invalidFormat
}

@objc class BacktraceBreadcrumbFile: NSObject {

private static let minimumQueueFileSizeBytes = 4096
private let maximumIndividualBreadcrumbSize: Int
private let maxQueueFileSizeBytes: Int
private let queue: Queue<Any>
private let breadcrumbLogURL: URL
private let dispatchQueue = DispatchQueue(label: "io.backtrace.BacktraceBreadcrumbFile@\(UUID().uuidString)")

public init(_ breadcrumbSettings: BacktraceBreadcrumbSettings) throws {
self.breadcrumbLogURL = try breadcrumbSettings.getBreadcrumbLogPath()
self.queue = Queue<Any>()
self.maximumIndividualBreadcrumbSize = breadcrumbSettings.maxIndividualBreadcrumbSizeBytes
if breadcrumbSettings.maxQueueFileSizeBytes < BacktraceBreadcrumbFile.minimumQueueFileSizeBytes {
BacktraceLogger.warning("\(breadcrumbSettings.maxQueueFileSizeBytes) is smaller than the minimum of " +
"\(BacktraceBreadcrumbFile.minimumQueueFileSizeBytes)" +
", ignoring value and overriding with minimum.")
self.maxQueueFileSizeBytes = BacktraceBreadcrumbFile.minimumQueueFileSizeBytes
} else {
self.maxQueueFileSizeBytes = breadcrumbSettings.maxQueueFileSizeBytes
}

super.init()
}

func addBreadcrumb(_ breadcrumb: [String: Any]) -> Bool {
do {
// Serialize breadcrumb: [String: Any] into Data
let breadcrumbJsonData = try JSONSerialization.data(withJSONObject: breadcrumb)
// Serialize Data into a JSON string
guard let breadcrumbJsonString = String(data: breadcrumbJsonData, encoding: .utf8) else {
BacktraceLogger.warning("Error when converting breadcrumb to string")
return false
}
// Calculate the size of the breadcrumb and add it to queue
let breadcrumbSize = breadcrumbJsonData.count
// Check if breadcrumb size is larger than the maximum specified
if breadcrumbSize > maximumIndividualBreadcrumbSize {
BacktraceLogger.warning(
"Discarding breadcrumb that was larger than the maximum specified (\(maximumIndividualBreadcrumbSize).")
return false
}
// Store breadcrumb Json String and size in Dictionary [String : Any]
let queueBreadcrumb = ["breadcrumbJson": breadcrumbJsonString, "size": breadcrumbSize] as [String : Any]
// Queue breacrumb
queue.enqueue(queueBreadcrumb)
// Iterate over the queue from newest to oldest breadcrumb and build an array of encoded strings
_ = dispatchQueue.sync {
let queuedBreadcrumbs = queue.allElements()
var breadcrumbsArray = [String]()
var size = 0
for index in (0..<queue.count).reversed() {
guard let queueBreadcrumb = queuedBreadcrumbs[index] as? [String: Any] else {
BacktraceLogger.warning("Error when fetching breacrumbs from queue")
return false
}
guard let breadcrumbSize = queueBreadcrumb["size"] as? Int else {
BacktraceLogger.warning("Error when adding breadcrumbSize to array")
return false
}
// Pop last element if size is greater than maxQueueFileSizeBytes
if size + breadcrumbSize > maxQueueFileSizeBytes && !queue.isEmpty {
while (index != 0) {
_ = queue.pop(at: index)
}
} else {
guard let breadcrumbJsonData = queueBreadcrumb["breadcrumbJson"] as? String else {
BacktraceLogger.warning("Error when adding breadcrumbJson to array")
return false
}
breadcrumbsArray.append(breadcrumbJsonData)
size += breadcrumbSize
}
}
// Write breadcrumbs to file
let breadcrumbString = "[\(breadcrumbsArray.joined(separator: ","))]"
writeBreadcrumbToLogFile(breadcrumb: breadcrumbString, at: self.breadcrumbLogURL)
return true
}
} catch {
BacktraceLogger.warning("Error when adding breadcrumb to file: \(error)")
return false
}
return true
}

func clear() -> Bool {
dispatchQueue.sync {
queue.clear()
clearBreadcrumbLogFile(at:self.breadcrumbLogURL)
}
return true
}
}

extension BacktraceBreadcrumbFile {

func writeBreadcrumbToLogFile(breadcrumb: String, at breadcrumbLogURL: URL) {
do {
try breadcrumb.write(to: breadcrumbLogURL, atomically: true, encoding: .utf8)
} catch {
BacktraceLogger.warning("Error writing breadcrumb to log file at: \(breadcrumbLogURL) - \(error.localizedDescription)")
}
}

func clearBreadcrumbLogFile(at breadcrumbLogURL: URL) {
do {
try "".write(to: breadcrumbLogURL, atomically: false, encoding: .utf8)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if someone deletes a file when you're generating breadcrumbs?

} catch {
BacktraceLogger.warning("Error clearing breadcrumb log file at: \(breadcrumbLogURL) - \(error.localizedDescription)")
}
}
}
113 changes: 0 additions & 113 deletions Sources/Features/Breadcrumb/BacktraceBreadcrumbFileHelper.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import Foundation
@objc class BacktraceBreadcrumbsLogManager: NSObject {

private var breadcrumbId: Int
private let backtraceBreadcrumbFileHelper: BacktraceBreadcrumbFileHelper
private let backtraceBreadcrumbFile: BacktraceBreadcrumbFile

init(breadcrumbSettings: BacktraceBreadcrumbSettings) throws {
self.backtraceBreadcrumbFileHelper = try BacktraceBreadcrumbFileHelper(breadcrumbSettings)
self.backtraceBreadcrumbFile = try BacktraceBreadcrumbFile(breadcrumbSettings)

self.breadcrumbId = Date().millisecondsSince1970
BreadcrumbsInfo.currentBreadcrumbsId = breadcrumbId
Expand All @@ -29,11 +29,11 @@ import Foundation
"message": message]
breadcrumb["attributes"] = attributes

return backtraceBreadcrumbFileHelper.addBreadcrumb(breadcrumb)
return backtraceBreadcrumbFile.addBreadcrumb(breadcrumb)
}

func clear() -> Bool {
let result = backtraceBreadcrumbFileHelper.clear()
let result = backtraceBreadcrumbFile.clear()
if result {
breadcrumbId = Date().millisecondsSince1970
BreadcrumbsInfo.currentBreadcrumbsId = breadcrumbId
Expand Down
59 changes: 59 additions & 0 deletions Sources/Features/Breadcrumb/QueueFile.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Foundation
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it QueueFile? I believe its a generic queue instead. Can we rename the file to Queue or something like that?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Queue it is!


@objcMembers
public class Queue<T>: NSObject {
private var elements: [T] = []

func enqueue(_ element: T) {
elements.append(element)
}

func dequeue() -> T? {
if elements.isEmpty {
return nil
} else {
return elements.removeFirst()
}
}

func peek() -> T? {
return elements.first
}

func remove(at index: Int) -> T? {
guard index < elements.count else {
return nil
}
return elements.remove(at: index)
}

func pop(at index: Int) -> T? {
guard !elements.isEmpty else {
return nil
}
return remove(at: index)
}

func pop() -> T? {
guard !elements.isEmpty else {
return nil
}
return elements.popLast()
}

public func allElements() -> [T] {
return elements
}

func clear() {
elements.removeAll()
}

var isEmpty: Bool {
return elements.isEmpty
}

var count: Int {
return elements.count
}
}
Loading