Update to new logging version

This commit is contained in:
Christoph Hagen 2023-02-16 18:31:30 +01:00
parent 77a214d2a2
commit e9a650ddec
5 changed files with 63 additions and 52 deletions

View File

@ -15,7 +15,7 @@ let package = Package(
// https://github.com/Joannis/SMTPKitten <- No updates since 0ct 2020 // https://github.com/Joannis/SMTPKitten <- No updates since 0ct 2020
// https://github.com/Joannis/VaporSMTPKit <- No updates since 0ct. 2020, uses SMTPKitten // 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/Kitura/Swift-SMTP", from: "6.0.0"),
.package(url: "https://github.com/christophhagen/clairvoyant.git", from: "0.4.0"), .package(url: "https://github.com/christophhagen/clairvoyant.git", branch: "main"),
], ],
targets: [ targets: [
.target( .target(

View File

@ -51,17 +51,15 @@ final class SQLiteDatabase {
private let registeredPlayerCountMetric: Metric<Int> private let registeredPlayerCountMetric: Metric<Int>
init(database: Database, mail: Configuration.EMail?) { init(database: Database, mail: Configuration.EMail?) async throws {
self.registeredPlayerCountMetric = Metric( self.registeredPlayerCountMetric = try await Metric(
"schafkopf.players", "schafkopf.players",
name: "Number of users", name: "Number of users",
description: "The total number of user accounts") description: "The total number of user accounts")
self.tables = TableManagement(database: database) self.tables = try await TableManagement(database: database)
self.mail = mail?.mailConfig self.mail = mail?.mailConfig
Task { await updateRegisteredPlayerCount(from: database)
await updateRegisteredPlayerCount(from: database)
}
} }
func registerPlayer(named name: PlayerName, hash: PasswordHash, email: String?, in database: Database) async throws -> SessionToken { func registerPlayer(named name: PlayerName, hash: PasswordHash, email: String?, in database: Database) async throws -> SessionToken {
@ -92,7 +90,7 @@ final class SQLiteDatabase {
func updateRegisteredPlayerCount(from database: Database) async { func updateRegisteredPlayerCount(from database: Database) async {
do { do {
let count = try await User.query(on: database).count() let count = try await User.query(on: database).count()
registeredPlayerCountMetric.update(count) try? await registeredPlayerCountMetric.update(count)
} catch { } catch {
log("Failed to update player count metric: \(error)") log("Failed to update player count metric: \(error)")
} }

View File

@ -27,26 +27,25 @@ final class TableManagement {
Load the tables from a file in the storage folder Load the tables from a file in the storage folder
- Throws: Errors when the file could not be read - Throws: Errors when the file could not be read
*/ */
init(database: Database) { init(database: Database) async throws {
self.tableCountMetric = .init( self.tableCountMetric = try await .init(
"schafkopf.tables", "schafkopf.tables",
name: "Open tables", name: "Open tables",
description: "The number of currently available tables") description: "The number of currently available tables")
self.playingPlayerCountMetric = .init( self.playingPlayerCountMetric = try await .init(
"schafkopf.playing", "schafkopf.playing",
name: "Sitting players", name: "Sitting players",
description: "The number of players currently sitting at a table") description: "The number of players currently sitting at a table")
self.connectedPlayerCountMetric = .init( self.connectedPlayerCountMetric = try await .init(
"schafkopf.connected", "schafkopf.connected",
name: "Connected players", name: "Connected players",
description: "The number of players with a websocket connection to the server") description: "The number of players with a websocket connection to the server")
Task {
do { do {
try await loadTables(from: database) try await loadTables(from: database)
} catch { } catch {
log("Failed to load tables: \(error)") log("Failed to load tables: \(error)")
}
} }
} }
@ -60,23 +59,23 @@ final class TableManagement {
self.tables[id] = WaitingTable(id: id, name: table.name, isPublic: table.isPublic, players: table.players) self.tables[id] = WaitingTable(id: id, name: table.name, isPublic: table.isPublic, players: table.players)
} }
log("\(tables.count) tables loaded") log("\(tables.count) tables loaded")
logTableCount() await logTableCount()
logPlayingPlayerCount() await logPlayingPlayerCount()
logConnectedPlayerCount() await logConnectedPlayerCount()
} }
private func logTableCount() { private func logTableCount() async {
tableCountMetric.update(tables.count) try? await tableCountMetric.update(tables.count)
} }
private func logPlayingPlayerCount() { private func logPlayingPlayerCount() async {
let count = tables.values.sum { $0.playerCount } let count = tables.values.sum { $0.playerCount }
playingPlayerCountMetric.update(count) try? await playingPlayerCountMetric.update(count)
} }
private func logConnectedPlayerCount() { private func logConnectedPlayerCount() async {
let count = tables.values.sum { $0.numberOfConnectedPlayers } let count = tables.values.sum { $0.numberOfConnectedPlayers }
connectedPlayerCountMetric.update(count) try? await connectedPlayerCountMetric.update(count)
} }
/** /**
@ -93,8 +92,8 @@ final class TableManagement {
try await player.update(on: database) try await player.update(on: database)
let waitingTable = WaitingTable(newTable: table, user: player) let waitingTable = WaitingTable(newTable: table, user: player)
self.tables[waitingTable.id] = waitingTable self.tables[waitingTable.id] = waitingTable
logTableCount() await logTableCount()
logPlayingPlayerCount() await logPlayingPlayerCount()
return waitingTable.tableInfo(forPlayer: player.name) return waitingTable.tableInfo(forPlayer: player.name)
} }
@ -127,7 +126,7 @@ final class TableManagement {
player.$table.id = table.id player.$table.id = table.id
try await player.update(on: database) try await player.update(on: database)
table.sendUpdateToAllPlayers() table.sendUpdateToAllPlayers()
logPlayingPlayerCount() await logPlayingPlayerCount()
return table.tableInfo(forPlayer: player.name) return table.tableInfo(forPlayer: player.name)
} }
@ -159,7 +158,7 @@ final class TableManagement {
player.$table.id = nil player.$table.id = nil
guard let table = WaitingTable(oldTable: oldTable, removing: player.name) else { guard let table = WaitingTable(oldTable: oldTable, removing: player.name) else {
tables[oldTable.id] = nil tables[oldTable.id] = nil
logTableCount() await logTableCount()
try await player.update(on: database) try await player.update(on: database)
try await Table.query(on: database).filter(\.$id == oldTable.id).delete() try await Table.query(on: database).filter(\.$id == oldTable.id).delete()
return return
@ -168,8 +167,8 @@ final class TableManagement {
tables[table.id] = table tables[table.id] = table
#warning("Update points for all players, add penalty if running game") #warning("Update points for all players, add penalty if running game")
table.sendUpdateToAllPlayers() table.sendUpdateToAllPlayers()
logPlayingPlayerCount() await logPlayingPlayerCount()
logConnectedPlayerCount() await logConnectedPlayerCount()
try await player.update(on: database) try await player.update(on: database)
} }
@ -177,16 +176,21 @@ final class TableManagement {
guard let table = currentTable(for: player) else { guard let table = currentTable(for: player) else {
return false return false
} }
defer { logConnectedPlayerCount() } let result = table.connect(player: player, using: socket)
return table.connect(player: player, using: socket) Task {
await logConnectedPlayerCount()
}
return result
} }
func disconnect(player: PlayerName) { func disconnect(player: PlayerName) {
guard let table = currentTable(for: player) else { guard let table = currentTable(for: player) else {
return return
} }
defer { logConnectedPlayerCount() }
table.disconnect(player: player) table.disconnect(player: player)
Task {
await logConnectedPlayerCount()
}
} }
func performAction(player: PlayerName, action: PlayerAction) -> PlayerActionResult { func performAction(player: PlayerName, action: PlayerAction) -> PlayerActionResult {
@ -255,6 +259,8 @@ final class TableManagement {
func disconnectAllSockets() { func disconnectAllSockets() {
tables.values.forEach { $0.disconnectAllPlayers() } tables.values.forEach { $0.disconnectAllPlayers() }
logConnectedPlayerCount() Task {
await logConnectedPlayerCount()
}
} }
} }

View File

@ -5,24 +5,24 @@ import Clairvoyant
var server: SQLiteDatabase! var server: SQLiteDatabase!
// configures your application // configures your application
public func configure(_ app: Application) throws { public func configure(_ app: Application) async throws {
let storageFolder = URL(fileURLWithPath: app.directory.resourcesDirectory) let storageFolder = URL(fileURLWithPath: app.directory.resourcesDirectory)
let logFolder = storageFolder.appendingPathComponent("logs") let logFolder = storageFolder.appendingPathComponent("logs")
let accessManager = AccessTokenManager([]) let accessManager = AccessTokenManager([])
let monitor = MetricObserver( let monitor = await MetricObserver(
logFolder: logFolder, logFolder: logFolder,
accessManager: accessManager, accessManager: accessManager,
logMetricId: "schafkopf.log") logMetricId: "schafkopf.log")
MetricObserver.standard = monitor MetricObserver.standard = monitor
let status = Metric<ServerStatus>( let status = try! await Metric<ServerStatus>(
"schafkopf.status", "schafkopf.status",
name: "Status", name: "Status",
description: "The main status of the server") description: "The main status of the server")
status.update(.initializing) try? await status.update(.initializing)
monitor.registerRoutes(app) await monitor.registerRoutes(app)
let configPath = URL(fileURLWithPath: app.directory.resourcesDirectory) let configPath = URL(fileURLWithPath: app.directory.resourcesDirectory)
.appendingPathComponent("config.json") .appendingPathComponent("config.json")
@ -31,8 +31,8 @@ public func configure(_ app: Application) throws {
do { do {
configuration = try Configuration(loadFromUrl: configPath) configuration = try Configuration(loadFromUrl: configPath)
} catch { } catch {
status.update(.initializationFailure) try? await status.update(.initializationFailure)
monitor.log("Failed to read configuration: \(error)") await monitor.log("Failed to read configuration: \(error)")
// Note: If configuration can't be loaded, then the server will run on the wrong port // Note: If configuration can't be loaded, then the server will run on the wrong port
// and access to metrics is impossible, since no tokens are loaded // and access to metrics is impossible, since no tokens are loaded
return return
@ -60,8 +60,8 @@ public func configure(_ app: Application) throws {
do { do {
try app.autoMigrate().wait() try app.autoMigrate().wait()
} catch { } catch {
monitor.log("Failed to migrate database: \(error)") await monitor.log("Failed to migrate database: \(error)")
status.update(.initializationFailure) try? await status.update(.initializationFailure)
return return
} }
@ -69,7 +69,7 @@ public func configure(_ app: Application) throws {
app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory)) app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
let db = app.databases.database(.sqlite, logger: .init(label: "Init"), on: app.databases.eventLoopGroup.next())! let db = app.databases.database(.sqlite, logger: .init(label: "Init"), on: app.databases.eventLoopGroup.next())!
server = SQLiteDatabase(database: db, mail: configuration.mail) server = try await SQLiteDatabase(database: db, mail: configuration.mail)
// Gracefully shut down by closing potentially open socket // Gracefully shut down by closing potentially open socket
DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + .seconds(5)) { DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + .seconds(5)) {
@ -81,10 +81,15 @@ public func configure(_ app: Application) throws {
// register routes // register routes
routes(app) routes(app)
status.update(.nominal) try? await status.update(.nominal)
} }
func log(_ message: String) { func log(_ message: String) {
MetricObserver.standard?.log(message) guard let observer = MetricObserver.standard else {
print(message) print(message)
return
}
Task {
await observer.log(message)
}
} }

View File

@ -5,5 +5,7 @@ var env = try Environment.detect()
try LoggingSystem.bootstrap(from: &env) try LoggingSystem.bootstrap(from: &env)
let app = Application(env) let app = Application(env)
defer { app.shutdown() } defer { app.shutdown() }
try configure(app) Task {
try app.run() try await configure(app)
try app.run()
}