Skip to content

Conversation

k-raina
Copy link
Member

@k-raina k-raina commented Aug 21, 2025

What

Key Features:

  • MetricsCollector: Real-time performance metrics collection with latency tracking, memory monitoring, and throughput analysis
  • MetricsBounds: Configurable performance thresholds with automatic validation
  • Enhanced Tests: All existing ducktape tests now include integrated benchmark metrics
  • Rich Reporting: Detailed performance reports with P50/P95/P99 latencies, memory usage, and batch efficiency

Metrics Collected:

  • Throughput: Send/delivery rates (msg/s, MB/s) with realistic bounds (1k+ msg/s)
  • Latency: P50/P95/P99 percentiles using Python's statistics.quantiles()
  • Memory: Peak usage and growth tracking via psutil
  • Efficiency: Messages per poll, buffer utilization, per-topic/partition breakdowns
  • Reliability: Success/error rates with comprehensive validation

Files Added:

  • tests/ducktape/benchmark_metrics.py - Complete benchmark framework

Files Modified:

  • tests/ducktape/test_producer.py - Enhanced all tests with integrated metrics
  • tests/ducktape/README.md - Updated documentation

Checklist

  • Contains customer facing changes? Including API/behavior changes
    • No breaking changes - all existing tests enhanced with metrics, not replaced
  • Did you add sufficient unit test and/or integration test coverage for this PR?
    • Yes - all existing ducktape tests now include comprehensive metrics validation
    • Validated with 348k+ msg/s throughput and sub-100ms P95 latency

References

Test & Review

# Run enhanced ducktape tests with integrated benchmarks ./tests/ducktape/run_ducktape_test.py
@Copilot Copilot AI review requested due to automatic review settings August 21, 2025 12:44
@k-raina k-raina requested review from a team and MSeal as code owners August 21, 2025 12:44
@confluent-cla-assistant
Copy link

🎉 All Contributor License Agreements have been signed. Ready to merge.
Please push an empty commit if you would like to re-run the checks to verify CLA status for all contributors.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a comprehensive benchmark framework for Kafka producer testing in the ducktape test suite. The framework provides real-time performance metrics collection, validation against configurable bounds, and detailed reporting capabilities.

  • Implements a complete MetricsCollector system with latency tracking, memory monitoring, and throughput analysis
  • Enhances all existing ducktape tests with integrated benchmark metrics without breaking changes
  • Adds configurable performance bounds validation with realistic thresholds (1k+ msg/s throughput)

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 9 comments.

File Description
tests/ducktape/benchmark_metrics.py New comprehensive benchmark framework with MetricsCollector, MetricsBounds, and reporting utilities
tests/ducktape/test_producer.py Enhanced all producer tests with integrated metrics collection and validation
tests/ducktape/README.md Updated documentation to reflect new metrics capabilities and additional psutil dependency

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.


# Use quantiles for P95, P99 (more accurate than custom implementation)
try:
quantiles = statistics.quantiles(self.delivery_latencies, n=100)
Copy link

Copilot AI Aug 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Computing quantiles with n=100 for every summary is computationally expensive. Consider using a more efficient approach like numpy.percentile or caching the sorted data.

Copilot uses AI. Check for mistakes.

@sonarqube-confluent

This comment has been minimized.

@sonarqube-confluent

This comment has been minimized.

Copy link
Contributor

@MSeal MSeal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments. I was debating if we should use something like locust for this.. might be worth switching to down the road but you kind of have to hack it to do any non-RESTful patterns for testing. e.g. https://github.com/SvenskaSpel/locust-plugins/blob/master/examples/kafka_ex.py

except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
# Handle edge cases where process might not exist or be accessible
return None
except Exception:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not catch generic Exception here and just let it boil up to be remediated

return None


class MetricsBounds:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a TODO: load from config file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in commit eb493bb

latency_ms = (time.time() - send_times[msg_key]) * 1000
del send_times[msg_key] # Clean up
else:
latency_ms = 5.0 # Default latency if timing info not available
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe better to just set to 0 or None

@MSeal
Copy link
Contributor

MSeal commented Aug 24, 2025

Let's touch up small things, get a merge then iterate / change things if we want later. I want to get this into the history so we can build abstractions above for simpler test definitions and swap the implementation details as needed / remove conflicts on future PRs

@k-raina k-raina requested a review from MSeal August 25, 2025 16:34
@sonarqube-confluent

This comment has been minimized.

Copy link
Member

@fangnx fangnx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work :) Just left some questions

}

return {
# Basic metrics
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the basic vs enhanced classification coming from some other source (e.g. some client benchmarking guides)? The list LGTM but just curious :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were no guidelines i refered to, it made sense to me having basic metrics and enhances metrics segregated for ease of reviewer.

Later on we can further divide these metrics in code/comments as "latency", "throughput", "message delivery" etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sense!


## Configuration

Performance bounds are loaded from a JSON config file. By default, it loads `benchmark_bounds.json`, but you can override this with the `BENCHMARK_BOUNDS_CONFIG` environment variable:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is default benchmark_bounds.json going to be added in the next PR

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added bounds in latest commit d0f4793

@sonarqube-confluent

This comment has been minimized.

@k-raina k-raina requested a review from fangnx August 26, 2025 08:45
@sonarqube-confluent
Copy link

Passed

Analysis Details

5 Issues

  • Bug 0 Bugs
  • Vulnerability 0 Vulnerabilities
  • Code Smell 5 Code Smells

Coverage and Duplications

  • Coverage No coverage information (66.40% Estimated after merge)
  • Duplications No duplication information (5.60% Estimated after merge)

Project ID: confluent-kafka-python

View in SonarQube

Copy link
Contributor

@MSeal MSeal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing minor comments. Let's move anything additional that's not a fix of a glaring issue to future PRs to unblock the history

@k-raina k-raina merged commit 858e77c into master Aug 27, 2025
3 checks passed
@k-raina k-raina deleted the kraina-add-benchmark-famework branch August 27, 2025 10:43
MSeal added a commit that referenced this pull request Oct 2, 2025
* Asyncio Producer and Consumer implementation with same API as the sync ones * Add unit tests for asyncio producer + consumer (#2036) * update * update * fix producer and add consumer uts * refactor * rename * Add Benchmark Framework for ducktape (#2030) * Integrate Schema Registry with ducktape load tests (#2027) * basic sr test * more tests * update * update * lint * Add ducktape benchmark tests for consumer (sync + async) (#2045) * draft * update and cleanup * add perf comments, add batch_size param to consume test, lint fix * linter fix * Fix linter issues in consumer testing code (#2051) * Add remaining functions missing in async producer & consumer (#2050) * Add semaphore block for ducktape tests (#2037) * Add semaphore block for ducktape tests * Increase kafka start timeout * Increase kafka start timeout * Increase kafka start timeout * Add logs to debug pipeline * Start kafka in kraft mode * Fix directory failures * Fix directory failures * Fix directory failures * templatise path * Fix ductape run * Fix kafka broker listner * Fix ducktape version error * Cleanup * Fix bound voilation should fail tests * Now expand bounds for success * Add schema registry instance * Update Schema Registry hostname * Update Schema Registry hostname * Update Schema Registry hostname * Fix for linux CI environment * Address minor feedback * Fix semaphore * Minor fix after rebase * Add more async consumer unit & integration tests (#2052) * basic rebalance test * rebalance tests * refactor and linter fix * feebdack * refactor and cleanup * update * remove jit imports * Add produce batch api to producer (#2047) * Add integration tests for transactions (#2056) * add tests * cleanup and linter fix * remove jit import * refactor * cleanup * minot rlinter * Update AsyncIO producer architecture to improve performance (#2044) * Fix helper function name to avoid ducktape test discovery * Integrate schema registry with producer sync/async performance test + clean up the old SR test (#2063) * Add comprehensive producer benchmark tests with Schema Registry support - Updated message serialization to use comprehensive structure with all protobuf fields - Implemented proper strategy pattern for sync/async serializers - Added Schema Registry authentication configuration - Fixed JSON serialization issues (schema title, async serializer initialization) - Added performance validation with configurable JSON validation - Enhanced producer strategies with comprehensive Avro, JSON, and Protobuf support * remove * remove confusing msg * Minor: Producer close calls flush() (#2066) * Integrate schema registry with consumer sync/async performance test (#2059) * update * remove auth * cleanup and ensure same msg size * more cleanup * Add comprehensive producer benchmark tests with Schema Registry support - Updated message serialization to use comprehensive structure with all protobuf fields - Implemented proper strategy pattern for sync/async serializers - Added Schema Registry authentication configuration - Fixed JSON serialization issues (schema title, async serializer initialization) - Added performance validation with configurable JSON validation - Enhanced producer strategies with comprehensive Avro, JSON, and Protobuf support * update * Group messages by topic partition before passing to produce_batch API (#2069) * Merge master to async (#2068) * Pre release (#2067) * Attempting to add python versioning to read from project toml and setting beta flag * Updated docs to read project toml version as well * Updated to read from c file for now. Updaed docs and fixed bad AI code * NPI-7572: Add content for AsyncIO Python client (#2070) * Updates for AsyncIO and other improvements * Add updates based on asyncio blog * Add SR updates relatd to AsyncIO * Reorganize content, remove redundancy, and improve content * Edits to diagram and other content * Add why to use this client in both readme files * Improve CHANGELOG title * Add release dates to versions in CHANGELOG * Add release dates back to v2.4.0 * Edits based on feedback * AsyncIO: Only clear messages from buffer if executor passed (#2071) * Fix async producer transaction behavior + add transactional produce benchmark test (#2072) * update * linter fix * Fix the async transaction behavior related to flush() (#2073) * fix * linter * more linter fix * linter and add link * Removed very old librdkafka version checks * Resolved admin import conflict issue * Fix test_version unit test (#2079) * Fix broken tests (#2077) * fix tests * fix linter * Removed set operation from test --------- Co-authored-by: Matthew Seal <mseal@confluent.io> * Async fix buffer cleanup (#2078) * Fix buffer cleanup logic * Add tests * fix linter * Remove SR key * Removed incorrect assert * Change ducktape tests to install more dependencies * Fix semaphore for producer ducktape tests + clean up files that should've been removed (#2081) * update * use warning for producer validate * remove unnecessary assert --------- Co-authored-by: Emanuele Sabellico <esabellico@confluent.io> Co-authored-by: Matthew Seal <mseal@confluent.io> Co-authored-by: Kaushik Raina <103954755+k-raina@users.noreply.github.com> Co-authored-by: Matthew Seal <mseal007@gmail.com> Co-authored-by: Steve Bang <sbang@confluent.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants