# FAQs ## Logging / Tracing ### Is Logging supported? Logging is supported by providing a `Logger` from [SwiftLog][swift-log] to the relevant configuration object. For the client: - `ClientConnection.Builder.withBackgroundActivityLogger` allows a logger to be supplied which logs information at the connection level, relating to things such as connectivity state changes, or connection errors. - `CallOptions` allows `logger` to be specified. It is used to log information at the RPC level, such as changes to the state of the RPC. Any connection level metadata will be attached to the logger so that RPC logs may be correlated with connection level changes. For the server: - `Server.Builder.withLogger` allows a `logger` to be specified. It is used as a root logger and is passed down to each accepted connection and in turn each RPC on a connection. The logger is made available in the `context` of each RPC handler. Note that gRPC will not emit logs unless a logger is explicitly provided. ### How can RPCs be traced? For the client: If `logger` is set in the `CallOptions` for an RPC then gRPC may attach a request ID to the metadata of that logger. This is determined by the value of `requestIDProvider` in `CallOptions`. The options for `requestIDProvider` include: - `autogenerated`: a new UUID will be generated (default). - `generated(_:)`: the provided callback will be called to generate a new ID. - `userDefined(_:)`: the provided value will be used. Note: this option should not be set as a default option on a client as all RPCs would used the same ID. - `none`: no request ID will be attached to the logger, this can be useful if a logger already has a request ID associated with it. If a request ID is attached to the logger's metadata it will use the key `grpc_request_id`. If a request ID is provided and the `requestIDHeader` option is set then gRPC will add the ID to the request headers. By default `requestIDHeader` is not set. ## Client Connection Lifecycle ### Is the client's connection long-lived? The `ClientConnection` is intended to be used as a long-living connection to a remote peer. It will manage the underlying network resources automatically, creating a connection when necessary and dropping it when it is no longer required. However, the user must `close()` the connection when finished with it. The underlying connection may be in any of the following states: - Idle: there is no underlying connection. - Connecting: an attempt to establish a connection is being made. - Ready: the connection has been established, a TLS handshake has completed (if applicable) and the first HTTP/2 settings frame has been received. - Transient failure: A transient error occurred either from a ready connection or from a connection attempt. An new connection will be established after some time. (See later sections on connection backoff for more details.) - Shutdown: The application requested that the connection be closed, or a connection error occurred and connection re-establishment was disabled. This state is terminal. The gRPC library [documents][grpc-conn-states] these states in more details. Note that not all information linked is applicable to gRPC Swift. ### How can connection states be observed? A connectivity state delegate may be set using `withConnectivityStateDelegate(_:executingOn:)` on the `ClientConnection.Builder`. The delegate is called on the `DispatchQueue` specified by the `executingOn` parameter. gRPC will create a `DispatchQueue` if one isn't otherwise specified. These state changes will also be logged by the `backgroundActivityLogger` (see above). ### When will the connection idle? The connection will be idled (i.e. the underlying connection closed and moved to the 'idle' state) if there are no outstanding RPCs for 5 minutes (by default). The connection will _not_ be idled if there outstanding RPCs which are not sending or receiving messages. This option may be configured using `withConnectionIdleTimeout` on the `ClientConnection.Builder`. Any RPC called after the connection has idled will trigger a connection attempt. ### How can I keep a connection alive? For long-lived, low-activity RPCs it may be beneficial to configure keepalive. Doing so will periodically send pings to the remote peer. It may also be used to detect unresponsive peers. See the [gRPC Keepalive][grpc-keepalive] documentation for details. ## RPC Lifecycle ### How do I start an RPC? RPCs are usually started by invoking a method on a generated client. Each generated client relies on an underlying `GRPCChannel` to provide transport. RPCs can also be made without a generated client by using `AnyServiceClient`. This requires the user know the path (i.e. '/echo/Get') and request and response types for the RPC. ### Are failing RPCs retried automatically? RPCs are never automatically retried by gRPC Swift. The framework cannot determine whether your RPC is idempotent, it is therefore not safe for gRPC Swift to automatically retry RPCs for you. ### Deadlines and Timeouts It's recommended that deadlines are used to enforce a limit on the duration of an RPC. Users may set a time limit (either a deadline or a timeout) on the `CallOptions` for each call, or as a default on a client. RPCs which have not completed before the time limit will be failed with status code 4 ('deadline exceeded'). ## Compression gRPC Swift supports compression. ### How to enable compression for the Client You can configure compression via the messageEncoding property on CallOptions: ```swift // Configure encoding let encodingConfiguration = ClientMessageEncoding.Configuration( forRequests: .gzip, // use gzip for requests acceptableForResponses: .all, // accept all supported algorithms for responses decompressionLimit: .ratio(20) // reject messages and fail the RPC if a response decompresses to over 20x its compressed size ) // Enable compression with configuration let options = CallOptions(messageEncoding: .enabled(encodingConfiguration)) // Use the options to make a request let rpc = echo.get(request, callOptions: options) // ... ``` [grpc-conn-states]: connectivity-semantics-and-api.md [grpc-keepalive]: keepalive.md [swift-log]: https://github.com/apple/swift-log