An open API service indexing awesome lists of open source software.

https://github.com/richardpiazza/occurrence

A swift logging library that integrates with `SwiftLog`
https://github.com/richardpiazza/occurrence

logger logging swift

Last synced: 4 months ago
JSON representation

A swift logging library that integrates with `SwiftLog`

Awesome Lists containing this project

README

          

# Occurrence

A multi-platform log handler for [swift-log](https://github.com/apple/swift-log).

[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Frichardpiazza%2FOccurrence%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/richardpiazza/Occurrence)
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Frichardpiazza%2FOccurrence%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/richardpiazza/Occurrence)

## Usage

> SwiftLog provides a unified, performant, and ergonomic logging API that can be adopted by libraries and applications across the Swift ecosystem.

The thing SwiftLog does not provide is a `LogHandler` - any instance that consumes logs being generated by libraries and applications.
This is where **Occurrence** steps in. This package provides a SQLite backed storage mechanism to capture, query, and export logs.
In order to provide this functionality, a `LogHandler` must first be _bootstrapped_ into the logging system.
**Occurrence** provides a convenience method to configure itself as the `LogHandler`:

```swift
Occurrence.bootstrap()
```

Bootstrapping must be completed before the initialization of any `Logger` instance.
Typically this is done at the very start of your application. For instance:

```swift
@main
struct MyApp: App {
init() {
Occurrence.bootstrap()
// … continued initialization.
}
}
```

That's everything needed to start capturing logs!

## Queries & Exports

Capturing logs is great, but somewhat useless if you can't _do_ anything with them.
To allow for observation, querying, and export of logging data, **Occurrence** defines `LogStreamer` and `LogProvider` instances.

### LogStreamer

```swift
protocol LogStreamer: Sendable {
var stream: AsyncStream { get }
func log(_ entry: Logger.Entry)
}
```

A `LogStream` provides an `AsyncStream` of `Logger.Entry` types as they are processed by framework.
These entries can easily be observed:

```swift
let task = Task {
for await entry in Occurrence.logStreamer.stream {
// process entry
}
}
```

### LogProvider

```swift
protocol LogProvider: Sendable {
func log(_ entry: Logger.Entry)
func subsystems() -> [Logger.Subsystem]
func entries(matching filter: Logger.Filter?, ascending: Bool, limit: UInt) -> [Logger.Entry]
func purge(matching filter: Logger.Filter?)
}
```

A `LogProvider` consumes log entries as they are registered and provides data about those entries as requested.
Various filters can be provided to fine-tune the results you're looking for.

## Conveniences

### `LogView`

If you are in a SwiftUI environment the `LogView` view provides a way to observe, manage, and export log entries.
This offers a prime example of how the `LogStreamer` and `LogProvider` types can be utilized within an application.

### `LoggableError`

A `LoggableError` is an `Error` type that can be easily converted to `Logger.Metadata`.
Many standard error types have conformances for this protocol, including:
* `CocoaError`
* `DecodingError`
* `EncodingError`
* `URLError`

There are also extensions to the `Logger` instance that allow for passthrough of a `LoggableError` instance:

```swift
@LazyLogger("MyApp") var logger: Logger

enum AppError: LoggableError {
case badData
}

func throwingFunction() throws {
guard condition else {
throw logger.error("Condition not met.", AppError.badData)
}
}
```

### `LazyLogger`

Every `Logger` instance supplies a label (Internally Occurrence uses the type `Logger.Subsystem` for this).
As a convenience to creating a `Logger` reference, use the `LazyLogger` property wrapper which will create a Logger with the specific label (`Logger.Subsystem`).

```swift
@LazyLogger("LoggerLabel") var logger: Logger
```