diff --git a/Package.swift b/Package.swift index 73089a6..8bc3ee9 100644 --- a/Package.swift +++ b/Package.swift @@ -11,10 +11,11 @@ let package = Package( .package(url: "https://github.com/vapor/fluent.git", from: "4.0.0"), .package(url: "https://github.com/vapor/fluent-sqlite.git", from: "4.0.0"), // Alternatives: - // https://github.com/onevcat/Hedwig - // https://github.com/Joannis/SMTPKitten - // https://github.com/Joannis/VaporSMTPKit <- Uses SMTPKitten + // https://github.com/onevcat/Hedwig <- No updates since Jun 2017 + // https://github.com/Joannis/SMTPKitten <- No updates since 0ct 2020 + // https://github.com/Joannis/VaporSMTPKit <- No updates since 0ct. 2020, uses SMTPKitten .package(url: "https://github.com/Kitura/Swift-SMTP", from: "6.0.0"), + .package(url: "https://github.com/christophhagen/clairvoyant.git", from: "0.3.0"), ], targets: [ .target( @@ -24,6 +25,7 @@ let package = Package( .product(name: "FluentSQLiteDriver", package: "fluent-sqlite"), .product(name: "Vapor", package: "vapor"), .product(name: "SwiftSMTP", package: "Swift-SMTP"), + .product(name: "Clairvoyant", package: "Clairvoyant"), ], swiftSettings: [ // Enable better optimizations when building in Release configuration. Despite the use of diff --git a/Resources/config_example.json b/Resources/config_example.json index 894ff7a..0a2c65a 100644 --- a/Resources/config_example.json +++ b/Resources/config_example.json @@ -7,5 +7,6 @@ "email": "schafkopf@example.com", "password": "some-secret-string", "tokenExpiryDuration": 15, - } + }, + "monitoringTokens": [], } diff --git a/Sources/App/Management/Configuration.swift b/Sources/App/Management/Configuration.swift index 4e5219c..f930eb9 100644 --- a/Sources/App/Management/Configuration.swift +++ b/Sources/App/Management/Configuration.swift @@ -30,6 +30,9 @@ struct Configuration { /// The number of minutes until a password reset token is no longer valid let tokenExpiryDuration: Int } + + /// The authentication tokens to access the metrics + let monitoringTokens: Set } extension Configuration { diff --git a/Sources/App/configure.swift b/Sources/App/configure.swift index f7b63e8..8b39e0f 100644 --- a/Sources/App/configure.swift +++ b/Sources/App/configure.swift @@ -1,5 +1,6 @@ import Vapor import Fluent +import Clairvoyant var server: SQLiteDatabase! @@ -7,9 +8,22 @@ var server: SQLiteDatabase! public func configure(_ app: Application) throws { let storageFolder = URL(fileURLWithPath: app.directory.resourcesDirectory) + let logFolder = storageFolder.appendingPathComponent("logs") + let accessManager = AccessTokenManager([]) + let monitor = MetricObserver( + logFolder: logFolder, + accessManager: accessManager, + logMetricId: "schafkopf.log") + MetricObserver.standard = monitor + + let status = Metric("schafkopf.status") + status.update(.initializing) + monitor.registerRoutes(app) + let configPath = URL(fileURLWithPath: app.directory.resourcesDirectory) .appendingPathComponent("config.json") let configuration = try Configuration(loadFromUrl: configPath) + configuration.monitoringTokens.map { $0.data(using: .utf8)! }.forEach(accessManager.add) app.http.server.configuration.port = configuration.serverPort @@ -29,7 +43,13 @@ public func configure(_ app: Application) throws { app.migrations.add(UserTableMigration()) app.migrations.add(PasswordResetMigration()) - try app.autoMigrate().wait() + do { + try app.autoMigrate().wait() + } catch { + monitor.log("Failed to migrate database: \(error)") + status.update(.initializationFailure) + return + } // serve files from /Public folder app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory)) @@ -46,4 +66,6 @@ public func configure(_ app: Application) throws { // register routes try routes(app) + + status.update(.nominal) }