Skip to content

[improve] Add jdbc common collect e2e code (#3273) #2

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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

arvi18
Copy link

@arvi18 arvi18 commented Apr 21, 2025

What's changed?

Benefit from testcontainers' rich jdbc driver support (SPI implementation), add jdbc common collect e2e code (postgresql/mysql supported for now)

Checklist

  • I have read the Contributing Guide
  • I have written the necessary doc or comment.
  • I have added the necessary unit tests and all cases have passed.

Add or update API

  • I have added the necessary e2e tests and all cases have passed.

Summary by CodeRabbit

  • New Features

    • Added support for constructing JDBC URLs for "testcontainers" database platforms.
    • Introduced a new enum for managing database image types and default tags.
    • Added end-to-end tests for collecting metrics from PostgreSQL databases running in test containers.
  • Chores

    • Updated project dependencies to support database testing with Testcontainers, including centralized version management and new test-scoped dependencies.

@arvi18
Copy link
Author

arvi18 commented Apr 21, 2025

please fix ci

Copy link

coderabbitai bot commented Apr 21, 2025

Walkthrough

The changes introduce enhanced support for database testing using Testcontainers within the Hertzbeat collector modules. A new enum for database image management is added, and a new end-to-end test class is implemented to verify JDBC metric collection against a PostgreSQL Testcontainer. The JDBC URL construction logic is extended to handle "testcontainers" as a platform. Maven configuration files are updated to manage Testcontainers dependencies via a BOM and to include specific JDBC drivers and Testcontainers modules for MySQL and PostgreSQL, ensuring consistent versions and improved test isolation.

Changes

File(s) Change Summary
hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/database/JdbcCommonCollect.java Added a new case to handle "testcontainers" in the database URL construction logic, enabling JDBC URLs compatible with Testcontainers.
hertzbeat-e2e/hertzbeat-collector-basic-e2e/pom.xml Updated Maven POM: added properties for MySQL and PostgreSQL JDBC driver versions; added test-scoped dependencies for Testcontainers (JUnit, JDBC, MySQL, PostgreSQL); switched Testcontainers dependency from generic to JDBC module; added explicit JDBC driver dependencies as optional and test-scoped.
hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/database/DatabaseImagesEnum.java Introduced a new enum DatabaseImagesEnum for managing supported database images and their default tags, with utility methods for lookup and string representation.
hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/database/JdbcCommonCollectE2eTest.java Added a new end-to-end test class for validating JDBC metric collection using Testcontainers, specifically targeting PostgreSQL, with custom setup, protocol configuration, and metric validation logic.
hertzbeat-e2e/pom.xml Added a <dependencyManagement> section to import the Testcontainers BOM, centralizing Testcontainers dependency version management for the project.

Sequence Diagram(s)

sequenceDiagram
    participant TestRunner
    participant JdbcCommonCollectE2eTest
    participant Testcontainer(PostgreSQL)
    participant JdbcCommonCollect

    TestRunner->>JdbcCommonCollectE2eTest: setUp()
    JdbcCommonCollectE2eTest->>Testcontainer(PostgreSQL): Start container
    JdbcCommonCollectE2eTest->>JdbcCommonCollect: Initialize with test config
    loop For each metric
        JdbcCommonCollectE2eTest->>JdbcCommonCollect: collectMetrics(metric)
        JdbcCommonCollect->>Testcontainer(PostgreSQL): Connect via JDBC (testcontainers URL)
        JdbcCommonCollect-->>JdbcCommonCollectE2eTest: Return collected data
        JdbcCommonCollectE2eTest->>JdbcCommonCollectE2eTest: Validate results
    end
    JdbcCommonCollectE2eTest-->>TestRunner: Test results
Loading

Poem

In tunnels of code where the test containers spin,
A rabbit hops in, with a whiskered grin.
Databases in jars, enum names set,
URLs constructed, no errors to fret.
Metrics are gathered, the tests all pass through—
A hop, a leap, and a cheer for the new!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 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.
  • @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.

@visz11
Copy link
Collaborator

visz11 commented Apr 21, 2025

@coderabbitai full review

Copy link

coderabbitai bot commented Apr 21, 2025

✅ Actions performed

Full review triggered.

@visz11
Copy link
Collaborator

visz11 commented Apr 22, 2025

@coderabbitai full review

Copy link

coderabbitai bot commented Apr 22, 2025

✅ Actions performed

Full review triggered.

Copy link

@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: 2

🧹 Nitpick comments (7)
hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/database/DatabaseImagesEnum.java (2)

56-63: Consider supporting custom tags in lookup.

The current implementation only matches exact "imageName:defaultTag" combinations. Consider enhancing the method to parse custom tags.

 public static DatabaseImagesEnum fromFullImageName(String fullImageName) {
+    // Split the image name and tag
+    String[] parts = fullImageName.split(":");
+    if (parts.length > 0) {
+        // Match by image name only, ignoring tag differences
+        return fromImageName(parts[0]);
+    }
     for (DatabaseImagesEnum value : values()) {
         if (value.getFullImageName().equalsIgnoreCase(fullImageName)) {
             return value;
         }
     }
     throw new IllegalArgumentException("Unknown full database image name: " + fullImageName);
 }

65-71: Fix class name in toString method.

The toString method references an incorrect class name "DatabaseImageNameEnum" which doesn't match the actual class name "DatabaseImagesEnum".

 @Override
 public String toString() {
-    return "DatabaseImageNameEnum{" +
+    return "DatabaseImagesEnum{" +
             "imageName='" + imageName + '\'' +
             ", defaultTag='" + defaultTag + '\'' +
             '}';
 }
hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/database/JdbcCommonCollect.java (2)

386-387: Good implementation of Testcontainers JDBC URL support.

The addition of the "testcontainers" case to the URL construction switch statement enables integration with Testcontainers for end-to-end testing. However, hard-coding credentials limits flexibility.

Consider parameterizing the credentials rather than hard-coding them:

-case "testcontainers" -> "jdbc:tc:" + host + ":" + port
-        + ":///" + (jdbcProtocol.getDatabase() == null ? "" : jdbcProtocol.getDatabase()) + "?user=root&password=root";
+case "testcontainers" -> "jdbc:tc:" + host + ":" + port
+        + ":///" + (jdbcProtocol.getDatabase() == null ? "" : jdbcProtocol.getDatabase()) 
+        + "?user=" + (StringUtils.hasText(jdbcProtocol.getUsername()) ? jdbcProtocol.getUsername() : "root") 
+        + "&password=" + (StringUtils.hasText(jdbcProtocol.getPassword()) ? jdbcProtocol.getPassword() : "root");

386-387: Add explanatory comment for the Testcontainers case.

Adding a comment explaining the purpose and usage of the Testcontainers case would improve maintainability.

+// Special case for test containers JDBC URL format (jdbc:tc:postgresql:15:///test?user=root&password=root)
 case "testcontainers" -> "jdbc:tc:" + host + ":" + port
         + ":///" + (jdbcProtocol.getDatabase() == null ? "" : jdbcProtocol.getDatabase()) + "?user=root&password=root";
hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/database/JdbcCommonCollectE2eTest.java (3)

48-53: Consider adding a comment explaining the database image selection

The code references a DatabaseImagesEnum class which appears to be used for selecting test container images. I recommend adding a brief comment explaining the purpose of this enum and why PostgreSQL was chosen as the default test database.


86-94: Document why 'slow_sql' metric requires special handling

The code has special handling for the "slow_sql" metric, only verifying that it doesn't throw an exception. Please add a comment explaining why this metric needs different validation logic than other metrics.

 if ("slow_sql".equals(metricName)) {
+    // The slow_sql metric requires special handling because it depends on database-specific features
+    // that may not be available in the test container or requires additional setup.
+    // For E2E testing purposes, we only verify it doesn't throw exceptions.
     Metrics finalMetricsDef = metricsDef;
     assertDoesNotThrow(() -> collectMetrics(finalMetricsDef),
             String.format("%s failed to collect metrics)", metricName));
     log.info("{} metrics validation passed", metricName);
     continue;  // skip slow_sql, extra extensions
 }

54-69: Consider adding more specific assertions for collection results

The test effectively sets up the collection environment, but could benefit from more specific assertions to validate the collected data, not just that collection occurred without errors.

For example, you could enhance the test by validating specific fields or values in the collected metrics:

// Example of more specific validation
CollectRep.MetricsData metricsData = validateMetricsCollection(metricsDef, metricName, true);
// Verify specific metrics were collected
if ("database_size".equals(metricName)) {
    assertFalse(metricsData.getValuesList().isEmpty(), "Should have collected database size metrics");
    // Further specific assertions based on expected values
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b02837b and 729e4a3.

📒 Files selected for processing (5)
  • hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/database/JdbcCommonCollect.java (1 hunks)
  • hertzbeat-e2e/hertzbeat-collector-basic-e2e/pom.xml (2 hunks)
  • hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/database/DatabaseImagesEnum.java (1 hunks)
  • hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/database/JdbcCommonCollectE2eTest.java (1 hunks)
  • hertzbeat-e2e/pom.xml (1 hunks)
🔇 Additional comments (8)
hertzbeat-e2e/pom.xml (1)

77-88: Well-structured dependency management addition.

Adding the Testcontainers BOM (Bill of Materials) as part of dependencyManagement is a great practice. This centralizes version management for all Testcontainers dependencies across the project, ensuring consistency and simplifying future version upgrades.

hertzbeat-e2e/hertzbeat-collector-basic-e2e/pom.xml (3)

34-35: Good versioning practice.

Defining database driver versions as properties follows Maven best practices, enabling centralized version management.


59-81: Well-organized Testcontainers dependencies.

The dependencies are properly organized with clear comments, correct scoping as "test", and appropriate module selection for database testing with Testcontainers.


83-97: Appropriate JDBC driver configuration.

The JDBC drivers are correctly configured with:

  • Specific versions tied to properties
  • Test scope to limit their inclusion to test classpath only
  • Optional flag to prevent transitive inclusion in dependent projects
hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/database/DatabaseImagesEnum.java (2)

23-26: Clean enum design for test database types.

The enum effectively defines the supported database types with appropriate image names and default tags for testing.


47-54: Well-implemented lookup method.

The lookup method correctly handles case-insensitive matching of database image names, ensuring flexibility in how tests reference image types.

hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/database/JdbcCommonCollectE2eTest.java (2)

1-47: Good implementation of E2E tests for JDBC collection

The class structure and test setup with Mockito look good. The class extends AbstractCollectE2eTest which is appropriate for E2E testing.


81-85: LGTM: Test method initialization looks good

The test initialization correctly retrieves the job definition and sets up the collection environment.

Comment on lines +95 to +97
CollectRep.MetricsData metricsData = validateMetricsCollection(metricsDef, metricName, true);
CollectUtil.getConfigmapFromPreCollectData(metricsData);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

The return value of getConfigmapFromPreCollectData is not used

Line 96 calls CollectUtil.getConfigmapFromPreCollectData(metricsData) but doesn't use the return value. Consider either storing and using the return value or adding a comment explaining why it's called without using the result.

-CollectUtil.getConfigmapFromPreCollectData(metricsData);
+// Extract configmap data for potential use in subsequent test iterations
+Map<String, Configmap> configmap = CollectUtil.getConfigmapFromPreCollectData(metricsData);
+if (!configmap.isEmpty()) {
+    configmapFromPreCollectData.add(configmap);
+}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +71 to +79
@Override
protected Protocol buildProtocol(Metrics metricsDef) {
JdbcProtocol jdbcProtocol = metricsDef.getJdbc();
jdbcProtocol.setHost(DATABASE_IMAGE_NAME);
jdbcProtocol.setPort(DATABASE_IMAGE_TAG);
jdbcProtocol.setDatabase("test");
jdbcProtocol.setPlatform("testcontainers");
return jdbcProtocol;
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify if port assignment is correct

Line 75 assigns DATABASE_IMAGE_TAG to the port property, which seems unusual as ports are typically numeric values. Consider verifying if this is the intended behavior or if it should be using an actual port number.


🏁 Script executed:

#!/bin/bash
# Check how DATABASE_IMAGE_TAG is used and if it's appropriate for port configuration
echo "Checking DatabaseImagesEnum class for tag definition..."
fd -t f -e java "DatabaseImagesEnum.java" | xargs cat

echo "Checking JdbcProtocol class for port field type..."
fd -t f -e java "JdbcProtocol.java" | xargs cat | grep -A 10 "private.*port"

Length of output: 2986


🏁 Script executed:

#!/bin/bash
# Display the relevant test file context around the buildProtocol method
fd -t f -e java "JdbcCommonCollectE2eTest.java" | xargs sed -n '1,200p'

Length of output: 4427


🏁 Script executed:

#!/bin/bash
# Locate and display AbstractCollectE2eTest class implementation context around container setup or protocol handling
fd -t f -e java "AbstractCollectE2eTest.java" | xargs sed -n '1,200p'

Length of output: 6135


Confirm port assignment in buildProtocol

The test currently does:

jdbcProtocol.setHost(DATABASE_IMAGE_NAME);
jdbcProtocol.setPort(DATABASE_IMAGE_TAG);

Here, DATABASE_IMAGE_TAG comes from DatabaseImagesEnum.getDefaultTag() (e.g. "15"), which is the Docker image version—not a TCP port. Since JdbcProtocol.port is the port used to connect to the database, this will direct the driver to port 15 rather than the actual database port (e.g. 5432 or the Testcontainers–mapped port).

Please verify and update accordingly:

  • If you’re using Testcontainers, start the container and set:
    jdbcProtocol.setPort(String.valueOf(container.getFirstMappedPort()));
  • Otherwise, use the default database port (e.g. "5432") or inject it via configuration.

Location:

  • hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/database/JdbcCommonCollectE2eTest.java
    protected Protocol buildProtocol(Metrics metricsDef) { … }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants