Skip to content

Conversation

@rafabene
Copy link
Contributor

@rafabene rafabene commented Jan 6, 2026

Summary

  • Migrate from glog to Go's native slog package for structured JSON logging per HyperFleet Logging Specification
  • Add support for required fields: timestamp, level, message, component, version, hostname
  • Add support for correlation fields: trace_id, span_id, request_id, operation_id
  • Maintain backward compatibility via OCMLogger interface
  • Fix Dockerfile.openapi for ARM64 Mac support (multi-arch build)

Changes

Logging Migration (HYPERFLEET-458)

  • Rewrite pkg/logger/logger.go to use slog with custom contextHandler
  • Add pkg/logger/context.go for trace/span/request ID helpers
  • Add pkg/logger/http.go for HTTP-specific logging fields
  • Add pkg/config/logging.go for log configuration (level, format, output)
  • Replace all glog imports across 24 files with slog equivalents
  • Configuration precedence: flags → env vars → defaults

Dockerfile Fix (HYPERFLEET-464)

  • Replace AMD64-only base image with multi-arch eclipse-temurin:17-jdk
  • Add automatic architecture detection for Go binary download
  • Download openapi-generator-cli JAR directly from Maven Central

Test plan

  • go build ./... passes
  • go test ./pkg/... passes (unit tests)
  • Integration tests (require database)
  • Verify JSON log output with LOG_FORMAT=json
  • Verify make generate works on ARM64 Mac

Summary by CodeRabbit

  • New Features

    • Configurable structured logging (level, format, output), request tracing (trace/span/request IDs), and enriched HTTP request/response attributes.
  • Improvements

    • Unified structured logger across the application for clearer, consistent logs and controlled debug output.
    • Debug logging now toggleable via LOG_LEVEL.
  • Chores

    • Tooling updated to a multi-arch generation environment with architecture-aware install flow.

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

Replace AMD64-only base image with multi-arch eclipse-temurin:17-jdk.
Auto-detect architecture to download correct Go binary (arm64/amd64).
Download openapi-generator-cli JAR directly from Maven Central.

This enables `make generate` to work on ARM64 Macs without QEMU crashes.
@openshift-ci openshift-ci bot requested review from aredenba-rh and tirthct January 6, 2026 15:44
@openshift-ci
Copy link

openshift-ci bot commented Jan 6, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign vkareh for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link

coderabbitai bot commented Jan 6, 2026

Walkthrough

The PR replaces glog with Go's structured slog across the codebase and introduces a new logging subsystem in pkg/logger (global initialization, context-aware handler, legacy-wrapper, HTTP logging helpers). It adds a LoggingConfig and wires it into ApplicationConfig, updates many files to use slog or the new logger API, and adds context helpers for tracing fields. The Dockerfile.openapi is replaced to use an Eclipse Temurin Java base, installs Go per-architecture, downloads the openapi-generator-cli JAR, and invokes it via java -jar.

Sequence Diagram(s)

(Skipped — changes are primarily logging library replacement, new logger package, config wiring, and build recipe updates; there is no new multi-component runtime control flow requiring a sequence diagram.)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

lgtm

Suggested reviewers

  • aredenba-rh

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 68.18% 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 accurately describes the main change: migrating from glog to slog-based structured logging, which is the primary focus across 24+ files in this changeset.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94e573f and 93ce867.

📒 Files selected for processing (2)
  • Dockerfile.openapi
  • test/helper.go
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/**/*.go : Use structured logging via pkg/logger/logger.go with Extra() method for adding context fields
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/{handlers,services}/**/*.go : Retrieve database sessions from context via db.NewContext() rather than creating new GORM connections
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/**/*.go : Use structured logging via pkg/logger/logger.go with Extra() method for adding context fields

Applied to files:

  • test/helper.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to cmd/hyperfleet/server/**/*.go : Extract user account ID and username from JWT claims for audit logging and authorization checks

Applied to files:

  • test/helper.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to test/factories/**/*.go : Provide test data factories in test/factories/ for consistent test fixture creation

Applied to files:

  • test/helper.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Use FIPS-compliant crypto with CGO_ENABLED=1 and GOEXPERIMENT=boringcrypto build flags

Applied to files:

  • test/helper.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to cmd/hyperfleet/environments/**/*.go : Use environment-based configuration via OCM_ENV to select development, unit_testing, integration_testing, or production settings

Applied to files:

  • test/helper.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Regenerate Go models from openapi/openapi.yaml using make generate command after specification changes

Applied to files:

  • Dockerfile.openapi
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/api/openapi_embed.go : Embed OpenAPI specification at compile time using //go:embed directive

Applied to files:

  • Dockerfile.openapi
🧬 Code graph analysis (1)
test/helper.go (1)
pkg/logger/logger.go (2)
  • Initialize (34-109)
  • Config (26-31)
🔇 Additional comments (3)
Dockerfile.openapi (1)

1-45: LGTM! Multi-arch support and past issues addressed.

The Dockerfile changes successfully implement multi-arch support (ARM64 and AMD64) and address all previous review feedback:

  • Base image changed to multi-arch eclipse-temurin:17-jdk
  • Go version updated to 1.24.9 (matching go.mod toolchain requirement)
  • openapi-generator-cli updated to 7.18.0 (latest stable release)
  • Architecture-aware Go installation with proper detection logic
  • JAR-based generation approach replaces docker-entrypoint.sh invocation

The implementation correctly handles architecture detection and downloads the appropriate Go binary, ensuring compatibility with ARM64 Macs and CI environments.

test/helper.go (2)

199-199: Fix typo: "Reseting" should be "Resetting".

🔎 Proposed fix
-	slog.Info("Resetting testing environment")
+	slog.Info("Resetting testing environment")

Likely an incorrect or invalid review comment.


9-9: Raw slog is appropriate for test code and doesn't require pkg/logger.

The retrieved learnings specify that structured logging via pkg/logger applies to pkg/**/*.go (production code only). Since this file is test code (test/**/*.go), it is outside the scope of that requirement. The design intentionally uses raw slog for test helpers and server initialization, as evidenced by the absence of logger.Initialize calls in the test suite.


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

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: 8

🤖 Fix all issues with AI Agents
In @cmd/hyperfleet-api/server/metrics_server.go:
- Line 58: The TLS startup log in metrics_server.go currently uses
env().Config.Server.BindAddress but should use the metrics-specific bind
address; update the slog.Info call that logs "Serving Metrics with TLS" to
reference env().Config.Metrics.BindAddress (matching the existing non-TLS log
that uses env().Config.Metrics.BindAddress) so both TLS and non-TLS logs
consistently show the metrics bind address.

In @Dockerfile.openapi:
- Around line 19-21: The Dockerfile currently downloads
openapi-generator-cli-7.16.0.jar via the wget command; update the URL and
filename to use version 7.18.0 (change occurrences of
openapi-generator-cli-7.16.0.jar to openapi-generator-cli-7.18.0.jar in the RUN
wget line) unless 7.16.0 is intentionally pinned, in which case add a clarifying
comment above the RUN wget line explaining the stability or compatibility reason
for pinning to 7.16.0.

In @pkg/api/error.go:
- Line 6: Replace direct usage of log/slog with the project's structured logger:
remove the "log/slog" import and import pkg/logger instead; update all logging
calls in this file (the error-handling helpers and any places referenced at the
comment locations) to use logger.FromContext(ctx).Error/Info (or the appropriate
level) and attach fields via logger.Extra() (e.g.,
logger.FromContext(ctx).Error("msg", logger.Extra("trace_id", traceID,
"span_id", spanID, "request_id", reqID, "err", err))). If any functions that log
do not currently accept a context.Context, add a ctx parameter or obtain a
context where appropriate so you can call logger.FromContext(ctx); keep message
text but replace slog field usage with logger.Extra() calls.

In @pkg/auth/authz_middleware_mock.go:
- Line 4: Replace the direct "log/slog" usage with the project logger
(pkg/logger) and use its Extra() context-enrichment API: remove the "log/slog"
import, import pkg/logger, and change any slog.* calls in
authz_middleware_mock.go to calls that obtain the logger and add required fields
via logger.Extra(...).Specifically, ensure the log invocation uses the logger
package's Extra() to include component, version, hostname and the correlation
fields (trace_id, span_id, request_id) (e.g., logger.Extra(ctx,
...).Info/Error(...)) so mock logging follows the same structured format as
production code.

In @pkg/db/db_session/testcontainer.go:
- Line 71: The slog.Info call currently logs the full connStr (variable connStr)
which may contain credentials; update the logging in the testcontainer code so
it does not emit sensitive data: either remove connStr from the slog.Info call
or parse/sanitize connStr to log only non-sensitive fields (e.g., host, port,
database name) or a safe placeholder like "<redacted-credentials>". Locate the
slog.Info invocation that references connStr and replace it with a sanitized log
message that omits username/password.

In @pkg/logger/logger.go:
- Around line 147-164: The Default() function has a race: after releasing
globalMu read lock another goroutine may initialize globalLogger, causing double
initialization; change the check-and-initialize to be atomic by either using a
package-level sync.Once (e.g. a once variable and call once.Do(func(){
Initialize(...) })) or by upgrading to a write lock for the initialize path (use
globalMu.Lock()/Unlock() to check nil and call Initialize), and ensure you still
return globalLogger; update references to Default(), globalMu, Initialize,
globalLogger accordingly.
- Around line 196-213: The NewOCMLogger function is injecting operation_id into
attrs, causing duplicate operation_id when contextHandler.Handle also adds it;
remove the operation_id addition from NewOCMLogger by stopping the append of
slog.String("operation_id", ...) (leave account_id and tx_id logic intact) so
that only contextHandler.Handle is responsible for adding operation_id before
calling l.With(...).
🧹 Nitpick comments (11)
pkg/handlers/openapi.go (1)

41-41: Consider adding structured fields to startup logs.

These slog.Info calls could benefit from structured fields for consistency with the coding guidelines. For example, adding context like the source file path or component name would align with the structured logging pattern used elsewhere in this file (lines 64-66, 76-78).

🔎 Example structured logging approach
-	slog.Info("Loaded fully resolved OpenAPI specification from embedded pkg/api/openapi/api/openapi.yaml")
+	slog.Info("Loaded fully resolved OpenAPI specification", "source", "pkg/api/openapi/api/openapi.yaml")
-	slog.Info("Loaded OpenAPI UI HTML from embedded file")
+	slog.Info("Loaded OpenAPI UI HTML", "source", "openapi-ui.html")

Also applies to: 51-51

test/helper.go (1)

206-206: Consider clarifying the comment.

The comment references the 'v' flag which was specific to glog's verbosity flag. Since the migration to slog, this reference may be less clear. Consider updating the comment to be more generic about avoiding flag redefinition conflicts.

🔎 Suggested comment update
-	// Also on reset, we don't care to be re-defining 'v' and other flags
+	// Also on reset, we don't care about redefining flags
test/integration/integration_test.go (1)

5-5: Consider using the centralized logger for consistency.

The test code uses slog directly rather than the centralized pkg/logger package. While this works, using logger.Info() and logger.Warn() from pkg/logger would ensure consistency with the rest of the codebase and automatically include standard fields like component, version, and hostname.

🔎 Example refactor to use centralized logger

Import the logger package:

 import (
 	"flag"
-	"log/slog"
 	"os"
 	"path/filepath"
 	"runtime"
 	"testing"
 
 	"github.com/openshift-hyperfleet/hyperfleet-api/test"
+	"github.com/openshift-hyperfleet/hyperfleet-api/pkg/logger"
 )

Initialize the logger before use:

 func TestMain(m *testing.M) {
 	flag.Parse()
+	logger.Initialize(logger.Config{
+		Level:  "info",
+		Format: "text",
+		Output: "stdout",
+	})
-	slog.Info("Starting integration test", "go_version", runtime.Version())
+	logger.Info("Starting integration test", "go_version", runtime.Version())

Update other log calls similarly.

Based on learnings, pkg/**/*.go should use structured logging via pkg/logger/logger.go.

Also applies to: 16-16, 25-25, 38-38, 41-41

cmd/hyperfleet-api/server/logging/formatter_json.go (1)

19-23: Consider caching the debug flag for better performance.

The isDebugEnabled() function reads the LOG_LEVEL environment variable on every call. While the performance impact is likely minimal for logging operations, caching this value at initialization would be more efficient and align with standard practices for configuration that doesn't change at runtime.

🔎 Proposed refactor to cache the debug flag
+var debugEnabled bool
+
+func init() {
+	level := strings.ToLower(os.Getenv("LOG_LEVEL"))
+	debugEnabled = (level == "debug")
+}
+
-// isDebugEnabled checks if debug logging is enabled via LOG_LEVEL
 func isDebugEnabled() bool {
-	level := strings.ToLower(os.Getenv("LOG_LEVEL"))
-	return level == "debug"
+	return debugEnabled
 }
pkg/config/logging.go (2)

22-41: Add validation for logging configuration values.

The configuration accepts Level, Format, and Output as strings without validation. Invalid values (e.g., Level="invalid", Format="xml", Output="file") could be passed through to pkg/logger, potentially causing unexpected behavior or silent failures.

🔎 Proposed validation in NewLoggingConfig
 func NewLoggingConfig() *LoggingConfig {
 	cfg := &LoggingConfig{
 		Level:  "info",
 		Format: "text",
 		Output: "stdout",
 	}
 
 	// Apply environment variables as overrides to defaults
 	// Flags (via AddFlags + Parse) will override these if explicitly set
 	if level := os.Getenv("LOG_LEVEL"); level != "" {
+		level = strings.ToLower(level)
+		if level != "debug" && level != "info" && level != "warn" && level != "error" {
+			// Log warning and use default
+			level = "info"
+		}
 		cfg.Level = level
 	}
 	if format := os.Getenv("LOG_FORMAT"); format != "" {
+		format = strings.ToLower(format)
+		if format != "text" && format != "json" {
+			format = "text"
+		}
 		cfg.Format = format
 	}
 	if output := os.Getenv("LOG_OUTPUT"); output != "" {
+		output = strings.ToLower(output)
+		if output != "stdout" && output != "stderr" {
+			output = "stdout"
+		}
 		cfg.Output = output
 	}
 
 	return cfg
 }

Note: Add "strings" import if not already present.


45-49: Add flag value validation to prevent invalid configurations.

The flag registration doesn't validate that users provide valid values. Consider adding validation or using enum-like types to constrain the valid options.

🔎 Proposed flag validation

One approach is to use pflag's ValidValues or add custom validation after flag parsing. Example:

// In AddFlags, document valid values more explicitly
flagset.StringVar(&c.Level, "log-level", c.Level, 
	"Minimum log level (valid: debug, info, warn, error)")
flagset.StringVar(&c.Format, "log-format", c.Format, 
	"Log output format (valid: text, json)")
flagset.StringVar(&c.Output, "log-output", c.Output, 
	"Log output destination (valid: stdout, stderr)")

Then add a Validate() method:

// Validate checks if the configuration values are valid
func (c *LoggingConfig) Validate() error {
	level := strings.ToLower(c.Level)
	if level != "debug" && level != "info" && level != "warn" && level != "error" {
		return fmt.Errorf("invalid log level: %s", c.Level)
	}
	
	format := strings.ToLower(c.Format)
	if format != "text" && format != "json" {
		return fmt.Errorf("invalid log format: %s", c.Format)
	}
	
	output := strings.ToLower(c.Output)
	if output != "stdout" && output != "stderr" {
		return fmt.Errorf("invalid log output: %s", c.Output)
	}
	
	return nil
}

Call this after flag parsing in the main initialization flow.

cmd/hyperfleet-api/server/healthcheck_server.go (1)

53-60: Consider using pkg/logger instead of slog directly.

The logging migration uses slog.Info directly, but the new pkg/logger package provides a context-aware logger that automatically enriches logs with component, version, hostname, and correlation IDs. For consistency with the HyperFleet Logging Specification mentioned in the PR objectives, consider using the logger package:

🔎 Proposed refactor to use pkg/logger
 import (
 	"context"
 	"fmt"
-	"log/slog"
 	"net"
 	"net/http"

 	health "github.com/docker/go-healthcheck"
 	"github.com/gorilla/mux"
+	"github.com/openshift-hyperfleet/hyperfleet-api/pkg/logger"
 )

Then update the log calls:

-		slog.Info("Serving HealthCheck with TLS", "address", env().Config.HealthCheck.BindAddress)
+		logger.Default().Info("Serving HealthCheck with TLS", "address", env().Config.HealthCheck.BindAddress)

Based on learnings, use structured logging via pkg/logger/logger.go.

cmd/hyperfleet-api/server/api_server.go (2)

121-130: Consider using pkg/logger for consistency with the logging specification.

Similar to the healthcheck server, these log statements use slog directly rather than the centralized pkg/logger package which adds standard fields (component, version, hostname) and context-based correlation IDs.

🔎 Proposed refactor
-		slog.Info("Serving with TLS", "address", env().Config.Server.BindAddress)
+		logger.Default().Info("Serving with TLS", "address", env().Config.Server.BindAddress)
-		slog.Info("Serving without TLS", "address", env().Config.Server.BindAddress)
+		logger.Default().Info("Serving without TLS", "address", env().Config.Server.BindAddress)
-	slog.Info("Web server terminated")
+	logger.Default().Info("Web server terminated")

Based on learnings, use structured logging via pkg/logger/logger.go.


151-153: Consider using pkg/logger for the database error log.

This should also use the centralized logger for consistency.

-		slog.Error("Error closing database connection", "error", err)
+		logger.Default().Error("Error closing database connection", "error", err)
pkg/logger/context.go (2)

10-21: Inconsistent naming convention for context keys.

The context key values use mixed naming conventions:

  • trace_id, span_id, request_id use snake_case
  • accountID uses camelCase
  • txid is an abbreviation

For consistency with the HyperFleet Logging Specification (which uses snake_case for log fields like trace_id, span_id, request_id), consider aligning all keys:

🔎 Proposed fix
 const (
 	// TraceIDKey is the context key for distributed trace ID (OpenTelemetry)
 	TraceIDKey contextKey = "trace_id"
 	// SpanIDKey is the context key for current span ID (OpenTelemetry)
 	SpanIDKey contextKey = "span_id"
 	// RequestIDKey is the context key for HTTP request ID
 	RequestIDKey contextKey = "request_id"
 	// AccountIDKey is the context key for account ID
-	AccountIDKey contextKey = "accountID"
+	AccountIDKey contextKey = "account_id"
 	// TransactionIDKey is the context key for transaction ID
-	TransactionIDKey contextKey = "txid"
+	TransactionIDKey contextKey = "transaction_id"
 )

Note: If these keys must match existing context values set elsewhere in the codebase, verify that those locations are also updated.


66-72: Simplify GetAccountID to match other getter patterns.

The nested nil check differs from the pattern used in other getters. Consider using the same single type assertion pattern for consistency:

🔎 Proposed fix
 // GetAccountID retrieves the account ID from context
 func GetAccountID(ctx context.Context) string {
-	if accountID := ctx.Value(AccountIDKey); accountID != nil {
-		if s, ok := accountID.(string); ok {
-			return s
-		}
+	if accountID, ok := ctx.Value(AccountIDKey).(string); ok {
+		return accountID
 	}
 	return ""
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 460f0ae and f9cff41.

📒 Files selected for processing (25)
  • Dockerfile.openapi
  • cmd/hyperfleet-api/environments/framework.go
  • cmd/hyperfleet-api/main.go
  • cmd/hyperfleet-api/migrate/cmd.go
  • cmd/hyperfleet-api/servecmd/cmd.go
  • cmd/hyperfleet-api/server/api_server.go
  • cmd/hyperfleet-api/server/healthcheck_server.go
  • cmd/hyperfleet-api/server/logging/formatter_json.go
  • cmd/hyperfleet-api/server/metrics_server.go
  • cmd/hyperfleet-api/server/server.go
  • go.mod
  • pkg/api/error.go
  • pkg/auth/authz_middleware_mock.go
  • pkg/config/config.go
  • pkg/config/logging.go
  • pkg/db/db_session/test.go
  • pkg/db/db_session/testcontainer.go
  • pkg/db/migrations.go
  • pkg/errors/errors.go
  • pkg/handlers/openapi.go
  • pkg/logger/context.go
  • pkg/logger/http.go
  • pkg/logger/logger.go
  • test/helper.go
  • test/integration/integration_test.go
🧰 Additional context used
📓 Path-based instructions (7)
pkg/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Use structured logging via pkg/logger/logger.go with Extra() method for adding context fields

Files:

  • pkg/errors/errors.go
  • pkg/db/migrations.go
  • pkg/config/logging.go
  • pkg/auth/authz_middleware_mock.go
  • pkg/logger/context.go
  • pkg/handlers/openapi.go
  • pkg/db/db_session/testcontainer.go
  • pkg/config/config.go
  • pkg/db/db_session/test.go
  • pkg/logger/http.go
  • pkg/api/error.go
  • pkg/logger/logger.go
test/integration/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Use Testcontainers to spin up isolated PostgreSQL instances for integration tests

Files:

  • test/integration/integration_test.go
pkg/{handlers,services}/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Retrieve database sessions from context via db.NewContext() rather than creating new GORM connections

Files:

  • pkg/handlers/openapi.go
pkg/handlers/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

pkg/handlers/**/*.go: Automatically convert errors to OpenAPI error responses using errors.SendError() in HTTP handlers
Parse HTTP request bodies using json.NewDecoder(r.Body) in handler functions
Write HTTP responses using json.NewEncoder(w) for consistency with request parsing
Ensure all HTTP handlers follow the pattern: parse request, call service/DAO, handle errors, send response
Implement handlers as methods on handler structs that accept (w http.ResponseWriter, r *http.Request) parameters
Set HTTP status codes correctly: 201 Created for POST, 200 OK for GET, 204 No Content for DELETE operations

Files:

  • pkg/handlers/openapi.go
pkg/{dao,handlers}/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Support pagination in list operations via ListArgs parameter with configurable limit and offset

Files:

  • pkg/handlers/openapi.go
pkg/{handlers,services,dao}/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Return ServiceError type from pkg/errors/ with HttpCode, Code, and Reason fields in error handling

Files:

  • pkg/handlers/openapi.go
pkg/{db/transaction_middleware.go,handlers}/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Store request operation IDs in context for tracing and debugging purposes in error logs

Files:

  • pkg/handlers/openapi.go
🧠 Learnings (25)
📓 Common learnings
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/**/*.go : Use structured logging via pkg/logger/logger.go with Extra() method for adding context fields
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/**/*.go : Use structured logging via pkg/logger/logger.go with Extra() method for adding context fields

Applied to files:

  • pkg/errors/errors.go
  • test/integration/integration_test.go
  • cmd/hyperfleet-api/server/logging/formatter_json.go
  • cmd/hyperfleet-api/server/api_server.go
  • pkg/db/migrations.go
  • pkg/config/logging.go
  • cmd/hyperfleet-api/migrate/cmd.go
  • cmd/hyperfleet-api/environments/framework.go
  • pkg/auth/authz_middleware_mock.go
  • cmd/hyperfleet-api/server/metrics_server.go
  • pkg/logger/context.go
  • pkg/handlers/openapi.go
  • pkg/db/db_session/testcontainer.go
  • pkg/config/config.go
  • pkg/db/db_session/test.go
  • pkg/logger/http.go
  • pkg/api/error.go
  • cmd/hyperfleet-api/servecmd/cmd.go
  • test/helper.go
  • cmd/hyperfleet-api/server/server.go
  • pkg/logger/logger.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/api/openapi_embed.go : Embed OpenAPI specification at compile time using //go:embed directive

Applied to files:

  • pkg/errors/errors.go
  • test/integration/integration_test.go
  • Dockerfile.openapi
  • pkg/handlers/openapi.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/api/openapi/model_*.go : Support JSON request/response serialization with proper struct tags on generated OpenAPI models

Applied to files:

  • pkg/errors/errors.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/handlers/**/*.go : Automatically convert errors to OpenAPI error responses using errors.SendError() in HTTP handlers

Applied to files:

  • pkg/errors/errors.go
  • pkg/handlers/openapi.go
  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to cmd/hyperfleet/server/**/*.go : Extract user account ID and username from JWT claims for audit logging and authorization checks

Applied to files:

  • pkg/errors/errors.go
  • cmd/hyperfleet-api/server/api_server.go
  • pkg/handlers/openapi.go
  • pkg/api/error.go
  • cmd/hyperfleet-api/servecmd/cmd.go
  • test/helper.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to cmd/hyperfleet/server/**/*.go : Validate JWT tokens from Red Hat SSO in middleware before allowing requests to handlers

Applied to files:

  • pkg/errors/errors.go
  • cmd/hyperfleet-api/server/api_server.go
  • pkg/auth/authz_middleware_mock.go
  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/{handlers,services,dao}/**/*.go : Return ServiceError type from pkg/errors/ with HttpCode, Code, and Reason fields in error handling

Applied to files:

  • pkg/errors/errors.go
  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/db/migrations/**/*.go : Use GORM AutoMigrate for schema management instead of manual SQL scripts

Applied to files:

  • test/integration/integration_test.go
  • pkg/db/migrations.go
  • cmd/hyperfleet-api/migrate/cmd.go
  • cmd/hyperfleet-api/main.go
  • pkg/db/db_session/testcontainer.go
  • pkg/db/db_session/test.go
  • go.mod
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to test/integration/**/*.go : Use Testcontainers to spin up isolated PostgreSQL instances for integration tests

Applied to files:

  • test/integration/integration_test.go
  • pkg/db/db_session/testcontainer.go
  • pkg/db/db_session/test.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to cmd/hyperfleet/environments/**/*.go : Use environment-based configuration via OCM_ENV to select development, unit_testing, integration_testing, or production settings

Applied to files:

  • test/integration/integration_test.go
  • cmd/hyperfleet-api/server/logging/formatter_json.go
  • cmd/hyperfleet-api/main.go
  • cmd/hyperfleet-api/environments/framework.go
  • cmd/hyperfleet-api/servecmd/cmd.go
  • test/helper.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to test/factories/**/*.go : Provide test data factories in test/factories/ for consistent test fixture creation

Applied to files:

  • test/integration/integration_test.go
  • test/helper.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/handlers/**/*.go : Write HTTP responses using json.NewEncoder(w) for consistency with request parsing

Applied to files:

  • cmd/hyperfleet-api/server/logging/formatter_json.go
  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Regenerate Go models from openapi/openapi.yaml using make generate command after specification changes

Applied to files:

  • Dockerfile.openapi
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/{handlers,services}/**/*.go : Retrieve database sessions from context via db.NewContext() rather than creating new GORM connections

Applied to files:

  • cmd/hyperfleet-api/server/api_server.go
  • pkg/db/migrations.go
  • cmd/hyperfleet-api/migrate/cmd.go
  • cmd/hyperfleet-api/server/healthcheck_server.go
  • pkg/logger/context.go
  • pkg/handlers/openapi.go
  • pkg/db/db_session/testcontainer.go
  • pkg/db/db_session/test.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/db/migrations/**/*.go : Store cluster and node pool specifications as JSONB columns to allow flexible cloud provider configurations

Applied to files:

  • pkg/db/migrations.go
  • cmd/hyperfleet-api/migrate/cmd.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/{db/migrations,dao}/**/*.go : Use polymorphic status tables with owner_type and owner_id columns to support multiple resource types

Applied to files:

  • pkg/db/migrations.go
  • pkg/db/db_session/testcontainer.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/{db/transaction_middleware.go,handlers}/**/*.go : Store request operation IDs in context for tracing and debugging purposes in error logs

Applied to files:

  • pkg/db/migrations.go
  • cmd/hyperfleet-api/migrate/cmd.go
  • pkg/logger/context.go
  • pkg/db/db_session/test.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/db/migrations/**/*.go : Enforce foreign key relationships between node pools and clusters via owner_references constraint

Applied to files:

  • pkg/db/migrations.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/db/transaction_middleware.go : Store database sessions in HTTP request context via middleware at request entry point

Applied to files:

  • cmd/hyperfleet-api/migrate/cmd.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/{dao,services}/**/*.go : Use context.Context as the first parameter in all DAO and service method signatures

Applied to files:

  • cmd/hyperfleet-api/migrate/cmd.go
  • pkg/logger/context.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/handlers/**/*.go : Ensure all HTTP handlers follow the pattern: parse request, call service/DAO, handle errors, send response

Applied to files:

  • cmd/hyperfleet-api/server/healthcheck_server.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/dao/**/*.go : Query JSONB columns using GORM's native operators for filtering on nested properties

Applied to files:

  • pkg/db/db_session/test.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/handlers/**/*.go : Implement handlers as methods on handler structs that accept (w http.ResponseWriter, r *http.Request) parameters

Applied to files:

  • pkg/logger/http.go
  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Use FIPS-compliant crypto with CGO_ENABLED=1 and GOEXPERIMENT=boringcrypto build flags

Applied to files:

  • test/helper.go
🧬 Code graph analysis (8)
cmd/hyperfleet-api/server/api_server.go (4)
pkg/logger/logger.go (1)
  • Config (25-30)
pkg/client/ocm/client.go (1)
  • Config (17-24)
cmd/hyperfleet-api/server/server.go (1)
  • Server (11-16)
cmd/hyperfleet-api/environments/types.go (1)
  • Database (36-38)
cmd/hyperfleet-api/environments/framework.go (2)
pkg/logger/logger.go (2)
  • Initialize (33-108)
  • Config (25-30)
cmd/hyperfleet-api/environments/types.go (3)
  • Database (36-38)
  • Clients (67-69)
  • Services (44-47)
cmd/hyperfleet-api/server/healthcheck_server.go (2)
pkg/logger/logger.go (1)
  • Config (25-30)
cmd/hyperfleet-api/server/server.go (1)
  • Server (11-16)
cmd/hyperfleet-api/server/metrics_server.go (2)
pkg/logger/logger.go (1)
  • Config (25-30)
cmd/hyperfleet-api/server/server.go (1)
  • Server (11-16)
pkg/db/db_session/testcontainer.go (1)
pkg/db/migrations.go (1)
  • Migrate (17-24)
pkg/config/config.go (1)
pkg/config/logging.go (2)
  • LoggingConfig (10-17)
  • NewLoggingConfig (22-42)
test/helper.go (2)
pkg/logger/logger.go (2)
  • Initialize (33-108)
  • Config (25-30)
cmd/hyperfleet-api/environments/framework.go (1)
  • Environment (55-57)
pkg/logger/logger.go (2)
pkg/logger/context.go (5)
  • GetTraceID (29-34)
  • GetSpanID (42-47)
  • GetRequestID (55-60)
  • GetAccountID (66-73)
  • GetTransactionID (76-81)
pkg/logger/operationid_middleware.go (1)
  • GetOperationID (38-43)
🔇 Additional comments (27)
pkg/db/migrations.go (1)

34-35: LGTM! Clean migration to structured logging.

The migration from glog.Fatalf to slog.Error with explicit os.Exit(1) is correct and maintains backward compatibility. The structured fields "migrationID" and "error" provide clear context for debugging migration failures.

pkg/db/db_session/test.go (1)

54-55: LGTM! Consistent structured logging.

Both error logging conversions correctly use slog.Error with the "error" field, maintaining the same control flow as the original implementation.

Also applies to: 59-60

pkg/errors/errors.go (1)

116-116: LGTM! Appropriate structured logging for developer errors.

The conversion to slog.Error with a "code" field correctly logs undefined error codes, which helps identify programming errors during development.

go.mod (1)

67-67: LGTM! Dependency correctly marked as indirect.

Moving github.com/golang/glog to the indirect dependencies section is correct, as it's no longer directly imported following the migration to slog.

cmd/hyperfleet-api/migrate/cmd.go (1)

6-7: LGTM - Migration to slog for bootstrap errors.

The migration from glog to slog with structured logging is correctly implemented. Using direct slog for these early initialization errors is appropriate since the custom pkg/logger may not yet be initialized at this stage.

Also applies to: 35-36, 41-42

cmd/hyperfleet-api/servecmd/cmd.go (1)

4-5: LGTM - Appropriate slog usage for initialization errors.

The migration to slog with structured logging is correctly implemented for these bootstrap error paths. Using direct slog is appropriate for early-stage initialization failures before the custom pkg/logger is initialized.

Also applies to: 22-23, 32-33

test/helper.go (1)

9-9: LGTM - Test helper migration to slog.

The migration from glog to slog in the test helper is correctly implemented with appropriate structured logging. Using direct slog in test infrastructure is acceptable.

Also applies to: 79-80, 83-83, 91-92, 142-143, 146-146, 148-148, 162-162, 164-164, 170-171, 178-178, 180-180, 186-186, 189-189, 195-195, 199-199, 209-210, 216-217

cmd/hyperfleet-api/main.go (1)

4-5: LGTM - Appropriate slog usage in main entry point.

The migration to slog for the main command error handling is correctly implemented. Using direct slog at the top-level entry point is appropriate for catching command execution failures.

Also applies to: 36-37

pkg/config/config.go (1)

21-21: LGTM! Clean integration of LoggingConfig.

The LoggingConfig integration follows the established pattern for other configuration components (Server, Metrics, Database, etc.). The initialization, flag registration, and file reading hooks are all properly wired.

Also applies to: 31-31, 42-42, 55-55

cmd/hyperfleet-api/environments/framework.go (2)

69-76: Good practice: Logger initialization before first use.

The logger is properly initialized early with configuration from e.Config.Logging and the application version. This ensures all subsequent logging operations have the correct settings and context.


77-185: Consistent migration to structured logging.

All logging calls have been successfully migrated from glog to slog with structured key-value pairs. The error handling pattern of slog.Error followed by os.Exit(1) is consistent throughout.

pkg/db/db_session/testcontainer.go (4)

7-8: LGTM!

The new imports correctly support the slog-based structured logging migration and the fatal error handling pattern using os.Exit(1).


134-154: LGTM!

The Close method appropriately uses slog.Error for non-fatal errors during cleanup and slog.Info for lifecycle events. The error handling correctly continues cleanup even when individual steps fail.


156-176: LGTM!

The ResetDB method uses structured logging with appropriate context fields ("table", "error") and correctly continues processing remaining tables even when one fails.


178-187: LGTM!

The NewListener method appropriately logs errors without terminating the process, allowing the caller to handle the failure gracefully.

Dockerfile.openapi (3)

1-2: LGTM!

The switch to eclipse-temurin:17-jdk provides multi-arch support while using a well-maintained, official OpenJDK distribution with LTS support.


38-42: LGTM!

The OpenAPI generation command correctly invokes the JAR with appropriate parameters. The paths are consistent with the Dockerfile structure.


8-17: Go 1.24.0 is a valid and available release.

The architecture detection logic is well-implemented, correctly mapping ARM variants and defaulting to AMD64. Go 1.24.0 is available at https://go.dev/dl/ and the download URLs follow the standard Go naming convention for both amd64 and arm64 architectures.

cmd/hyperfleet-api/server/server.go (1)

4-4: LGTM!

The migration from glog to slog is correctly implemented with proper structured logging using the "error" field.

Also applies to: 28-28

cmd/hyperfleet-api/server/metrics_server.go (1)

61-61: LGTM!

The non-TLS serving and termination messages use appropriate structured logging with clear, informative messages.

Also applies to: 65-65

pkg/logger/http.go (1)

1-57: Well-designed HTTP logging utilities.

The API provides clean, composable structured logging attributes for HTTP requests and responses. The design follows Go conventions and aligns well with the HyperFleet logging specification.

cmd/hyperfleet-api/server/api_server.go (2)

41-44: Authentication logger setup looks good.

The migration to sdk.NewStdLoggerBuilder() with explicit stdout/stderr streams and disabled debug mode is appropriate for the OCM SDK authentication handler.


143-144: Error handling with os.Exit(1) is appropriate for fatal startup failure.

Exiting on listener failure is a reasonable approach since the API server cannot function without a network listener.

pkg/logger/logger.go (4)

241-252: Extra() method implementation looks correct.

The method creates a new slice, copies existing attributes, appends the new one, and returns a new legacyLogger instance. This immutable pattern is appropriate.

This aligns with the coding guidelines: "Use structured logging via pkg/logger/logger.go with Extra() method for adding context fields."


266-269: Fatal() exits immediately without flushing.

The Fatal() method logs and exits, but doesn't flush the logger. For slog, this is generally fine as it writes synchronously, but verify that buffered outputs (if any) are flushed.


94-108: Context handler and global logger initialization looks well-structured.

The implementation correctly:

  • Wraps the base handler with contextHandler for attribute injection
  • Adds base attributes (component, version, hostname)
  • Sets the global default via slog.SetDefault()

232-239: V() level mapping collapses granular levels to debug.

The V(level) implementation maps all levels > 1 to debug, collapsing granular verbosity. Current codebase usage (V(10) in db_session and V(Threshold) in logging/writer) relies only on high-level debug messages, so this mapping poses no compatibility issue. Worth documenting if other V() levels are introduced in future migrations.

…ging

Implement HyperFleet Logging Specification with Go's slog package:

- Add LoggingConfig with LOG_LEVEL, LOG_FORMAT, LOG_OUTPUT env vars
- Rewrite pkg/logger to use slog internally (OCMLogger interface preserved)
- Add context helpers for trace_id, request_id, account_id correlation
- Support JSON format (production) and text format (development)
- Include required fields: timestamp, level, message, component, version, hostname

Replace all glog imports across 18 files with slog equivalents.
@rafabene rafabene force-pushed the HYPERFLEET-458-migrate-to-slog branch from f9cff41 to 94e573f Compare January 6, 2026 15:58
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

🤖 Fix all issues with AI Agents
In @Dockerfile.openapi:
- Around line 8-17: The Dockerfile installs Go 1.24.0 but your toolchain
requires go1.24.9; update the hardcoded version string in the RUN block so the
wget URL and the filenames used by tar and rm use go1.24.9 instead of go1.24.0
(the logic that sets ARCH/GO_ARCH can stay the same — update only the version in
the wget URL, the tar -xzf argument, and the rm filename).

In @test/helper.go:
- Line 199: Fix the typo in the log message by updating the slog.Info call that
currently reads "Reseting testing environment" to "Resetting testing
environment" so the log uses the correct spelling in the slog.Info(...)
invocation.
🧹 Nitpick comments (5)
cmd/hyperfleet-api/migrate/cmd.go (1)

40-43: Consider adding success logging for operational visibility.

The migration command logs errors but doesn't log success. Adding a success message would improve operational visibility and provide confirmation when migrations complete successfully.

🔎 Suggested enhancement
 	connection := db_session.NewProdFactory(dbConfig)
 	if err := db.Migrate(connection.New(context.Background())); err != nil {
 		slog.Error("Migration failed", "error", err)
 		os.Exit(1)
 	}
+	slog.Info("Migration completed successfully")
 }
cmd/hyperfleet-api/server/logging/formatter_json.go (1)

19-23: Consider using centralized logging configuration.

The isDebugEnabled() function reads LOG_LEVEL from the environment on every call without caching. According to the PR summary, logging configuration (level, format, output) is now centralized in pkg/config/logging.go. Consider using the centralized configuration instead of direct environment variable access to ensure consistent log level handling across the codebase.

📋 Potential approach

The formatter could accept a reference to the logging config during initialization, or access a global logger configuration instance to check debug status, ensuring consistency with how log levels are determined elsewhere in the application.

Dockerfile.openapi (2)

8-17: Architecture detection may silently default to amd64 for unsupported platforms.

The logic maps arm64/aarch64 to arm64 and defaults everything else to amd64. If the build runs on an unsupported architecture (e.g., s390x, ppc64le), it will download the amd64 binary which will fail at runtime.

🔎 Suggested enhancement for explicit architecture validation
-RUN ARCH=$(dpkg --print-architecture) && \
-    if [ "$ARCH" = "arm64" ] || [ "$ARCH" = "aarch64" ]; then \
-        GO_ARCH="arm64"; \
-    else \
-        GO_ARCH="amd64"; \
-    fi && \
+RUN ARCH=$(dpkg --print-architecture) && \
+    case "$ARCH" in \
+        arm64|aarch64) GO_ARCH="arm64" ;; \
+        amd64|x86_64) GO_ARCH="amd64" ;; \
+        *) echo "Unsupported architecture: $ARCH" && exit 1 ;; \
+    esac && \
     wget https://go.dev/dl/go1.24.0.linux-${GO_ARCH}.tar.gz && \
     tar -C /usr/local -xzf go1.24.0.linux-${GO_ARCH}.tar.gz && \
     rm go1.24.0.linux-${GO_ARCH}.tar.gz

19-21: Consider adding checksum verification for the JAR download.

Downloading executable artifacts without checksum verification poses a supply chain security risk. Consider verifying the SHA256 checksum of the JAR file after download.

🔎 Example with checksum verification
 # Download openapi-generator-cli
-RUN wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.18.0/openapi-generator-cli-7.18.0.jar \
-    -O /usr/local/bin/openapi-generator-cli.jar
+RUN wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.18.0/openapi-generator-cli-7.18.0.jar \
+    -O /usr/local/bin/openapi-generator-cli.jar && \
+    wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.18.0/openapi-generator-cli-7.18.0.jar.sha1 \
+    -O /tmp/openapi-generator-cli.jar.sha1 && \
+    echo "$(cat /tmp/openapi-generator-cli.jar.sha1)  /usr/local/bin/openapi-generator-cli.jar" | sha1sum -c - && \
+    rm /tmp/openapi-generator-cli.jar.sha1

Maven Central provides .sha1 files alongside JARs for verification.

pkg/logger/context.go (1)

10-21: Consider standardizing context key values.

The context key values are inconsistent: TraceIDKey, SpanIDKey, and RequestIDKey use snake_case ("trace_id", "span_id", "request_id"), while AccountIDKey uses camelCase ("accountID") and TransactionIDKey uses an abbreviation ("txid"). Consider standardizing to snake_case ("account_id", "transaction_id") unless the current values are required for backward compatibility.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9cff41 and 94e573f.

📒 Files selected for processing (25)
  • Dockerfile.openapi
  • cmd/hyperfleet-api/environments/framework.go
  • cmd/hyperfleet-api/main.go
  • cmd/hyperfleet-api/migrate/cmd.go
  • cmd/hyperfleet-api/servecmd/cmd.go
  • cmd/hyperfleet-api/server/api_server.go
  • cmd/hyperfleet-api/server/healthcheck_server.go
  • cmd/hyperfleet-api/server/logging/formatter_json.go
  • cmd/hyperfleet-api/server/metrics_server.go
  • cmd/hyperfleet-api/server/server.go
  • go.mod
  • pkg/api/error.go
  • pkg/auth/authz_middleware_mock.go
  • pkg/config/config.go
  • pkg/config/logging.go
  • pkg/db/db_session/test.go
  • pkg/db/db_session/testcontainer.go
  • pkg/db/migrations.go
  • pkg/errors/errors.go
  • pkg/handlers/openapi.go
  • pkg/logger/context.go
  • pkg/logger/http.go
  • pkg/logger/logger.go
  • test/helper.go
  • test/integration/integration_test.go
🚧 Files skipped from review as they are similar to previous changes (11)
  • cmd/hyperfleet-api/server/api_server.go
  • pkg/db/migrations.go
  • cmd/hyperfleet-api/environments/framework.go
  • pkg/db/db_session/test.go
  • pkg/errors/errors.go
  • cmd/hyperfleet-api/main.go
  • cmd/hyperfleet-api/server/metrics_server.go
  • cmd/hyperfleet-api/server/healthcheck_server.go
  • pkg/auth/authz_middleware_mock.go
  • test/integration/integration_test.go
  • pkg/handlers/openapi.go
🧰 Additional context used
📓 Path-based instructions (1)
pkg/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Use structured logging via pkg/logger/logger.go with Extra() method for adding context fields

Files:

  • pkg/config/config.go
  • pkg/config/logging.go
  • pkg/logger/context.go
  • pkg/db/db_session/testcontainer.go
  • pkg/logger/http.go
  • pkg/api/error.go
  • pkg/logger/logger.go
🧠 Learnings (21)
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/**/*.go : Use structured logging via pkg/logger/logger.go with Extra() method for adding context fields

Applied to files:

  • pkg/config/config.go
  • test/helper.go
  • pkg/config/logging.go
  • cmd/hyperfleet-api/migrate/cmd.go
  • cmd/hyperfleet-api/servecmd/cmd.go
  • pkg/logger/context.go
  • pkg/db/db_session/testcontainer.go
  • cmd/hyperfleet-api/server/logging/formatter_json.go
  • pkg/logger/http.go
  • cmd/hyperfleet-api/server/server.go
  • pkg/api/error.go
  • pkg/logger/logger.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to cmd/hyperfleet/server/**/*.go : Extract user account ID and username from JWT claims for audit logging and authorization checks

Applied to files:

  • test/helper.go
  • cmd/hyperfleet-api/servecmd/cmd.go
  • pkg/logger/context.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to test/factories/**/*.go : Provide test data factories in test/factories/ for consistent test fixture creation

Applied to files:

  • test/helper.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Use FIPS-compliant crypto with CGO_ENABLED=1 and GOEXPERIMENT=boringcrypto build flags

Applied to files:

  • test/helper.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to cmd/hyperfleet/environments/**/*.go : Use environment-based configuration via OCM_ENV to select development, unit_testing, integration_testing, or production settings

Applied to files:

  • test/helper.go
  • cmd/hyperfleet-api/servecmd/cmd.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/db/migrations/**/*.go : Use GORM AutoMigrate for schema management instead of manual SQL scripts

Applied to files:

  • cmd/hyperfleet-api/migrate/cmd.go
  • go.mod
  • pkg/db/db_session/testcontainer.go
  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/db/migrations/**/*.go : Store cluster and node pool specifications as JSONB columns to allow flexible cloud provider configurations

Applied to files:

  • cmd/hyperfleet-api/migrate/cmd.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/{handlers,services}/**/*.go : Retrieve database sessions from context via db.NewContext() rather than creating new GORM connections

Applied to files:

  • cmd/hyperfleet-api/migrate/cmd.go
  • pkg/logger/context.go
  • pkg/db/db_session/testcontainer.go
  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/db/transaction_middleware.go : Store database sessions in HTTP request context via middleware at request entry point

Applied to files:

  • cmd/hyperfleet-api/migrate/cmd.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/{db/transaction_middleware.go,handlers}/**/*.go : Store request operation IDs in context for tracing and debugging purposes in error logs

Applied to files:

  • cmd/hyperfleet-api/migrate/cmd.go
  • pkg/logger/context.go
  • pkg/db/db_session/testcontainer.go
  • pkg/api/error.go
  • pkg/logger/logger.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/{dao,services}/**/*.go : Use context.Context as the first parameter in all DAO and service method signatures

Applied to files:

  • cmd/hyperfleet-api/migrate/cmd.go
  • pkg/logger/context.go
  • pkg/db/db_session/testcontainer.go
  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to cmd/hyperfleet/server/**/*.go : Validate JWT tokens from Red Hat SSO in middleware before allowing requests to handlers

Applied to files:

  • cmd/hyperfleet-api/servecmd/cmd.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to test/integration/**/*.go : Use Testcontainers to spin up isolated PostgreSQL instances for integration tests

Applied to files:

  • pkg/db/db_session/testcontainer.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/handlers/**/*.go : Write HTTP responses using json.NewEncoder(w) for consistency with request parsing

Applied to files:

  • cmd/hyperfleet-api/server/logging/formatter_json.go
  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/handlers/**/*.go : Implement handlers as methods on handler structs that accept (w http.ResponseWriter, r *http.Request) parameters

Applied to files:

  • pkg/logger/http.go
  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/handlers/**/*.go : Automatically convert errors to OpenAPI error responses using errors.SendError() in HTTP handlers

Applied to files:

  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/handlers/**/*.go : Ensure all HTTP handlers follow the pattern: parse request, call service/DAO, handle errors, send response

Applied to files:

  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/services/**/*.go : Implement service layer between handlers and DAOs for business logic like status aggregation and generation tracking

Applied to files:

  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/handlers/**/*.go : Set HTTP status codes correctly: 201 Created for POST, 200 OK for GET, 204 No Content for DELETE operations

Applied to files:

  • pkg/api/error.go
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Regenerate Go models from openapi/openapi.yaml using make generate command after specification changes

Applied to files:

  • Dockerfile.openapi
📚 Learning: 2025-12-12T11:04:29.971Z
Learnt from: CR
Repo: openshift-hyperfleet/hyperfleet-api PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T11:04:29.971Z
Learning: Applies to pkg/api/openapi_embed.go : Embed OpenAPI specification at compile time using //go:embed directive

Applied to files:

  • Dockerfile.openapi
🧬 Code graph analysis (6)
pkg/config/config.go (1)
pkg/config/logging.go (2)
  • LoggingConfig (10-17)
  • NewLoggingConfig (22-42)
test/helper.go (1)
pkg/logger/logger.go (2)
  • Initialize (34-109)
  • Config (26-31)
cmd/hyperfleet-api/migrate/cmd.go (3)
pkg/db/db_session/default.go (1)
  • NewProdFactory (33-37)
pkg/db/migrations.go (1)
  • Migrate (17-24)
pkg/errors/errors.go (1)
  • New (111-130)
pkg/db/db_session/testcontainer.go (2)
pkg/logger/logger.go (1)
  • NewOCMLogger (197-222)
pkg/db/migrations.go (1)
  • Migrate (17-24)
pkg/api/error.go (1)
pkg/logger/logger.go (1)
  • NewOCMLogger (197-222)
pkg/logger/logger.go (2)
pkg/logger/context.go (5)
  • GetTraceID (29-34)
  • GetSpanID (42-47)
  • GetRequestID (55-60)
  • GetAccountID (71-78)
  • GetTransactionID (86-91)
pkg/logger/operationid_middleware.go (1)
  • GetOperationID (38-43)
🔇 Additional comments (44)
cmd/hyperfleet-api/migrate/cmd.go (2)

6-7: LGTM! Clean migration to standard library logging.

The addition of log/slog and os imports correctly supports the migration from glog to Go's native structured logging. Using standard library packages reduces external dependencies.


35-36: No action required—logging pattern is correct and consistent with codebase standards.

The code correctly uses direct slog.Error with structured key-value pairs. All CLI commands in the codebase (main.go, servecmd/cmd.go, etc.) uniformly use direct slog for early initialization errors before pkg/logger is initialized in the environment setup. The pkg/logger pattern applies to application runtime code (pkg/**/*.go) and request-scoped logging, not CLI initialization.

cmd/hyperfleet-api/server/server.go (1)

4-4: LGTM! Clean migration to structured logging.

The migration from glog to slog is implemented correctly with proper structured field naming for the error value.

Also applies to: 28-28

go.mod (1)

67-67: LGTM! Correct dependency update.

Moving glog from direct to indirect correctly reflects the migration to slog. The library remains available as a transitive dependency for any remaining indirect usages.

cmd/hyperfleet-api/server/logging/formatter_json.go (1)

31-31: LGTM! Debug-gated logging updated correctly.

The replacement of glog.V(10) with isDebugEnabled() maintains the existing behavior of only including sensitive request/response details when debug logging is enabled.

Also applies to: 45-45

Dockerfile.openapi (2)

1-2: LGTM! Multi-arch base image selected.

The eclipse-temurin:17-jdk base image provides excellent multi-arch support for ARM64 and AMD64 builds, resolving the original ARM64 Mac compatibility issue.


38-42: LGTM! OpenAPI generation command updated correctly.

The java -jar invocation properly references the downloaded JAR and specifies the correct input/output paths for OpenAPI code generation.

cmd/hyperfleet-api/servecmd/cmd.go (1)

22-23: The learning applies to pkg/ files only, not cmd/ files.

The cited learning specifically states "Applies to pkg/**/*.go" and covers structured logging standards within the package directory. The file under review (cmd/hyperfleet-api/servecmd/cmd.go) is in the cmd/ directory and falls outside that scope. Direct slog usage is the established pattern throughout cmd/ for initialization and CLI entry points, including command flag setup and error handling at startup.

Likely an incorrect or invalid review comment.

pkg/db/db_session/testcontainer.go (7)

7-8: LGTM!

The new imports are appropriate: net/url for sanitizing connection strings, os for process termination, and pkglogger for structured logging.

Also applies to: 21-21


43-62: LGTM!

Logger initialization and container startup follow the structured logging pattern correctly, using Extra() for context fields.


66-78: Good sanitization of connection string.

The URL parsing and selective logging of only host and database effectively prevents credential leakage. This addresses the security concern from the previous review.


80-109: LGTM!

Database connection setup with consistent error handling and structured logging throughout.


111-118: LGTM!

Migration logging is clear and follows the structured logging pattern with appropriate error handling.


141-162: LGTM!

The Close function appropriately logs errors without terminating the process, which is correct for cleanup operations.


164-198: LGTM!

Both ResetDB and NewListener use structured logging correctly. Error handling is appropriate for their non-critical nature (reset and listener setup).

pkg/logger/http.go (1)

1-57: LGTM!

Well-structured HTTP logging helpers with consistent field naming. The aggregator functions provide a convenient API for common logging patterns, and duration in milliseconds is a good choice for observability.

pkg/logger/context.go (1)

23-60: LGTM!

TraceID, SpanID, and RequestID helpers follow a consistent, safe pattern with proper type assertions and sensible defaults.

test/helper.go (5)

9-9: LGTM!

Using log/slog directly in test helper code is appropriate. Test utilities don't require the full production logging infrastructure from pkg/logger.


79-92: LGTM!

Error handling in NewHelper follows a consistent pattern with structured logging and proper process termination on critical failures.


142-149: LGTM!

API server lifecycle logging appropriately uses Debug level for start/stop messages and Error level with process termination for critical failures.


159-182: LGTM!

Metrics and health check server logging consistently uses Debug level for lifecycle events and Error level for failures.


184-221: LGTM!

Server restart and environment reset functions use appropriate log levels and consistent error handling patterns.

pkg/api/error.go (5)

4-4: LGTM!

Import of context and pkg/logger enables structured logging with context-aware fields, addressing the past review comment about using the project's logging infrastructure.

Also applies to: 11-11


42-42: LGTM!

Logging now uses pkg/logger with the Extra() method for structured fields and extracts context from the request, enabling automatic inclusion of trace/span/request IDs. This addresses the past review comment.


62-62: LGTM!

Consistent structured logging with context awareness.


72-72: LGTM!

Panic handler logging follows the same structured pattern.


98-98: LGTM!

Initialization error logging appropriately uses context.Background() and follows the structured logging pattern with fatal error handling.

pkg/config/config.go (1)

21-21: LGTM! Consistent integration of LoggingConfig.

The addition of the Logging field to ApplicationConfig follows the established pattern for other configuration components. The integration is complete across constructor, flag registration, and file reading lifecycle methods.

Also applies to: 31-31, 42-42, 55-55

pkg/config/logging.go (4)

9-17: LGTM! Clean configuration structure.

The LoggingConfig struct is well-documented with clear field descriptions for Level, Format, and Output.


22-42: LGTM! Correct precedence implementation.

The constructor correctly implements the documented precedence (flags → environment variables → defaults) by:

  1. Setting defaults first
  2. Applying environment variable overrides
  3. Allowing flags (via AddFlags) to override during parsing

45-49: LGTM! Proper flag registration.

The flag defaults use the current field values, which may include environment variable overrides, ensuring correct precedence when flags are parsed.


54-56: LGTM! Intentional no-op with clear rationale.

The comment correctly explains that environment variables are read in NewLoggingConfig() to maintain proper precedence, making ReadFiles unnecessary for this config type.

pkg/logger/logger.go (12)

14-23: LGTM! Proper initialization infrastructure.

The global variables are well-organized with sync.Once for safe lazy initialization, addressing the race condition from previous reviews.


25-31: LGTM! Clean configuration structure.

The Config struct provides clear, simple configuration options for the logger.


34-109: LGTM! Comprehensive initialization with HyperFleet standard compliance.

The Initialize function correctly:

  • Configures output and log level with sensible defaults
  • Renames timetimestamp and msgmessage per HyperFleet Logging Specification
  • Adds required base attributes (component, version, hostname)
  • Wraps the handler to inject context-based correlation fields

112-146: LGTM! Correct context-based attribute injection.

The contextHandler properly extracts and injects correlation fields (trace_id, span_id, request_id, operation_id) from context without modifying the original context. The WithAttrs and WithGroup methods correctly preserve the wrapper.


148-168: LGTM! Race condition resolved with sync.Once.

The Default() function now uses sync.Once to ensure atomic initialization, addressing the race condition flagged in previous reviews.


170-173: LGTM! Convenient helper function.

Simple wrapper for adding attributes to the default logger.


176-222: LGTM! Duplicate operation_id issue resolved.

The NewOCMLogger function correctly avoids duplicate operation_id attributes by relying on contextHandler.Handle to inject it (as noted in the comment on line 201). Only account_id and tx_id are added here, which are not handled by the context handler. This addresses the duplication issue from previous reviews.


224-231: LGTM! Correct verbosity level handling.

The V() method returns a new logger instance with the specified verbosity level, maintaining immutability.


233-240: LGTM! Appropriate level mapping.

The Infof method correctly maps verbosity levels: V(1) → Info, V(>1) → Debug, aligning with common logging conventions.


242-253: LGTM! Immutable attribute accumulation.

The Extra method correctly creates a new logger instance with additional attributes, following immutable logger patterns. The pre-allocated capacity (len+2) for the new slice is efficient.

As per coding guidelines, this implements the required pattern for adding context fields via structured logging.


255-270: LGTM! Standard logging methods with proper context propagation.

All logging methods (Info, Warning, Error, Fatal) correctly use *Context methods to propagate context for attribute extraction. The Fatal method appropriately logs at Error level before exiting.


273-278: LGTM! Safe string formatting helper.

The sprintf helper correctly handles the case when no arguments are provided, avoiding unnecessary formatting.

- Update Go from 1.24.0 to 1.24.9 in Dockerfile.openapi
- Fix typo: "Reseting" -> "Resetting" in test/helper.go
Comment on lines +195 to +197
// NewOCMLogger creates a new logger instance with a default verbosity of 1
// This maintains backward compatibility with existing code
func NewOCMLogger(ctx context.Context) OCMLogger {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need to maintain compatibility at this MVP stage, IMO it would be better to simplify the code

"strings"
)

func NewJSONLogFormatter() *jsonLogFormatter {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need a JSON formatter? doesn't slog come already with support for this?

authnLogger, err := sdk.NewGlogLoggerBuilder().
InfoV(glog.Level(1)).
DebugV(glog.Level(5)).
authnLogger, err := sdk.NewStdLoggerBuilder().
Copy link
Contributor

Choose a reason for hiding this comment

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

I was curios and looked at the definition of this, which says

// NewStdLoggerBuilder has been moved to the logging package.
func NewStdLoggerBuilder() *StdLoggerBuilder {
	return logging.NewStdLoggerBuilder()
}

We could update it to call that logging.NewStdLoggerBuilder() directly and not the depcrecated one.


if l.accountID != "" {
prefix = fmt.Sprintf("[accountID=%s]%s", l.accountID, prefix)
type legacyLogger struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this legacyLogger required?

@@ -1,17 +1,27 @@
FROM openapitools/openapi-generator-cli:v7.16.0
# Multi-arch base image with Java for openapi-generator
FROM eclipse-temurin:17-jdk
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm curious about the error for arm64 , since I never had an error working on a Macbook M3 and also the image openapitools/openapi-generator-cli:v7.16.0 and is the one used in Sentinel....

was that one also giving you problems?

Either way, it doesn't hurt if this fixes errors, and we may transition to discard completely the Java based generator in favor of a faster go-based one (without containers)


"github.com/openshift-hyperfleet/hyperfleet-api/pkg/config"
"github.com/openshift-hyperfleet/hyperfleet-api/pkg/db"
pkglogger "github.com/openshift-hyperfleet/hyperfleet-api/pkg/logger"
Copy link
Contributor

Choose a reason for hiding this comment

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

If I understand this correctly, the pkglogger is needed since there is already an import for gorm.io/gorm/logger

I think it would be better to use logger for the hyperfleet-api/pkg/logger the same as the rest of the application, and change the gorm one

github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/golang/glog v1.2.5 // indirect
Copy link
Contributor

Choose a reason for hiding this comment

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

ouch, still here!

(seems to come from github.com/openshift-online/ocm-sdk-go/logging so nothing to do, just wanted to point this)

@openshift-ci
Copy link

openshift-ci bot commented Jan 7, 2026

@rafabene: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/presubmits-integration 93ce867 link true /test presubmits-integration

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@rafabene
Copy link
Contributor Author

rafabene commented Jan 7, 2026

Closing this PR as it's duplicated with #29

@rafabene rafabene closed this Jan 7, 2026
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.

2 participants