@@ -19,8 +19,6 @@ import Metrics
1919import NIO
2020import NIOConcurrencyHelpers
2121
22- private let loggingKeyID = String ( describing: RedisConnection . self)
23-
2422extension RedisConnection {
2523 /// The documented default port that Redis connects through.
2624 ///
@@ -54,15 +52,15 @@ extension RedisConnection {
5452 /// - socket: The `NIO.SocketAddress` information of the Redis instance to connect to.
5553 /// - eventLoop: The `NIO.EventLoop` that this connection will execute all tasks on.
5654 /// - password: The optional password to use for authorizing the connection with Redis.
57- /// - logger: The `Logging.Logger` instance to use for all logging purposes. If one is not provided, one will be created.
55+ /// - logger: The `Logging.Logger` instance to use for all client logging purposes. If one is not provided, one will be created.
5856 /// A `Foundation.UUID` will be attached to the metadata to uniquely identify this connection instance's logs.
59- /// - tcpClient: If you have chosen to configure a `NIO.ClientBootstrap` yourself, this will.
57+ /// - tcpClient: If you have chosen to configure a `NIO.ClientBootstrap` yourself, this will be used instead of the `makeRedisTCPClient` instance .
6058 /// - Returns: A `NIO.EventLoopFuture` that resolves with the new connection after it has been opened, and if a `password` is provided, authenticated.
6159 public static func connect(
6260 to socket: SocketAddress ,
6361 on eventLoop: EventLoop ,
6462 password: String ? = nil ,
65- logger: Logger = Logger ( label: " RediStack.RedisConnection " ) ,
63+ logger: Logger = . init ( label: " RediStack.RedisConnection " ) ,
6664 tcpClient: ClientBootstrap ? = nil
6765 ) -> EventLoopFuture < RedisConnection > {
6866 let client = tcpClient ?? ClientBootstrap . makeRedisTCPClient ( group: eventLoop)
@@ -101,7 +99,13 @@ extension RedisConnection {
10199///
102100/// See `NIO.SocketAddress`, `NIO.EventLoop`, and `RedisClient`
103101public final class RedisConnection : RedisClient {
104- /// See `RedisClient.eventLoop`
102+ /// A unique identifer to represent this connection.
103+ public let id = UUID ( )
104+ public private( set) var logger : Logger {
105+ didSet {
106+ self . logger [ metadataKey: String ( describing: RedisConnection . self) ] = . string( self . id. description)
107+ }
108+ }
105109 public var eventLoop : EventLoop { return self . channel. eventLoop }
106110 /// Is the connection to Redis still open?
107111 public var isConnected : Bool {
@@ -124,11 +128,10 @@ public final class RedisConnection: RedisClient {
124128 }
125129
126130 internal let channel : Channel
127- private var logger : Logger
128131
129132 private let autoflush = Atomic < Bool > ( value: true )
130133 private let _stateLock = Lock ( )
131- private var _state : ConnectionState
134+ private var _state = ConnectionState . open
132135 private var state : ConnectionState {
133136 get { return _stateLock. withLock { self . _state } }
134137 set ( newValue) { _stateLock. withLockVoid { self . _state = newValue } }
@@ -144,10 +147,7 @@ public final class RedisConnection: RedisClient {
144147 internal init ( configuredRESPChannel: Channel , logger: Logger ) {
145148 self . channel = configuredRESPChannel
146149 self . logger = logger
147-
148- self . logger [ metadataKey: loggingKeyID] = " \( UUID ( ) ) "
149- self . _state = . open
150- self . logger. debug ( " Connection created. " )
150+
151151 RedisMetrics . activeConnectionCount. increment ( )
152152 RedisMetrics . totalConnectionCount. increment ( )
153153
@@ -159,9 +159,11 @@ public final class RedisConnection: RedisClient {
159159 guard self . state == . open else { return }
160160
161161 self . state = . closed
162- self . logger. warning ( " Channel was closed unexpectedly. " )
162+ self . logger. error ( " Channel was closed unexpectedly. " )
163163 RedisMetrics . activeConnectionCount. decrement ( )
164164 }
165+
166+ self . logger. trace ( " Connection created. " )
165167 }
166168
167169 internal enum ConnectionState {
@@ -182,6 +184,8 @@ extension RedisConnection {
182184 /// - Returns: A `NIO.EventLoopFuture` that resolves with the command's result stored in a `RESPValue`.
183185 /// If a `RedisError` is returned, the future will be failed instead.
184186 public func send( command: String , with arguments: [ RESPValue ] ) -> EventLoopFuture < RESPValue > {
187+ self . logger. trace ( " Received command " )
188+
185189 guard self . isConnected else {
186190 let error = RedisClientError . connectionClosed
187191 logger. warning ( " \( error. localizedDescription) " )
@@ -203,12 +207,17 @@ extension RedisConnection {
203207 RedisMetrics . commandRoundTripTime. recordNanoseconds ( duration)
204208
205209 // log the error here instead
206- guard case let . failure( error) = result else { return }
210+ guard case let . failure( error) = result else {
211+ self . logger. trace ( " Command completed. " )
212+ return
213+ }
207214 self . logger. error ( " \( error. localizedDescription) " )
208215 }
209216
210217 self . logger. debug ( " Sending command \" \( command) \" \( arguments. count > 0 ? " with \( arguments) " : " " ) " )
211218
219+ defer { self . logger. trace ( " Command sent through channel. " ) }
220+
212221 if self . sendCommandsImmediately {
213222 return channel. writeAndFlush ( command) . flatMap { promise. futureResult }
214223 } else {
@@ -228,6 +237,8 @@ extension RedisConnection {
228237 /// - Returns: A `NIO.EventLoopFuture` that resolves when the connection has been closed.
229238 @discardableResult
230239 public func close( ) -> EventLoopFuture < Void > {
240+ self . logger. trace ( " Received request to close the connection. " )
241+
231242 guard self . isConnected else {
232243 // return the channel's close future, which is resolved as the last step in channel shutdown
233244 return self . channel. closeFuture
@@ -257,9 +268,9 @@ extension RedisConnection {
257268 message: . array( [ RESPValue ( bulk: " QUIT " ) ] ) ,
258269 responsePromise: promise
259270 )
260-
261- logger. debug ( " Sending QUIT command. " )
262-
271+
272+ logger. trace ( " Sending QUIT command. " )
273+
263274 return channel. writeAndFlush ( command) // write the command
264275 . flatMap { promise. futureResult } // chain the callback to the response's
265276 . map { _ in ( ) } // ignore the result's value
@@ -290,3 +301,15 @@ extension RedisConnection {
290301 }
291302 }
292303}
304+
305+ // MARK: Logging
306+
307+ extension RedisConnection {
308+ /// Updates the client's logger, attaching this connection's ID to the metadata.
309+ ///
310+ /// See `RedisClient.setLogging(to:)` and `RedisConnection.id`.
311+ /// - Parameter logger: The `Logging.Logger` that is desired to receive all client logs.
312+ public func setLogging( to logger: Logger ) {
313+ self . logger = logger
314+ }
315+ }
0 commit comments