This is an automated email from the ASF dual-hosted git repository.

Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git


The following commit(s) were added to refs/heads/master by this push:
     new a85bd46c18 [fix] make the Windows native collector start, and smoke 
test the packages in CI (#4379)
a85bd46c18 is described below

commit a85bd46c18d33130298f0e223bd84ea6e29a17de
Author: Duansg <[email protected]>
AuthorDate: Sun Sep 13 19:18:08 2026 +0800

    [fix] make the Windows native collector start, and smoke test the packages 
in CI (#4379)
---
 .github/workflows/collector-native-build.yml       | 57 ++++++++++++++++++++++
 .../collect/redis/RedisCommonCollectImpl.java      | 27 +++++++---
 2 files changed, 78 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/collector-native-build.yml 
b/.github/workflows/collector-native-build.yml
index 715526918a..3c8aadbf1f 100644
--- a/.github/workflows/collector-native-build.yml
+++ b/.github/workflows/collector-native-build.yml
@@ -75,6 +75,63 @@ jobs:
           }
           "archive=$($package.FullName)" >> $env:GITHUB_OUTPUT
 
+      - name: Smoke test native collector package
+        shell: pwsh
+        run: |
+          $ErrorActionPreference = "Stop"
+          $archive = "${{ steps.package.outputs.archive }}"
+          $work = Join-Path ([System.IO.Path]::GetTempPath()) "hzb-smoke"
+          Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue
+          New-Item -ItemType Directory -Path $work | Out-Null
+
+          if ($archive.EndsWith(".zip")) {
+            Expand-Archive -Path $archive -DestinationPath $work -Force
+          } else {
+            tar -xzf $archive -C $work
+          }
+
+          $binary = Get-ChildItem -Path $work -Recurse -File |
+            Where-Object { $_.Name -like "apache-hertzbeat-collector-native-*" 
-and $_.Name -notlike "*.txt" } |
+            Where-Object { $_.Length -gt 10MB } | Select-Object -First 1
+          if (-not $binary) { throw "native executable not found in $archive" }
+          $conf = Join-Path $binary.DirectoryName "config"
+          Write-Host "executable: $($binary.FullName)"
+
+          $out = Join-Path $work "stdout.log"
+          $err = Join-Path $work "stderr.log"
+          $env:MANAGER_HOST = "127.0.0.1"
+          $env:IDENTITY = "ci-smoke-${{ matrix.platform }}"
+          $proc = Start-Process -FilePath $binary.FullName `
+            -ArgumentList 
"--spring.config.location=$conf$([IO.Path]::DirectorySeparatorChar)" `
+            -RedirectStandardOutput $out -RedirectStandardError $err -PassThru
+
+          # The collector prints "Started Collector" before the runners 
execute, and past
+          # failures crashed after that line, so wait for the ServiceLoader 
registration too
+          # and then confirm the process is still alive.
+          $deadline = (Get-Date).AddSeconds(90)
+          $registered = $false
+          while ((Get-Date) -lt $deadline) {
+            Start-Sleep -Seconds 2
+            $log = (Get-Content $out, $err -ErrorAction SilentlyContinue) 
-join "`n"
+            if ($log -match "collect strategies") { $registered = $true; break 
}
+            if ($proc.HasExited) { break }
+          }
+
+          Start-Sleep -Seconds 10
+          $proc.Refresh()
+          $alive = -not $proc.HasExited
+          $exitCode = if ($alive) { $null } else { $proc.ExitCode }
+          if ($alive) { Stop-Process -Id $proc.Id -Force -ErrorAction 
SilentlyContinue }
+
+          $log = (Get-Content $out, $err -ErrorAction SilentlyContinue) -join 
"`n"
+          Write-Host "----- collector output (tail) -----"
+          Write-Host (($log -split "`n") | Select-Object -Last 40 | Out-String)
+          Write-Host "-----------------------------------"
+
+          if (-not $alive) { throw "collector process exited (exit code 
$exitCode)" }
+          if (-not $registered) { throw "collector stayed up but never 
registered its collect strategies" }
+          Write-Host "smoke test passed for ${{ matrix.platform }}"
+
       - name: Upload native collector package
         uses: actions/upload-artifact@v4
         with:
diff --git 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/redis/RedisCommonCollectImpl.java
 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/redis/RedisCommonCollectImpl.java
index ac520cf72b..c5b05ff148 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/redis/RedisCommonCollectImpl.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/redis/RedisCommonCollectImpl.java
@@ -73,11 +73,26 @@ public class RedisCommonCollectImpl extends AbstractCollect 
{
 
     private static final String UNIQUE_IDENTITY = "identity";
 
-    private final ClientResources defaultClientResources;
     private final GlobalConnectionCache connectionCache = 
GlobalConnectionCache.getInstance();
-    
-    public RedisCommonCollectImpl() {
-        defaultClientResources = DefaultClientResources.create();
+
+    /**
+     * Holds the lettuce client resources, created on first use.
+     * <p>
+     * Loading {@link DefaultClientResources} runs a static initializer that 
resolves netty's DNS
+     * address resolver group. That resolver is unavailable in a native image 
on Windows, where it
+     * fails with a NullPointerException from 
sun.net.dns.ResolverConfigurationImpl
+     * (see oracle/graal#11280 and oracle/graal#4304). Because every collector 
is instantiated
+     * eagerly through the ServiceLoader at startup, doing this in the 
constructor took the whole
+     * collector process down before it could serve anything. Deferring it 
keeps startup working;
+     * on the platforms where the resolver is broken only Redis collection 
fails, and it fails with
+     * a clear error at collect time.
+     */
+    private static final class ClientResourcesHolder {
+        private static final ClientResources INSTANCE = 
DefaultClientResources.create();
+    }
+
+    private static ClientResources clientResources() {
+        return ClientResourcesHolder.INSTANCE;
     }
 
     @Override
@@ -292,7 +307,7 @@ public class RedisCommonCollectImpl extends AbstractCollect 
{
      * @return redis cluster client
      */
     private RedisClusterClient buildClusterClient(RedisProtocol redisProtocol, 
String host, String port) {
-        return RedisClusterClient.create(defaultClientResources, 
redisUri(redisProtocol, host, port));
+        return RedisClusterClient.create(clientResources(), 
redisUri(redisProtocol, host, port));
     }
 
     /**
@@ -302,7 +317,7 @@ public class RedisCommonCollectImpl extends AbstractCollect 
{
      * @return redis single client
      */
     private RedisClient buildSingleClient(RedisProtocol redisProtocol, String 
host, String port) {
-        return RedisClient.create(defaultClientResources, 
redisUri(redisProtocol, host, port));
+        return RedisClient.create(clientResources(), redisUri(redisProtocol, 
host, port));
     }
 
     private RedisURI redisUri(RedisProtocol redisProtocol, String host, String 
port) {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to