Repository: envoyproxy/gateway
Pull request #5586 (2025-03-24 04:32:05)

build(deps): bump fortio.org/fortio from 1.68.0 to 1.68.1
Bumps [fortio.org/fortio](https://github.com/fortio/fortio) from 1.68.0 to 1.68.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/fortio/fortio/releases">fortio.org/fortio's releases</a>.</em></p>
<blockquote>
<h2>v1.68.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Use flag set.Func() instead of custom type for -H by <a href="https://github.com/proooooogiba"><code>@​proooooogiba</code></a> in <a href="https://redirect.github.com/fortio/fortio/pull/999">fortio/fortio#999</a></li>
<li>Switch to go 1.23.7, update test to remove dns flakey reliance on <a href="http://www.google.com">www.google.com</a> returned IPs by <a href="https://github.com/ldemailly"><code>@​ldemailly</code></a> in <a href="https://redirect.github.com/fortio/fortio/pull/1022">fortio/fortio#1022</a></li>
<li>Update <code>main.go</code> reference by <a href="https://github.com/emmanuel-ferdman"><code>@​emmanuel-ferdman</code></a> in <a href="https://redirect.github.com/fortio/fortio/pull/1001">fortio/fortio#1001</a></li>
<li>Misc other dep updates</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/proooooogiba"><code>@​proooooogiba</code></a> made their first contribution in <a href="https://redirect.github.com/fortio/fortio/pull/999">fortio/fortio#999</a></li>
<li><a href="https://github.com/emmanuel-ferdman"><code>@​emmanuel-ferdman</code></a> made their first contribution in <a href="https://redirect.github.com/fortio/fortio/pull/1001">fortio/fortio#1001</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/fortio/fortio/compare/v1.68.0...v1.68.1">https://github.com/fortio/fortio/compare/v1.68.0...v1.68.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/fortio/fortio/commit/2a4e270ba82a310bfa4cb7429b5f7eb86270c6a6"><code>2a4e270</code></a> Bump docker/build-push-action from 6.9.0 to 6.15.0 (<a href="https://redirect.github.com/fortio/fortio/issues/1020">#1020</a>)</li>
<li><a href="https://github.com/fortio/fortio/commit/ca6a8fa4cd588ddd1f47df5de630f7148e74918f"><code>ca6a8fa</code></a> Bump google.golang.org/grpc from 1.68.0 to 1.71.0 (<a href="https://redirect.github.com/fortio/fortio/issues/1017">#1017</a>)</li>
<li><a href="https://github.com/fortio/fortio/commit/4f6f9cc6520002d6d93a2dee41fef6447662c982"><code>4f6f9cc</code></a> Update <code>main.go</code> reference (<a href="https://redirect.github.com/fortio/fortio/issues/1001">#1001</a>)</li>
<li><a href="https://github.com/fortio/fortio/commit/86bed5262c42f2263494ebc23433f0f9c0f7e154"><code>86bed52</code></a> Switch to go 1.23.7, update test to remove dns flakey reliance on <a href="http://www.google">www.google</a>....</li>
<li><a href="https://github.com/fortio/fortio/commit/2158d3eee2c08f060385902374969686e5d5e829"><code>2158d3e</code></a> Use flag set.Func() instead of custom type for -H (<a href="https://redirect.github.com/fortio/fortio/issues/999">#999</a>)</li>
<li>See full diff in <a href="https://github.com/fortio/fortio/compare/v1.68.0...v1.68.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=fortio.org/fortio&package-manager=go_modules&previous-version=1.68.0&new-version=1.68.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/5586?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 65.25%. Comparing base [(`d87fed8`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/d87fed81c9c2d5a4ed7cc586ffdbb58e6b1bf591?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`ced3935`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/ced3935951887ade701bfb7b865ad9ac01c2461d?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main    #5586   +/-   ##
=======================================
  Coverage   65.25%   65.25%           
=======================================
  Files         213      213           
  Lines       34069    34069           
=======================================
  Hits        22233    22233           
- Misses      10501    10503    +2     
+ Partials     1335     1333    -2     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/5586?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>

Patch:
diff --git a/VERSION b/VERSION
index 757407982..968e750a6 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-v1.3.1
+v1.3.2
diff --git a/go.mod b/go.mod
index 0d79d1adb..033a8b171 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/envoyproxy/gateway
 go 1.24.1
 
 require (
-	fortio.org/fortio v1.68.0
+	fortio.org/fortio v1.68.1
 	fortio.org/log v1.17.1
 	github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24
 	github.com/Masterminds/semver/v3 v3.3.1
diff --git a/go.sum b/go.sum
index fb2bd2fe4..4998a066e 100644
--- a/go.sum
+++ b/go.sum
@@ -39,8 +39,8 @@ fortio.org/cli v1.9.2 h1:17eJ8QZPjXHcLBpeCe0QMO/0fj5Bw0ZTxVgL7V9jOqc=
 fortio.org/cli v1.9.2/go.mod h1:7r55OoTV8NXcTvJT4boWk8s3I2LP6TMZh/0LLMJEYw0=
 fortio.org/dflag v1.7.3 h1:yws+v+/fJ67bYgrgcWpLtgdZPEWkYuwdfqz/WyQ8UXo=
 fortio.org/dflag v1.7.3/go.mod h1:O1Pk4lKRolw9wwAGyjTo8IsNyqqNRQGKxPOfpOElMqM=
-fortio.org/fortio v1.68.0 h1:2M9RuitiN+MgW6QlTJCHjW6PJLAPj/YCXegxSCLQ3rw=
-fortio.org/fortio v1.68.0/go.mod h1:1IjDaEoT5crHBN7BRLBwrHE24pIT6rOPKrYG3jEIWaA=
+fortio.org/fortio v1.68.1 h1:dhs9px7xkXLPzS8gVE3AKe+NRD/5aylV/qebD7vfv7E=
+fortio.org/fortio v1.68.1/go.mod h1:bZBFAxe8hfh/fdtEugVOBZvANGJcMdB91cwaul61K8w=
 fortio.org/log v1.17.1 h1:YQoGyZBnXTVIs77/nZw7BppwSOIamP3I092PGBenBZs=
 fortio.org/log v1.17.1/go.mod h1:t58Spg9njjymvRioh5F6qKGSupEsnMjXLGWIS1i3khE=
 fortio.org/safecast v1.0.0 h1:dr3131WPX8iS1pTf76+39WeXbTrerDYLvi9s7Oi3wiY=
diff --git a/internal/cmd/certgen.go b/internal/cmd/certgen.go
index 6b34158a8..835a583d9 100644
--- a/internal/cmd/certgen.go
+++ b/internal/cmd/certgen.go
@@ -9,6 +9,7 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"io"
 	"path"
 
 	"github.com/spf13/cobra"
@@ -36,7 +37,7 @@ func GetCertGenCommand() *cobra.Command {
 		Use:   "certgen",
 		Short: "Generate Control Plane Certificates",
 		RunE: func(cmd *cobra.Command, args []string) error {
-			return certGen(cmd.Context(), local)
+			return certGen(cmd.Context(), cmd.OutOrStdout(), local)
 		},
 	}
 
@@ -48,8 +49,8 @@ func GetCertGenCommand() *cobra.Command {
 }
 
 // certGen generates control plane certificates.
-func certGen(ctx context.Context, local bool) error {
-	cfg, err := config.New()
+func certGen(ctx context.Context, logOut io.Writer, local bool) error {
+	cfg, err := config.New(logOut)
 	if err != nil {
 		return err
 	}
diff --git a/internal/cmd/egctl/status.go b/internal/cmd/egctl/status.go
index 814bd1593..cdb243369 100644
--- a/internal/cmd/egctl/status.go
+++ b/internal/cmd/egctl/status.go
@@ -9,7 +9,6 @@ import (
 	"context"
 	"fmt"
 	"io"
-	"os"
 	"reflect"
 	"strconv"
 	"strings"
@@ -93,27 +92,27 @@ func newStatusCommand() *cobra.Command {
 			switch strings.ToLower(resourceType) {
 			case "all":
 				for _, rt := range supportedAllTypes {
-					if err = runStatus(ctx, k8sClient, rt, namespace, quiet, verbose, allNamespaces, true, true); err != nil {
+					if err = runStatus(ctx, cmd.OutOrStdout(), k8sClient, rt, namespace, quiet, verbose, allNamespaces, true, true); err != nil {
 						return err
 					}
 				}
 				return nil
 			case "xroute":
 				for _, rt := range supportedXRouteTypes {
-					if err = runStatus(ctx, k8sClient, rt, namespace, quiet, verbose, allNamespaces, true, true); err != nil {
+					if err = runStatus(ctx, cmd.OutOrStdout(), k8sClient, rt, namespace, quiet, verbose, allNamespaces, true, true); err != nil {
 						return err
 					}
 				}
 				return nil
 			case "xpolicy":
 				for _, rt := range supportedXPolicyTypes {
-					if err = runStatus(ctx, k8sClient, rt, namespace, quiet, verbose, allNamespaces, true, true); err != nil {
+					if err = runStatus(ctx, cmd.OutOrStdout(), k8sClient, rt, namespace, quiet, verbose, allNamespaces, true, true); err != nil {
 						return err
 					}
 				}
 				return nil
 			default:
-				return runStatus(ctx, k8sClient, resourceType, namespace, quiet, verbose, allNamespaces, false, false)
+				return runStatus(ctx, cmd.OutOrStdout(), k8sClient, resourceType, namespace, quiet, verbose, allNamespaces, false, false)
 			}
 		},
 	}
@@ -138,11 +137,11 @@ func writeStatusTable(table *tabwriter.Writer, header []string, body [][]string)
 }
 
 // runStatus find and write the summary table of status for a specific resource type.
-func runStatus(ctx context.Context, cli client.Client, inputResourceType, namespace string, quiet, verbose, allNamespaces, ignoreEmpty, typedName bool) error {
+func runStatus(ctx context.Context, logOut io.Writer, cli client.Client, inputResourceType, namespace string, quiet, verbose, allNamespaces, ignoreEmpty, typedName bool) error {
 	var (
 		resourcesList client.ObjectList
 		resourceKind  string
-		table         = newStatusTableWriter(os.Stdout)
+		table         = newStatusTableWriter(logOut)
 	)
 
 	if allNamespaces {
diff --git a/internal/cmd/envoy/shutdown_manager.go b/internal/cmd/envoy/shutdown_manager.go
index 627c2f034..e35793df9 100644
--- a/internal/cmd/envoy/shutdown_manager.go
+++ b/internal/cmd/envoy/shutdown_manager.go
@@ -21,7 +21,8 @@ import (
 	"github.com/envoyproxy/gateway/internal/xds/bootstrap"
 )
 
-var logger = logging.DefaultLogger(egv1a1.LogLevelInfo).WithName("shutdown-manager")
+// TODO: Remove the global logger and localize the scope of the logger.
+var logger = logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo).WithName("shutdown-manager")
 
 const (
 	// ShutdownManagerPort is the port Envoy shutdown manager will listen on.
diff --git a/internal/cmd/server.go b/internal/cmd/server.go
index 99c1856b4..6a39bcc24 100644
--- a/internal/cmd/server.go
+++ b/internal/cmd/server.go
@@ -105,7 +105,7 @@ func getConfig(logOut io.Writer) (*config.Server, error) {
 // make `cfgPath` an argument to test it without polluting the global var
 func getConfigByPath(logOut io.Writer, cfgPath string) (*config.Server, error) {
 	// Initialize with default config parameters.
-	cfg, err := config.New()
+	cfg, err := config.New(logOut)
 	if err != nil {
 		return nil, err
 	}
diff --git a/internal/envoygateway/config/config.go b/internal/envoygateway/config/config.go
index e8d1fece3..63d740de1 100644
--- a/internal/envoygateway/config/config.go
+++ b/internal/envoygateway/config/config.go
@@ -7,6 +7,7 @@ package config
 
 import (
 	"errors"
+	"io"
 
 	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
 	"github.com/envoyproxy/gateway/api/v1alpha1/validation"
@@ -41,12 +42,12 @@ type Server struct {
 }
 
 // New returns a Server with default parameters.
-func New() (*Server, error) {
+func New(logOut io.Writer) (*Server, error) {
 	return &Server{
 		EnvoyGateway: egv1a1.DefaultEnvoyGateway(),
 		Namespace:    env.Lookup("ENVOY_GATEWAY_NAMESPACE", DefaultNamespace),
 		DNSDomain:    env.Lookup("KUBERNETES_CLUSTER_DOMAIN", DefaultDNSDomain),
-		Logger:       logging.DefaultLogger(egv1a1.LogLevelInfo),
+		Logger:       logging.DefaultLogger(logOut, egv1a1.LogLevelInfo),
 		Elected:      make(chan struct{}),
 	}, nil
 }
diff --git a/internal/logging/log.go b/internal/logging/log.go
index e38af9082..394e3919e 100644
--- a/internal/logging/log.go
+++ b/internal/logging/log.go
@@ -19,6 +19,7 @@ import (
 
 type Logger struct {
 	logr.Logger
+	out           io.Writer
 	logging       *egv1a1.EnvoyGatewayLogging
 	sugaredLogger *zap.SugaredLogger
 }
@@ -28,6 +29,7 @@ func NewLogger(w io.Writer, logging *egv1a1.EnvoyGatewayLogging) Logger {
 
 	return Logger{
 		Logger:        zapr.NewLogger(logger),
+		out:           w,
 		logging:       logging,
 		sugaredLogger: logger.Sugar(),
 	}
@@ -45,16 +47,18 @@ func FileLogger(file string, name string, level egv1a1.LogLevel) Logger {
 	return Logger{
 		Logger:        zapr.NewLogger(logger).WithName(name),
 		logging:       logging,
+		out:           writer,
 		sugaredLogger: logger.Sugar(),
 	}
 }
 
-func DefaultLogger(level egv1a1.LogLevel) Logger {
+func DefaultLogger(out io.Writer, level egv1a1.LogLevel) Logger {
 	logging := egv1a1.DefaultEnvoyGatewayLogging()
-	logger := initZapLogger(os.Stdout, logging, level)
+	logger := initZapLogger(out, logging, level)
 
 	return Logger{
 		Logger:        zapr.NewLogger(logger),
+		out:           out,
 		logging:       logging,
 		sugaredLogger: logger.Sugar(),
 	}
@@ -67,11 +71,12 @@ func DefaultLogger(level egv1a1.LogLevel) Logger {
 // more information).
 func (l Logger) WithName(name string) Logger {
 	logLevel := l.logging.Level[egv1a1.EnvoyGatewayLogComponent(name)]
-	logger := initZapLogger(os.Stdout, l.logging, logLevel)
+	logger := initZapLogger(l.out, l.logging, logLevel)
 
 	return Logger{
 		Logger:        zapr.NewLogger(logger).WithName(name),
 		logging:       l.logging,
+		out:           l.out,
 		sugaredLogger: logger.Sugar().Named(name),
 	}
 }
diff --git a/internal/message/watchutil.go b/internal/message/watchutil.go
index 77caa4af3..fc0f65dcc 100644
--- a/internal/message/watchutil.go
+++ b/internal/message/watchutil.go
@@ -7,6 +7,7 @@ package message
 
 import (
 	"fmt"
+	"os"
 	"runtime/debug"
 	"time"
 
@@ -19,7 +20,8 @@ import (
 
 type Update[K comparable, V any] watchable.Update[K, V]
 
-var logger = logging.DefaultLogger(egv1a1.LogLevelInfo).WithName("watchable")
+// TODO: Remove the global logger and localize the scope of the logger.
+var logger = logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo).WithName("watchable")
 
 type Metadata struct {
 	Runner  string
diff --git a/release-notes/v1.3.2.yaml b/release-notes/v1.3.2.yaml
new file mode 100644
index 000000000..3422655b4
--- /dev/null
+++ b/release-notes/v1.3.2.yaml
@@ -0,0 +1,19 @@
+date: March 24, 2025
+
+bug fixes: |
+  Added support for BackendTLSPolicy and EnvoyExtensionPolicy parsing in Standalone mode.
+  Fixed updates of endpoints when mirrored backend Pod IPs are changed.
+  Fix not logging an error and returning it in the K8s Reconcile method when a GatewayClass is not accepted.
+  Fix allowing empty text field for opentelemetry sink when using JSON format.
+  Fixed validation of host header in RequestHeaderModifier filter.
+  Retrigger reconciliation when backendRef of type ServiceImport is updated or when EndpointSlice(s) for a ServiceImport are updated.
+
+# Enhancements that improve performance.
+performance improvements: |
+  Added a cache for the Wasm OCI image permission checks and check the pullSecrets against the OCI image registry in
+  a background goroutine.
+
+# Other notable changes not covered by the above sections.
+Other changes: |
+  Bumped envoy to v1.33.1.
+  Bumped ratelimit to 0141a24f.
diff --git a/site/content/en/news/releases/notes/v1.3.2.md b/site/content/en/news/releases/notes/v1.3.2.md
new file mode 100644
index 000000000..73760e606
--- /dev/null
+++ b/site/content/en/news/releases/notes/v1.3.2.md
@@ -0,0 +1,23 @@
+---
+title: "v1.3.2"
+publishdate: 2025-03-24
+---
+
+Date: March 24, 2025
+
+## Bug fixes
+- Added support for BackendTLSPolicy and EnvoyExtensionPolicy parsing in Standalone mode.
+- Fixed updates of endpoints when mirrored backend Pod IPs are changed.
+- Fix not logging an error and returning it in the K8s Reconcile method when a GatewayClass is not accepted.
+- Fix allowing empty text field for opentelemetry sink when using JSON format.
+- Fixed validation of host header in RequestHeaderModifier filter.
+- Retrigger reconciliation when backendRef of type ServiceImport is updated or when EndpointSlice(s) for a ServiceImport are updated.
+
+## Performance improvements
+- Added a cache for the Wasm OCI image permission checks and check the pullSecrets against the OCI image registry in
+- a background goroutine.
+
+## Other changes
+- Bumped envoy to v1.33.1.
+- Bumped ratelimit to 0141a24f.
+


Test patch:
diff --git a/internal/crypto/certgen_test.go b/internal/crypto/certgen_test.go
index 429fea518..5e3a6f1d3 100644
--- a/internal/crypto/certgen_test.go
+++ b/internal/crypto/certgen_test.go
@@ -10,6 +10,7 @@ import (
 	"encoding/base64"
 	"encoding/pem"
 	"fmt"
+	"os"
 	"testing"
 	"time"
 
@@ -25,7 +26,7 @@ func TestGenerateCerts(t *testing.T) {
 		wantEnvoyDNSName        string
 	}
 
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	run := func(t *testing.T, name string, tc testcase) {
diff --git a/internal/envoygateway/config/config_test.go b/internal/envoygateway/config/config_test.go
index 59bba1294..1e68977ea 100644
--- a/internal/envoygateway/config/config_test.go
+++ b/internal/envoygateway/config/config_test.go
@@ -6,6 +6,7 @@
 package config
 
 import (
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
@@ -21,7 +22,7 @@ var (
 )
 
 func TestValidate(t *testing.T) {
-	cfg, err := New()
+	cfg, err := New(os.Stdout)
 	require.NoError(t, err)
 
 	testCases := []struct {
@@ -56,7 +57,7 @@ func TestValidate(t *testing.T) {
 			name: "unspecified envoy gateway",
 			cfg: &Server{
 				Namespace: "test-ns",
-				Logger:    logging.DefaultLogger(egv1a1.LogLevelInfo),
+				Logger:    logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo),
 			},
 			expect: false,
 		},
diff --git a/internal/envoygateway/config/loader/configloader_test.go b/internal/envoygateway/config/loader/configloader_test.go
index b5aa30bf1..fe6186c88 100644
--- a/internal/envoygateway/config/loader/configloader_test.go
+++ b/internal/envoygateway/config/loader/configloader_test.go
@@ -32,7 +32,7 @@ func TestConfigLoader(t *testing.T) {
 
 	cfgPath := tmpDir + "/config.yaml"
 	require.NoError(t, os.WriteFile(cfgPath, []byte(defaultConfig), 0o600))
-	s, err := config.New()
+	s, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	ctx, cancel := context.WithCancel(context.TODO())
diff --git a/internal/gatewayapi/runner/runner_test.go b/internal/gatewayapi/runner/runner_test.go
index 58515da7e..4596a8290 100644
--- a/internal/gatewayapi/runner/runner_test.go
+++ b/internal/gatewayapi/runner/runner_test.go
@@ -7,6 +7,7 @@ package runner
 
 import (
 	"context"
+	"os"
 	"reflect"
 	"testing"
 	"time"
@@ -30,7 +31,7 @@ func TestRunner(t *testing.T) {
 	pResources := new(message.ProviderResources)
 	xdsIR := new(message.XdsIR)
 	infraIR := new(message.InfraIR)
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	extMgr, closeFunc, err := registry.NewInMemoryManager(egv1a1.ExtensionManager{}, &pb.UnimplementedEnvoyGatewayExtensionServer{})
 	require.NoError(t, err)
@@ -116,7 +117,7 @@ func TestDeleteStatusKeys(t *testing.T) {
 	pResources := new(message.ProviderResources)
 	xdsIR := new(message.XdsIR)
 	infraIR := new(message.InfraIR)
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	extMgr, closeFunc, err := registry.NewInMemoryManager(egv1a1.ExtensionManager{}, &pb.UnimplementedEnvoyGatewayExtensionServer{})
 	require.NoError(t, err)
@@ -217,7 +218,7 @@ func TestDeleteAllStatusKeys(t *testing.T) {
 	pResources := new(message.ProviderResources)
 	xdsIR := new(message.XdsIR)
 	infraIR := new(message.InfraIR)
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	extMgr, closeFunc, err := registry.NewInMemoryManager(egv1a1.ExtensionManager{}, &pb.UnimplementedEnvoyGatewayExtensionServer{})
 	require.NoError(t, err)
diff --git a/internal/globalratelimit/runner/runner_test.go b/internal/globalratelimit/runner/runner_test.go
index 80598f790..bbb8b4fda 100644
--- a/internal/globalratelimit/runner/runner_test.go
+++ b/internal/globalratelimit/runner/runner_test.go
@@ -8,6 +8,7 @@ package runner
 import (
 	"context"
 	"fmt"
+	"os"
 	"testing"
 	"time"
 
@@ -209,7 +210,7 @@ func Test_subscribeAndTranslate(t *testing.T) {
 			defer cancel()
 			xdsIR := new(message.XdsIR)
 			defer xdsIR.Close()
-			cfg, err := config.New()
+			cfg, err := config.New(os.Stdout)
 			require.NoError(t, err)
 
 			r := New(&Config{
diff --git a/internal/infrastructure/host/proxy_infra_test.go b/internal/infrastructure/host/proxy_infra_test.go
index de3651da4..2d82cc689 100644
--- a/internal/infrastructure/host/proxy_infra_test.go
+++ b/internal/infrastructure/host/proxy_infra_test.go
@@ -8,6 +8,7 @@ package host
 import (
 	"bytes"
 	"context"
+	"os"
 	"path"
 	"testing"
 
@@ -42,7 +43,7 @@ func newMockInfra(t *testing.T, cfg *config.Server) *Infra {
 
 	infra := &Infra{
 		HomeDir:         homeDir,
-		Logger:          logging.DefaultLogger(egv1a1.LogLevelInfo),
+		Logger:          logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo),
 		EnvoyGateway:    cfg.EnvoyGateway,
 		proxyContextMap: make(map[string]*proxyContext),
 		sdsConfigPath:   proxyDir,
@@ -51,7 +52,7 @@ func newMockInfra(t *testing.T, cfg *config.Server) *Infra {
 }
 
 func TestInfraCreateProxy(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	infra := newMockInfra(t, cfg)
 
diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go
index c005a5db4..478a70dec 100644
--- a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go
+++ b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go
@@ -116,7 +116,7 @@ func newTestInfraWithAnnotationsAndLabels(annotations, labels map[string]string)
 }
 
 func TestDeployment(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	cases := []struct {
@@ -645,7 +645,7 @@ func loadDeployment(caseName string) (*appsv1.Deployment, error) {
 }
 
 func TestDaemonSet(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	cases := []struct {
@@ -1074,7 +1074,7 @@ func loadDaemonSet(caseName string) (*appsv1.DaemonSet, error) {
 }
 
 func TestService(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	svcType := egv1a1.ServiceTypeClusterIP
@@ -1222,7 +1222,7 @@ func loadService(caseName string) (*corev1.Service, error) {
 }
 
 func TestConfigMap(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	cases := []struct {
 		name  string
@@ -1265,7 +1265,7 @@ func loadConfigmap(tc string) (*corev1.ConfigMap, error) {
 }
 
 func TestServiceAccount(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	cases := []struct {
 		name  string
@@ -1308,7 +1308,7 @@ func loadServiceAccount(tc string) (*corev1.ServiceAccount, error) {
 }
 
 func TestPDB(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	cases := []struct {
@@ -1414,7 +1414,7 @@ func TestPDB(t *testing.T) {
 }
 
 func TestHorizontalPodAutoscaler(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	cases := []struct {
diff --git a/internal/infrastructure/kubernetes/proxy_configmap_test.go b/internal/infrastructure/kubernetes/proxy_configmap_test.go
index ec4c0ec74..60ccbbca6 100644
--- a/internal/infrastructure/kubernetes/proxy_configmap_test.go
+++ b/internal/infrastructure/kubernetes/proxy_configmap_test.go
@@ -7,6 +7,7 @@ package kubernetes
 
 import (
 	"context"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -26,7 +27,7 @@ import (
 )
 
 func TestCreateOrUpdateProxyConfigMap(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	infra := ir.NewInfra()
@@ -128,7 +129,7 @@ func TestCreateOrUpdateProxyConfigMap(t *testing.T) {
 }
 
 func TestDeleteConfigProxyMap(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	infra := ir.NewInfra()
diff --git a/internal/infrastructure/kubernetes/proxy_daemonset_test.go b/internal/infrastructure/kubernetes/proxy_daemonset_test.go
index 2c1265862..d60c9a617 100644
--- a/internal/infrastructure/kubernetes/proxy_daemonset_test.go
+++ b/internal/infrastructure/kubernetes/proxy_daemonset_test.go
@@ -7,6 +7,7 @@ package kubernetes
 
 import (
 	"context"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
@@ -47,7 +48,7 @@ func daemonsetWithSelectorAndLabel(ds *appsv1.DaemonSet, selector *metav1.LabelS
 }
 
 func TestCreateOrUpdateProxyDaemonSet(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	infra := ir.NewInfra()
diff --git a/internal/infrastructure/kubernetes/proxy_deployment_test.go b/internal/infrastructure/kubernetes/proxy_deployment_test.go
index 188c92961..73460e00e 100644
--- a/internal/infrastructure/kubernetes/proxy_deployment_test.go
+++ b/internal/infrastructure/kubernetes/proxy_deployment_test.go
@@ -7,6 +7,7 @@ package kubernetes
 
 import (
 	"context"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
@@ -52,7 +53,7 @@ func deploymentWithSelectorAndLabel(deploy *appsv1.Deployment, selector *metav1.
 }
 
 func TestCreateOrUpdateProxyDeployment(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	infra := ir.NewInfra()
@@ -264,7 +265,7 @@ func TestDeleteProxyDeployment(t *testing.T) {
 		WithObjects().
 		WithInterceptorFuncs(interceptorFunc).
 		Build()
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	testCases := []struct {
diff --git a/internal/infrastructure/kubernetes/proxy_infra_test.go b/internal/infrastructure/kubernetes/proxy_infra_test.go
index de0690e82..5363b4e80 100644
--- a/internal/infrastructure/kubernetes/proxy_infra_test.go
+++ b/internal/infrastructure/kubernetes/proxy_infra_test.go
@@ -9,6 +9,7 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"os"
 	"reflect"
 	"testing"
 
@@ -81,7 +82,7 @@ func TestCmpBytes(t *testing.T) {
 }
 
 func newTestInfraWithClient(t *testing.T, cli client.Client) *Infra {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	cfg.EnvoyGateway = &egv1a1.EnvoyGateway{
diff --git a/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go b/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go
index 44732bf6b..18aa79ffd 100644
--- a/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go
+++ b/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go
@@ -7,6 +7,7 @@ package kubernetes
 
 import (
 	"context"
+	"os"
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
@@ -167,7 +168,7 @@ func TestCreateOrUpdateProxyServiceAccount(t *testing.T) {
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
-			cfg, err := config.New()
+			cfg, err := config.New(os.Stdout)
 			require.NoError(t, err)
 			cfg.Namespace = tc.ns
 
diff --git a/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go b/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go
index d3bd7243d..5c2a1edf0 100644
--- a/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go
+++ b/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go
@@ -89,7 +89,7 @@ func TestRateLimitLabels(t *testing.T) {
 }
 
 func TestServiceAccount(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	cfg.EnvoyGateway.RateLimit = &egv1a1.RateLimit{
@@ -122,7 +122,7 @@ func loadServiceAccount() (*corev1.ServiceAccount, error) {
 }
 
 func TestService(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	cases := []struct {
@@ -185,7 +185,7 @@ func loadService(caseName string) (*corev1.Service, error) {
 }
 
 func TestConfigmap(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	cfg.EnvoyGateway.RateLimit = &egv1a1.RateLimit{
@@ -226,7 +226,7 @@ func loadConfigmap() (*corev1.ConfigMap, error) {
 }
 
 func TestDeployment(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	rateLimit := &egv1a1.RateLimit{
 		Backend: egv1a1.RateLimitDatabaseBackend{
@@ -798,7 +798,7 @@ func loadDeployment(caseName string) (*appsv1.Deployment, error) {
 }
 
 func TestHorizontalPodAutoscaler(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	cases := []struct {
 		caseName            string
diff --git a/internal/infrastructure/kubernetes/ratelimit_deployment_test.go b/internal/infrastructure/kubernetes/ratelimit_deployment_test.go
index ea0e5017f..e66b69a06 100644
--- a/internal/infrastructure/kubernetes/ratelimit_deployment_test.go
+++ b/internal/infrastructure/kubernetes/ratelimit_deployment_test.go
@@ -7,6 +7,7 @@ package kubernetes
 
 import (
 	"context"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
@@ -23,7 +24,7 @@ import (
 )
 
 func TestCreateOrUpdateRateLimitDeployment(t *testing.T) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 
 	cfg.EnvoyGateway.RateLimit = &egv1a1.RateLimit{
diff --git a/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go b/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go
index 630fa2e33..2e5805129 100644
--- a/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go
+++ b/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go
@@ -7,6 +7,7 @@ package kubernetes
 
 import (
 	"context"
+	"os"
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
@@ -103,7 +104,7 @@ func TestCreateOrUpdateRateLimitServiceAccount(t *testing.T) {
 					Build()
 			}
 
-			cfg, err := config.New()
+			cfg, err := config.New(os.Stdout)
 			require.NoError(t, err)
 			cfg.Namespace = tc.ns
 
diff --git a/internal/logging/log_test.go b/internal/logging/log_test.go
index 265df4111..a5f75e438 100644
--- a/internal/logging/log_test.go
+++ b/internal/logging/log_test.go
@@ -38,7 +38,7 @@ func TestLogger(t *testing.T) {
 
 	logger.WithName(string(egv1a1.LogComponentGlobalRateLimitRunner)).WithValues("runner", egv1a1.LogComponentGlobalRateLimitRunner).Info("msg", "k", "v")
 
-	defaultLogger := DefaultLogger(egv1a1.LogLevelInfo)
+	defaultLogger := DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 	assert.NotNil(t, defaultLogger.logging)
 	assert.NotNil(t, defaultLogger.sugaredLogger)
 
diff --git a/internal/provider/file/file_test.go b/internal/provider/file/file_test.go
index 8f681d47d..57909ea69 100644
--- a/internal/provider/file/file_test.go
+++ b/internal/provider/file/file_test.go
@@ -50,7 +50,7 @@ func newDefaultResourcesParam() *resourcesParam {
 }
 
 func newFileProviderConfig(paths []string) (*config.Server, error) {
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	if err != nil {
 		return nil, err
 	}
diff --git a/internal/provider/kubernetes/controller_test.go b/internal/provider/kubernetes/controller_test.go
index d008e7b2f..b2d6cdaf7 100644
--- a/internal/provider/kubernetes/controller_test.go
+++ b/internal/provider/kubernetes/controller_test.go
@@ -7,6 +7,7 @@ package kubernetes
 
 import (
 	"context"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
@@ -256,7 +257,7 @@ func TestProcessGatewayClassParamsRef(t *testing.T) {
 		tc := testCases[i]
 
 		// Create the reconciler.
-		logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+		logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 		r := &gatewayAPIReconciler{
 			log:             logger,
@@ -421,7 +422,7 @@ func TestProcessEnvoyExtensionPolicyObjectRefs(t *testing.T) {
 			objs := []client.Object{tc.envoyExtensionPolicy, tc.backend, tc.referenceGrant}
 
 			// Create the reconciler.
-			logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+			logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 			ctx := context.Background()
 
diff --git a/internal/provider/kubernetes/extensionpolicies_test.go b/internal/provider/kubernetes/extensionpolicies_test.go
index 3d74ff270..54010a19e 100644
--- a/internal/provider/kubernetes/extensionpolicies_test.go
+++ b/internal/provider/kubernetes/extensionpolicies_test.go
@@ -7,6 +7,7 @@ package kubernetes
 
 import (
 	"context"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
@@ -206,7 +207,7 @@ func TestProcessExtensionPolicies(t *testing.T) {
 			objs := []client.Object{}
 
 			// Create the reconciler.
-			logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+			logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 			ctx := context.Background()
 
diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go
index 4665f510e..5daf6fba6 100644
--- a/internal/provider/kubernetes/kubernetes_test.go
+++ b/internal/provider/kubernetes/kubernetes_test.go
@@ -60,7 +60,7 @@ func TestProvider(t *testing.T) {
 	require.NoError(t, err)
 
 	// Setup and start the kube provider.
-	svr, err := config.New()
+	svr, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	resources := new(message.ProviderResources)
 	provider, err := New(context.Background(), cliCfg, svr, resources)
@@ -1263,7 +1263,7 @@ func TestNamespacedProvider(t *testing.T) {
 	require.NoError(t, err)
 
 	// Setup and start the kube provider.
-	svr, err := config.New()
+	svr, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	// config to watch a subset of namespaces
 	svr.EnvoyGateway.Provider.Kubernetes = &egv1a1.EnvoyGatewayKubernetesProvider{
@@ -1323,7 +1323,7 @@ func TestNamespaceSelectorProvider(t *testing.T) {
 	require.NoError(t, err)
 
 	// Setup and start the kube provider.
-	svr, err := config.New()
+	svr, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	// config to watch a subset of namespaces
 	svr.EnvoyGateway.Provider.Kubernetes = &egv1a1.EnvoyGatewayKubernetesProvider{
diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go
index 5c9dbba1c..0ccb4999c 100644
--- a/internal/provider/kubernetes/predicates_test.go
+++ b/internal/provider/kubernetes/predicates_test.go
@@ -7,6 +7,7 @@ package kubernetes
 
 import (
 	"fmt"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
@@ -52,7 +53,7 @@ func TestGatewayClassHasMatchingController(t *testing.T) {
 	}
 
 	// Create the reconciler.
-	logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+	logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 	r := gatewayAPIReconciler{
 		classController: egv1a1.GatewayControllerName,
@@ -104,7 +105,7 @@ func TestGatewayClassHasMatchingNamespaceLabels(t *testing.T) {
 		},
 	}
 
-	logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+	logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 	for _, tc := range testCases {
 		r := gatewayAPIReconciler{
@@ -158,7 +159,7 @@ func TestValidateGatewayForReconcile(t *testing.T) {
 	}
 
 	// Create the reconciler.
-	logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+	logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 	r := gatewayAPIReconciler{
 		classController: egv1a1.GatewayControllerName,
@@ -384,7 +385,7 @@ func TestValidateSecretForReconcile(t *testing.T) {
 	}
 
 	// Create the reconciler.
-	logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+	logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 	r := gatewayAPIReconciler{
 		classController: egv1a1.GatewayControllerName,
@@ -512,7 +513,7 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) {
 	}
 
 	// Create the reconciler.
-	logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+	logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 	r := gatewayAPIReconciler{
 		classController: egv1a1.GatewayControllerName,
@@ -941,7 +942,7 @@ func TestValidateServiceForReconcile(t *testing.T) {
 	}
 
 	// Create the reconciler.
-	logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+	logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 	r := gatewayAPIReconciler{
 		classController:    egv1a1.GatewayControllerName,
@@ -1060,7 +1061,7 @@ func TestValidateObjectForReconcile(t *testing.T) {
 	}
 
 	// Create the reconciler.
-	logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+	logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 	r := gatewayAPIReconciler{
 		classController: egv1a1.GatewayControllerName,
@@ -1167,7 +1168,7 @@ func TestCheckObjectNamespaceLabels(t *testing.T) {
 	}
 
 	// Create the reconciler.
-	logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+	logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 	r := gatewayAPIReconciler{
 		classController: egv1a1.GatewayControllerName,
@@ -1320,7 +1321,7 @@ func TestValidateHTTPRouteFilerForReconcile(t *testing.T) {
 	}
 
 	// Create the reconciler.
-	logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+	logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 	r := gatewayAPIReconciler{
 		classController: egv1a1.GatewayControllerName,
diff --git a/internal/provider/kubernetes/routes_test.go b/internal/provider/kubernetes/routes_test.go
index d1850b9bf..a9e1f7820 100644
--- a/internal/provider/kubernetes/routes_test.go
+++ b/internal/provider/kubernetes/routes_test.go
@@ -7,6 +7,7 @@ package kubernetes
 
 import (
 	"context"
+	"os"
 	"testing"
 	"time"
 
@@ -596,7 +597,7 @@ func TestProcessHTTPRoutes(t *testing.T) {
 			objs := []client.Object{gc, gw}
 
 			// Create the reconciler.
-			logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+			logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 			ctx := context.Background()
 
@@ -756,7 +757,7 @@ func TestProcessGRPCRoutes(t *testing.T) {
 			objs := []client.Object{gc, gw}
 
 			// Create the reconciler.
-			logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+			logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 
 			ctx := context.Background()
 
diff --git a/internal/wasm/cache_test.go b/internal/wasm/cache_test.go
index ba40c0625..6d3edd572 100644
--- a/internal/wasm/cache_test.go
+++ b/internal/wasm/cache_test.go
@@ -691,7 +691,7 @@ func TestWasmCache(t *testing.T) {
 			if c.wasmModuleExpiry != 0 {
 				options.ModuleExpiry = c.wasmModuleExpiry
 			}
-			cache := newLocalFileCache(options, logging.DefaultLogger(egv1a1.LogLevelInfo))
+			cache := newLocalFileCache(options, logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo))
 			cache.httpFetcher.initialBackoff = time.Microsecond
 			ctx, cancel := context.WithTimeout(context.Background(), time.Second*60)
 			cache.Start(ctx)
@@ -878,7 +878,7 @@ func TestWasmCachePolicyChangesUsingHTTP(t *testing.T) {
 	tmpDir := t.TempDir()
 	options := defaultCacheOptions()
 	options.CacheDir = tmpDir
-	cache := newLocalFileCache(options, logging.DefaultLogger(egv1a1.LogLevelInfo))
+	cache := newLocalFileCache(options, logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo))
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*60)
 	cache.Start(ctx)
 	defer cancel()
@@ -944,7 +944,7 @@ func TestAllInsecureServer(t *testing.T) {
 	options := defaultCacheOptions()
 	options.CacheDir = tmpDir
 	options.InsecureRegistries = sets.New[string]("*")
-	cache := newLocalFileCache(options, logging.DefaultLogger(egv1a1.LogLevelInfo))
+	cache := newLocalFileCache(options, logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo))
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*60)
 	cache.Start(ctx)
 	defer cancel()
diff --git a/internal/wasm/httpfetcher_test.go b/internal/wasm/httpfetcher_test.go
index 98fdda500..3a27e19f1 100644
--- a/internal/wasm/httpfetcher_test.go
+++ b/internal/wasm/httpfetcher_test.go
@@ -27,6 +27,7 @@ import (
 	"fmt"
 	"net/http"
 	"net/http/httptest"
+	"os"
 	"regexp"
 	"strings"
 	"testing"
@@ -97,7 +98,7 @@ func TestWasmHTTPFetch(t *testing.T) {
 				gotNumRequest++
 			}))
 			defer ts.Close()
-			fetcher := NewHTTPFetcher(DefaultHTTPRequestTimeout, DefaultHTTPRequestMaxRetries, logging.DefaultLogger(egv1a1.LogLevelInfo))
+			fetcher := NewHTTPFetcher(DefaultHTTPRequestTimeout, DefaultHTTPRequestMaxRetries, logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo))
 			fetcher.initialBackoff = time.Microsecond
 			ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
 			defer cancel()
@@ -156,7 +157,7 @@ func TestWasmHTTPInsecureServer(t *testing.T) {
 				gotNumRequest++
 			}))
 			defer ts.Close()
-			fetcher := NewHTTPFetcher(DefaultHTTPRequestTimeout, DefaultHTTPRequestMaxRetries, logging.DefaultLogger(egv1a1.LogLevelInfo))
+			fetcher := NewHTTPFetcher(DefaultHTTPRequestTimeout, DefaultHTTPRequestMaxRetries, logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo))
 			fetcher.initialBackoff = time.Microsecond
 			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 			defer cancel()
@@ -257,7 +258,7 @@ func TestWasmHTTPFetchCompressedOrTarFile(t *testing.T) {
 				gotNumRequest++
 			}))
 			defer ts.Close()
-			fetcher := NewHTTPFetcher(DefaultHTTPRequestTimeout, DefaultHTTPRequestMaxRetries, logging.DefaultLogger(egv1a1.LogLevelInfo))
+			fetcher := NewHTTPFetcher(DefaultHTTPRequestTimeout, DefaultHTTPRequestMaxRetries, logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo))
 			fetcher.initialBackoff = time.Microsecond
 			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 			defer cancel()
diff --git a/internal/wasm/httpserver_test.go b/internal/wasm/httpserver_test.go
index 0f054ea84..0fd7c099b 100644
--- a/internal/wasm/httpserver_test.go
+++ b/internal/wasm/httpserver_test.go
@@ -12,6 +12,7 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"net/url"
+	"os"
 	"strings"
 	"testing"
 	"time"
@@ -327,7 +328,7 @@ func setupFakeRegistry(host string) error {
 }
 
 func startLocalHTTPServer(ctx context.Context, cacheDir string, maxFailedAttempts int, failedAttemptResetDelay, failedAttemptsResetInterval time.Duration) (*HTTPServer, error) {
-	logger := logging.DefaultLogger(egv1a1.LogLevelInfo)
+	logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
 	s := NewHTTPServerWithFileCache(
 		SeverOptions{
 			Salt:                        []byte("salt"),
diff --git a/internal/wasm/premissioncache_test.go b/internal/wasm/premissioncache_test.go
index 2fdb95ff1..5066a4189 100644
--- a/internal/wasm/premissioncache_test.go
+++ b/internal/wasm/premissioncache_test.go
@@ -25,6 +25,7 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"net/url"
+	"os"
 	"sync"
 	"testing"
 	"time"
@@ -256,7 +257,7 @@ func setupTestPermissionCache(options permissionCacheOptions, image, latestImage
 	// Setup the permission cache.
 	cache := newPermissionCache(
 		options,
-		logging.DefaultLogger(egv1a1.LogLevelInfo))
+		logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo))
 
 	entry := &permissionCacheEntry{
 		image: image,
diff --git a/internal/xds/server/runner/runner_test.go b/internal/xds/server/runner/runner_test.go
index e0517d1fa..69dd798b8 100644
--- a/internal/xds/server/runner/runner_test.go
+++ b/internal/xds/server/runner/runner_test.go
@@ -195,7 +195,7 @@ func TestServeXdsServerListenFailed(t *testing.T) {
 	require.NoError(t, err)
 	defer l.Close()
 
-	cfg, _ := config.New()
+	cfg, _ := config.New(os.Stdout)
 	r := New(&Config{
 		Server: *cfg,
 	})
diff --git a/internal/xds/translator/runner/runner_test.go b/internal/xds/translator/runner/runner_test.go
index a154b9f82..ee1765f48 100644
--- a/internal/xds/translator/runner/runner_test.go
+++ b/internal/xds/translator/runner/runner_test.go
@@ -8,6 +8,7 @@ package runner
 import (
 	"context"
 	"fmt"
+	"os"
 	"testing"
 	"time"
 
@@ -28,7 +29,7 @@ func TestRunner(t *testing.T) {
 	xdsIR := new(message.XdsIR)
 	xds := new(message.Xds)
 	pResource := new(message.ProviderResources)
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	r := New(&Config{
 		Server:            *cfg,
@@ -108,7 +109,7 @@ func TestRunner_withExtensionManager(t *testing.T) {
 	xds := new(message.Xds)
 	pResource := new(message.ProviderResources)
 
-	cfg, err := config.New()
+	cfg, err := config.New(os.Stdout)
 	require.NoError(t, err)
 	r := New(&Config{
 		Server:            *cfg,
diff --git a/site/content/en/latest/tasks/traffic/grpc-routing.md b/site/content/en/latest/tasks/traffic/grpc-routing.md
index 15f10601b..3a36e9fd7 100644
--- a/site/content/en/latest/tasks/traffic/grpc-routing.md
+++ b/site/content/en/latest/tasks/traffic/grpc-routing.md
@@ -99,7 +99,7 @@ as well as a match for all services with a method name `Ping` which matches `yag
 
 ```shell
 cat <<EOF | kubectl apply -f -
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1
 kind: GRPCRoute
 metadata:
   name: yages
@@ -132,7 +132,7 @@ Save and apply the following resource to your cluster:
 
 ```yaml
 ---
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1
 kind: GRPCRoute
 metadata:
   name: yages
@@ -184,7 +184,7 @@ with match type `RegularExpression`. It matches all the services and methods wit
 
 ```shell
 cat <<EOF | kubectl apply -f -
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1
 kind: GRPCRoute
 metadata:
   name: yages
@@ -219,7 +219,7 @@ Save and apply the following resource to your cluster:
 
 ```yaml
 ---
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1
 kind: GRPCRoute
 metadata:
   name: yages