https://github.com/cookpad/puree-swift
🍯 Awesome log aggregator for iOS
https://github.com/cookpad/puree-swift
Last synced: 28 days ago
JSON representation
🍯 Awesome log aggregator for iOS
- Host: GitHub
- URL: https://github.com/cookpad/puree-swift
- Owner: cookpad
- License: mit
- Created: 2018-02-09T06:58:17.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2024-10-04T11:19:32.000Z (7 months ago)
- Last Synced: 2025-04-02T06:09:24.038Z (about 1 month ago)
- Language: Swift
- Homepage:
- Size: 287 KB
- Stars: 218
- Watchers: 17
- Forks: 26
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Puree

[](https://github.com/cookpad/Puree-Swift/actions)
[](https://swift.org)
[](https://github.com/Carthage/Carthage)
[](http://cocoadocs.org/docsets/Puree)
[](http://cocoadocs.org/docsets/Puree)
[](https://github.com/cookpad/Puree-Swift/blob/master/LICENSE)## Description
Puree is a log aggregator which provides the following features.
- Filtering: Log entries can be processed before being sent. You can add common parameters, do random sampling, ...
- Buffering: Log entries are stored in a buffer until it's time to send them.
- Batching: Multiple log entries are grouped and sent in one request.
- Retrying: Automatically retry to send after some backoff time if a transmission error occurred.
Puree helps you unify your logging infrastructure.
Currently in development so the interface might change.
## Installation
### Carthage
```
github "cookpad/Puree-Swift"
```### CocoaPods
```ruby
use_frameworks!pod 'Puree', '~> 5.0'
```### Swift PM
The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but Puree-Swift does support its use on supported platforms.Once you have your Swift package set up, adding Puree-Swift as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`.
```swift
dependencies: [
.package(url: "https://github.com/cookpad/Puree-Swift.git", .upToNextMinor(from: "5.3.0"))
]
```## Usage
### Define your own Filter/Output
#### Filter
A `Filter` should convert any objects into `LogEntry`.
```swift
import Foundation
import Pureestruct PVLogFilter: Filter {
let tagPattern: TagPatterninit(tagPattern: TagPattern) {
self.tagPattern = tagPattern
}func convertToLogs(_ payload: [String: Any]?, tag: String, captured: String?, logger: Logger) -> Set {
let currentDate = logger.currentDatelet userData: Data?
if let payload = payload {
userData = try! JSONSerialization.data(withJSONObject: payload)
} else {
userData = nil
}
let log = LogEntry(tag: tag,
date: currentDate,
userData: userData)
return [log]
}
}
```#### Output
An `Output` should emit log entries to wherever they need.
The following `ConsoleOutput` will output logs to the standard output.
```swift
class ConsoleOutput: Output {
let tagPattern: TagPatternrequired init(logStore: LogStore, tagPattern: TagPattern) {
self.tagPattern = tagPattern
}func emit(log: LogEntry) {
if let userData = log.userData {
let jsonObject = try! JSONSerialization.jsonObject(with: userData)
print(jsonObject)
}
}
}
```##### BufferedOutput
If you use `BufferedOutput` instead of raw `Output`, log entries are buffered and emitted on a routine schedule.
```swift
class LogServerOutput: BufferedOutput {
override func write(_ chunk: BufferedOutput.Chunk, completion: @escaping (Bool) -> Void) {
let payload = chunk.logs.flatMap { log in
if let userData = log.userData {
return try? JSONSerialization.jsonObject(with: userData, options: [])
}
return nil
}
if let data = try? JSONSerialization.data(withJSONObject: payload, options: []) {
let task = URLSession.shared.uploadTask(with: request, from: data)
task.resume()
}
}
}
```### Make logger and post log
After implementing filters and outputs, you can configure the routing with `Logger.Configuration`.
```swift
import Pureelet configuration = Logger.Configuration(filterSettings: [
FilterSetting {
PVLogFilter(tagPattern: TagPattern(string: "pv.**")!)
}
],
outputSettings: [
OutputSetting {
PVLogOutput(logStore: $0, tagPattern: TagPattern(string: "activity.**")!)
},
OutputSetting {
ConsoleOutput(logStore: $0, tagPattern: TagPattern(string: "pv.**")!)
},
OutputSetting {
LogServerOutput(logStore: $0, tagPattern: TagPattern(string: "pv.**")!)
},
])
let logger = try! Logger(configuration: configuration)
logger.postLog(["page_name": "top", "user_id": 100], tag: "pv.top")
```Using this configuration, the expected result is as follows:
|tag name |-> [ Filter Plugin ] |-> [ Output Plugin ] |
|----------------------|---------------------|---------------------|
|pv.recipe.list |-> [ `PVLogFilter` ] |-> [ `ConsoleOutput` ], [ `LogServerOutput` ]|
|pv.recipe.detail |-> [ `PVLogFilter` ] |-> [ `ConsoleOutput` ], [ `LogServerOutput` ]|
|activity.recipe.tap |-> ( no filter ) |-> [ `ConsoleOutput` ] |
|event.special |-> ( no filter ) |-> ( no output ) |We recommend suspending loggers while the application is in the background.
```swift
class AppDelegate: UIApplicationDelegate {
func applicationDidEnterBackground(_ application: UIApplication) {
logger.suspend()
}func applicationWillEnterForeground(_ application: UIApplication) {
logger.resume()
}
}
```## Tag system
### Tag
A tag is consisted of multiple term delimited by `.`.
For example `activity.recipe.view`, `pv.recipe_detail`.
You can choose your tags logged freely.### Pattern
`Filter`, `Output` and `BufferedOutput` plugins are applied to log entries with a matching tag.
You can specify tag pattern for plugin reaction rules.#### Simple pattern
Pattern `aaa.bbb` matches tag `aaa.bbb`, doesn't match tag `aaa.ccc` (Perfect matching).
#### Wildcard
Pattern `aaa.*` matches tags `aaa.bbb` and `aaa.ccc`, but not `aaa` or `aaa.bbb.ccc` (single term).
Pattern `aaa.**` matches tags `aaa`, `aaa.bbb` and `aaa.bbb.ccc`, but not `xxx.yyy.zzz` (zero or more terms).
## Log Store
In the case an application couldn't send log entries (e.g. network connection unavailable), Puree stores the unsent entries.
By default, Puree stores them in local files in the `Library/Caches` directory.
You can also define your own custom log store backed by any storage (e.g. Core Data, Realm, YapDatabase, etc.).
See the `LogStore` protocol for more details.
## License
Please do read the [License](https://github.com/cookpad/Puree-Swift/blob/master/LICENSE) before contributing.