Added logging to the DocCMiddleware middleware in the library target.

This commit is contained in:
Javier Cicchelli 2025-04-22 10:37:49 +02:00
parent de2e2dd656
commit c35c81413c
3 changed files with 95 additions and 11 deletions

View File

@ -58,7 +58,7 @@ private extension ArchiveController {
defer { defer {
logger.debug( logger.debug(
"The codable response returned: \(String(describing: archiveList))", "A codable response returned: \(String(describing: archiveList))",
metadata: .metadata( metadata: .metadata(
context: context, context: context,
request: request, request: request,
@ -86,7 +86,7 @@ private extension ArchiveController {
} catch .folderPathEmpty, .folderNotDirectory { } catch .folderPathEmpty, .folderNotDirectory {
defer { defer {
logger.error( logger.error(
"The folder for the resource has not been located.", "The folder of the resource has not been located.",
metadata: .metadata( metadata: .metadata(
context: context, context: context,
request: request, request: request,
@ -126,14 +126,12 @@ private extension Logger.Metadata {
context: Context, context: Context,
request: Request, request: Request,
statusCode: HTTPResponse.Status statusCode: HTTPResponse.Status
) -> Logger.Metadata { ) -> Logger.Metadata {[
return [
"hb.request.id": "\(context.id)", "hb.request.id": "\(context.id)",
"hb.request.method": "\(request.method.rawValue)", "hb.request.method": "\(request.method.rawValue)",
"hb.request.path": "\(request.uri.path)", "hb.request.path": "\(request.uri.path)",
"hb.request.status": "\(statusCode.code)" "hb.request.status": "\(statusCode.code)"
] ]}
}
} }

View File

@ -19,6 +19,7 @@ struct DocCMiddleware<
// MARK: Properties // MARK: Properties
private let assetProvider: AssetProvider private let assetProvider: AssetProvider
private let logger: Logger
// MARK: Initialisers // MARK: Initialisers
@ -26,23 +27,30 @@ struct DocCMiddleware<
/// - Parameters: /// - Parameters:
/// - rootFolder: A root folder in the local file system where the *DocC* archive containers are located. /// - rootFolder: A root folder in the local file system where the *DocC* archive containers are located.
/// - threadPool: A thread pool used when loading archives from the file system. /// - threadPool: A thread pool used when loading archives from the file system.
/// - logger: A Logger that outputs information about the root folder requests. /// - logger: A service that interacts with the logging system,
init( init(
_ rootFolder: String, _ rootFolder: String,
threadPool: NIOThreadPool = .singleton, threadPool: NIOThreadPool = .singleton,
logger: Logger = .init(label: "DocCMiddleware") logger: Logger
) where AssetProvider == LocalFileSystem { ) where AssetProvider == LocalFileSystem {
self.assetProvider = LocalFileSystem( self.assetProvider = LocalFileSystem(
rootFolder: rootFolder, rootFolder: rootFolder,
threadPool: threadPool, threadPool: threadPool,
logger: logger logger: logger
) )
self.logger = logger
} }
/// Initialises this middleware with an asset provider, that conforms to the `FileProvider` protocol. /// Initialises this middleware with an asset provider, that conforms to the `FileProvider` protocol.
/// - Parameter assetProvider: An asset provider to use with the middleware. /// - Parameters:
init(assetProvider: AssetProvider) { /// - assetProvider: An asset provider to use with the middleware.
/// - logger: A service that interacts with the logging system,
init(
assetProvider: AssetProvider,
logger: Logger
) {
self.assetProvider = assetProvider self.assetProvider = assetProvider
self.logger = logger
} }
// MARK: Functions // MARK: Functions
@ -57,6 +65,18 @@ struct DocCMiddleware<
!uriPath.contains(.previousFolder), !uriPath.contains(.previousFolder),
uriPath.hasPrefix(.forwardSlash) uriPath.hasPrefix(.forwardSlash)
else { else {
defer {
logger.error(
"The request has issues.",
metadata: .metadata(
context: context,
request: input,
statusCode: .badRequest
),
source: .source
)
}
throw HTTPError(.badRequest) throw HTTPError(.badRequest)
} }
@ -85,6 +105,7 @@ struct DocCMiddleware<
return try await serveFile( return try await serveFile(
String(format: .Format.Path.documentationJSON, nameArchive), String(format: .Format.Path.documentationJSON, nameArchive),
at: pathArchive, at: pathArchive,
input: input,
context: context context: context
) )
} else { } else {
@ -93,6 +114,7 @@ struct DocCMiddleware<
return try await serveFile( return try await serveFile(
uriResource, uriResource,
at: pathArchive, at: pathArchive,
input: input,
context: context context: context
) )
} }
@ -106,6 +128,7 @@ struct DocCMiddleware<
return try await serveFile( return try await serveFile(
uriResource, uriResource,
at: pathArchive, at: pathArchive,
input: input,
context: context context: context
) )
} }
@ -118,6 +141,7 @@ struct DocCMiddleware<
return try await serveFile( return try await serveFile(
String(format: .Format.Path.index, indexPrefix.path, nameArchive), String(format: .Format.Path.index, indexPrefix.path, nameArchive),
at: pathArchive, at: pathArchive,
input: input,
context: context context: context
) )
} else { } else {
@ -128,6 +152,18 @@ struct DocCMiddleware<
} }
} }
defer {
logger.error(
"The request has not been implemented yet.",
metadata: .metadata(
context: context,
request: input,
statusCode: .notImplemented
),
source: .source
)
}
throw HTTPError(.notImplemented) throw HTTPError(.notImplemented)
} }
@ -149,14 +185,39 @@ private extension DocCMiddleware {
func serveFile( func serveFile(
_ path: String, _ path: String,
at folder: String, at folder: String,
input: Request,
context: Context context: Context
) async throws -> Response { ) async throws -> Response {
guard let fileIdentifier = assetProvider.getFileIdentifier(folder + path) else { guard let fileIdentifier = assetProvider.getFileIdentifier(folder + path) else {
defer {
logger.error(
"The resource has not been found.",
metadata: .metadata(
context: context,
request: input,
statusCode: .notFound
),
source: .source
)
}
throw HTTPError(.notFound) throw HTTPError(.notFound)
} }
let body = try await assetProvider.loadFile(id: fileIdentifier, context: context) let body = try await assetProvider.loadFile(id: fileIdentifier, context: context)
defer {
logger.debug(
"The body of the response returned: \(body.contentLength ?? 0) bytes.",
metadata: .metadata(
context: context,
request: input,
statusCode: .ok
),
source: .source
)
}
return .init( return .init(
status: .ok, status: .ok,
headers: [:], headers: [:],
@ -165,3 +226,28 @@ private extension DocCMiddleware {
} }
} }
// MARK: - Logger,Metadata+Functions
private extension Logger.Metadata {
// MARK: Functions
static func metadata<Context: RequestContext>(
context: Context,
request: Request,
statusCode: HTTPResponse.Status
) -> Logger.Metadata {[
"hb.request.id": "\(context.id)",
"hb.request.method": "\(request.method.rawValue)",
"hb.request.path": "\(request.uri.path)",
"hb.request.status": "\(statusCode.code)"
]}
}
// MARK: - String+Constants
private extension String {
static let source = "DocCMiddleware"
}

View File

@ -79,7 +79,7 @@ private extension AppBuilder {
router.addMiddleware { router.addMiddleware {
LogRequestsMiddleware(logger.logLevel) LogRequestsMiddleware(logger.logLevel)
DocCMiddleware(archivesPath) DocCMiddleware(archivesPath, logger: logger)
} }
ArchiveController( ArchiveController(