Skip to main content

Reporting tool for kafka topics with retentions, sizes, earliest and latest message timestamps

Project description

A reporting tool for kafka topics.

Show any or all of the following attributes for each topic in a cluster:

  • sizes (DescribeLogDirsRequest)
  • retention policies
  • earliest/latest message timestamps (watermarks)

With larger teams and installations, misconfiguration often results in lots of resource waste. Auditing with this tool has helped.

Installation

pip install kafkareport

Usage

Tested only with SASL_SSL + SCRAM_SHA_512 u/p, and with AWS_MSK_IAM on AWS MSK provisioned. MSK Serverless is not supported because it doesn't expose DescribeLogDirs, which the size report depends on. See Addenda for details.

All times should be UTC.

Configuration

SASL/SCRAM

Json file of a dict passed to confluent_kafka's consumer, so it should follow the same format except for group.id. It is automatically set. See env.json for a sample conf file.

AWS MSK IAM

Set sasl.mechanism to the sentinel AWS_MSK_IAM and drop the sasl.username / sasl.password keys. See env-iam.json for a sample conf file.

Credentials come from the default AWS chain (env, profile, instance profile). Region resolves from AWS_REGION / AWS_DEFAULT_REGION / ~/.aws/config. KafkaReport(debug=True)/kafkareport -v also enables the MSK signer's credential debug, which logs the AWS credentials being used to sign the OAUTHBEARER token, handy when access is denied.

CLI

% kafkareport ~/aws.json --csv report.csv
+----------------+-------+----------------------------------+----------------------------------+--------------+-----------------+---------------------+
| topic          | bytes | earliest                         | latest                           | retention.ms | retention.bytes | delete.retention.ms |
+----------------+-------+----------------------------------+----------------------------------+--------------+-----------------+---------------------+
| kafkareportdue | 2330  | 2024-06-30 20:04:44.486000+00:00 | 2024-06-30 20:04:46.041000+00:00 | 16800001     | 16800001        | 16800001            |
| kafkareportuno | 2268  | 2024-06-30 20:04:42.880000+00:00 | 2024-06-30 20:04:44.431000+00:00 | 16800001     | 16800001        | 16800001            |
+----------------+-------+----------------------------------+----------------------------------+--------------+-----------------+---------------------+

% cat report.csv
topic,bytes,earliest,latest,retention.ms,retention.bytes,delete.retention.ms
kafkareportdue,2330,2024-06-30 20:04:44.486000+00:00,2024-06-30 20:04:46.041000+00:00,16800001,16800001,16800001
kafkareportuno,2268,2024-06-30 20:04:42.880000+00:00,2024-06-30 20:04:44.431000+00:00,16800001,16800001,16800001

Lib

Docs

>>> from kafkareport import KafkaReport

>>> conf = {"bootstrap.servers": "localhost:9092", "ssl.endpoint.identification.algorithm": "none"}

>>> report = KafkaReport(conf)

>>> report.get_topicnames()
dict_keys(['kafkareportdue', 'kafkareportuno', '__consumer_offsets'])

>>> for topic in report.get_topicnames():
...     print(topic)
...     report.retentions(topic)
...     report.watermarks(topic)
...
kafkareportdue
{'retention.ms': 16800001, 'retention.bytes': 16800001, 'delete.retention.ms': 16800001}
{'earliest': datetime.datetime(2024, 6, 30, 20, 8, 57, 554000, tzinfo=datetime.timezone.utc), 'latest': datetime.datetime(2024, 6, 30, 20, 8, 59, 99000, tzinfo=datetime.timezone.utc)}
kafkareportuno
{'retention.ms': 16800001, 'retention.bytes': 16800001, 'delete.retention.ms': 16800001}
{'earliest': datetime.datetime(2024, 6, 30, 20, 8, 55, 975000, tzinfo=datetime.timezone.utc), 'latest': datetime.datetime(2024, 6, 30, 20, 8, 57, 503000, tzinfo=datetime.timezone.utc)}
__consumer_offsets
{'retention.ms': 604800000, 'retention.bytes': -1, 'delete.retention.ms': 86400000}
{'earliest': '', 'latest': ''}

>>> report.topic_sizes()
[{'topic': 'kafkareportuno', 'bytes': 2690}, {'topic': 'kafkareportdue', 'bytes': 2328}, {'topic': '__consumer_offsets', 'bytes': 0}]

>>> report.watermarks("kafkareportuno")
{'earliest': datetime.datetime(2024, 6, 30, 20, 8, 55, 975000, tzinfo=datetime.timezone.utc), 'latest': datetime.datetime(2024, 6, 30, 20, 8, 57, 503000, tzinfo=datetime.timezone.utc)}

Development

This is a poetry project, so it should be butter once you get that sorted. Install pre-commit for lint/format on commit, typing on push.

pre-commit install --hook-type pre-push for typing pre-push.

Testing

Testing runs against kafka/zookeper containers (plaintext only; no auth), as you can see in the Github actions. docker compose up should do the trick.

pytest can use --conf=/some/file.json instead of default for localstack. This will manipulate pytest.topics on the kafka servers.

See Live testing against AWS MSK for details on how to quickly smoke test against actual clusters.

Occasionally, e.g. on laptop wake, the kafka container will be in a weird state. docker compose down && docker compose up always did the trick.

Addenda

Watermarks use a thread for each topic partition, but it can still take a while. -v for gory details along the way, KafkaReport(debug=True) for the lib.

This project started with confluent_kafka, but DescribeLogDirsRequest still isn't implemented in confluent_kafka or the underlying librdkafka. kafka-python has had a native describe_log_dirs since 2.1.0, but the stable 2.x signature can't target a specific broker — that landed on master/3.0.0.dev via PR #2881. Until that ships, logdirs.py monkey-patches a per-broker wrapper onto KafkaAdminClient.describe_log_dirs.

As a result, there is a janky confluent_kafka to kafka-python AdminClient conf map, now lifted into kafkareport/auth.py since IAM doubled its complexity. It handles plaintext, SCRAM, and the AWS_MSK_IAM sentinel (translated to OAUTHBEARER + an MSK signer-backed token provider for kafka-python and an oauth_cb for confluent_kafka).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kafkareport-0.1.1.tar.gz (12.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kafkareport-0.1.1-py3-none-any.whl (12.3 kB view details)

Uploaded Python 3

File details

Details for the file kafkareport-0.1.1.tar.gz.

File metadata

  • Download URL: kafkareport-0.1.1.tar.gz
  • Upload date:
  • Size: 12.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for kafkareport-0.1.1.tar.gz
Algorithm Hash digest
SHA256 27c9cf40e06a582a0d1ceb9c21c33c5ce8e184420fdfd69917771236607175b9
MD5 967f6113fb0b678069858d49a48ab69f
BLAKE2b-256 d6d2f1791cfff459db576dfd8cccef5f4a901c0aab2da3dd917cd4338378b849

See more details on using hashes here.

Provenance

The following attestation bundles were made for kafkareport-0.1.1.tar.gz:

Publisher: publish.yml on newvoll/kafkareport

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kafkareport-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: kafkareport-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 12.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for kafkareport-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 75f5c1e0feb4b7dbb2784f9970d96cde76177102c9c5dd87eb89b439fa341f89
MD5 3e83c9c3e70e19594ae89a3870714430
BLAKE2b-256 99fa8386d3b74ec3d64a38d9b7a0f75b3b70acae0276b8a674cf9825c210000d

See more details on using hashes here.

Provenance

The following attestation bundles were made for kafkareport-0.1.1-py3-none-any.whl:

Publisher: publish.yml on newvoll/kafkareport

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page