Skip to content

Streaming Data Generator: support Kafka record keys and headers - #4482

Open
kylase wants to merge 1 commit into
GoogleCloudPlatform:mainfrom
yuanchuankee:improve-streaming-data-generator
Open

kylase wants to merge 1 commit into
GoogleCloudPlatform:mainfrom
yuanchuankee:improve-streaming-data-generator

Conversation

@kylase

@kylase kylase commented Oct 26, 2026

Copy link
Copy Markdown

The Kafka sink wrote every message keyless and without headers because it used KafkaIO.write().values(). The sink now produces ProducerRecord<String, byte[]> through KafkaIO.writeRecords() and lets the schema opt in to a key and headers with an envelope, mirroring the Pub/Sub payload/attributes convention:

  {"payload": {...}, "key": "{{get('accountId')}}", "headers": {...}}
  • payload is written as the record value (JSON, or Avro binary for outputType=AVRO; the Avro output was previously Arrays.toString(bytes)).
  • key becomes the record key (StringSerializer); absent -> keyless.
  • each headers member becomes a record header (UTF-8 text / compact JSON).
  • messages without an envelope are written exactly as before.

KafkaIO.Write is still configured the same way (including withGCPApplicationDefaultCredentials() for Managed Kafka) and its WriteRecords transform is applied to the records.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the Streaming Data Generator's Kafka sink by enabling support for record keys and headers. By introducing an optional envelope structure in the schema, users can now specify keys and headers alongside the message payload. The implementation migrates the sink to use KafkaIO.writeRecords(), providing better integration with Kafka's producer record features while maintaining backward compatibility for existing keyless message generation.

Highlights

  • Kafka Sink Enhancement: Added support for Kafka record keys and headers by introducing an optional envelope schema format.
  • Implementation Update: Refactored the Kafka sink to use KafkaIO.writeRecords(), allowing for granular control over producer records.
  • Documentation: Updated the README to include examples and usage instructions for the new Kafka envelope schema.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request adds support for Kafka as a sink in the streaming data generator, allowing messages to be written with optional keys and headers using an envelope schema format. It updates the Kafka writing transform to process these envelopes and adds comprehensive unit tests. The review feedback suggests renaming the production base class FakeKafkaMessageFn to a more appropriate name like BaseKafkaMessageFn to avoid confusion, and marking non-serializable Avro fields in AvroKafkaMessageFn as transient to prevent serialization errors during pipeline execution.

The Kafka sink wrote every message keyless and without headers because it
used KafkaIO.write().values(). The sink now produces
ProducerRecord<String, byte[]> through KafkaIO.writeRecords() and lets the
schema opt in to a key and headers with an envelope, mirroring the Pub/Sub
payload/attributes convention:

  {"payload": {...}, "key": "{{get('accountId')}}", "headers": {...}}

- payload is written as the record value (JSON, or Avro binary for
  outputType=AVRO; the Avro output was previously Arrays.toString(bytes)).
- key becomes the record key (StringSerializer); absent -> keyless.
- each headers member becomes a record header (UTF-8 text / compact JSON).
- messages without an envelope are written exactly as before.

KafkaIO.Write is still configured the same way (including
withGCPApplicationDefaultCredentials() for Managed Kafka) and its
WriteRecords transform is applied to the records. Adds unit tests and
README documentation.
@kylase
kylase force-pushed the improve-streaming-data-generator branch from 08f48a0 to 733e38e Compare October 26, 2026 10:32
@codecov

codecov Bot commented Oct 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.33333% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.04%. Comparing base (71fb475) to head (733e38e).
⚠️ Report is 27 commits behind head on main.

Files with missing lines Patch % Lines
...transforms/StreamingDataGeneratorWriteToKafka.java 68.33% 15 Missing and 4 partials ⚠️

❌ Your patch check has failed because the patch coverage (68.33%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@              Coverage Diff              @@
##               main    #4482       +/-   ##
=============================================
+ Coverage     38.03%   57.04%   +19.01%     
- Complexity      518     7619     +7101     
=============================================
  Files           195     1161      +966     
  Lines         11885    73930    +62045     
  Branches       1213     8709     +7496     
=============================================
+ Hits           4520    42171    +37651     
- Misses         6994    28951    +21957     
- Partials        371     2808     +2437     
Components Coverage Δ
spanner-templates 84.14% <ø> (∅)
spanner-import-export 72.17% <ø> (∅)
spanner-live-forward-migration 87.77% <ø> (∅)
spanner-live-reverse-replication 80.08% <ø> (∅)
spanner-bulk-migration 88.34% <ø> (∅)
gcs-spanner-dv 86.66% <ø> (∅)
Files with missing lines Coverage Δ
...transforms/StreamingDataGeneratorWriteToKafka.java 57.84% <68.33%> (ø)

... and 990 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant