diff --git a/Package.swift b/Package.swift index 789c788..82295dd 100644 --- a/Package.swift +++ b/Package.swift @@ -12,7 +12,8 @@ let package = Package( targets: [ .target( name: "TimeIt", - dependencies: []), + dependencies: [], + resources: [.copy("TimeIt.docc")]), .testTarget( name: "TimeItTests", dependencies: ["TimeIt"]), diff --git a/README.md b/README.md index 837ba27..41d5257 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,56 @@ # TimeIt -Debugging Tool to investigate code execution coordination, sequencing and timing. +A debugging tool for investigating code execution coordination, sequencing, and timing. + +## Overview + +TimeIt is a lightweight debugging utility that helps you track timing information and execution order in your Swift code. It provides a simple API to log events with automatic timestamps and compute time intervals between operations. + +## Usage + +```swift +import TimeIt + +// Log events with timestamps +TimeIt.log("myOperation", entry: "Started processing") +// ... do some work ... +TimeIt.log("myOperation", entry: "Finished step 1") +// ... do more work ... +TimeIt.log("myOperation", entry: "Completed") + +// Retrieve formatted logs with timing information +TimeIt.complete(log: "myOperation") { logs in + logs.forEach { print($0) } + // Output: [myOperation] 14:23:45.1234 0.0000secs Started processing + // [myOperation] 14:23:45.2234 0.1000secs Finished step 1 + // [myOperation] 14:23:45.3234 0.2000secs Completed +} +``` + +## Documentation + +Full API documentation is available as DocC documentation. To generate and view the documentation: + +```bash +swift package generate-documentation +``` + +Or explore the inline documentation in Xcode by Option-clicking on any TimeIt method. + +## Installation + +Add TimeIt as a dependency in your `Package.swift`: + +```swift +dependencies: [ + .package(url: "https://github.com/mikelrob/TimeIt.git", from: "1.0.0") +] +``` + +## Features + +- **Simple API**: Just two static methods to log events and retrieve results +- **Thread-Safe**: All operations use a serial dispatch queue for thread safety +- **Time Tracking**: Automatically captures timestamps and computes intervals +- **Organized Logs**: Group related events using named logs + diff --git a/Sources/TimeIt/TimeIt.docc/TimeIt.md b/Sources/TimeIt/TimeIt.docc/TimeIt.md new file mode 100644 index 0000000..37cdc1a --- /dev/null +++ b/Sources/TimeIt/TimeIt.docc/TimeIt.md @@ -0,0 +1,55 @@ +# ``TimeIt`` + +A debugging tool for investigating code execution coordination, sequencing, and timing. + +## Overview + +TimeIt is a lightweight debugging utility that helps you track timing information and execution order in your Swift code. It provides a simple API to log events with automatic timestamps and compute time intervals between operations. + +### Key Features + +- **Simple API**: Just two static methods to log events and retrieve results +- **Thread-Safe**: All operations use a serial dispatch queue for thread safety +- **Time Tracking**: Automatically captures timestamps and computes intervals +- **Organized Logs**: Group related events using named logs + +### Usage Example + +Here's a simple example of using TimeIt to track the execution of an async operation: + +```swift +import TimeIt + +// Start tracking events +TimeIt.log("networkRequest", entry: "Request started") + +// ... perform network request ... +TimeIt.log("networkRequest", entry: "Response received") + +// ... process response ... +TimeIt.log("networkRequest", entry: "Processing complete") + +// Retrieve formatted logs with timing information +TimeIt.complete(log: "networkRequest") { logs in + for log in logs { + print(log) + // Output format: [networkRequest] 14:23:45.1234 0.1234secs Request started + } +} +``` + +### When to Use TimeIt + +TimeIt is particularly useful for: + +- Debugging asynchronous code execution order +- Measuring performance of different code paths +- Understanding timing dependencies in complex operations +- Investigating race conditions and timing-related bugs + +## Topics + +### Logging and Completion + +- ``TimeIt/log(_:entry:)`` +- ``TimeIt/complete(log:completion:)`` diff --git a/Sources/TimeIt/TimeIt.swift b/Sources/TimeIt/TimeIt.swift index 3a581a0..e98dcce 100644 --- a/Sources/TimeIt/TimeIt.swift +++ b/Sources/TimeIt/TimeIt.swift @@ -1,6 +1,37 @@ import Foundation +/// A debugging tool for investigating code execution coordination, sequencing, and timing. +/// +/// `TimeIt` helps you track timing information and execution order in your code by +/// logging entries with timestamps and computing time intervals between events. +/// +/// ## Overview +/// +/// Use `TimeIt` to create named logs that capture execution events with timestamps. +/// When you're done logging, call ``complete(log:completion:)`` to retrieve +/// formatted log entries showing time intervals from the start. +/// +/// ## Usage +/// +/// ```swift +/// // Log some events +/// TimeIt.log("myOperation", entry: "Started processing") +/// // ... do some work ... +/// TimeIt.log("myOperation", entry: "Finished step 1") +/// // ... do more work ... +/// TimeIt.log("myOperation", entry: "Completed") +/// +/// // Retrieve the formatted log +/// TimeIt.complete(log: "myOperation") { logs in +/// logs.forEach { print($0) } +/// } +/// ``` +/// +/// ## Thread Safety +/// +/// All operations are thread-safe and use an internal serial dispatch queue. public class TimeIt { + /// A log entry capturing a message and timestamp. struct LogEntry { let entry: String let stamp = Date() @@ -14,12 +45,62 @@ public class TimeIt { return df }() + /// Logs an entry with a timestamp to a named log. + /// + /// Creates a new log entry associated with the specified log name. Each entry is + /// timestamped automatically. Multiple entries can be logged to the same log name, + /// and they will be stored in order until retrieved with ``complete(log:completion:)``. + /// + /// - Parameters: + /// - log: The name of the log to add this entry to. Multiple calls with the same + /// log name will accumulate entries in the same log. + /// - entry: A descriptive message for this log entry. + /// + /// - Note: This operation is asynchronous and thread-safe. + /// + /// ## Example + /// + /// ```swift + /// TimeIt.log("download", entry: "Started download") + /// // ... perform download ... + /// TimeIt.log("download", entry: "Download complete") + /// ``` public static func log(_ log: String, entry: String) { queue.async { storage[log, default: []].append(LogEntry(entry: entry)) } } + /// Completes a log and returns all entries with timing information. + /// + /// Retrieves and removes all entries for the specified log name, formatting each entry + /// with its timestamp and time interval from the first entry. + /// + /// Each formatted log line contains: + /// - The log name in brackets + /// - The absolute timestamp (H:mm:ss.SSSS format) + /// - The time interval in seconds from the first entry + /// - The entry message + /// + /// - Parameters: + /// - log: The name of the log to complete and retrieve. + /// - completion: A closure called with an array of formatted log strings. + /// If the log doesn't exist, the array will be empty. + /// + /// - Note: This operation is asynchronous and thread-safe. The log is removed + /// from storage after completion, so subsequent calls with the same + /// log name will return empty arrays. + /// + /// ## Example + /// + /// ```swift + /// TimeIt.complete(log: "myLog") { logs in + /// for log in logs { + /// print(log) + /// // Prints: [myLog] 14:23:45.1234 0.1234secs Entry message + /// } + /// } + /// ``` public static func complete(log: String, completion: @escaping ([String]) -> Void) { queue.async { if let logEntries = storage.removeValue(forKey: log), let start = logEntries.first?.stamp {