-
Notifications
You must be signed in to change notification settings - Fork 37
Expand DocC: config-type reference, rebalances/events, error handling, observability #248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 4 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
2b3e5b0
Document configuration types via DocC extension files
ssikka100 2fe3d7e
Document consumer rebalances and the events sequence
ssikka100 a35ea3b
Add error-handling, observability, and migration articles
ssikka100 4a768b8
Merge branch 'main' into docc-current-client
ssikka100 43ac7fa
Address review: prose abstracts, active voice, remove Migrating
ssikka100 bfdd4e8
Cross-link DocC articles and add symbol pages for consumer/producer
ssikka100 8817026
Drop librdkafka from config-type overviews
ssikka100 281386b
Remove sibling-article Topics groups to break DocC curation cycles
ssikka100 0a0bc4e
Merge branch 'main' into docc-current-client
ssikka100 c4e00aa
Address review feedback: prose abstracts, imperative headings, error-…
ssikka100 f4b2a3f
Make RDKafkaCode curation page headings parallel
ssikka100 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # Handling errors | ||
|
|
||
| Learn where Kafka errors surface and how to classify them to decide whether to retry, recreate the client, or fail. | ||
|
ssikka100 marked this conversation as resolved.
Outdated
|
||
|
|
||
| ## Overview | ||
|
|
||
| Both the producer and the consumer report failures as ``KafkaError`` values. A ``KafkaError`` carries a ``KafkaError/code`` describing the kind of failure and, when the error originates from librdkafka, a ``KafkaError/rdKafkaCode`` with the specific underlying code. The ``KafkaError/isFatal`` and ``KafkaError/isRetriable`` flags tell you how to respond. | ||
|
|
||
| ## Where errors surface | ||
|
ssikka100 marked this conversation as resolved.
Outdated
|
||
|
|
||
| A ``KafkaError`` reaches your code in three ways: | ||
|
|
||
| - **Thrown** from throwing calls such as ``KafkaProducer/send(_:)``, ``KafkaProducer/sendAndAwait(_:)``, ``KafkaConsumer/subscribe(topics:)``, and ``KafkaConsumer/commit(_:)``. | ||
| - **On an event sequence**, as ``KafkaConsumerEvent/error(_:)`` or ``KafkaProducerEvent/error(_:)`` — for example, a broker disconnection or an authentication failure. | ||
| - **In a delivery report**, when a ``KafkaDeliveryReport``'s status is `failure` because a message could not be delivered. | ||
|
|
||
| ## Classify an error | ||
|
|
||
| Use ``KafkaError/isFatal`` and ``KafkaError/isRetriable`` to decide how to respond, and inspect ``KafkaError/rdKafkaCode`` for finer-grained handling: | ||
|
|
||
| ```swift | ||
| func handle(_ error: KafkaError, logger: Logger) { | ||
| // A fatal error means the client instance can no longer be used: | ||
| // shut it down and create a new one. | ||
| if error.isFatal { | ||
| logger.critical("Fatal Kafka error, recreate the client", metadata: ["error": "\(error)"]) | ||
| return | ||
| } | ||
|
|
||
| // A retriable error may succeed if the operation is attempted again. | ||
| if error.isRetriable { | ||
| logger.warning("Retriable Kafka error, retrying", metadata: ["error": "\(error)"]) | ||
| return | ||
| } | ||
|
|
||
| // For finer-grained handling, inspect the underlying librdkafka code. | ||
| switch error.rdKafkaCode { | ||
| case .allBrokersDown, .transport: | ||
| logger.warning("Lost connectivity to the cluster", metadata: ["error": "\(error)"]) | ||
| case .authentication, .ssl: | ||
| logger.error("Authentication or TLS failure", metadata: ["error": "\(error)"]) | ||
| default: | ||
| logger.error("Kafka error", metadata: ["kind": "\(error.code)", "error": "\(error)"]) | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ``KafkaError/rdKafkaCode`` is `nil` for errors that don't originate from librdkafka — such as configuration or lifecycle errors — in which case ``KafkaError/isFatal`` and ``KafkaError/isRetriable`` are both `false`. | ||
|
ssikka100 marked this conversation as resolved.
|
||
|
|
||
| ## Topics | ||
|
|
||
| ### Errors | ||
|
|
||
| - ``KafkaError`` | ||
| - ``KafkaError/ErrorCode`` | ||
| - ``KafkaError/RDKafkaCode`` | ||
|
|
||
| ### Error events | ||
|
|
||
| - ``KafkaConsumerEvent`` | ||
| - ``KafkaProducerEvent`` | ||
| - ``KafkaDeliveryReport`` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # ``Kafka/KafkaConfig`` | ||
|
|
||
| A namespace of typed option values for Kafka client configuration properties. | ||
|
|
||
| ## Overview | ||
|
|
||
| Nested types provide type-safe wrappers for the string values librdkafka accepts for enum-valued options such as ``KafkaConfig/SecurityProtocol``, ``KafkaConfig/CompressionCodec``, and ``KafkaConfig/GroupProtocol``. Assign these values to properties on ``KafkaConsumerConfig`` and ``KafkaProducerConfig``. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # ``Kafka/KafkaConsumerConfig`` | ||
|
|
||
| Configures a ``KafkaConsumer``. | ||
|
ssikka100 marked this conversation as resolved.
Outdated
|
||
|
|
||
| ## Overview | ||
|
|
||
| Provide broker addresses through ``KafkaConsumerConfig/bootstrapServers`` and a consumption strategy through ``KafkaConsumerConfig/consumptionStrategy``, then pass the configuration to a ``KafkaConsumer`` initializer. Additional properties mirror librdkafka's consumer configuration surface; consult individual property documentation for defaults and semantics. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # ``Kafka/KafkaProducerConfig`` | ||
|
|
||
| Configures a ``KafkaProducer``. | ||
|
ssikka100 marked this conversation as resolved.
Outdated
|
||
|
|
||
| ## Overview | ||
|
|
||
| Provide broker addresses through ``KafkaProducerConfig/bootstrapServers``, then pass the configuration to a ``KafkaProducer`` initializer. Additional properties mirror librdkafka's producer configuration surface; consult individual property documentation for defaults and semantics. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # Migrating to the current API | ||
|
ssikka100 marked this conversation as resolved.
Outdated
|
||
|
|
||
| Move from the deprecated configuration types and methods to their current replacements. | ||
|
|
||
| ## Overview | ||
|
|
||
| Earlier versions of the client configured a ``KafkaConsumer`` or ``KafkaProducer`` with the ``KafkaConsumerConfiguration`` and ``KafkaProducerConfiguration`` types. These are deprecated in favor of ``KafkaConsumerConfig`` and ``KafkaProducerConfig``, which expose librdkafka's full configuration surface as typed Swift properties. | ||
|
|
||
| The deprecated types still compile, but the compiler emits a warning pointing to the replacement. Adopt the current API to silence those warnings and to reach configuration options the older types don't expose. | ||
|
|
||
| ## Configuration types | ||
|
|
||
| Replace each `Configuration` type with the corresponding `Config` type: | ||
|
|
||
| | Deprecated | Current | | ||
| | --- | --- | | ||
| | ``KafkaConsumerConfiguration`` | ``KafkaConsumerConfig`` | | ||
| | ``KafkaProducerConfiguration`` | ``KafkaProducerConfig`` | | ||
|
|
||
| ## Initializers | ||
|
|
||
| The client initializers now take a `config:` parameter of the `Config` type in place of the `configuration:` parameter of the `Configuration` type: | ||
|
|
||
| ```swift | ||
| // Deprecated | ||
| let consumer = try KafkaConsumer(configuration: consumerConfiguration, logger: logger) | ||
|
|
||
| // Current | ||
| var config = KafkaConsumerConfig() | ||
| config.bootstrapServers = ["localhost:9092"] | ||
| config.consumptionStrategy = .group(id: "example-group", topics: ["topic-name"]) | ||
| let consumer = try KafkaConsumer(config: config, logger: logger) | ||
| ``` | ||
|
|
||
| For the event-carrying variants, use ``KafkaConsumer/makeConsumerWithEvents(config:logger:)`` and ``KafkaProducer/makeProducerWithEvents(config:logger:)``, which likewise take the `Config` type. | ||
|
|
||
| ## Renamed methods | ||
|
|
||
| ``KafkaConsumer/commitSync(_:)`` was renamed to ``KafkaConsumer/commit(_:)``. The behavior is unchanged. | ||
|
|
||
| ## Topics | ||
|
|
||
| ### Current configuration types | ||
|
|
||
| - ``KafkaConsumerConfig`` | ||
| - ``KafkaProducerConfig`` | ||
|
|
||
| ### Deprecated types | ||
|
|
||
| - ``KafkaConsumerConfiguration`` | ||
| - ``KafkaProducerConfiguration`` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| # Observability | ||
|
ssikka100 marked this conversation as resolved.
Outdated
|
||
|
|
||
| Emit metrics and structured logs from the producer and consumer. | ||
|
|
||
| ## Overview | ||
|
|
||
| The Kafka client integrates with [swift-metrics](https://github.com/apple/swift-metrics) for runtime metrics and [swift-log](https://github.com/apple/swift-log) for structured logging. Both are opt-in through the client configuration and the `Logger` you provide. | ||
|
|
||
| ## Emit metrics | ||
|
|
||
| The client periodically samples librdkafka's internal statistics and records them into [swift-metrics](https://github.com/apple/swift-metrics) gauges that you supply. Configure this through the ``KafkaConsumerConfig/metrics`` (or ``KafkaProducerConfig/metrics``) property: set an update interval and assign a `Gauge` to each statistic you want to track. | ||
|
ssikka100 marked this conversation as resolved.
Outdated
|
||
|
|
||
|
ssikka100 marked this conversation as resolved.
|
||
| ```swift | ||
| import Kafka | ||
| import Metrics | ||
|
|
||
| var config = KafkaConsumerConfig() | ||
| config.bootstrapServers = ["localhost:9092"] | ||
| config.consumptionStrategy = .group(id: "example-group", topics: ["topic-name"]) | ||
|
|
||
| // Sample statistics once per second into swift-metrics gauges. | ||
| config.metrics.updateInterval = .seconds(1) | ||
| config.metrics.totalKafkaBrokerRequests = Gauge(label: "kafka_consumer_broker_requests") | ||
| config.metrics.totalKafkaBrokerMessagesReceived = Gauge(label: "kafka_consumer_messages_received") | ||
| config.metrics.queuedOperation = Gauge(label: "kafka_consumer_queued_operations") | ||
|
|
||
| let consumer = try KafkaConsumer(config: config, logger: logger) | ||
| ``` | ||
|
|
||
| Metrics are emitted only when ``KafkaConfiguration/ConsumerMetrics/updateInterval`` is set **and** at least one gauge is assigned; otherwise the client skips statistics collection entirely. The producer exposes the same pattern through ``KafkaProducerConfig/metrics`` with producer-specific gauges such as ``KafkaConfiguration/ProducerMetrics/queuedProducerMessages`` and ``KafkaConfiguration/ProducerMetrics/totalKafkaBrokerMessagesSent``. | ||
|
ssikka100 marked this conversation as resolved.
Outdated
|
||
|
|
||
| The gauges you assign are ordinary [swift-metrics](https://github.com/apple/swift-metrics) types, so the values reach whatever metrics backend you bootstrap through `MetricsSystem`. | ||
|
|
||
| ## Structured logging | ||
|
ssikka100 marked this conversation as resolved.
Outdated
|
||
|
|
||
| Pass a `Logger` when creating a ``KafkaProducer`` or ``KafkaConsumer``. The client logs lifecycle and operational events through it, and enriches every entry with structured metadata so you can filter and correlate logs across many clients: | ||
|
|
||
| | Metadata key | Value | | ||
| | --- | --- | | ||
| | `kafka.client.id` | the configured `clientId` | | ||
| | `kafka.client.type` | `producer` or `consumer` | | ||
| | `kafka.group.id` | the consumer group (consumers only) | | ||
|
|
||
| ```swift | ||
| import Kafka | ||
| import Logging | ||
|
|
||
| let logger = Logger(label: "kafka") | ||
|
|
||
| var config = KafkaConsumerConfig() | ||
| config.clientId = "orders-consumer" | ||
| config.consumptionStrategy = .group(id: "orders", topics: ["orders"]) | ||
|
|
||
| let consumer = try KafkaConsumer(config: config, logger: logger) | ||
| // Every log entry from this consumer now carries kafka.client.id, kafka.client.type, | ||
| // and kafka.group.id. | ||
| ``` | ||
|
|
||
| Set the `Logger`'s log level to control verbosity — the client logs routine progress at `debug` and `trace`, and surfaces problems at `info` and above. | ||
|
|
||
| ## Topics | ||
|
|
||
| ### Metrics | ||
|
|
||
| - ``KafkaConfiguration/ConsumerMetrics`` | ||
| - ``KafkaConfiguration/ProducerMetrics`` | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.