Skip to content

Commit

Permalink
Allow client error delegate to have a logger injected (#654)
Browse files Browse the repository at this point in the history
Motivation:

When errors are logged it's useful to have some contextual information.
We can enable this by injecting a `logger` into the error delegate.

Modifications:

Change the API for the `ClientErrorDelegate` to also pass in a logger.
Remove additional logging from next to the call to the delegate.

Result:

Users can log errors with more contextual information in the delegate.
  • Loading branch information
glbrntt authored Dec 11, 2019
1 parent 3111de6 commit 58762ba
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Sources/GRPC/ClientConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ extension ClientConnection {
public init(
target: ConnectionTarget,
eventLoopGroup: EventLoopGroup,
errorDelegate: ClientErrorDelegate? = DebugOnlyLoggingClientErrorDelegate.shared,
errorDelegate: ClientErrorDelegate? = LoggingClientErrorDelegate(),
connectivityStateDelegate: ConnectivityStateDelegate? = nil,
tls: Configuration.TLS? = nil,
connectionBackoff: ConnectionBackoff? = ConnectionBackoff()
Expand Down
39 changes: 13 additions & 26 deletions Sources/GRPC/ClientErrorDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,36 +27,23 @@ public protocol ClientErrorDelegate: class {
///
/// - Parameters:
/// - error: The error which was caught.
/// - logger: A logger with relevant metadata for the RPC or connection the error relates to.
/// - file: The file where the error was raised.
/// - line: The line within the file where the error was raised.
func didCatchError(_ error: Error, file: StaticString, line: Int)
func didCatchError(_ error: Error, logger: Logger, file: StaticString, line: Int)
}

/// A `ClientErrorDelegate` which logs errors only in debug builds.
public class DebugOnlyLoggingClientErrorDelegate: ClientErrorDelegate {
public static let shared = DebugOnlyLoggingClientErrorDelegate()
private let logger = Logger(labelSuffix: "ClientErrorDelegate")
/// A `ClientErrorDelegate` which logs errors.
public class LoggingClientErrorDelegate: ClientErrorDelegate {
public init() { }

private init() { }

public func didCatchError(_ error: Error, file: StaticString, line: Int) {
debugOnly {
self.logger.error(
"client error",
metadata: [MetadataKey.error: "\(error)"],
file: "\(file)",
function: "<unknown>",
line: UInt(line)
)
}
public func didCatchError(_ error: Error, logger: Logger, file: StaticString, line: Int) {
logger.error(
"grpc client error",
metadata: [MetadataKey.error: "\(error)"],
file: "\(file)",
function: "<unknown>",
line: UInt(line)
)
}
}

/// A utility function that runs the body code only in debug builds, without emitting compiler
/// warnings.
///
/// This is currently the only way to do this in Swift: see
/// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion.
internal func debugOnly(_ body: () -> Void) {
assert({ body(); return true }())
}
3 changes: 1 addition & 2 deletions Sources/GRPC/DelegatingErrorHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ public class DelegatingErrorHandler: ChannelInboundHandler {

if let delegate = self.delegate {
let grpcError = (error as? GRPCError) ?? .unknown(error, origin: .client)
delegate.didCatchError(grpcError.wrappedError, file: grpcError.file, line: grpcError.line)
delegate.didCatchError(grpcError.wrappedError, logger: self.logger, file: grpcError.file, line: grpcError.line)
}
self.logger.error("caught error in client channel", metadata: [MetadataKey.error: "\(error)"])
context.close(promise: nil)
}
}
2 changes: 1 addition & 1 deletion Sources/GRPC/GRPCClientResponseChannelHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ internal class GRPCClientResponseChannelHandler<ResponseMessage: Message>: Chann
/// - Parameter error: the error to observe.
internal func onError(_ error: Error) {
let grpcError = (error as? GRPCError) ?? GRPCError.unknown(error, origin: .client)
self.errorDelegate?.didCatchError(grpcError.wrappedError, file: grpcError.file, line: grpcError.line)
self.errorDelegate?.didCatchError(grpcError.wrappedError, logger: self.logger, file: grpcError.file, line: grpcError.line)
self.onStatus(grpcError.asGRPCStatus())
}

Expand Down
5 changes: 5 additions & 0 deletions Sources/GRPC/Shims.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ extension Server.Configuration {

@available(*, deprecated, renamed: "PlatformSupport")
public enum GRPCNIO {}

extension ClientErrorDelegate {
@available(*, deprecated, message: "Please use 'didCatchError(_:logger:file:line:)' instead")
public func didCatchError(_ error: Error, file: StaticString, line: Int) { }
}
3 changes: 2 additions & 1 deletion Tests/GRPCTests/ClientTLSFailureTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Foundation
import GRPC
import GRPCSampleData
import EchoImplementation
import Logging
import NIO
import NIOSSL
import XCTest
Expand All @@ -29,7 +30,7 @@ class ErrorRecordingDelegate: ClientErrorDelegate {
self.expectation = expectation
}

func didCatchError(_ error: Error, file: StaticString, line: Int) {
func didCatchError(_ error: Error, logger: Logger, file: StaticString, line: Int) {
self.errors.append(error)
self.expectation.fulfill()
}
Expand Down
3 changes: 2 additions & 1 deletion Tests/GRPCTests/DelegatingErrorHandlerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Foundation
import GRPC
import NIO
import NIOSSL
import Logging
import XCTest

class DelegatingErrorHandlerTests: GRPCTestCase {
Expand All @@ -25,7 +26,7 @@ class DelegatingErrorHandlerTests: GRPCTestCase {

init() { }

func didCatchError(_ error: Error, file: StaticString, line: Int) {
func didCatchError(_ error: Error, logger: Logger, file: StaticString, line: Int) {
self.errors.append(error)
}
}
Expand Down

0 comments on commit 58762ba

Please sign in to comment.