Skip to content

Conversation

@GAlexIHU
Copy link
Contributor

@GAlexIHU GAlexIHU commented Jan 3, 2026

Overview

Depends on #3689

Breaks up Config signature so Config can separately be used (see later cloud PRs)

Summary by CodeRabbit

  • New Features

    • Export operations now accept a unified parameters object that bundles export settings and period.
    • Export window timezone is now required and configurable.
  • Bug Fixes

    • Validation now aggregates and surfaces all configuration errors for clearer feedback.
  • Chores

    • Tests updated to use the new parameters shape.

✏️ Tip: You can customize this high-level summary in your review settings.

@GAlexIHU GAlexIHU added the release-note/ignore Ignore this change when generating release notes label Jan 3, 2026
@GAlexIHU GAlexIHU requested a review from a team as a code owner January 3, 2026 19:49
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 3, 2026

📝 Walkthrough

Walkthrough

Refactors export API to replace passing DataExportConfig with a new composite DataExportParams (which embeds DataExportConfig and Period), adds ExportWindowTimeZone to config, and centralizes/updates validation. Service signatures and tests updated accordingly.

Changes

Cohort / File(s) Summary
Types & Interface
openmeter/meterexport/service.go
Added DataExportParams (embeds DataExportConfig + Period); moved Period out of DataExportConfig; added ExportWindowTimeZone *time.Location; updated DataExportConfig.Validate() and added DataExportParams.Validate(); updated ExportSyntheticMeterData and ExportSyntheticMeterDataIter signatures to accept DataExportParams.
Implementations
openmeter/meterexport/service/syntheticdata.go, openmeter/meterexport/service/syntheticdata_iter.go
Updated implementations to accept DataExportParams; use params.DataExportConfig and params.Period where needed; derive funnel/query window timezone from params instead of hardcoded time.UTC.
Tests
openmeter/meterexport/service/service_test.go
Replaced DataExportConfig usage with DataExportParams in test fixtures and calls; populated embedded ExportWindowTimeZone in test configs; updated references to nested config fields where applicable.

Sequence Diagram(s)

(omitted — changes are refactors of parameter types and validation, not multi-component control-flow additions)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • feat: meterexport #3674: Modifies the same meterexport service API (types and export methods); this PR appears to evolve and refactor those previously introduced types and signatures.

Suggested reviewers

  • chrisgacsal

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor(meterexport): break up param signature' clearly reflects the main change: restructuring the parameter signature by separating DataExportConfig and Period into a new DataExportParams wrapper struct.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/meterexport

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
openmeter/meterexport/service.go (1)

68-88: Wrap validation errors with models.NewNillableGenericValidationError() for consistency.

The validation looks solid, but it's inconsistent with the rest of the codebase. Nearly every other Validate() method wraps the error with models.NewNillableGenericValidationError(errors.Join(errs...)). Both DataExportConfig.Validate() and DataExportParams.Validate() should follow the same pattern.

🧹 Nitpick comments (2)
openmeter/meterexport/service/service_test.go (2)

642-658: Missing ExportWindowTimeZone in invalid config test.

This test case for "should return error for invalid config" doesn't set ExportWindowTimeZone. While the test expects an error for missing meter ID, it would also trigger the "export window time zone is required" validation error.

This is actually fine since both errors would be joined, and the test checks Contains for the meter ID error. But if you want the test to be more precise about which validation fails, you might consider setting the timezone.

Optional: Make the test more specific
 		params := meterexport.DataExportParams{
 			DataExportConfig: meterexport.DataExportConfig{
-				ExportWindowSize: meter.WindowSizeMinute,
+				ExportWindowSize:     meter.WindowSizeMinute,
+				ExportWindowTimeZone: time.UTC,
 				MeterID: models.NamespacedID{
 					Namespace: "test-ns",
 					ID:        "", // Missing ID
 				},
 			},

266-287: Consider adding a test for missing ExportWindowTimeZone.

The validation now requires ExportWindowTimeZone to be set, but there's no explicit test case verifying this validation error. Adding one would improve coverage of the new validation logic.

Example test case to add
{
    name:  "should fail validation with missing time zone",
    meter: meter.Meter{},
    params: meterexport.DataExportParams{
        DataExportConfig: meterexport.DataExportConfig{
            ExportWindowSize:     meter.WindowSizeMinute,
            ExportWindowTimeZone: nil, // Missing timezone
            MeterID: models.NamespacedID{
                Namespace: "test-ns",
                ID:        "meter-1",
            },
        },
        Period: timeutil.StartBoundedPeriod{
            From: now.Add(-5 * time.Minute),
            To:   lo.ToPtr(now),
        },
    },
    wantErr:    true,
    wantErrMsg: "export window time zone is required",
},
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c99561 and 9373901.

📒 Files selected for processing (4)
  • openmeter/meterexport/service.go
  • openmeter/meterexport/service/service_test.go
  • openmeter/meterexport/service/syntheticdata.go
  • openmeter/meterexport/service/syntheticdata_iter.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

⚙️ CodeRabbit configuration file

**/*.go: In general when reviewing the Golang code make readability and maintainability a priority, even potentially suggest restructuring the code to improve them.

Performance should be a priority in critical code paths. Anything related to event ingestion, message processing, database operations (regardless of database) should be vetted for potential performance bottlenecks.

Files:

  • openmeter/meterexport/service/syntheticdata_iter.go
  • openmeter/meterexport/service/syntheticdata.go
  • openmeter/meterexport/service.go
  • openmeter/meterexport/service/service_test.go
**/*_test.go

⚙️ CodeRabbit configuration file

**/*_test.go: Make sure the tests are comprehensive and cover the changes. Keep a strong focus on unit tests and in-code integration tests.
When appropriate, recommend e2e tests for critical changes.

Files:

  • openmeter/meterexport/service/service_test.go
🧬 Code graph analysis (4)
openmeter/meterexport/service/syntheticdata_iter.go (1)
openmeter/meterexport/service.go (2)
  • DataExportParams (90-95)
  • DataExportConfig (57-66)
openmeter/meterexport/service/syntheticdata.go (2)
openmeter/meterexport/service.go (2)
  • DataExportParams (90-95)
  • DataExportConfig (57-66)
openmeter/streaming/connector.go (1)
  • RawEvent (24-36)
openmeter/meterexport/service.go (2)
pkg/timeutil/boundedperiod.go (1)
  • StartBoundedPeriod (8-11)
pkg/models/validator.go (1)
  • Validate (16-26)
openmeter/meterexport/service/service_test.go (4)
openmeter/meterexport/service.go (2)
  • DataExportParams (90-95)
  • DataExportConfig (57-66)
pkg/models/id.go (1)
  • NamespacedID (7-10)
app/common/namespace.go (1)
  • Namespace (13-15)
pkg/timeutil/boundedperiod.go (1)
  • StartBoundedPeriod (8-11)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Test
  • GitHub Check: Artifacts / Benthos Collector Container image
  • GitHub Check: Lint
  • GitHub Check: Artifacts / Container image
  • GitHub Check: Code Generators
  • GitHub Check: Migration Checks
  • GitHub Check: Build
🔇 Additional comments (9)
openmeter/meterexport/service.go (2)

57-66: Clean separation of concerns here.

The DataExportConfig now holds the reusable configuration aspects (window size, timezone, meter ID), making it independent of any specific export operation. This aligns well with the PR objective of making Config usable separately for upcoming cloud-related work.


90-109: DataExportParams wrapper is well-structured.

The embedding of DataExportConfig allows access to its fields directly on DataExportParams, which keeps the API ergonomic. The composite Validate() method correctly delegates to both the embedded config and the period.

openmeter/meterexport/service/syntheticdata.go (2)

57-66: Signature update looks good.

The method now takes DataExportParams and correctly accesses the embedded DataExportConfig for validation. Clean transition.


119-131: Query params construction is correct.

The fields are properly extracted from the params struct:

  • From and To from params.Period
  • WindowSize and WindowTimeZone from the embedded DataExportConfig

This aligns with the type definitions in service.go.

openmeter/meterexport/service/syntheticdata_iter.go (2)

13-17: Upfront validation correctly uses embedded config.

The iterator wrapper validates using params.DataExportConfig which is appropriate since validateAndGetMeter expects a DataExportConfig. The rest of the iterator logic remains unchanged, which is expected.


30-36: Goroutine correctly passes the full params object.

Since ExportSyntheticMeterData now expects DataExportParams, passing the entire params here is correct.

openmeter/meterexport/service/service_test.go (3)

53-98: Test case structure updated correctly.

The test data now uses meterexport.DataExportParams with the embedded DataExportConfig. The ExportWindowTimeZone: time.UTC is consistently set across all test cases, which aligns with the new validation requirement.


249-251: Good use of embedded config for descriptor lookup.

Using tt.params.DataExportConfig to call GetTargetMeterDescriptor is the right approach since that method still accepts DataExportConfig (not DataExportParams), keeping the descriptor lookup independent of the period.


292-454: Context cancellation tests are thorough.

Good coverage for both mid-export cancellation and pre-canceled context scenarios. The tests verify that exactly one context.Canceled error is emitted (no duplicates), which is important for the streaming error handling behavior.

chrisgacsal
chrisgacsal previously approved these changes Jan 5, 2026
Base automatically changed from fix/meterexport to main January 5, 2026 09:50
@GAlexIHU GAlexIHU dismissed chrisgacsal’s stale review January 5, 2026 09:50

The base branch was changed.

@GAlexIHU GAlexIHU force-pushed the refactor/meterexport branch from 9373901 to 54d65e2 Compare January 5, 2026 09:52
@GAlexIHU GAlexIHU enabled auto-merge (squash) January 5, 2026 09:52
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
openmeter/meterexport/service.go (1)

75-77: Good validation, but consider the error message.

The validation correctly catches nil time zones, but the error message "export window time zone is required" might not give users enough guidance. Consider mentioning that it should be a valid *time.Location or providing an example.

Optional: More descriptive error message
 	if c.ExportWindowTimeZone == nil {
-		errs = append(errs, errors.New("export window time zone is required"))
+		errs = append(errs, errors.New("export window time zone is required (e.g., time.UTC or time.Local)"))
 	}
openmeter/meterexport/service/service_test.go (1)

642-658: Nice edge case coverage!

This test verifies that validation works correctly with the new structure, specifically checking that missing meter ID is caught. However, I notice that ExportWindowTimeZone is missing from this test case's config (line 644-648), but the test expects to catch the missing ID error.

This might accidentally also catch the missing timezone validation error. Consider either:

  1. Setting the timezone to test only the ID validation
  2. Verifying that both errors are returned (since validation aggregates errors)
Optional: Make validation test more specific
 		params := meterexport.DataExportParams{
 			DataExportConfig: meterexport.DataExportConfig{
 				ExportWindowSize: meter.WindowSizeMinute,
+				ExportWindowTimeZone: time.UTC,
 				MeterID: models.NamespacedID{
 					Namespace: "test-ns",
 					ID:        "", // Missing ID
 				},
 			},

Or alternatively, verify both errors are present:

 		_, err = svc.ExportSyntheticMeterDataIter(context.Background(), params)
 		require.Error(t, err)
 		assert.Contains(t, err.Error(), "meter id is required")
+		assert.Contains(t, err.Error(), "export window time zone is required")
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9373901 and 54d65e2.

📒 Files selected for processing (4)
  • openmeter/meterexport/service.go
  • openmeter/meterexport/service/service_test.go
  • openmeter/meterexport/service/syntheticdata.go
  • openmeter/meterexport/service/syntheticdata_iter.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • openmeter/meterexport/service/syntheticdata_iter.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

⚙️ CodeRabbit configuration file

**/*.go: In general when reviewing the Golang code make readability and maintainability a priority, even potentially suggest restructuring the code to improve them.

Performance should be a priority in critical code paths. Anything related to event ingestion, message processing, database operations (regardless of database) should be vetted for potential performance bottlenecks.

Files:

  • openmeter/meterexport/service/service_test.go
  • openmeter/meterexport/service.go
  • openmeter/meterexport/service/syntheticdata.go
**/*_test.go

⚙️ CodeRabbit configuration file

**/*_test.go: Make sure the tests are comprehensive and cover the changes. Keep a strong focus on unit tests and in-code integration tests.
When appropriate, recommend e2e tests for critical changes.

Files:

  • openmeter/meterexport/service/service_test.go
🧠 Learnings (1)
📚 Learning: 2025-03-07T12:17:43.129Z
Learnt from: GAlexIHU
Repo: openmeterio/openmeter PR: 2383
File: openmeter/entitlement/metered/lateevents_test.go:37-45
Timestamp: 2025-03-07T12:17:43.129Z
Learning: In the OpenMeter codebase, test files like `openmeter/entitlement/metered/lateevents_test.go` may use variables like `meterSlug` and `namespace` without explicit declarations visible in the same file. This appears to be an accepted pattern in their test structure.

Applied to files:

  • openmeter/meterexport/service/service_test.go
🧬 Code graph analysis (3)
openmeter/meterexport/service/service_test.go (3)
openmeter/meterexport/service.go (2)
  • DataExportParams (90-95)
  • DataExportConfig (57-66)
pkg/models/id.go (1)
  • NamespacedID (7-10)
pkg/timeutil/boundedperiod.go (1)
  • StartBoundedPeriod (8-11)
openmeter/meterexport/service.go (2)
pkg/timeutil/boundedperiod.go (1)
  • StartBoundedPeriod (8-11)
pkg/models/validator.go (1)
  • Validate (16-26)
openmeter/meterexport/service/syntheticdata.go (2)
openmeter/meterexport/service.go (2)
  • DataExportParams (90-95)
  • DataExportConfig (57-66)
openmeter/streaming/connector.go (1)
  • RawEvent (24-36)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Quickstart
  • GitHub Check: E2E
  • GitHub Check: Test
  • GitHub Check: Code Generators
  • GitHub Check: Migration Checks
  • GitHub Check: Lint
  • GitHub Check: Build
  • GitHub Check: Repository Scan
  • GitHub Check: Analyze (go)
🔇 Additional comments (7)
openmeter/meterexport/service.go (2)

61-62: Nice separation of concerns here!

The ExportWindowTimeZone field makes sense as part of DataExportConfig since it defines how the export windows are calculated. The pointer allows for explicit validation, though you might want to consider if there's a sensible default (like UTC) that could be applied when nil, or if explicit nil is the right approach for your use case.


90-109: Clean validation aggregation!

The DataExportParams.Validate() method nicely aggregates errors from both the embedded config and the period. The use of errors.Join throughout provides a great user experience by reporting all validation issues at once rather than one at a time.

I also checked Period.Validate() (in pkg/timeutil/boundedperiod.go), and it's solid—it properly validates that From is required and that From comes before To, with good handling of the optional To field.

openmeter/meterexport/service/syntheticdata.go (2)

57-66: Refactoring applied correctly!

The method signature update and the access to params.DataExportConfig for validation are both correct. The embedded struct pattern means you can access DataExportConfig fields directly through params, but being explicit with params.DataExportConfig in the validation call is clearer and more maintainable.


121-130: Clean parameter extraction from the new structure!

The funnel parameters now correctly pull from the new DataExportParams structure:

  • params.Period.From and params.Period.To for the time range
  • params.ExportWindowSize and params.ExportWindowTimeZone for window configuration

This is exactly what you'd expect from the refactoring. The field access is correct since DataExportConfig is embedded in DataExportParams.

openmeter/meterexport/service/service_test.go (3)

79-92: Test structure updated consistently!

All test cases now properly construct DataExportParams with the embedded DataExportConfig and separate Period. The structure is clean and consistent across all tests.

One minor observation: you're correctly setting ExportWindowTimeZone: time.UTC in all tests, which is good for avoiding nil validation errors.


239-250: Good test pattern with descriptor verification!

The test correctly:

  1. Calls ExportSyntheticMeterData with the full params (line 239)
  2. Separately calls GetTargetMeterDescriptor with just the config (line 250)

This verifies that the config can be used independently, which aligns perfectly with the PR objective to enable config reuse.


337-350: Context cancellation test properly updated!

The test constructs the params structure correctly for the cancellation scenario. The large time range (1000 minutes) ensures multiple query iterations, which is good for testing mid-operation cancellation.

@GAlexIHU GAlexIHU merged commit 450bd5c into main Jan 5, 2026
27 checks passed
@GAlexIHU GAlexIHU deleted the refactor/meterexport branch January 5, 2026 09:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/ignore Ignore this change when generating release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants