Skip to content
This repository was archived by the owner on Apr 20, 2024. It is now read-only.

Commit 0fb20f3

Browse files
Merge pull request #65 from nodes-vapor/tn-vapor-4
Vapor 4
2 parents c410b2c + fb49120 commit 0fb20f3

22 files changed

+826
-978
lines changed

Package.swift

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
1-
// swift-tools-version:4.2
1+
// swift-tools-version:5.2
22
import PackageDescription
33

44
let package = Package(
5-
name: "Bugsnag",
5+
name: "bugsnag",
6+
platforms: [
7+
.macOS(.v10_15)
8+
],
69
products: [
7-
.library(
8-
name: "Bugsnag",
9-
targets: ["Bugsnag"]),
10+
.library(name: "Bugsnag", targets: ["Bugsnag"]),
1011
],
1112
dependencies: [
12-
.package(url: "https://github.com/vapor/auth.git", from: "2.0.0"),
13-
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),
13+
.package(url: "https://github.com/vapor/vapor.git", from: "4.10.0"),
1414
],
1515
targets: [
16-
.target(
17-
name: "Bugsnag",
18-
dependencies: ["Vapor", "Authentication"]),
19-
.testTarget(
20-
name: "BugsnagTests",
21-
dependencies: ["Bugsnag", "Vapor"]),
16+
.target(name: "Bugsnag", dependencies: [
17+
.product(name: "Vapor", package: "vapor"),
18+
]),
19+
.testTarget(name: "BugsnagTests", dependencies: [
20+
.target(name: "Bugsnag"),
21+
.product(name: "XCTVapor", package: "vapor"),
22+
]),
2223
]
2324
)

README.md

Lines changed: 54 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Bugsnag 🐛
2-
[![Swift Version](https://img.shields.io/badge/Swift-4-brightgreen.svg)](http://swift.org)
3-
[![Vapor Version](https://img.shields.io/badge/Vapor-3-F6CBCA.svg)](http://vapor.codes)
2+
[![Swift Version](https://img.shields.io/badge/Swift-5.2-brightgreen.svg)](http://swift.org)
3+
[![Vapor Version](https://img.shields.io/badge/Vapor-4-e040fb.svg)](https://vapor.codes)
44
[![Circle CI](https://circleci.com/gh/nodes-vapor/bugsnag/tree/master.svg?style=shield)](https://circleci.com/gh/nodes-vapor/bugsnag)
55
[![codebeat badge](https://codebeat.co/badges/e93cc2d5-7365-4916-bc92-3f6bb39b18f4)](https://codebeat.co/projects/github-com-nodes-vapor-bugsnag-master)
66
[![codecov](https://codecov.io/gh/nodes-vapor/bugsnag/branch/master/graph/badge.svg)](https://codecov.io/gh/nodes-vapor/bugsnag)
@@ -16,118 +16,108 @@ Reporting errors to [Bugsnag](https://www.bugsnag.com/).
1616
Update your `Package.swift` file.
1717

1818
```swift
19-
.package(url: "https://github.com/nodes-vapor/bugsnag.git", from: "3.0.0")
19+
.package(url: "https://github.com/nodes-vapor/bugsnag.git", from: "4.0.0")
2020
```
2121

22-
Update `Sources/App/configure.swift`
22+
Update `configure.swift`
2323

2424
```swift
25-
public func configure(
26-
_ config: inout Config,
27-
_ environment: inout Environment,
28-
_ services: inout Services
29-
) throws {
30-
...
31-
// Register provider
32-
let bugsnagProvider = BugsnagProvider(config: BugsnagConfig(
25+
public func configure(_ app: Application) throws {
26+
// Configure Bugsnag.
27+
app.bugsnag.configuration = .init(
3328
apiKey: "<YOUR BUGSNAG API KEY>",
34-
releaseStage: environment.name,
35-
shouldReport: environment.name != "local"
36-
debug: false
37-
))
38-
try services.register(bugsnagProvider)
29+
releaseStage: app.environment.name,
30+
shouldReport: app.environment.name != "local"
31+
)
3932

40-
...
41-
42-
// Register middleware
43-
44-
var middlewaresConfig = MiddlewareConfig()
45-
...
46-
middlewaresConfig.use(BugsnagMiddleware.self) // Catch errors and report to bugsnag
47-
...
48-
services.register(middlewaresConfig)
49-
50-
...
33+
// Add Bugsnag middleware.
34+
app.middleware.use(BugsnagMiddleware())
5135
}
5236
```
5337

5438
### Reporting
55-
Bugsnag offers three different types of reports: info, warning and error. To make a report just instantiate an `ErrorReporter` and use the respective functions.
5639

57-
##### Examples
58-
```swift
59-
let reporter = try req.make(ErrorReporter.self) // or `BugsnagReporter.self`
40+
`BugsnagMiddleware` will automatically report errors thrown by your route handlers. You can report errors manually from `Application` or `Request`.
6041

61-
reporter.report(Abort(.upgradeRequired), severity: .info, on: req)
62-
reporter.report(Abort(.notFound), severity: .warning, on: req)
63-
reporter.report(Abort(.internalServerError), severity: .error, on: req) // you can omit the `severity` parameter since `.error` is the default
64-
```
65-
66-
It's also possible to attach metadata to the report.
6742
```swift
68-
reporter.report(
69-
Abort(.internalServerError),
70-
metadata: ["key": "value"],
71-
on: req
72-
)
43+
// Reporting from Application.
44+
app.bugsnag.report(Abort(.internalServerError))
45+
46+
// Reporting from Request.
47+
app.get("test") { req in
48+
req.bugsnag.report(Abort(.upgradeRequired))
49+
return HTTPStatus.ok
50+
}
7351
```
7452

75-
By conforming to the `ReportableError` protocol you can have full control over how (and if) the BugsnagMiddleware reports your errors. It has the following properties:
53+
By conforming to the `BugsnagError` protocol you can have full control over how your errors are reported. It has the following properties:
7654

7755
| Name | Type | Function | Default |
7856
|---|---|---|---|
7957
| `shouldReport` | `Bool` | Opt out of error reporting by returning `false` | `true` |
8058
| `severity` | `Severity` | Indicate error severity (`.info`\|`.warning`\|`.error`) | `.error` |
81-
| `userId` | `CustomStringConvertible?` | An optional user id associated with the error | `nil` |
8259
| `metadata` | `[String: CustomDebugStringConvertible]` | Additional metadata to include in the report | `[:]` |
8360

84-
#### Users
85-
Conforming your `Authenticatable` model to `BugsnagReportableUser` allows you to easily pair the data to a report. The protocol requires your model to have an `id` field that is `CustomStringConvertible`.
61+
### Users
62+
Conforming your `Authenticatable` model to `BugsnagUser` allows you to easily pair the data to a report.
8663

8764
```swift
88-
extension YourUser: BugsnagReportableUser {}
65+
extension TestUser: BugsnagUser {
66+
var bugsnagID: CustomStringConvertible? {
67+
self.id
68+
}
69+
}
70+
```
71+
72+
Configure all user models you would like Bugsnag to report.
8973

90-
try reporter.error(userType: YourUser.self, Abort(.notFound), on: req)
74+
```swift
75+
// Add to configure.swift.
76+
app.bugsnag.users.add(TestUser.self)
9177
```
9278

93-
#### Breadcrumbs
79+
Bugsnag will automatically check Vapor's authentication API for the configured user types and report the user's identifier if they are logged in.
80+
81+
### Breadcrumbs
9482
Breadcrumbs enable you to attach custom events to your reports. Leave a breadcrumb using the convenience function on `Request`.
9583

9684
```swift
97-
req.breadcrumb(
85+
req.bugsnag.breadcrumb(
9886
name: "Something happened!",
9987
type: .manual,
10088
metadata: ["foo": "bar"]
10189
)
10290
```
10391

10492
The breadcrumb types are provided by Bugsnag:
93+
10594
```swift
106-
enum BreadcrumbType {
95+
enum BugsnagBreadcrumbType {
96+
case error
97+
case log
98+
case manual
10799
case navigation
108-
case request
109100
case process
110-
case log
111-
case user
101+
case request
112102
case state
113-
case error
114-
case manual
103+
case user
115104
}
116105
```
117106

118-
#### Filter out fields from reports
107+
### Key Filters
108+
119109
Usually you will receive information such as headers, query params or post body fields in the reports from Bugsnag. To ensure that you do not track sensitive information, you can configure Bugsnag with a list of fields that should be filtered out:
120110

121111
```swift
122-
BugsnagConfig(
123-
apiKey: "apiKey",
124-
releaseStage: "test",
125-
keyFilters: ["password", "email", "authorization", "lastname"]
112+
app.bugsnag.configuration = .init(
113+
apiKey: "foo",
114+
releaseStage: "debug",
115+
keyFilters: ["email", "password"]
126116
)
127117
```
128-
In this case Bugsnag Reports won't contain header fields, query params or post body json fields with the keys/names **password**, **email**, **authorization**, **lastname**.
118+
In this case Bugsnag Reports will hide header fields, query params or post body json fields with the keys/names **email** and **password**.
129119

130-
⚠️ Note: in JSON bodies, this only works for the first level of fields and not for nested children.
120+
⚠️ Note: If key filters are defined and Bugsnag does not know how to parse the request body, the entire body will be hidden.
131121

132122
## 🏆 Credits
133123

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import Vapor
2+
3+
extension Application {
4+
/// Bugsnag helper. Use to configure and send reports.
5+
///
6+
/// // Configure Bugsnag.
7+
/// app.bugsnag.configuration = ...
8+
///
9+
/// // Report an error.
10+
/// app.bugsnag.report(...)
11+
///
12+
public var bugsnag: Bugsnag {
13+
.init(application: self)
14+
}
15+
16+
/// Application's Bugsnag helper.
17+
public struct Bugsnag {
18+
/// The root application.
19+
public let application: Application
20+
}
21+
}
22+
23+
extension Application.Bugsnag {
24+
private struct BugsnagConfigurationKey: StorageKey {
25+
typealias Value = BugsnagConfiguration
26+
}
27+
28+
/// Configures Bugsnag for this application.
29+
///
30+
/// This is usually set in `configure.swift`.
31+
///
32+
/// // Configure Bugsnag.
33+
/// app.bugsnag.configuration = ...
34+
///
35+
/// Must be set before accessing Bugsnag helpers on `Application` and `Request`.
36+
public var configuration: BugsnagConfiguration? {
37+
get {
38+
self.application.storage[BugsnagConfigurationKey.self]
39+
}
40+
nonmutating set {
41+
self.application.storage[BugsnagConfigurationKey.self] = newValue
42+
}
43+
}
44+
}
45+
46+
extension Application.Bugsnag {
47+
private struct BugsnagUsersKey: StorageKey {
48+
typealias Value = BugsnagUsers
49+
}
50+
51+
/// Configures which users will be reported by Bugsnag.
52+
///
53+
/// // Adds TestUser to Bugsnag reports.
54+
/// app.bugsnag.users.add(TestUser.self)
55+
///
56+
/// User types must conform to `Authenticatable` and `BugsnagUser`.
57+
/// Configured user types will be automatically included in Bugsnag reports
58+
/// if they are logged in via the authentication API when reporting though `Request`.
59+
///
60+
/// // Logs in a user.
61+
/// req.auth.login(TestUser())
62+
///
63+
/// // This error report will include the logged in
64+
/// // user's identifier.
65+
/// req.bugsnag.report(someError)
66+
///
67+
/// Only one user can be included in a Bugsnag report.
68+
public var users: BugsnagUsers {
69+
get {
70+
self.application.storage[BugsnagUsersKey.self] ?? .init(storage: [])
71+
}
72+
nonmutating set {
73+
self.application.storage[BugsnagUsersKey.self] = newValue
74+
}
75+
}
76+
}
77+
78+
extension Application.Bugsnag: BugsnagReporter {
79+
/// See `BugsnagReporter`.
80+
public var logger: Logger {
81+
self.application.logger
82+
}
83+
84+
/// See `BugsnagReporter`.
85+
public var currentRequest: Request? {
86+
nil
87+
}
88+
89+
/// See `BugsnagReporter`.
90+
public var client: Client {
91+
self.application.client
92+
}
93+
94+
/// See `BugsnagReporter`.
95+
public var eventLoop: EventLoop {
96+
self.application.eventLoopGroup.next()
97+
}
98+
}

Sources/Bugsnag/Breadcrumb.swift

Lines changed: 0 additions & 59 deletions
This file was deleted.

0 commit comments

Comments
 (0)