Skip to content

adds gorm logger - #830

Merged
akshaydeo merged 1 commit into
mainfrom
11-14-adds_gorm_logger
Nov 14, 2025
Merged

adds gorm logger#830
akshaydeo merged 1 commit into
mainfrom
11-14-adds_gorm_logger

Conversation

@akshaydeo

@akshaydeo akshaydeo commented Nov 14, 2025

Copy link
Copy Markdown
Contributor

Summary

Enhance test coverage workflow with improved integration testing capabilities and fix AWS Bedrock URL encoding issues.

Changes

  • Enhanced test coverage workflow to include UI build, Redis and Weaviate services for integration tests, and plugin rebuilding
  • Fixed AWS Bedrock URL encoding by properly handling percent-encoded sequences in query parameters
  • Added GORM logger implementations for configstore and logstore to improve database logging
  • Updated core-chatbot test module to work with latest Bifrost API changes
  • Fixed model catalog pricing lookup method naming for consistency

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (Next.js)
  • Docs

How to test

# Test AWS Bedrock URL encoding fix
go test ./core/providers/bedrock -v

# Test the enhanced test coverage workflow
cd .github/workflows
./test-coverage.yml

# Test GORM logger implementations
go test ./framework/configstore -v
go test ./framework/logstore -v

# Test core-chatbot with latest API changes
cd tests/core-chatbot
go test -v

Breaking changes

  • Yes
  • No

Related issues

Fixes AWS Bedrock URL encoding issues with special characters in query parameters.

Security considerations

The AWS Bedrock URL encoding fix improves request signing security by properly handling percent-encoded sequences.

Checklist

  • I added/updated tests where appropriate
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Suite Available

This PR can be tested by a repository admin.

Run tests for PR #830

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@coderabbitai

coderabbitai Bot commented Nov 14, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for cluster configuration with auto-discovery capabilities
    • Added SAML/SCIM authentication support (Okta and Microsoft Entra integration)
    • Added load balancer configuration options
    • Added guardrails configuration with rules and provider support
    • Added Redis and Weaviate services to deployment infrastructure
  • Bug Fixes

    • Fixed potential nil pointer issue in pricing manager initialization
  • Chores

    • Enhanced internal logging system integration
    • Updated CI/CD test coverage workflow with improved service orchestration

Walkthrough

Adds Bedrock V4 signer, GORM logger adapters, docker services (redis, weaviate), expanded config schema (cluster/saml/load_balancer/guardrails), chat-based test API migration, model catalog pool population, CI enhancements for UI/integration tests, and wiring for custom DB loggers.

Changes

Cohort / File(s) Change Summary
CI / Workflow
/.github/workflows/test-coverage.yml
Multi-phase CI: Node.js setup, UI build & copy, install deps for additional test modules, docker-compose integration services start & health waits, plugin rebuild, per-module tests including providers tests, coverage aggregation, and teardown.
Bedrock Signer
core/providers/bedrock/signer.go
New AWS SigV4 signer for fasthttp: percent-decode/encode utilities, canonical query string builder, signing key cache, canonical request and Authorization header computation.
GORM Logger Adapters
framework/configstore/logger.go, framework/logstore/logger.go
New unexported gormLogger adapters that forward GORM log calls (Info/Warn/Error) to project schemas.Logger; Trace/LogMode are no-ops; constructors added.
Database Init — use custom logger
framework/configstore/postgres.go, framework/configstore/sqlite.go, framework/logstore/postgres.go, framework/logstore/sqlite.go
Database opens now pass gorm.Config{Logger: newGormLogger(logger)} replacing prior silent/default logger usage; imports adjusted accordingly.
Docker Compose
framework/docker-compose.yml
Adds redis and weaviate services with ports, healthchecks, restart policies, and volumes redis_data and weaviate_data.
Model Catalog
framework/modelcatalog/main.go, framework/modelcatalog/pricing.go, docs/architecture/framework/model-catalog.mdx
Adds AddModelDataToPool method; renames receiver from pm to mc across pricing-related methods and docs; updates internal references to use mc.
Model Pricing Safety
transports/bifrost-http/server/server.go
Guards call to AddModelDataToPool behind a check for PricingManager to avoid nil dereference.
Chat API Migration (tests)
tests/core-chatbot/main.go, tests/core-chatbot/go.mod
Tests migrated from model-based types to chat variants (BifrostChatRequest, ChatParameters, ChatToolChoice), adjust message content wrapping and role constants; go.mod bumped/updated (Go toolchain and many indirect deps).
Config Schema Expansion
transports/config.schema.json
Adds top-level cluster_config, saml_config, load_balancer_config, guardrails_config; renames clusterConfigcluster_config; introduces discovery, Okta/Entra subconfigs, guardrail rule/provider schemas, and related validations.
OTEL Plugin
plugins/otel/main.go
Log warning when pricingManager is nil; leaves control flow otherwise unchanged.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Server as Bifrost HTTP Server
    participant BootstrapFlow
    participant ModelCatalog
    participant PricingMgr

    Client->>Server: Bootstrap request
    Server->>BootstrapFlow: Initialize services
    BootstrapFlow->>Server: listModels()
    alt listModels() success
        alt PricingMgr exists
            Server->>ModelCatalog: AddModelDataToPool(modelData)
            ModelCatalog->>PricingMgr: Populate model pool
        else PricingMgr missing
            Note over Server: Skip AddModelDataToPool
        end
    else listModels() error
        Note over Server: Skip pool update
    end
    BootstrapFlow->>Server: Bootstrap complete
Loading
sequenceDiagram
    participant App
    participant GORMDB as GORM DB
    participant GORMLogger as custom gormLogger
    participant ProjectLogger as schemas.Logger

    App->>GORMDB: Open DB with gorm.Config{Logger: newGormLogger}
    GORMDB->>GORMLogger: emit log events (Info/Warn/Error)
    GORMLogger->>ProjectLogger: forward logs
    Note over GORMLogger: Trace and LogMode are NOOPs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~35 minutes

  • tests/core-chatbot/main.go — verify semantic correctness after chat-type migration and pointer/value handling.
  • transports/config.schema.json — validate schema additions, conditional/allOf logic, and renames.
  • core/providers/bedrock/signer.go — review RFC3986 percent-decode/encode and signing-key caching correctness.
  • GORM logger adapters & DB wiring — confirm consistent behavior across configstore and logstore and that logging level/semantics remain appropriate.
  • CI workflow & docker-compose — validate service healthchecks, startup ordering, and coverage aggregation steps.

"I hopped into code with a twitch of my nose,
Built keys and queues where the red service grows.
I signed every query with a flourish and grin,
And nudged logs to whisper where errors had been.
— 🐰"

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'adds gorm logger' accurately describes a key component of the changeset and is related to the main objective, but is incomplete as it covers only one aspect of a multi-faceted PR that includes AWS Bedrock fixes, test workflow enhancements, and API updates.
Description check ✅ Passed The description follows the template structure comprehensively, including summary, changes, type of change, affected areas, testing instructions, breaking changes, related issues, security considerations, and a complete checklist.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9771bf4 and 3765d4d.

⛔ Files ignored due to path filters (1)
  • tests/core-chatbot/go.sum is excluded by !**/*.sum
📒 Files selected for processing (17)
  • .github/workflows/test-coverage.yml (1 hunks)
  • core/providers/bedrock/signer.go (1 hunks)
  • docs/architecture/framework/model-catalog.mdx (1 hunks)
  • framework/configstore/logger.go (1 hunks)
  • framework/configstore/postgres.go (1 hunks)
  • framework/configstore/sqlite.go (1 hunks)
  • framework/docker-compose.yml (1 hunks)
  • framework/logstore/logger.go (1 hunks)
  • framework/logstore/postgres.go (2 hunks)
  • framework/logstore/sqlite.go (1 hunks)
  • framework/modelcatalog/main.go (1 hunks)
  • framework/modelcatalog/pricing.go (9 hunks)
  • plugins/otel/main.go (1 hunks)
  • tests/core-chatbot/go.mod (1 hunks)
  • tests/core-chatbot/main.go (12 hunks)
  • transports/bifrost-http/server/server.go (1 hunks)
  • transports/config.schema.json (4 hunks)

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

@akshaydeo
akshaydeo marked this pull request as ready for review November 14, 2025 09:33

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (3)
transports/config.schema.json (2)

495-497: Fix non-standard JSON pointer path in logs_store conditional.

The relative path "../type" is not valid JSON Schema syntax. JSON Schema conditionals should use absolute paths (starting with #/) or be restructured using standard patterns.

             "if": {
               "properties": {
-                "../type": {
+                "type": {
                   "const": "sqlite"
                 }
               }
             },

Note: If this was intended to check the parent's type field, consider restructuring the conditional logic outside the nested object, as JSON Schema's if/then/else works at the object level where the conditional is defined.


438-438: Inconsistent port field types between config_store and logs_store requires alignment.

The port field uses "type": "string" in config_store (line 436) but "type": "integer" in logs_store (line 527). This inconsistency breaks API consistency and could cause runtime type mismatches. The gossip port configuration also uses integer, confirming integer is the correct type.

Align config_store to use "type": "integer":

           "port": {
-            "type": "string",
+            "type": "integer",
             "description": "Database port"
           },
tests/core-chatbot/main.go (1)

620-693: Add Provider and Model to synthesisRequest to match required struct fields and SendMessage pattern.

The BifrostChatRequest struct definition requires both Provider (non-pointer ModelProvider) and Model (non-pointer string) fields—they are not optional. The normal SendMessage path at line 485-490 correctly includes both, but the synthesisRequest at line 632-638 omits them, resulting in zero-valued fields. All test scenarios throughout the codebase consistently set both fields for every request.

-	synthesisRequest := &schemas.BifrostChatRequest{
-		Input:    conversationWithSynthesis,
-		Params:   &schemas.ChatParameters{
-			Temperature: s.config.Temperature,
-			MaxCompletionTokens: s.config.MaxTokens,
-		},
-	}
+	synthesisRequest := &schemas.BifrostChatRequest{
+		Provider: s.config.Provider,
+		Model:    s.config.Model,
+		Input:    conversationWithSynthesis,
+		Params: &schemas.ChatParameters{
+			Temperature:         s.config.Temperature,
+			MaxCompletionTokens: s.config.MaxTokens,
+		},
+	}
🧹 Nitpick comments (10)
transports/config.schema.json (2)

1513-1580: Add conditional required fields based on discovery type.

The discovery section only requires type, but depending on the selected discovery mechanism, other fields should be conditionally required:

  • Kubernetes: require k8s_namespace and k8s_label_selector
  • DNS: require dns_names
  • UDP: require udp_broadcast_port
  • Consul: require consul_address
  • Etcd: require etcd_endpoints
  • mDNS: require mdns_service

Currently, invalid configurations like {"type": "kubernetes"} with no Kubernetes-specific fields would pass schema validation.

Consider adding oneOf conditionals (similar to the mcp_client_config pattern at lines 1331–1362) to enforce type-specific required fields.


1769-1771: Add required fields to load_balancer_config if tracker_config is enabled.

The load_balancer_config only requires enabled. If enabled is true, tracker_config should likely be required. Consider adding conditional schema validation similar to the plugin config patterns (lines 604–875) to enforce this.

framework/logstore/logger.go (1)

23-35: Context is not propagated to the internal logger.

The context.Context parameter in Info, Warn, and Error methods is ignored. If your logging system supports context-aware logging (e.g., extracting request IDs, trace IDs, or other metadata from the context), this information will be lost.

If schemas.Logger supports context-aware logging, consider propagating the context. For example, if there's a WithContext method or similar:

 func (l *gormLogger) Info(ctx context.Context, msg string, data ...interface{}) {
-	l.logger.Info(msg, data...)
+	// If schemas.Logger supports context, use it here
+	l.logger.Info(msg, data...)
 }
framework/modelcatalog/main.go (1)

266-282: Consider deduplicating models when adding to the pool.

The method appends models without checking for duplicates. If AddModelDataToPool is called multiple times with overlapping data, the same model could appear multiple times in the provider's slice, potentially leading to inefficiencies or incorrect behavior in downstream code.

Consider adding duplicate checks or using a set-based approach:

 func (mc *ModelCatalog) AddModelDataToPool(modelData *schemas.BifrostListModelsResponse) {
 	if modelData == nil {
 		return
 	}
 	mc.mu.Lock()
 	defer mc.mu.Unlock()
 
 	for _, model := range modelData.Data {
 		provider, model := schemas.ParseModelString(model.ID, "")
 		if provider == "" {
 			continue
 		}
 		provider = schemas.ModelProvider(provider)
-		mc.modelPool[provider] = append(mc.modelPool[provider], model)
+		// Check for duplicates before appending
+		if !slices.Contains(mc.modelPool[provider], model) {
+			mc.modelPool[provider] = append(mc.modelPool[provider], model)
+		}
 	}
 }
framework/docker-compose.yml (1)

69-70: Remove unused redis_data volume declaration.

The redis_data volume is declared but not mounted by any service. If Redis persistence is not needed, remove this declaration to avoid confusion.

 volumes:
   postgres_data:
     driver: local
   weaviate_data:
     driver: local
-  redis_data:
-    driver: local
.github/workflows/test-coverage.yml (2)

59-67: Service health check could be more robust.

The health check logic uses grep -q "healthy" which might match partial states or be fragile. The || true at the end means failures are silently ignored, and the fixed 5-second sleep may not be sufficient for all services.

Consider checking each service explicitly:

       - name: Start services for integration tests
         run: |
           echo "Starting Redis and Weaviate for vector store tests..."
           cd framework
           docker-compose up -d
           # Wait for services to be healthy
           echo "Waiting for services to be ready..."
-          timeout 60 bash -c 'until docker-compose ps | grep -q "healthy"; do sleep 2; done' || true
-          sleep 5
+          for i in {1..30}; do
+            if docker-compose ps | grep -E "bifrost-redis.*healthy" > /dev/null && \
+               docker-compose ps | grep -E "bifrost-weaviate.*healthy" > /dev/null; then
+              echo "All services are healthy"
+              break
+            fi
+            echo "Waiting for services... ($i/30)"
+            sleep 2
+          done
+          docker-compose ps

69-79: Plugin build failure is silently ignored.

The plugin build uses || echo "Plugin build failed, tests will skip" which suppresses the error. If tests depend on the plugin, they might pass incorrectly or produce confusing results when the plugin is missing.

Consider making plugin build failures more visible or explicitly checking if tests require the plugin:

       - name: Rebuild plugins
         run: |
           echo "Rebuilding example plugins..."
           if [ -d "examples/plugins/hello-world" ]; then
             cd examples/plugins/hello-world
             # Clean old build
             rm -rf build
             mkdir -p build
             # Rebuild plugin with current dependencies
-            go build -buildmode=plugin -o build/hello-world.so main.go || echo "Plugin build failed, tests will skip"
+            if ! go build -buildmode=plugin -o build/hello-world.so main.go; then
+              echo "::warning::Plugin build failed - plugin tests may be skipped"
+            fi
           fi
tests/core-chatbot/main.go (3)

539-595: Tool-call handling uses the new tool role/message types correctly; consider richer rendering of results.

  • Assigning toolCalls := assistantMessage.ToolCalls and iterating directly over them is fine given the guard in SendMessage that only calls handleToolCalls when ToolCalls is non-nil and non-empty.
  • The error-path ChatMessage correctly uses Role: ChatMessageRoleTool and a ChatToolMessage with ToolCallID: toolCall.ID, preserving the linkage between tool calls and their results.
  • Appending tool results into history as values is consistent with the rest of the code.

One improvement: in the non-agentic path you only render result.Content.ContentStr. If MCP tools ever return structured ContentBlocks instead of (or in addition to) ContentStr, those would be silently ignored here. You could reuse the same content-extraction helper you use for standard assistant messages to handle both cases uniformly.


703-725: History printing with chat roles is correct; consider a defensive nil check for Content.

Skipping messages with msg.Role == schemas.ChatMessageRoleSystem matches how you seed the system prompt and prevents clutter in the history view. The content rendering (prefer ContentStr, otherwise join ContentBlocks.Text) mirrors the response-handling logic and will produce readable output.

To make this more robust against unexpected provider behavior, you might add a quick guard like if msg.Content == nil { continue } before dereferencing msg.Content.*, which would avoid panics if a future provider/plugin emits a message without content.


522-533: Factor out repeated ChatMessageContent text extraction into a helper.

The pattern:

  • Prefer ContentStr when set.
  • Otherwise, iterate ContentBlocks and concatenate block.Text.

is duplicated in SendMessage, synthesizeToolResults, and PrintHistory. A small helper such as:

func chatMessageText(msg schemas.ChatMessage) string {
	if msg.Content == nil {
		return ""
	}
	if msg.Content.ContentStr != nil {
		return *msg.Content.ContentStr
	}
	if msg.Content.ContentBlocks != nil {
		var parts []string
		for _, block := range msg.Content.ContentBlocks {
			if block.Text != nil {
				parts = append(parts, *block.Text)
			}
		}
		return strings.Join(parts, "\n")
	}
	return ""
}

would remove this duplication, centralize any future changes (e.g., nil checks or new modalities), and keep the call sites much simpler.

Also applies to: 682-693, 708-719

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9567ca6 and 9771bf4.

⛔ Files ignored due to path filters (1)
  • tests/core-chatbot/go.sum is excluded by !**/*.sum
📒 Files selected for processing (17)
  • .github/workflows/test-coverage.yml (1 hunks)
  • core/providers/bedrock/signer.go (2 hunks)
  • docs/architecture/framework/model-catalog.mdx (1 hunks)
  • framework/configstore/logger.go (1 hunks)
  • framework/configstore/postgres.go (1 hunks)
  • framework/configstore/sqlite.go (1 hunks)
  • framework/docker-compose.yml (1 hunks)
  • framework/logstore/logger.go (1 hunks)
  • framework/logstore/postgres.go (2 hunks)
  • framework/logstore/sqlite.go (1 hunks)
  • framework/modelcatalog/main.go (1 hunks)
  • framework/modelcatalog/pricing.go (9 hunks)
  • plugins/otel/main.go (1 hunks)
  • tests/core-chatbot/go.mod (1 hunks)
  • tests/core-chatbot/main.go (12 hunks)
  • transports/bifrost-http/server/server.go (1 hunks)
  • transports/config.schema.json (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (9)
framework/logstore/sqlite.go (1)
core/schemas/logger.go (1)
  • Logger (28-55)
framework/configstore/postgres.go (1)
core/schemas/logger.go (1)
  • Logger (28-55)
framework/configstore/sqlite.go (1)
core/schemas/logger.go (1)
  • Logger (28-55)
framework/logstore/postgres.go (1)
core/schemas/logger.go (1)
  • Logger (28-55)
framework/configstore/logger.go (1)
core/schemas/logger.go (2)
  • Logger (28-55)
  • LogLevel (6-6)
transports/bifrost-http/server/server.go (2)
framework/modelcatalog/main.go (1)
  • Config (26-29)
transports/bifrost-http/lib/config.go (1)
  • Config (139-169)
framework/logstore/logger.go (1)
core/schemas/logger.go (2)
  • Logger (28-55)
  • LogLevel (6-6)
framework/modelcatalog/pricing.go (4)
framework/modelcatalog/main.go (1)
  • ModelCatalog (31-52)
core/schemas/bifrost.go (6)
  • BifrostResponse (243-253)
  • RequestType (81-81)
  • Gemini (48-48)
  • ResponsesRequest (89-89)
  • ResponsesStreamRequest (90-90)
  • ChatCompletionRequest (87-87)
core/schemas/chatcompletions.go (1)
  • BifrostLLMUsage (558-565)
core/schemas/transcriptions.go (1)
  • TranscriptionUsageInputTokenDetails (81-84)
tests/core-chatbot/main.go (1)
core/schemas/chatcompletions.go (6)
  • ChatMessageRoleSystem (340-340)
  • ChatParameters (154-183)
  • ChatToolChoice (265-268)
  • BifrostChatRequest (11-18)
  • ChatMessageRoleTool (341-341)
  • ChatToolMessage (455-457)
🔇 Additional comments (23)
tests/core-chatbot/go.mod (2)

3-3: Verify Go version and new direct dependency addition.

The go.mod file reflects systematic dependency updates across AWS SDK submodules and golang.org/x packages, which aligns with the PR's infrastructure modernization goals. However, two items warrant clarification:

  1. Go version bump (line 3): go 1.24.1 is a very recent release. While the PR confirms successful builds, please confirm this version is intentionally selected and compatible with the rest of the codebase.

  2. New direct dependency (line 9): golang.org/x/text v0.30.0 is now a direct requirement. Verify this was previously a transitive dependency and is required for the GORM logger or other core-chatbot test changes introduced in this PR.

Also applies to: 7-10


15-28: AWS SDK v2 package versions are coherent across submodules.

The AWS SDK v2 indirect dependencies are updated consistently to v1.39.5+ across all related submodules (config, credentials, internal packages, service packages, smithy-go). This systematic update pattern is appropriate and reduces risk of version conflicts.

transports/config.schema.json (1)

564-575: Verify new top-level config references are registered correctly.

These four new public properties are added to the root schema. Ensure that:

  1. These are intentional public API additions (not internal only).
  2. Documentation/migration guides exist for users upgrading to this schema version.
  3. Any existing tooling or validators have been updated to handle these new top-level fields.
framework/logstore/logger.go (1)

37-40: Verify that disabling SQL query tracing is intentional.

The Trace method is a NOOP, which means SQL queries, execution times, and row counts will not be logged. This is often desirable in production to reduce log volume, but it may hinder debugging of slow queries or database issues.

If query logging is needed for development or debugging, consider implementing basic trace logging:

 func (l *gormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
-	// NOOP
+	if err != nil {
+		sql, rows := fc()
+		l.logger.Debug("SQL error: %v, query: %s, rows: %d, duration: %v", err, sql, rows, time.Since(begin))
+	}
 }

Alternatively, if the NOOP is intentional for performance, consider adding a comment explaining the rationale.

docs/architecture/framework/model-catalog.mdx (1)

237-254: LGTM! Receiver rename improves consistency.

The receiver rename from pm to mc aligns with the broader refactoring across the ModelCatalog codebase. The internal references (mc.mu, mc.logger, mc.pricingData) are correctly updated.

core/providers/bedrock/signer.go (2)

160-200: LGTM! URL decoding logic correctly preserves plus signs.

The percentDecode function properly handles percent-encoded sequences without treating + as a space (unlike url.QueryUnescape). The comment clearly explains the distinction from form encoding, and the implementation is correct.


235-244: URL encoding implementation is correct and thoroughly tested.

The code review comment requests have been verified:

  1. Already percent-encoded sequences – Test cases confirm: key=%20key=%20, percent=%25percent=%25, path=%2Fto%2Ffilepath=%2Fto%2Ffile

  2. Plus signs encode as %2B – Confirmed: key=a+bkey=a%2Bb, and mixed case search=hello world+testsearch=hello%20world%2Btest

  3. Special characters – All tested and correct: =%3D, &%26, /%2F

The implementation correctly uses the decode-then-encode normalization approach to prevent double-encoding while ensuring RFC 3986 compliance for AWS SigV4 canonical query strings. The percentDecode function properly avoids treating + as a space (unlike url.QueryUnescape), and percentEncodeRFC3986 preserves only RFC 3986 unreserved characters. Test coverage is comprehensive with 25+ test cases in buildCanonicalQueryString tests alone, including AWS SigV4 examples and edge cases.

framework/modelcatalog/pricing.go (1)

11-11: LGTM! Receiver rename improves code consistency.

The receiver rename from pm to mc across all pricing methods aligns with the ModelCatalog type name and improves readability. All internal references are correctly updated.

Also applies to: 101-101, 139-139, 262-262

plugins/otel/main.go (1)

87-89: LGTM! Graceful degradation when pricing manager is unavailable.

Making the pricing manager optional allows the OTEL plugin to function in environments where cost tracking is not configured. The warning clearly communicates the limitation, and the downstream code (lines 249, 268) already handles nil pricing managers safely.

transports/bifrost-http/server/server.go (1)

816-818: LGTM! Defensive nil-check prevents potential panic.

The guard ensures AddModelDataToPool is only called when the pricing manager is available, preventing a nil pointer dereference. This aligns with the broader PR theme of making the pricing manager optional.

framework/logstore/postgres.go (1)

25-27: LGTM! GORM logger integration is clean.

The custom logger adapter is correctly integrated into the Postgres log store configuration, enabling per-instance logging that bridges GORM to the internal logging system.

framework/configstore/postgres.go (1)

24-26: LGTM! GORM logger integration is clean.

The custom logger adapter is correctly integrated into the Postgres config store configuration, enabling per-instance logging that bridges GORM to the internal logging system.

framework/logstore/sqlite.go (1)

32-32: LGTM! Logger integration improvement.

The switch from the static GORM logger to a per-instance custom logger properly integrates with the project's internal logging system and provides better control over log output.

framework/configstore/sqlite.go (1)

31-31: LGTM! Consistent logger integration.

The custom logger integration matches the pattern applied in logstore and properly routes GORM logs through the project's internal logging system.

framework/docker-compose.yml (2)

23-35: Redis service configuration looks good.

The Redis service is properly configured with healthcheck, ports, and networking. However, note that no volume is mounted for data persistence—Redis will lose data on container restart.

If data persistence is needed, consider mounting the redis_data volume (defined at lines 69-70 but currently unused):

   redis:
     image: redis/redis-stack:latest
     container_name: bifrost-redis
     ports:
       - "6379:6379"
+    volumes:
+      - redis_data:/data
     healthcheck:
       test: ["CMD", "redis-cli", "ping"]
       interval: 10s
       timeout: 5s
       retries: 5
     restart: unless-stopped
     networks:
       - bifrost_network

37-58: LGTM! Weaviate service properly configured.

The Weaviate service includes proper healthcheck, volume mounting for persistence, and necessary environment variables for anonymous access and configuration.

framework/configstore/logger.go (2)

11-20: LGTM! Clean GORM logger adapter implementation.

The adapter properly bridges GORM's logging interface to the project's internal logger. The LogMode NOOP is acceptable since log level control is handled by the internal schemas.Logger.


37-40: SQL query logging is disabled—verify this is intentional.

The Trace method is a NOOP, which means GORM SQL queries, execution times, and row counts will not be logged. This improves performance and reduces log noise but makes debugging database issues more difficult.

If SQL query logging is needed for debugging, consider implementing Trace to conditionally log based on the internal logger's level:

 func (l *gormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
-	// NOOP
+	// Only log slow queries or errors
+	elapsed := time.Since(begin)
+	if err != nil || elapsed > 200*time.Millisecond {
+		sql, rows := fc()
+		l.logger.Debug("SQL: %s | rows: %d | elapsed: %v | error: %v", sql, rows, elapsed, err)
+	}
 }
.github/workflows/test-coverage.yml (2)

25-30: LGTM! Node.js setup for UI builds.

Proper Node.js setup with caching configured for the UI build steps.


100-105: LGTM! Proper cleanup with if: always().

The cleanup step ensures Docker services are stopped regardless of test outcome, preventing resource leaks in the CI environment.

tests/core-chatbot/main.go (3)

289-297: System prompt ChatMessage construction is correct and keeps history invariant.

Using schemas.ChatMessageRoleSystem plus &schemas.ChatMessageContent{ContentStr: bifrost.Ptr(session.systemPrompt)} cleanly seeds the system prompt as the first history entry, which aligns with the /clear handler’s assumption that history[0] is the system message. No issues here.


456-465: User message creation with ChatMessage / ChatMessageContent looks good.

The user message is built with ChatMessageRoleUser and a ChatMessageContent holding ContentStr, then appended by value to history. This matches the system message shape and the expectations of downstream chat handling.


472-533: Chat request construction and assistant message handling align with new chat APIs.

  • schemas.ChatParameters is populated with Temperature, MaxCompletionTokens, and ToolChoice: ChatToolChoiceStr="auto", which matches the new chatcompletions parameter shape.
  • schemas.BifrostChatRequest is correctly filled with Provider, Model, Input: s.history, and Params: params, so the primary chat call should behave as before.
  • Appending *assistantMessage (value, not pointer) into history keeps the history consistent with other messages and avoids aliasing the choice struct.

No functional issues spotted in this section.

Comment thread transports/config.schema.json
@akshaydeo
akshaydeo force-pushed the 11-14-adds_gorm_logger branch from 9771bf4 to 3765d4d Compare November 14, 2025 10:43

akshaydeo commented Nov 14, 2025

Copy link
Copy Markdown
Contributor Author

Merge activity

  • Nov 14, 10:52 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Nov 14, 10:52 AM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo merged commit 2c2f450 into main Nov 14, 2025
3 of 5 checks passed
@akshaydeo
akshaydeo deleted the 11-14-adds_gorm_logger branch November 14, 2025 10:52
akshaydeo added a commit that referenced this pull request Nov 17, 2025
## Summary

Enhance test coverage workflow with improved integration testing capabilities and fix AWS Bedrock URL encoding issues.

## Changes

- Enhanced test coverage workflow to include UI build, Redis and Weaviate services for integration tests, and plugin rebuilding
- Fixed AWS Bedrock URL encoding by properly handling percent-encoded sequences in query parameters
- Added GORM logger implementations for configstore and logstore to improve database logging
- Updated core-chatbot test module to work with latest Bifrost API changes
- Fixed model catalog pricing lookup method naming for consistency

## Type of change

- [x] Bug fix
- [x] Feature
- [x] Refactor
- [ ] Documentation
- [x] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [x] Providers/Integrations
- [x] Plugins
- [x] UI (Next.js)
- [ ] Docs

## How to test

```sh
# Test AWS Bedrock URL encoding fix
go test ./core/providers/bedrock -v

# Test the enhanced test coverage workflow
cd .github/workflows
./test-coverage.yml

# Test GORM logger implementations
go test ./framework/configstore -v
go test ./framework/logstore -v

# Test core-chatbot with latest API changes
cd tests/core-chatbot
go test -v
```

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

Fixes AWS Bedrock URL encoding issues with special characters in query parameters.

## Security considerations

The AWS Bedrock URL encoding fix improves request signing security by properly handling percent-encoded sequences.

## Checklist

- [x] I added/updated tests where appropriate
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable
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.

1 participant