Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ let package = Package(
targets: [
.target(
name: "TimeIt",
dependencies: []),
dependencies: [],
resources: [.copy("TimeIt.docc")]),
.testTarget(
name: "TimeItTests",
dependencies: ["TimeIt"]),
Expand Down
55 changes: 54 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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

55 changes: 55 additions & 0 deletions Sources/TimeIt/TimeIt.docc/TimeIt.md
Original file line number Diff line number Diff line change
@@ -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:)``
81 changes: 81 additions & 0 deletions Sources/TimeIt/TimeIt.swift
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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 {
Expand Down
Loading