Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ let package = Package(
name: "FluentPostgresDriverTests",
dependencies: [
.product(name: "FluentBenchmark", package: "fluent-kit"),
.product(name: "InMemoryLogging", package: "swift-log"),
.target(name: "FluentPostgresDriver"),
],
swiftSettings: swiftSettings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ extension _FluentPostgresDatabase: Database {
self.withConnection { (underlying: any PostgresDatabase) in
closure(
_FluentPostgresDatabase(
database: underlying.sql(
database: underlying.logging(to: self.logger).sql(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice if we could fix the larger issue with the various versions of logging(to:) in FluentKit and SQLKit; thanks to protocol dispatch rules, it tends not to work with some APIs. But I think that will require API breakage to deal with.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah once everything is swift concurrency we can just rely on Logger.current, which is what we do in Vapor 5, resolves so many of these issues

encodingContext: self.encodingContext,
decodingContext: self.decodingContext,
queryLogLevel: self.database.queryLogLevel
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import FluentKit
import InMemoryLogging
import Logging
import SQLKit
import Testing

extension AllSuites {
@Suite
struct FluentPostgresLoggingTests {
init() { #expect(isLoggingConfigured) }

@Test(arguments: TestDriver.allCases)
func withConnectionUsesContextLogger(_ driver: TestDriver) async throws {
try await withDbs(driver) { dbs, _ in
let (first, second) = try await Self.warmedUpDatabases(dbs)

try await second.db.withConnection { db in
try await (db as! any SQLDatabase).raw("SELECT 'inside withConnection'").run()
}

#expect(second.logs.loggedQueries.contains("SELECT 'inside withConnection'"))
#expect(!first.logs.loggedQueries.contains("SELECT 'inside withConnection'"))
}
}

@Test(arguments: TestDriver.allCases)
func transactionUsesContextLogger(_ driver: TestDriver) async throws {
try await withDbs(driver) { dbs, _ in
let (first, second) = try await Self.warmedUpDatabases(dbs)

try await second.db.transaction { db in
try await (db as! any SQLDatabase).raw("SELECT 'inside transaction'").run()
}

#expect(second.logs.loggedQueries.contains("BEGIN"))
#expect(second.logs.loggedQueries.contains("SELECT 'inside transaction'"))
#expect(second.logs.loggedQueries.contains("COMMIT"))
#expect(!first.logs.loggedQueries.contains("SELECT 'inside transaction'"))
}
}

private static func warmedUpDatabases(
_ dbs: Databases
) async throws -> (first: (db: any Database, logs: InMemoryLogHandler), second: (db: any Database, logs: InMemoryLogHandler)) {
let eventLoop = dbs.eventLoopGroup.any()
let firstLogs = InMemoryLogHandler.capturingAllLevels(), secondLogs = InMemoryLogHandler.capturingAllLevels()
let first = dbs.database(.a, logger: Logger(label: "first") { _ in firstLogs }, on: eventLoop)!
let second = dbs.database(.a, logger: Logger(label: "second") { _ in secondLogs }, on: eventLoop)!

try await first.withConnection { db in
try await (db as! any SQLDatabase).raw("SELECT 'warm up'").run()
}
return ((first, firstLogs), (second, secondLogs))
}
}
}

extension InMemoryLogHandler {
/// A handler that captures everything, since SQL queries are logged at `.debug` by default.
static func capturingAllLevels() -> Self {
var handler = Self()
handler.logLevel = .trace
return handler
}

/// The SQL of every query that was logged to this handler.
var loggedQueries: [String] {
self.entries.compactMap { entry in
guard case .string(let sql) = entry.metadata["sql"] else { return nil }
return sql
}
}
}
Loading