Skip to content
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

Make ingestion of EVM events idempotent #760

Merged
merged 13 commits into from
Feb 21, 2025

Conversation

m-Peter
Copy link
Collaborator

@m-Peter m-Peter commented Feb 18, 2025

Depends on: onflow/flow-go#7050
Work towards: onflow/flow-go#6962

Description


For contributor use:

  • Targeted PR against master branch
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the standards mentioned here.
  • Updated relevant documentation
  • Re-reviewed Files changed in the Github PR explorer
  • Added appropriate labels

Summary by CodeRabbit

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced block state snapshot timing to improve transaction trace accuracy and register state consistency.
  • Chores

    • Upgraded key dependencies to the latest versions for improved integration and system stability.
  • New Features

    • Introduced new Prometheus metrics to track API performance and state.
  • Tests

    • Added a new test to verify the idempotency of the ingestion process with the ForceStartHeight configuration.

Copy link
Contributor

coderabbitai bot commented Feb 18, 2025

Walkthrough

This pull request modifies the snapshot retrieval logic in the DebugAPI and RegisterStorage components. The executorAtBlock method now fetches snapshots based on the current block height, while the GetSnapshotAt method adjusts the block height parameter to reflect the previous block. Additionally, several dependency versions in the go.mod files for both the main and test modules have been updated to newer releases. Significant changes were also made to the bootstrap package, enhancing the organization of server management and error handling in the metrics package.

Changes

File(s) Change Summary
api/debug.go Updated executorAtBlock to retrieve snapshots using the current block height and adjusted the related error message accordingly.
storage/pebble/register_storage.go Modified GetSnapshotAt to clarify parameter name and prevent underflow by adjusting block height handling.
bootstrap/bootstrap.go Refactored Run method to be a method of the Bootstrap struct, integrated metrics server shutdown into the Stop method, and improved overall organization.
metrics/collector.go Introduced new Prometheus metrics for tracking API performance and state, and updated metric registration logic.
go.mod, tests/go.mod Updated dependency versions for multiple packages, including github.com/onflow/flow-go, github.com/onflow/flow-core-contracts, github.com/onflow/flow-nft, and github.com/onflow/flow/protobuf.

Possibly related PRs

  • Start event ingestion on proper block height when connecting to local Emulator #753: The changes in the main PR, which modify the executorAtBlock method to adjust the block height for snapshot retrieval, are related to the changes in the retrieved PR that add logic to handle block height in the StartEventIngestion method.
  • Support block overrides parameter for eth_call & debug_traceCall #691: The changes in the main PR, specifically the modification of the executorAtBlock method in api/debug.go, are related to the changes in the retrieved PR, which also involves modifications to the api/debug.go file, particularly in the TraceCall method.
  • Local index register validator #550: The changes in the main PR, specifically the modification of the executorAtBlock method in the DebugAPI struct, are related to the changes in the retrieved PR, which involves the introduction of a RegisterValidator that validates register values against the on-chain state.

Suggested labels

Improvement, Bugfix, Testing

Suggested reviewers

  • zhangchiqing
  • m-Peter
  • janezpodhostnik

Poem

Oh, I hopped through lines of code with glee,
Adjusting snapshots with a flick and a spree.
From current blocks to past states in play,
New versions guiding me on my way.
I’m a rabbit of code, dancing in the byte array! 🐰✨

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@janezpodhostnik janezpodhostnik left a comment

Choose a reason for hiding this comment

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

Nice!

Copy link
Contributor

@peterargue peterargue left a comment

Choose a reason for hiding this comment

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

looks good, but let's wait for the merged commit in flow-go before merging

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 (6)
tests/integration_test.go (3)

507-544: Add comments to explain the test scenario.

Consider adding comments to explain:

  • Why we're submitting this specific number of transactions
  • What we're testing with the controlled block mining
  • The expected behavior of transaction receipts in this scenario
 	totalTxs := keyCount*5 + 3
+	// Submit more transactions than available keys to verify key rotation
+	// and transaction processing under load
 	hashes := make([]common.Hash, totalTxs)
 	nonce := uint64(0)

545-565: Add validation for the ingestion process.

The test should verify that the ingestion process is working correctly after restart by checking:

  • The current block height
  • The state of the ingested events
 	<-ready2
 
 	time.Sleep(3 * time.Second) // some time to startup
+
+	// Verify that the ingestion process started from the correct block
+	currentBlock, err := ethClient.BlockNumber(ctx)
+	require.NoError(t, err)
+	assert.Greater(t, currentBlock, uint64(0), "Block height should be greater than 0")

566-576: Improve the assertion message for clarity.

The current error message "all transactions were not executed" is ambiguous. Consider making it more specific to the idempotency test case.

-	}, time.Second*15, time.Second*1, "all transactions were not executed")
+	}, time.Second*15, time.Second*1, "transactions should remain valid after service restart with earlier start height")
bootstrap/bootstrap.go (2)

671-698: Handle partial initialization failures

If an error occurs after successfully starting one or more components (e.g. the API server), consider stopping any previously started components before returning to avoid leaving orphan processes. You might call b.Stop() or define a partial-rollback mechanism upon encountering an error in the startup chain.


710-726: Consider graceful cleanup on Run errors

If boot.Run() fails, the function immediately returns without calling boot.Stop(), potentially leaving allocated resources unclosed. To prevent partial-leak scenarios, call boot.Stop() in a defer or in an error-handling block to ensure graceful cleanup.

metrics/collector.go (1)

147-149: Skip only the conflicting metric registration instead of all

Returning on the first AlreadyRegisteredError halts registration of subsequent metrics. If you'd like to continue registering remaining metrics, consider individually ignoring the conflict rather than returning.

Here is a possible modification:

 if err := prometheus.Register(m); err != nil {
-  if errors.As(err, &prometheus.AlreadyRegisteredError{}) {
-    return nil
-  }
+  var are *prometheus.AlreadyRegisteredError
+  if errors.As(err, &are) {
+    logger.Warn().Msgf("metric %s already registered, skipping", are.ExistingCollector)
+    continue
+  }
   logger.Err(err).Msg("failed to register metric")
   return err
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3045799 and 8fc6281.

📒 Files selected for processing (4)
  • bootstrap/bootstrap.go (3 hunks)
  • metrics/collector.go (2 hunks)
  • storage/pebble/register_storage.go (1 hunks)
  • tests/integration_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • storage/pebble/register_storage.go
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test
🔇 Additional comments (5)
tests/integration_test.go (1)

441-506: LGTM! Test setup follows established patterns.

The test setup is well-structured and consistent with other integration tests in the file.

bootstrap/bootstrap.go (3)

210-210: Good clarity in the log message

Changing the message to reference the API server accurately aligns the log with the actual operation.


409-409: Confirm intentional omission of metrics server completion

Commenting out <-b.metrics.Done() prevents waiting on the metrics server to exit gracefully, which might lead to unpredictable termination. Consider confirming that this is desired, as it can introduce concurrency risks if the metrics server isn’t fully stopped.


700-708: Validate stopping sequence

Stopping the event ingestion first is valid to prevent further writes, but you may consider keeping the metrics server active until all other shutdown tasks complete, so it can record final teardown metrics. Ensure the order here meets the intended architectural constraints.

metrics/collector.go (1)

4-4: Import is valid

Importing the errors package is necessary to handle the newly introduced error check.

@janezpodhostnik janezpodhostnik mentioned this pull request Feb 19, 2025
6 tasks
@m-Peter m-Peter force-pushed the mpeter/make-ingestion-idempotent branch from 8fc6281 to 1d16241 Compare February 19, 2025 16:07
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: 3

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8fc6281 and 1d16241.

⛔ Files ignored due to path filters (2)
  • go.sum is excluded by !**/*.sum
  • tests/go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • api/debug.go (1 hunks)
  • bootstrap/bootstrap.go (2 hunks)
  • go.mod (1 hunks)
  • metrics/collector.go (2 hunks)
  • storage/pebble/register_storage.go (1 hunks)
  • tests/go.mod (1 hunks)
  • tests/integration_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • api/debug.go
  • metrics/collector.go
  • tests/go.mod
  • storage/pebble/register_storage.go
  • go.mod
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test

Copy link
Member

@zhangchiqing zhangchiqing left a comment

Choose a reason for hiding this comment

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

Could you highlight the change that make the ingestion idempotent. I didn't quite get how it works

func (r *RegisterStorage) GetSnapshotAt(evmBlockHeight uint64) (types.BackendStorageSnapshot, error) {
return NewStorageSnapshot(r.Get, evmBlockHeight), nil
// `evmBlockHeight-1` to get the end state of the previous block.
return NewStorageSnapshot(r.Get, evmBlockHeight-1), nil
Copy link
Member

Choose a reason for hiding this comment

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

Can we let the caller do the -1 and deals with potential underflow? So the GetSnapshotAt always return the end state. I think end state is easy to think.

Copy link
Contributor

Choose a reason for hiding this comment

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

the interface defines it as the start of block state

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for handling the underflow. it would only happen on block 0, but that happens when syncing from the start or when starting the emulator.

Copy link
Member

Choose a reason for hiding this comment

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

I see. I found it's easy it can easily lead to confusion.

If we can't change the interface name into GetStartStateSnapshotAt, at least we should put it into the argument name evmBlockHeightOfStartStateToQuery. I don't mind being verbose here, but I think it's important to raise attention for the caller to ensure the correct value gets passed in.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added in ea6e833

go.mod Outdated
@@ -8,7 +8,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/onflow/atree v0.9.0
github.com/onflow/cadence v1.3.1
github.com/onflow/flow-go v0.38.1-0.20250213171922-77f4db56bb54
github.com/onflow/flow-go v0.38.1-0.20250218133611-bca6e7286932
Copy link
Contributor

Choose a reason for hiding this comment

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

let's update this with the commit from master

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated in c0a8880 .
Note that I used the merge commit from master, not the commit hash itself.
I also updated the flow-emulator dependency to the merge commit on master.

@@ -143,6 +144,9 @@ func NewCollector(logger zerolog.Logger) Collector {
func registerMetrics(logger zerolog.Logger, metrics ...prometheus.Collector) error {
for _, m := range metrics {
if err := prometheus.Register(m); err != nil {
if errors.As(err, &prometheus.AlreadyRegisteredError{}) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this seems fine, but also points to a bug where we're registering the same metrics more than once. any idea why you needed to add this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I have added a fix for this in 71996c2

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The EVM GW can be bootstrapped again & again during E2E tests, so the metrics were registered more than once.

func (r *RegisterStorage) GetSnapshotAt(evmBlockHeight uint64) (types.BackendStorageSnapshot, error) {
return NewStorageSnapshot(r.Get, evmBlockHeight), nil
// `evmBlockHeight-1` to get the end state of the previous block.
return NewStorageSnapshot(r.Get, evmBlockHeight-1), nil
Copy link
Contributor

Choose a reason for hiding this comment

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

the interface defines it as the start of block state

func (r *RegisterStorage) GetSnapshotAt(evmBlockHeight uint64) (types.BackendStorageSnapshot, error) {
return NewStorageSnapshot(r.Get, evmBlockHeight), nil
// `evmBlockHeight-1` to get the end state of the previous block.
return NewStorageSnapshot(r.Get, evmBlockHeight-1), nil
Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for handling the underflow. it would only happen on block 0, but that happens when syncing from the start or when starting the emulator.

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

♻️ Duplicate comments (1)
tests/integration_test.go (1)

551-571: 🛠️ Refactor suggestion

Enhance idempotency verification after restart.

The test could be improved by verifying additional aspects of idempotency:

  1. Event logs to ensure no duplicate events
  2. Transaction counts to ensure no duplicate transactions
  3. State consistency checks

This is a duplicate of a previous review comment. The suggested improvements remain valid and should be implemented to ensure comprehensive idempotency testing.

🧹 Nitpick comments (6)
tests/integration_test.go (3)

478-492: Consider adding test cases for different validation modes.

The test only verifies idempotency with LocalIndexValidation. Consider parameterizing the test to verify idempotency with both LocalIndexValidation and TxSealValidation modes.

 func Test_ForceStartHeightIdempotency(t *testing.T) {
+	testCases := []struct {
+		name       string
+		validation config.TxValidation
+	}{
+		{"LocalIndexValidation", config.LocalIndexValidation},
+		{"TxSealValidation", config.TxSealValidation},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			// Move existing test code here
+			cfg.TxStateValidation = tc.validation
+			// ... rest of the test
+		})
+	}
 }

572-583: Add timeout configuration for assertions.

The hardcoded timeout values could be made configurable to accommodate different test environments.

+const (
+	defaultAssertTimeout  = 15 * time.Second
+	defaultAssertInterval = 1 * time.Second
+)

 assert.Eventually(t, func() bool {
     // ... existing code ...
-}, time.Second*15, time.Second*1, "all transactions were not executed")
+}, defaultAssertTimeout, defaultAssertInterval, "all transactions were not executed")

498-550: Consider adding error scenarios.

The test only covers the happy path. Consider adding test cases for error scenarios such as:

  1. Network interruptions during restart
  2. Invalid ForceStartHeight values
  3. Database corruption scenarios

Example error scenario:

+func Test_ForceStartHeightIdempotencyErrors(t *testing.T) {
+	// ... setup code ...
+
+	// Test invalid ForceStartHeight
+	cfg.ForceStartCadenceHeight = 999999 // Set to a height that doesn't exist
+	boot, err = bootstrap.New(cfg)
+	require.NoError(t, err)
+
+	err = boot.Run(ctx, cfg, func() {})
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "invalid start height")
+}
metrics/collector.go (3)

47-50: Consider limiting cardinality of address labels.

The address label in evmAccountCallCounters could lead to high cardinality as there could be millions of unique EVM addresses. Consider implementing one or more of these strategies:

  1. Add a limit to the number of unique addresses tracked
  2. Use address ranges or categories instead of raw addresses
  3. Implement label value aggregation for less frequent addresses

52-57: Consider implementing the status code label.

The TODO comment suggests adding a 'status_code' label to request durations. This would be valuable for:

  1. Distinguishing between successful and failed requests
  2. Identifying specific error patterns
  3. Setting up meaningful alerting rules

Would you like me to help implement the status code label for the request duration metric?


146-149: Document the idempotent registration behavior.

The unregister-before-register pattern makes the metrics registration idempotent, which is good. However, this behavior should be documented to prevent confusion about potential metric gaps during re-registration.

Add a comment explaining the behavior:

 // During E2E tests, the EVM GW might be bootstrapped again
 // and again, so we make sure to register the metrics on a
 // clean state.
+// Note: This makes metric registration idempotent but may
+// cause brief gaps in metric collection during re-registration.
 prometheus.Unregister(m)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e43cf0e and 71996c2.

📒 Files selected for processing (2)
  • metrics/collector.go (2 hunks)
  • tests/integration_test.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test
🔇 Additional comments (2)
tests/integration_test.go (1)

441-447: LGTM! Well-documented test purpose.

The test documentation clearly outlines the key aspects of idempotency being verified.

metrics/collector.go (1)

75-88: LGTM!

The metrics slice is well-organized and includes all declared metrics.

@m-Peter m-Peter force-pushed the mpeter/make-ingestion-idempotent branch from b92120d to 951734b Compare February 21, 2025 09:32
@m-Peter m-Peter requested a review from peterargue February 21, 2025 09:39

<-ready

time.Sleep(3 * time.Second) // some time to startup
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure this is needed. It should be ready at this point.

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

♻️ Duplicate comments (1)
tests/integration_test.go (1)

572-582: 🛠️ Refactor suggestion

Enhance idempotency verification.

The current test only verifies transaction receipts. Consider adding additional checks to ensure complete idempotency:

  1. Event verification
  2. State verification
  3. Transaction count verification

The previous review already suggested these improvements. Please refer to the earlier comment for the implementation details.

🧹 Nitpick comments (3)
metrics/collector.go (1)

52-58: Consider implementing the TODO suggestion.

Adding a 'status_code' label to the request duration metric would provide valuable insights into API performance across different response types.

Would you like me to help implement this enhancement? Here's what we could track:

  • Success responses (2xx)
  • Client errors (4xx)
  • Server errors (5xx)
tests/integration_test.go (2)

478-492: Consider adding test coverage for different validation modes.

The test only covers LocalIndexValidation mode. Since idempotency is critical for data consistency, consider parameterizing the test to cover both TxSealValidation and LocalIndexValidation modes.

 func Test_ForceStartHeightIdempotency(t *testing.T) {
+	testCases := []struct {
+		name           string
+		validationMode config.TxValidationMode
+	}{
+		{"LocalIndexValidation", config.LocalIndexValidation},
+		{"TxSealValidation", config.TxSealValidation},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			// Move existing test code here
+			cfg.TxStateValidation = tc.validationMode
+			// ...
+		})
+	}
 }

551-555: Consider testing multiple restart scenarios.

The test only verifies restarting from block height 1. Consider testing additional scenarios:

  1. Restart from the middle of the block range
  2. Restart from the latest block
+	testHeights := []uint64{
+		1,                    // Start
+		totalTxs / 2,        // Middle
+		totalTxs,            // End
+	}
+	for _, height := range testHeights {
-		cfg.ForceStartCadenceHeight = 1
+		cfg.ForceStartCadenceHeight = height
+		t.Logf("Testing restart from height %d", height)
		// ... rest of the test
+	}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b92120d and 55713b8.

⛔ Files ignored due to path filters (2)
  • go.sum is excluded by !**/*.sum
  • tests/go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • api/debug.go (1 hunks)
  • bootstrap/bootstrap.go (2 hunks)
  • go.mod (2 hunks)
  • metrics/collector.go (2 hunks)
  • storage/pebble/register_storage.go (1 hunks)
  • tests/go.mod (2 hunks)
  • tests/integration_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • api/debug.go
  • storage/pebble/register_storage.go
  • bootstrap/bootstrap.go
  • go.mod
  • tests/go.mod
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test
🔇 Additional comments (4)
metrics/collector.go (3)

12-74: Well-structured metric definitions!

The metric declarations follow Prometheus best practices with:

  • Clear naming conventions with consistent prefixing
  • Descriptive help text
  • Appropriate metric types for different use cases

75-88: LGTM!

The metrics slice is complete and well-organized, containing all declared metrics.


146-149: Good solution for handling metric re-registration!

This change addresses the issue discussed in previous reviews where metrics were being registered multiple times during E2E tests. The unregistration step ensures idempotent metric registration.

tests/integration_test.go (1)

441-447: LGTM! Well-documented test function.

The test documentation clearly outlines the purpose and verification criteria for idempotency.

@peterargue peterargue merged commit 5b8d549 into main Feb 21, 2025
2 checks passed
@peterargue peterargue deleted the mpeter/make-ingestion-idempotent branch February 21, 2025 19:33
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.

4 participants