From f22ea7076f7444d3d1a38db0d1a0bb5939fa9edb Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 17 Jan 2024 16:08:38 +0000
Subject: [PATCH] Bump google.golang.org/grpc from 1.54.0 to 1.56.3

Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.54.0 to 1.56.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.54.0...v1.56.3)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 go.mod                                        |    4 +-
 go.sum                                        |    8 +-
 vendor/github.com/golang/glog/glog.go         | 1217 +++++------------
 vendor/github.com/golang/glog/glog_file.go    |  305 ++++-
 vendor/github.com/golang/glog/glog_flags.go   |  395 ++++++
 .../golang/glog/internal/logsink/logsink.go   |  387 ++++++
 .../glog/internal/logsink/logsink_fatal.go    |   35 +
 .../glog/internal/stackdump/stackdump.go      |  127 ++
 vendor/google.golang.org/grpc/CONTRIBUTING.md |    4 -
 .../grpc/attributes/attributes.go             |   29 +
 .../grpc/balancer/balancer.go                 |    2 +-
 .../grpc/balancer_conn_wrappers.go            |  486 ++++---
 .../grpc_binarylog_v1/binarylog.pb.go         |    2 +-
 vendor/google.golang.org/grpc/call.go         |    5 +
 vendor/google.golang.org/grpc/clientconn.go   |  622 ++++++---
 vendor/google.golang.org/grpc/dialoptions.go  |   30 +
 vendor/google.golang.org/grpc/idle.go         |  287 ++++
 .../grpc/internal/binarylog/binarylog.go      |    3 +
 .../grpc/internal/binarylog/method_logger.go  |    9 +
 .../grpc/internal/buffer/unbounded.go         |   26 +-
 .../grpc/internal/envconfig/envconfig.go      |    4 +
 .../grpc/internal/envconfig/observability.go  |    6 +
 .../grpc/internal/envconfig/xds.go            |   21 +-
 .../grpc/internal/grpcrand/grpcrand.go        |   14 +
 .../internal/grpcsync/callback_serializer.go  |  119 ++
 .../grpc/internal/internal.go                 |   24 +
 .../grpc/internal/serviceconfig/duration.go   |  130 ++
 .../grpc/internal/transport/controlbuf.go     |   17 +-
 .../grpc/internal/transport/handler_server.go |   11 +-
 .../grpc/internal/transport/http2_client.go   |   27 +-
 .../grpc/internal/transport/http2_server.go   |   74 +-
 .../grpc/internal/transport/http_util.go      |    2 -
 .../grpc/internal/transport/logging.go        |   40 +
 .../grpc/internal/transport/transport.go      |    2 +-
 .../google.golang.org/grpc/picker_wrapper.go  |   38 +-
 vendor/google.golang.org/grpc/pickfirst.go    |   52 +-
 .../grpc/resolver/resolver.go                 |   16 +-
 .../grpc/resolver_conn_wrapper.go             |  229 ++--
 vendor/google.golang.org/grpc/server.go       |   99 +-
 .../google.golang.org/grpc/service_config.go  |   75 +-
 .../google.golang.org/grpc/status/status.go   |   53 +-
 vendor/google.golang.org/grpc/stream.go       |   29 +-
 vendor/google.golang.org/grpc/version.go      |    2 +-
 vendor/modules.txt                            |    8 +-
 44 files changed, 3415 insertions(+), 1660 deletions(-)
 create mode 100644 vendor/github.com/golang/glog/glog_flags.go
 create mode 100644 vendor/github.com/golang/glog/internal/logsink/logsink.go
 create mode 100644 vendor/github.com/golang/glog/internal/logsink/logsink_fatal.go
 create mode 100644 vendor/github.com/golang/glog/internal/stackdump/stackdump.go
 create mode 100644 vendor/google.golang.org/grpc/idle.go
 create mode 100644 vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go
 create mode 100644 vendor/google.golang.org/grpc/internal/serviceconfig/duration.go
 create mode 100644 vendor/google.golang.org/grpc/internal/transport/logging.go

diff --git a/go.mod b/go.mod
index 07a3178d8..4c3878244 100644
--- a/go.mod
+++ b/go.mod
@@ -73,7 +73,7 @@ require (
 	github.com/go-openapi/swag v0.22.4 // indirect
 	github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
-	github.com/golang/glog v1.0.0 // indirect
+	github.com/golang/glog v1.1.0 // indirect
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/google/btree v1.0.1 // indirect
@@ -136,7 +136,7 @@ require (
 	gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
 	google.golang.org/appengine v1.6.8 // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
-	google.golang.org/grpc v1.54.0 // indirect
+	google.golang.org/grpc v1.56.3 // indirect
 	google.golang.org/protobuf v1.31.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
diff --git a/go.sum b/go.sum
index dfaf5fdc2..f8763b531 100644
--- a/go.sum
+++ b/go.sum
@@ -173,8 +173,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
-github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
+github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
+github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -795,8 +795,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
 google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
-google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
+google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
+google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/vendor/github.com/golang/glog/glog.go b/vendor/github.com/golang/glog/glog.go
index 718c34f88..e108ae8b4 100644
--- a/vendor/github.com/golang/glog/glog.go
+++ b/vendor/github.com/golang/glog/glog.go
@@ -1,6 +1,6 @@
-// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
+// Go support for leveled logs, analogous to https://github.com/google/glog.
 //
-// Copyright 2013 Google Inc. All Rights Reserved.
+// Copyright 2023 Google Inc. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -50,15 +50,15 @@
 //		Log files will be written to this directory instead of the
 //		default temporary directory.
 //
-//	Other flags provide aids to debugging.
+// Other flags provide aids to debugging.
 //
 //	-log_backtrace_at=""
-//		When set to a file and line number holding a logging statement,
-//		such as
+//		A comma-separated list of file and line numbers holding a logging
+//		statement, such as
 //			-log_backtrace_at=gopherflakes.go:234
-//		a stack trace will be written to the Info log whenever execution
-//		hits that statement. (Unlike with -vmodule, the ".go" must be
-//		present.)
+//		A stack trace will be written to the Info log whenever execution
+//		hits one of these statements. (Unlike with -vmodule, the ".go"
+//		must bepresent.)
 //	-v=0
 //		Enable V-leveled logging at the specified level.
 //	-vmodule=""
@@ -66,100 +66,47 @@
 //		where pattern is a literal file name (minus the ".go" suffix) or
 //		"glob" pattern and N is a V level. For instance,
 //			-vmodule=gopher*=3
-//		sets the V level to 3 in all Go files whose names begin "gopher".
-//
+//		sets the V level to 3 in all Go files whose names begin with "gopher",
+//		and
+//			-vmodule=/path/to/glog/glog_test=1
+//		sets the V level to 1 in the Go file /path/to/glog/glog_test.go.
+//		If a glob pattern contains a slash, it is matched against the full path,
+//		and the file name. Otherwise, the pattern is
+//		matched only against the file's basename.  When both -vmodule and -v
+//		are specified, the -vmodule values take precedence for the specified
+//		modules.
 package glog
 
+// This file contains the parts of the log package that are shared among all
+// implementations (file, envelope, and appengine).
+
 import (
-	"bufio"
 	"bytes"
 	"errors"
-	"flag"
 	"fmt"
-	"io"
 	stdLog "log"
 	"os"
-	"path/filepath"
+	"reflect"
 	"runtime"
+	"runtime/pprof"
 	"strconv"
-	"strings"
 	"sync"
 	"sync/atomic"
+	"syscall"
 	"time"
-)
-
-// severity identifies the sort of log: info, warning etc. It also implements
-// the flag.Value interface. The -stderrthreshold flag is of type severity and
-// should be modified only through the flag.Value interface. The values match
-// the corresponding constants in C++.
-type severity int32 // sync/atomic int32
 
-// These constants identify the log levels in order of increasing severity.
-// A message written to a high-severity log file is also written to each
-// lower-severity log file.
-const (
-	infoLog severity = iota
-	warningLog
-	errorLog
-	fatalLog
-	numSeverity = 4
+	"github.com/golang/glog/internal/logsink"
+	"github.com/golang/glog/internal/stackdump"
 )
 
-const severityChar = "IWEF"
-
-var severityName = []string{
-	infoLog:    "INFO",
-	warningLog: "WARNING",
-	errorLog:   "ERROR",
-	fatalLog:   "FATAL",
-}
-
-// get returns the value of the severity.
-func (s *severity) get() severity {
-	return severity(atomic.LoadInt32((*int32)(s)))
-}
-
-// set sets the value of the severity.
-func (s *severity) set(val severity) {
-	atomic.StoreInt32((*int32)(s), int32(val))
-}
-
-// String is part of the flag.Value interface.
-func (s *severity) String() string {
-	return strconv.FormatInt(int64(*s), 10)
-}
-
-// Get is part of the flag.Value interface.
-func (s *severity) Get() interface{} {
-	return *s
-}
+var timeNow = time.Now // Stubbed out for testing.
 
-// Set is part of the flag.Value interface.
-func (s *severity) Set(value string) error {
-	var threshold severity
-	// Is it a known name?
-	if v, ok := severityByName(value); ok {
-		threshold = v
-	} else {
-		v, err := strconv.Atoi(value)
-		if err != nil {
-			return err
-		}
-		threshold = severity(v)
-	}
-	logging.stderrThreshold.set(threshold)
-	return nil
-}
+// MaxSize is the maximum size of a log file in bytes.
+var MaxSize uint64 = 1024 * 1024 * 1800
 
-func severityByName(s string) (severity, bool) {
-	s = strings.ToUpper(s)
-	for i, name := range severityName {
-		if name == s {
-			return severity(i), true
-		}
-	}
-	return 0, false
-}
+// ErrNoLog is the error we return if no log file has yet been created
+// for the specified log type.
+var ErrNoLog = errors.New("log file not yet created")
 
 // OutputStats tracks the number of output lines and bytes written.
 type OutputStats struct {
@@ -183,724 +130,99 @@ var Stats struct {
 	Info, Warning, Error OutputStats
 }
 
-var severityStats = [numSeverity]*OutputStats{
-	infoLog:    &Stats.Info,
-	warningLog: &Stats.Warning,
-	errorLog:   &Stats.Error,
+var severityStats = [...]*OutputStats{
+	logsink.Info:    &Stats.Info,
+	logsink.Warning: &Stats.Warning,
+	logsink.Error:   &Stats.Error,
+	logsink.Fatal:   nil,
 }
 
-// Level is exported because it appears in the arguments to V and is
-// the type of the v flag, which can be set programmatically.
-// It's a distinct type because we want to discriminate it from logType.
-// Variables of type level are only changed under logging.mu.
-// The -v flag is read only with atomic ops, so the state of the logging
-// module is consistent.
-
-// Level is treated as a sync/atomic int32.
-
-// Level specifies a level of verbosity for V logs. *Level implements
-// flag.Value; the -v flag is of type Level and should be modified
-// only through the flag.Value interface.
+// Level specifies a level of verbosity for V logs.  The -v flag is of type
+// Level and should be modified only through the flag.Value interface.
 type Level int32
 
-// get returns the value of the Level.
-func (l *Level) get() Level {
-	return Level(atomic.LoadInt32((*int32)(l)))
-}
-
-// set sets the value of the Level.
-func (l *Level) set(val Level) {
-	atomic.StoreInt32((*int32)(l), int32(val))
-}
-
-// String is part of the flag.Value interface.
-func (l *Level) String() string {
-	return strconv.FormatInt(int64(*l), 10)
-}
+var metaPool sync.Pool // Pool of *logsink.Meta.
 
-// Get is part of the flag.Value interface.
-func (l *Level) Get() interface{} {
-	return *l
-}
-
-// Set is part of the flag.Value interface.
-func (l *Level) Set(value string) error {
-	v, err := strconv.Atoi(value)
-	if err != nil {
-		return err
-	}
-	logging.mu.Lock()
-	defer logging.mu.Unlock()
-	logging.setVState(Level(v), logging.vmodule.filter, false)
-	return nil
-}
-
-// moduleSpec represents the setting of the -vmodule flag.
-type moduleSpec struct {
-	filter []modulePat
-}
-
-// modulePat contains a filter for the -vmodule flag.
-// It holds a verbosity level and a file pattern to match.
-type modulePat struct {
-	pattern string
-	literal bool // The pattern is a literal string
-	level   Level
-}
-
-// match reports whether the file matches the pattern. It uses a string
-// comparison if the pattern contains no metacharacters.
-func (m *modulePat) match(file string) bool {
-	if m.literal {
-		return file == m.pattern
-	}
-	match, _ := filepath.Match(m.pattern, file)
-	return match
-}
-
-func (m *moduleSpec) String() string {
-	// Lock because the type is not atomic. TODO: clean this up.
-	logging.mu.Lock()
-	defer logging.mu.Unlock()
-	var b bytes.Buffer
-	for i, f := range m.filter {
-		if i > 0 {
-			b.WriteRune(',')
-		}
-		fmt.Fprintf(&b, "%s=%d", f.pattern, f.level)
+// metaPoolGet returns a *logsink.Meta from metaPool as both an interface and a
+// pointer, allocating a new one if necessary.  (Returning the interface value
+// directly avoids an allocation if there was an existing pointer in the pool.)
+func metaPoolGet() (any, *logsink.Meta) {
+	if metai := metaPool.Get(); metai != nil {
+		return metai, metai.(*logsink.Meta)
 	}
-	return b.String()
-}
-
-// Get is part of the (Go 1.2)  flag.Getter interface. It always returns nil for this flag type since the
-// struct is not exported.
-func (m *moduleSpec) Get() interface{} {
-	return nil
+	meta := new(logsink.Meta)
+	return meta, meta
 }
 
-var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N")
-
-// Syntax: -vmodule=recordio=2,file=1,gfs*=3
-func (m *moduleSpec) Set(value string) error {
-	var filter []modulePat
-	for _, pat := range strings.Split(value, ",") {
-		if len(pat) == 0 {
-			// Empty strings such as from a trailing comma can be ignored.
-			continue
-		}
-		patLev := strings.Split(pat, "=")
-		if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 {
-			return errVmoduleSyntax
-		}
-		pattern := patLev[0]
-		v, err := strconv.Atoi(patLev[1])
-		if err != nil {
-			return errors.New("syntax error: expect comma-separated list of filename=N")
-		}
-		if v < 0 {
-			return errors.New("negative value for vmodule level")
-		}
-		if v == 0 {
-			continue // Ignore. It's harmless but no point in paying the overhead.
-		}
-		// TODO: check syntax of filter?
-		filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)})
-	}
-	logging.mu.Lock()
-	defer logging.mu.Unlock()
-	logging.setVState(logging.verbosity, filter, true)
-	return nil
-}
-
-// isLiteral reports whether the pattern is a literal string, that is, has no metacharacters
-// that require filepath.Match to be called to match the pattern.
-func isLiteral(pattern string) bool {
-	return !strings.ContainsAny(pattern, `\*?[]`)
-}
-
-// traceLocation represents the setting of the -log_backtrace_at flag.
-type traceLocation struct {
-	file string
-	line int
-}
-
-// isSet reports whether the trace location has been specified.
-// logging.mu is held.
-func (t *traceLocation) isSet() bool {
-	return t.line > 0
-}
+type stack bool
 
-// match reports whether the specified file and line matches the trace location.
-// The argument file name is the full path, not the basename specified in the flag.
-// logging.mu is held.
-func (t *traceLocation) match(file string, line int) bool {
-	if t.line != line {
-		return false
-	}
-	if i := strings.LastIndex(file, "/"); i >= 0 {
-		file = file[i+1:]
-	}
-	return t.file == file
-}
-
-func (t *traceLocation) String() string {
-	// Lock because the type is not atomic. TODO: clean this up.
-	logging.mu.Lock()
-	defer logging.mu.Unlock()
-	return fmt.Sprintf("%s:%d", t.file, t.line)
-}
-
-// Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the
-// struct is not exported
-func (t *traceLocation) Get() interface{} {
-	return nil
-}
-
-var errTraceSyntax = errors.New("syntax error: expect file.go:234")
-
-// Syntax: -log_backtrace_at=gopherflakes.go:234
-// Note that unlike vmodule the file extension is included here.
-func (t *traceLocation) Set(value string) error {
-	if value == "" {
-		// Unset.
-		t.line = 0
-		t.file = ""
-	}
-	fields := strings.Split(value, ":")
-	if len(fields) != 2 {
-		return errTraceSyntax
-	}
-	file, line := fields[0], fields[1]
-	if !strings.Contains(file, ".") {
-		return errTraceSyntax
-	}
-	v, err := strconv.Atoi(line)
-	if err != nil {
-		return errTraceSyntax
-	}
-	if v <= 0 {
-		return errors.New("negative or zero value for level")
-	}
-	logging.mu.Lock()
-	defer logging.mu.Unlock()
-	t.line = v
-	t.file = file
-	return nil
-}
-
-// flushSyncWriter is the interface satisfied by logging destinations.
-type flushSyncWriter interface {
-	Flush() error
-	Sync() error
-	io.Writer
-}
-
-func init() {
-	flag.BoolVar(&logging.toStderr, "logtostderr", false, "log to standard error instead of files")
-	flag.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files")
-	flag.Var(&logging.verbosity, "v", "log level for V logs")
-	flag.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr")
-	flag.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging")
-	flag.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace")
-
-	// Default stderrThreshold is ERROR.
-	logging.stderrThreshold = errorLog
-
-	logging.setVState(0, nil, false)
-	go logging.flushDaemon()
-}
-
-// Flush flushes all pending log I/O.
-func Flush() {
-	logging.lockAndFlushAll()
-}
-
-// loggingT collects all the global state of the logging setup.
-type loggingT struct {
-	// Boolean flags. Not handled atomically because the flag.Value interface
-	// does not let us avoid the =true, and that shorthand is necessary for
-	// compatibility. TODO: does this matter enough to fix? Seems unlikely.
-	toStderr     bool // The -logtostderr flag.
-	alsoToStderr bool // The -alsologtostderr flag.
-
-	// Level flag. Handled atomically.
-	stderrThreshold severity // The -stderrthreshold flag.
-
-	// freeList is a list of byte buffers, maintained under freeListMu.
-	freeList *buffer
-	// freeListMu maintains the free list. It is separate from the main mutex
-	// so buffers can be grabbed and printed to without holding the main lock,
-	// for better parallelization.
-	freeListMu sync.Mutex
-
-	// mu protects the remaining elements of this structure and is
-	// used to synchronize logging.
-	mu sync.Mutex
-	// file holds writer for each of the log types.
-	file [numSeverity]flushSyncWriter
-	// pcs is used in V to avoid an allocation when computing the caller's PC.
-	pcs [1]uintptr
-	// vmap is a cache of the V Level for each V() call site, identified by PC.
-	// It is wiped whenever the vmodule flag changes state.
-	vmap map[uintptr]Level
-	// filterLength stores the length of the vmodule filter chain. If greater
-	// than zero, it means vmodule is enabled. It may be read safely
-	// using sync.LoadInt32, but is only modified under mu.
-	filterLength int32
-	// traceLocation is the state of the -log_backtrace_at flag.
-	traceLocation traceLocation
-	// These flags are modified only under lock, although verbosity may be fetched
-	// safely using atomic.LoadInt32.
-	vmodule   moduleSpec // The state of the -vmodule flag.
-	verbosity Level      // V logging level, the value of the -v flag/
-}
-
-// buffer holds a byte Buffer for reuse. The zero value is ready for use.
-type buffer struct {
-	bytes.Buffer
-	tmp  [64]byte // temporary byte array for creating headers.
-	next *buffer
-}
-
-var logging loggingT
-
-// setVState sets a consistent state for V logging.
-// l.mu is held.
-func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) {
-	// Turn verbosity off so V will not fire while we are in transition.
-	logging.verbosity.set(0)
-	// Ditto for filter length.
-	atomic.StoreInt32(&logging.filterLength, 0)
-
-	// Set the new filters and wipe the pc->Level map if the filter has changed.
-	if setFilter {
-		logging.vmodule.filter = filter
-		logging.vmap = make(map[uintptr]Level)
-	}
-
-	// Things are consistent now, so enable filtering and verbosity.
-	// They are enabled in order opposite to that in V.
-	atomic.StoreInt32(&logging.filterLength, int32(len(filter)))
-	logging.verbosity.set(verbosity)
-}
-
-// getBuffer returns a new, ready-to-use buffer.
-func (l *loggingT) getBuffer() *buffer {
-	l.freeListMu.Lock()
-	b := l.freeList
-	if b != nil {
-		l.freeList = b.next
-	}
-	l.freeListMu.Unlock()
-	if b == nil {
-		b = new(buffer)
-	} else {
-		b.next = nil
-		b.Reset()
-	}
-	return b
-}
-
-// putBuffer returns a buffer to the free list.
-func (l *loggingT) putBuffer(b *buffer) {
-	if b.Len() >= 256 {
-		// Let big buffers die a natural death.
-		return
-	}
-	l.freeListMu.Lock()
-	b.next = l.freeList
-	l.freeList = b
-	l.freeListMu.Unlock()
-}
-
-var timeNow = time.Now // Stubbed out for testing.
+const (
+	noStack   = stack(false)
+	withStack = stack(true)
+)
 
-/*
-header formats a log header as defined by the C++ implementation.
-It returns a buffer containing the formatted header and the user's file and line number.
-The depth specifies how many stack frames above lives the source line to be identified in the log message.
-
-Log lines have this form:
-	Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
-where the fields are defined as follows:
-	L                A single character, representing the log level (eg 'I' for INFO)
-	mm               The month (zero padded; ie May is '05')
-	dd               The day (zero padded)
-	hh:mm:ss.uuuuuu  Time in hours, minutes and fractional seconds
-	threadid         The space-padded thread ID as returned by GetTID()
-	file             The file name
-	line             The line number
-	msg              The user-supplied message
-*/
-func (l *loggingT) header(s severity, depth int) (*buffer, string, int) {
-	_, file, line, ok := runtime.Caller(3 + depth)
+func appendBacktrace(depth int, format string, args []any) (string, []any) {
+	// Capture a backtrace as a stackdump.Stack (both text and PC slice).
+	// Structured log sinks can extract the backtrace in whichever format they
+	// prefer (PCs or text), and Text sinks will include it as just another part
+	// of the log message.
+	//
+	// Use depth instead of depth+1 so that the backtrace always includes the
+	// log function itself - otherwise the reason for the trace appearing in the
+	// log may not be obvious to the reader.
+	dump := stackdump.Caller(depth)
+
+	// Add an arg and an entry in the format string for the stack dump.
+	//
+	// Copy the "args" slice to avoid a rare but serious aliasing bug
+	// (corrupting the caller's slice if they passed it to a non-Fatal call
+	// using "...").
+	format = format + "\n\n%v\n"
+	args = append(append([]any(nil), args...), dump)
+
+	return format, args
+}
+
+// logf writes a log message for a log function call (or log function wrapper)
+// at the given depth in the current goroutine's stack.
+func logf(depth int, severity logsink.Severity, verbose bool, stack stack, format string, args ...any) {
+	now := timeNow()
+	_, file, line, ok := runtime.Caller(depth + 1)
 	if !ok {
 		file = "???"
 		line = 1
-	} else {
-		slash := strings.LastIndex(file, "/")
-		if slash >= 0 {
-			file = file[slash+1:]
-		}
 	}
-	return l.formatHeader(s, file, line), file, line
-}
 
-// formatHeader formats a log header using the provided file name and line number.
-func (l *loggingT) formatHeader(s severity, file string, line int) *buffer {
-	now := timeNow()
-	if line < 0 {
-		line = 0 // not a real line number, but acceptable to someDigits
+	if stack == withStack || backtraceAt(file, line) {
+		format, args = appendBacktrace(depth+1, format, args)
 	}
-	if s > fatalLog {
-		s = infoLog // for safety.
-	}
-	buf := l.getBuffer()
-
-	// Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand.
-	// It's worth about 3X. Fprintf is hard.
-	_, month, day := now.Date()
-	hour, minute, second := now.Clock()
-	// Lmmdd hh:mm:ss.uuuuuu threadid file:line]
-	buf.tmp[0] = severityChar[s]
-	buf.twoDigits(1, int(month))
-	buf.twoDigits(3, day)
-	buf.tmp[5] = ' '
-	buf.twoDigits(6, hour)
-	buf.tmp[8] = ':'
-	buf.twoDigits(9, minute)
-	buf.tmp[11] = ':'
-	buf.twoDigits(12, second)
-	buf.tmp[14] = '.'
-	buf.nDigits(6, 15, now.Nanosecond()/1000, '0')
-	buf.tmp[21] = ' '
-	buf.nDigits(7, 22, pid, ' ') // TODO: should be TID
-	buf.tmp[29] = ' '
-	buf.Write(buf.tmp[:30])
-	buf.WriteString(file)
-	buf.tmp[0] = ':'
-	n := buf.someDigits(1, line)
-	buf.tmp[n+1] = ']'
-	buf.tmp[n+2] = ' '
-	buf.Write(buf.tmp[:n+3])
-	return buf
-}
-
-// Some custom tiny helper functions to print the log header efficiently.
-
-const digits = "0123456789"
 
-// twoDigits formats a zero-prefixed two-digit integer at buf.tmp[i].
-func (buf *buffer) twoDigits(i, d int) {
-	buf.tmp[i+1] = digits[d%10]
-	d /= 10
-	buf.tmp[i] = digits[d%10]
-}
-
-// nDigits formats an n-digit integer at buf.tmp[i],
-// padding with pad on the left.
-// It assumes d >= 0.
-func (buf *buffer) nDigits(n, i, d int, pad byte) {
-	j := n - 1
-	for ; j >= 0 && d > 0; j-- {
-		buf.tmp[i+j] = digits[d%10]
-		d /= 10
-	}
-	for ; j >= 0; j-- {
-		buf.tmp[i+j] = pad
-	}
-}
-
-// someDigits formats a zero-prefixed variable-width integer at buf.tmp[i].
-func (buf *buffer) someDigits(i, d int) int {
-	// Print into the top, then copy down. We know there's space for at least
-	// a 10-digit number.
-	j := len(buf.tmp)
-	for {
-		j--
-		buf.tmp[j] = digits[d%10]
-		d /= 10
-		if d == 0 {
-			break
-		}
+	metai, meta := metaPoolGet()
+	*meta = logsink.Meta{
+		Time:     now,
+		File:     file,
+		Line:     line,
+		Depth:    depth + 1,
+		Severity: severity,
+		Verbose:  verbose,
+		Thread:   int64(pid),
 	}
-	return copy(buf.tmp[i:], buf.tmp[j:])
+	sinkf(meta, format, args...)
+	metaPool.Put(metai)
 }
 
-func (l *loggingT) println(s severity, args ...interface{}) {
-	buf, file, line := l.header(s, 0)
-	fmt.Fprintln(buf, args...)
-	l.output(s, buf, file, line, false)
-}
-
-func (l *loggingT) print(s severity, args ...interface{}) {
-	l.printDepth(s, 1, args...)
-}
-
-func (l *loggingT) printDepth(s severity, depth int, args ...interface{}) {
-	buf, file, line := l.header(s, depth)
-	fmt.Fprint(buf, args...)
-	if buf.Bytes()[buf.Len()-1] != '\n' {
-		buf.WriteByte('\n')
-	}
-	l.output(s, buf, file, line, false)
-}
-
-func (l *loggingT) printf(s severity, format string, args ...interface{}) {
-	buf, file, line := l.header(s, 0)
-	fmt.Fprintf(buf, format, args...)
-	if buf.Bytes()[buf.Len()-1] != '\n' {
-		buf.WriteByte('\n')
-	}
-	l.output(s, buf, file, line, false)
-}
-
-// printWithFileLine behaves like print but uses the provided file and line number.  If
-// alsoLogToStderr is true, the log message always appears on standard error; it
-// will also appear in the log file unless --logtostderr is set.
-func (l *loggingT) printWithFileLine(s severity, file string, line int, alsoToStderr bool, args ...interface{}) {
-	buf := l.formatHeader(s, file, line)
-	fmt.Fprint(buf, args...)
-	if buf.Bytes()[buf.Len()-1] != '\n' {
-		buf.WriteByte('\n')
-	}
-	l.output(s, buf, file, line, alsoToStderr)
-}
-
-// output writes the data to the log files and releases the buffer.
-func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoToStderr bool) {
-	l.mu.Lock()
-	if l.traceLocation.isSet() {
-		if l.traceLocation.match(file, line) {
-			buf.Write(stacks(false))
-		}
-	}
-	data := buf.Bytes()
-	if !flag.Parsed() {
-		os.Stderr.Write([]byte("ERROR: logging before flag.Parse: "))
-		os.Stderr.Write(data)
-	} else if l.toStderr {
-		os.Stderr.Write(data)
-	} else {
-		if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() {
-			os.Stderr.Write(data)
-		}
-		if l.file[s] == nil {
-			if err := l.createFiles(s); err != nil {
-				os.Stderr.Write(data) // Make sure the message appears somewhere.
-				l.exit(err)
-			}
-		}
-		switch s {
-		case fatalLog:
-			l.file[fatalLog].Write(data)
-			fallthrough
-		case errorLog:
-			l.file[errorLog].Write(data)
-			fallthrough
-		case warningLog:
-			l.file[warningLog].Write(data)
-			fallthrough
-		case infoLog:
-			l.file[infoLog].Write(data)
-		}
-	}
-	if s == fatalLog {
-		// If we got here via Exit rather than Fatal, print no stacks.
-		if atomic.LoadUint32(&fatalNoStacks) > 0 {
-			l.mu.Unlock()
-			timeoutFlush(10 * time.Second)
-			os.Exit(1)
-		}
-		// Dump all goroutine stacks before exiting.
-		// First, make sure we see the trace for the current goroutine on standard error.
-		// If -logtostderr has been specified, the loop below will do that anyway
-		// as the first stack in the full dump.
-		if !l.toStderr {
-			os.Stderr.Write(stacks(false))
-		}
-		// Write the stack trace for all goroutines to the files.
-		trace := stacks(true)
-		logExitFunc = func(error) {} // If we get a write error, we'll still exit below.
-		for log := fatalLog; log >= infoLog; log-- {
-			if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set.
-				f.Write(trace)
-			}
-		}
-		l.mu.Unlock()
-		timeoutFlush(10 * time.Second)
-		os.Exit(255) // C++ uses -1, which is silly because it's anded with 255 anyway.
-	}
-	l.putBuffer(buf)
-	l.mu.Unlock()
-	if stats := severityStats[s]; stats != nil {
+func sinkf(meta *logsink.Meta, format string, args ...any) {
+	meta.Depth++
+	n, err := logsink.Printf(meta, format, args...)
+	if stats := severityStats[meta.Severity]; stats != nil {
 		atomic.AddInt64(&stats.lines, 1)
-		atomic.AddInt64(&stats.bytes, int64(len(data)))
-	}
-}
-
-// timeoutFlush calls Flush and returns when it completes or after timeout
-// elapses, whichever happens first.  This is needed because the hooks invoked
-// by Flush may deadlock when glog.Fatal is called from a hook that holds
-// a lock.
-func timeoutFlush(timeout time.Duration) {
-	done := make(chan bool, 1)
-	go func() {
-		Flush() // calls logging.lockAndFlushAll()
-		done <- true
-	}()
-	select {
-	case <-done:
-	case <-time.After(timeout):
-		fmt.Fprintln(os.Stderr, "glog: Flush took longer than", timeout)
-	}
-}
-
-// stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines.
-func stacks(all bool) []byte {
-	// We don't know how big the traces are, so grow a few times if they don't fit. Start large, though.
-	n := 10000
-	if all {
-		n = 100000
-	}
-	var trace []byte
-	for i := 0; i < 5; i++ {
-		trace = make([]byte, n)
-		nbytes := runtime.Stack(trace, all)
-		if nbytes < len(trace) {
-			return trace[:nbytes]
-		}
-		n *= 2
-	}
-	return trace
-}
-
-// logExitFunc provides a simple mechanism to override the default behavior
-// of exiting on error. Used in testing and to guarantee we reach a required exit
-// for fatal logs. Instead, exit could be a function rather than a method but that
-// would make its use clumsier.
-var logExitFunc func(error)
-
-// exit is called if there is trouble creating or writing log files.
-// It flushes the logs and exits the program; there's no point in hanging around.
-// l.mu is held.
-func (l *loggingT) exit(err error) {
-	fmt.Fprintf(os.Stderr, "log: exiting because of error: %s\n", err)
-	// If logExitFunc is set, we do that instead of exiting.
-	if logExitFunc != nil {
-		logExitFunc(err)
-		return
-	}
-	l.flushAll()
-	os.Exit(2)
-}
-
-// syncBuffer joins a bufio.Writer to its underlying file, providing access to the
-// file's Sync method and providing a wrapper for the Write method that provides log
-// file rotation. There are conflicting methods, so the file cannot be embedded.
-// l.mu is held for all its methods.
-type syncBuffer struct {
-	logger *loggingT
-	*bufio.Writer
-	file   *os.File
-	sev    severity
-	nbytes uint64 // The number of bytes written to this file
-}
-
-func (sb *syncBuffer) Sync() error {
-	return sb.file.Sync()
-}
-
-func (sb *syncBuffer) Write(p []byte) (n int, err error) {
-	if sb.nbytes+uint64(len(p)) >= MaxSize {
-		if err := sb.rotateFile(time.Now()); err != nil {
-			sb.logger.exit(err)
-		}
+		atomic.AddInt64(&stats.bytes, int64(n))
 	}
-	n, err = sb.Writer.Write(p)
-	sb.nbytes += uint64(n)
-	if err != nil {
-		sb.logger.exit(err)
-	}
-	return
-}
 
-// rotateFile closes the syncBuffer's file and starts a new one.
-func (sb *syncBuffer) rotateFile(now time.Time) error {
-	if sb.file != nil {
-		sb.Flush()
-		sb.file.Close()
-	}
-	var err error
-	sb.file, _, err = create(severityName[sb.sev], now)
-	sb.nbytes = 0
 	if err != nil {
-		return err
-	}
-
-	sb.Writer = bufio.NewWriterSize(sb.file, bufferSize)
-
-	// Write header.
-	var buf bytes.Buffer
-	fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05"))
-	fmt.Fprintf(&buf, "Running on machine: %s\n", host)
-	fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH)
-	fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n")
-	n, err := sb.file.Write(buf.Bytes())
-	sb.nbytes += uint64(n)
-	return err
-}
-
-// bufferSize sizes the buffer associated with each log file. It's large
-// so that log records can accumulate without the logging thread blocking
-// on disk I/O. The flushDaemon will block instead.
-const bufferSize = 256 * 1024
-
-// createFiles creates all the log files for severity from sev down to infoLog.
-// l.mu is held.
-func (l *loggingT) createFiles(sev severity) error {
-	now := time.Now()
-	// Files are created in decreasing severity order, so as soon as we find one
-	// has already been created, we can stop.
-	for s := sev; s >= infoLog && l.file[s] == nil; s-- {
-		sb := &syncBuffer{
-			logger: l,
-			sev:    s,
-		}
-		if err := sb.rotateFile(now); err != nil {
-			return err
-		}
-		l.file[s] = sb
-	}
-	return nil
-}
-
-const flushInterval = 30 * time.Second
-
-// flushDaemon periodically flushes the log file buffers.
-func (l *loggingT) flushDaemon() {
-	for range time.NewTicker(flushInterval).C {
-		l.lockAndFlushAll()
-	}
-}
-
-// lockAndFlushAll is like flushAll but locks l.mu first.
-func (l *loggingT) lockAndFlushAll() {
-	l.mu.Lock()
-	l.flushAll()
-	l.mu.Unlock()
-}
-
-// flushAll flushes all the logs and attempts to "sync" their data to disk.
-// l.mu is held.
-func (l *loggingT) flushAll() {
-	// Flush from fatal down, in case there's trouble flushing.
-	for s := fatalLog; s >= infoLog; s-- {
-		file := l.file[s]
-		if file != nil {
-			file.Flush() // ignore error
-			file.Sync()  // ignore error
-		}
+		logsink.Printf(meta, "glog: exiting because of error: %s", err)
+		sinks.file.Flush()
+		os.Exit(2)
 	}
 }
 
@@ -912,9 +234,9 @@ func (l *loggingT) flushAll() {
 // Valid names are "INFO", "WARNING", "ERROR", and "FATAL".  If the name is not
 // recognized, CopyStandardLogTo panics.
 func CopyStandardLogTo(name string) {
-	sev, ok := severityByName(name)
-	if !ok {
-		panic(fmt.Sprintf("log.CopyStandardLogTo(%q): unrecognized severity name", name))
+	sev, err := logsink.ParseSeverity(name)
+	if err != nil {
+		panic(fmt.Sprintf("log.CopyStandardLogTo(%q): %v", name, err))
 	}
 	// Set a log format that captures the user's file and line:
 	//   d.go:23: message
@@ -922,9 +244,22 @@ func CopyStandardLogTo(name string) {
 	stdLog.SetOutput(logBridge(sev))
 }
 
+// NewStandardLogger returns a Logger that writes to the Google logs for the
+// named and lower severities.
+//
+// Valid names are "INFO", "WARNING", "ERROR", and "FATAL". If the name is not
+// recognized, NewStandardLogger panics.
+func NewStandardLogger(name string) *stdLog.Logger {
+	sev, err := logsink.ParseSeverity(name)
+	if err != nil {
+		panic(fmt.Sprintf("log.NewStandardLogger(%q): %v", name, err))
+	}
+	return stdLog.New(logBridge(sev), "", stdLog.Lshortfile)
+}
+
 // logBridge provides the Write method that enables CopyStandardLogTo to connect
 // Go's standard logs to the logs provided by this package.
-type logBridge severity
+type logBridge logsink.Severity
 
 // Write parses the standard logging line and passes its components to the
 // logger for severity(lb).
@@ -946,36 +281,72 @@ func (lb logBridge) Write(b []byte) (n int, err error) {
 			line = 1
 		}
 	}
-	// printWithFileLine with alsoToStderr=true, so standard log messages
-	// always appear on standard error.
-	logging.printWithFileLine(severity(lb), file, line, true, text)
+
+	// The depth below hard-codes details of how stdlog gets here.  The alternative would be to walk
+	// up the stack looking for src/log/log.go but that seems like it would be
+	// unfortunately slow.
+	const stdLogDepth = 4
+
+	metai, meta := metaPoolGet()
+	*meta = logsink.Meta{
+		Time:     timeNow(),
+		File:     file,
+		Line:     line,
+		Depth:    stdLogDepth,
+		Severity: logsink.Severity(lb),
+		Thread:   int64(pid),
+	}
+
+	format := "%s"
+	args := []any{text}
+	if backtraceAt(file, line) {
+		format, args = appendBacktrace(meta.Depth, format, args)
+	}
+
+	sinkf(meta, format, args...)
+	metaPool.Put(metai)
+
 	return len(b), nil
 }
 
-// setV computes and remembers the V level for a given PC
-// when vmodule is enabled.
-// File pattern matching takes the basename of the file, stripped
-// of its .go suffix, and uses filepath.Match, which is a little more
-// general than the *? matching used in C++.
-// l.mu is held.
-func (l *loggingT) setV(pc uintptr) Level {
-	fn := runtime.FuncForPC(pc)
-	file, _ := fn.FileLine(pc)
-	// The file is something like /a/b/c/d.go. We want just the d.
-	if strings.HasSuffix(file, ".go") {
-		file = file[:len(file)-3]
+// defaultFormat returns a fmt.Printf format specifier that formats its
+// arguments as if they were passed to fmt.Print.
+func defaultFormat(args []any) string {
+	n := len(args)
+	switch n {
+	case 0:
+		return ""
+	case 1:
+		return "%v"
+	}
+
+	b := make([]byte, 0, n*3-1)
+	wasString := true // Suppress leading space.
+	for _, arg := range args {
+		isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
+		if wasString || isString {
+			b = append(b, "%v"...)
+		} else {
+			b = append(b, " %v"...)
+		}
+		wasString = isString
 	}
-	if slash := strings.LastIndex(file, "/"); slash >= 0 {
-		file = file[slash+1:]
+	return string(b)
+}
+
+// lnFormat returns a fmt.Printf format specifier that formats its arguments
+// as if they were passed to fmt.Println.
+func lnFormat(args []any) string {
+	if len(args) == 0 {
+		return "\n"
 	}
-	for _, filter := range l.vmodule.filter {
-		if filter.match(file) {
-			l.vmap[pc] = filter.level
-			return filter.level
-		}
+
+	b := make([]byte, 0, len(args)*3)
+	for range args {
+		b = append(b, "%v "...)
 	}
-	l.vmap[pc] = 0
-	return 0
+	b[len(b)-1] = '\n' // Replace the last space with a newline.
+	return string(b)
 }
 
 // Verbose is a boolean type that implements Infof (like Printf) etc.
@@ -986,9 +357,13 @@ type Verbose bool
 // The returned value is a boolean of type Verbose, which implements Info, Infoln
 // and Infof. These methods will write to the Info log if called.
 // Thus, one may write either
+//
 //	if glog.V(2) { glog.Info("log this") }
+//
 // or
+//
 //	glog.V(2).Info("log this")
+//
 // The second form is shorter but the first is cheaper if logging is off because it does
 // not evaluate its arguments.
 //
@@ -997,184 +372,250 @@ type Verbose bool
 // V is at most the value of -v, or of -vmodule for the source file containing the
 // call, the V call will log.
 func V(level Level) Verbose {
-	// This function tries hard to be cheap unless there's work to do.
-	// The fast path is two atomic loads and compares.
+	return VDepth(1, level)
+}
 
-	// Here is a cheap but safe test to see if V logging is enabled globally.
-	if logging.verbosity.get() >= level {
-		return Verbose(true)
-	}
+// VDepth acts as V but uses depth to determine which call frame to check vmodule for.
+// VDepth(0, level) is the same as V(level).
+func VDepth(depth int, level Level) Verbose {
+	return Verbose(verboseEnabled(depth+1, level))
+}
 
-	// It's off globally but it vmodule may still be set.
-	// Here is another cheap but safe test to see if vmodule is enabled.
-	if atomic.LoadInt32(&logging.filterLength) > 0 {
-		// Now we need a proper lock to use the logging structure. The pcs field
-		// is shared so we must lock before accessing it. This is fairly expensive,
-		// but if V logging is enabled we're slow anyway.
-		logging.mu.Lock()
-		defer logging.mu.Unlock()
-		if runtime.Callers(2, logging.pcs[:]) == 0 {
-			return Verbose(false)
-		}
-		v, ok := logging.vmap[logging.pcs[0]]
-		if !ok {
-			v = logging.setV(logging.pcs[0])
-		}
-		return Verbose(v >= level)
+// Info is equivalent to the global Info function, guarded by the value of v.
+// See the documentation of V for usage.
+func (v Verbose) Info(args ...any) {
+	v.InfoDepth(1, args...)
+}
+
+// InfoDepth is equivalent to the global InfoDepth function, guarded by the value of v.
+// See the documentation of V for usage.
+func (v Verbose) InfoDepth(depth int, args ...any) {
+	if v {
+		logf(depth+1, logsink.Info, true, noStack, defaultFormat(args), args...)
 	}
-	return Verbose(false)
 }
 
-// Info is equivalent to the global Info function, guarded by the value of v.
+// InfoDepthf is equivalent to the global InfoDepthf function, guarded by the value of v.
 // See the documentation of V for usage.
-func (v Verbose) Info(args ...interface{}) {
+func (v Verbose) InfoDepthf(depth int, format string, args ...any) {
 	if v {
-		logging.print(infoLog, args...)
+		logf(depth+1, logsink.Info, true, noStack, format, args...)
 	}
 }
 
 // Infoln is equivalent to the global Infoln function, guarded by the value of v.
 // See the documentation of V for usage.
-func (v Verbose) Infoln(args ...interface{}) {
+func (v Verbose) Infoln(args ...any) {
 	if v {
-		logging.println(infoLog, args...)
+		logf(1, logsink.Info, true, noStack, lnFormat(args), args...)
 	}
 }
 
 // Infof is equivalent to the global Infof function, guarded by the value of v.
 // See the documentation of V for usage.
-func (v Verbose) Infof(format string, args ...interface{}) {
+func (v Verbose) Infof(format string, args ...any) {
 	if v {
-		logging.printf(infoLog, format, args...)
+		logf(1, logsink.Info, true, noStack, format, args...)
 	}
 }
 
 // Info logs to the INFO log.
 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
-func Info(args ...interface{}) {
-	logging.print(infoLog, args...)
+func Info(args ...any) {
+	InfoDepth(1, args...)
+}
+
+// InfoDepth calls Info from a different depth in the call stack.
+// This enables a callee to emit logs that use the callsite information of its caller
+// or any other callers in the stack. When depth == 0, the original callee's line
+// information is emitted. When depth > 0, depth frames are skipped in the call stack
+// and the final frame is treated like the original callee to Info.
+func InfoDepth(depth int, args ...any) {
+	logf(depth+1, logsink.Info, false, noStack, defaultFormat(args), args...)
 }
 
-// InfoDepth acts as Info but uses depth to determine which call frame to log.
-// InfoDepth(0, "msg") is the same as Info("msg").
-func InfoDepth(depth int, args ...interface{}) {
-	logging.printDepth(infoLog, depth, args...)
+// InfoDepthf acts as InfoDepth but with format string.
+func InfoDepthf(depth int, format string, args ...any) {
+	logf(depth+1, logsink.Info, false, noStack, format, args...)
 }
 
 // Infoln logs to the INFO log.
 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
-func Infoln(args ...interface{}) {
-	logging.println(infoLog, args...)
+func Infoln(args ...any) {
+	logf(1, logsink.Info, false, noStack, lnFormat(args), args...)
 }
 
 // Infof logs to the INFO log.
 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
-func Infof(format string, args ...interface{}) {
-	logging.printf(infoLog, format, args...)
+func Infof(format string, args ...any) {
+	logf(1, logsink.Info, false, noStack, format, args...)
 }
 
 // Warning logs to the WARNING and INFO logs.
 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
-func Warning(args ...interface{}) {
-	logging.print(warningLog, args...)
+func Warning(args ...any) {
+	WarningDepth(1, args...)
 }
 
 // WarningDepth acts as Warning but uses depth to determine which call frame to log.
 // WarningDepth(0, "msg") is the same as Warning("msg").
-func WarningDepth(depth int, args ...interface{}) {
-	logging.printDepth(warningLog, depth, args...)
+func WarningDepth(depth int, args ...any) {
+	logf(depth+1, logsink.Warning, false, noStack, defaultFormat(args), args...)
+}
+
+// WarningDepthf acts as Warningf but uses depth to determine which call frame to log.
+// WarningDepthf(0, "msg") is the same as Warningf("msg").
+func WarningDepthf(depth int, format string, args ...any) {
+	logf(depth+1, logsink.Warning, false, noStack, format, args...)
 }
 
 // Warningln logs to the WARNING and INFO logs.
 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
-func Warningln(args ...interface{}) {
-	logging.println(warningLog, args...)
+func Warningln(args ...any) {
+	logf(1, logsink.Warning, false, noStack, lnFormat(args), args...)
 }
 
 // Warningf logs to the WARNING and INFO logs.
 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
-func Warningf(format string, args ...interface{}) {
-	logging.printf(warningLog, format, args...)
+func Warningf(format string, args ...any) {
+	logf(1, logsink.Warning, false, noStack, format, args...)
 }
 
 // Error logs to the ERROR, WARNING, and INFO logs.
 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
-func Error(args ...interface{}) {
-	logging.print(errorLog, args...)
+func Error(args ...any) {
+	ErrorDepth(1, args...)
 }
 
 // ErrorDepth acts as Error but uses depth to determine which call frame to log.
 // ErrorDepth(0, "msg") is the same as Error("msg").
-func ErrorDepth(depth int, args ...interface{}) {
-	logging.printDepth(errorLog, depth, args...)
+func ErrorDepth(depth int, args ...any) {
+	logf(depth+1, logsink.Error, false, noStack, defaultFormat(args), args...)
+}
+
+// ErrorDepthf acts as Errorf but uses depth to determine which call frame to log.
+// ErrorDepthf(0, "msg") is the same as Errorf("msg").
+func ErrorDepthf(depth int, format string, args ...any) {
+	logf(depth+1, logsink.Error, false, noStack, format, args...)
 }
 
 // Errorln logs to the ERROR, WARNING, and INFO logs.
 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
-func Errorln(args ...interface{}) {
-	logging.println(errorLog, args...)
+func Errorln(args ...any) {
+	logf(1, logsink.Error, false, noStack, lnFormat(args), args...)
 }
 
 // Errorf logs to the ERROR, WARNING, and INFO logs.
 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
-func Errorf(format string, args ...interface{}) {
-	logging.printf(errorLog, format, args...)
+func Errorf(format string, args ...any) {
+	logf(1, logsink.Error, false, noStack, format, args...)
+}
+
+func fatalf(depth int, format string, args ...any) {
+	logf(depth+1, logsink.Fatal, false, withStack, format, args...)
+	sinks.file.Flush()
+
+	err := abortProcess() // Should not return.
+
+	// Failed to abort the process using signals.  Dump a stack trace and exit.
+	Errorf("abortProcess returned unexpectedly: %v", err)
+	sinks.file.Flush()
+	pprof.Lookup("goroutine").WriteTo(os.Stderr, 1)
+	os.Exit(2) // Exit with the same code as the default SIGABRT handler.
+}
+
+// abortProcess attempts to kill the current process in a way that will dump the
+// currently-running goroutines someplace useful (Coroner or stderr).
+//
+// It does this by sending SIGABRT to the current process. Unfortunately, the
+// signal may or may not be delivered to the current thread; in order to do that
+// portably, we would need to add a cgo dependency and call pthread_kill.
+//
+// If successful, abortProcess does not return.
+func abortProcess() error {
+	p, err := os.FindProcess(os.Getpid())
+	if err != nil {
+		return err
+	}
+	if err := p.Signal(syscall.SIGABRT); err != nil {
+		return err
+	}
+
+	// Sent the signal.  Now we wait for it to arrive and any SIGABRT handlers to
+	// run (and eventually terminate the process themselves).
+	//
+	// We could just "select{}" here, but there's an outside chance that would
+	// trigger the runtime's deadlock detector if there happen not to be any
+	// background goroutines running.  So we'll sleep a while first to give
+	// the signal some time.
+	time.Sleep(10 * time.Second)
+	select {}
 }
 
 // Fatal logs to the FATAL, ERROR, WARNING, and INFO logs,
-// including a stack trace of all running goroutines, then calls os.Exit(255).
+// including a stack trace of all running goroutines, then calls os.Exit(2).
 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
-func Fatal(args ...interface{}) {
-	logging.print(fatalLog, args...)
+func Fatal(args ...any) {
+	FatalDepth(1, args...)
 }
 
 // FatalDepth acts as Fatal but uses depth to determine which call frame to log.
 // FatalDepth(0, "msg") is the same as Fatal("msg").
-func FatalDepth(depth int, args ...interface{}) {
-	logging.printDepth(fatalLog, depth, args...)
+func FatalDepth(depth int, args ...any) {
+	fatalf(depth+1, defaultFormat(args), args...)
+}
+
+// FatalDepthf acts as Fatalf but uses depth to determine which call frame to log.
+// FatalDepthf(0, "msg") is the same as Fatalf("msg").
+func FatalDepthf(depth int, format string, args ...any) {
+	fatalf(depth+1, format, args...)
 }
 
 // Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs,
-// including a stack trace of all running goroutines, then calls os.Exit(255).
+// including a stack trace of all running goroutines, then calls os.Exit(2).
 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
-func Fatalln(args ...interface{}) {
-	logging.println(fatalLog, args...)
+func Fatalln(args ...any) {
+	fatalf(1, lnFormat(args), args...)
 }
 
 // Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs,
-// including a stack trace of all running goroutines, then calls os.Exit(255).
+// including a stack trace of all running goroutines, then calls os.Exit(2).
 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
-func Fatalf(format string, args ...interface{}) {
-	logging.printf(fatalLog, format, args...)
+func Fatalf(format string, args ...any) {
+	fatalf(1, format, args...)
 }
 
-// fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks.
-// It allows Exit and relatives to use the Fatal logs.
-var fatalNoStacks uint32
+func exitf(depth int, format string, args ...any) {
+	logf(depth+1, logsink.Fatal, false, noStack, format, args...)
+	sinks.file.Flush()
+	os.Exit(1)
+}
 
 // Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
-func Exit(args ...interface{}) {
-	atomic.StoreUint32(&fatalNoStacks, 1)
-	logging.print(fatalLog, args...)
+func Exit(args ...any) {
+	ExitDepth(1, args...)
 }
 
 // ExitDepth acts as Exit but uses depth to determine which call frame to log.
 // ExitDepth(0, "msg") is the same as Exit("msg").
-func ExitDepth(depth int, args ...interface{}) {
-	atomic.StoreUint32(&fatalNoStacks, 1)
-	logging.printDepth(fatalLog, depth, args...)
+func ExitDepth(depth int, args ...any) {
+	exitf(depth+1, defaultFormat(args), args...)
+}
+
+// ExitDepthf acts as Exitf but uses depth to determine which call frame to log.
+// ExitDepthf(0, "msg") is the same as Exitf("msg").
+func ExitDepthf(depth int, format string, args ...any) {
+	exitf(depth+1, format, args...)
 }
 
 // Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
-func Exitln(args ...interface{}) {
-	atomic.StoreUint32(&fatalNoStacks, 1)
-	logging.println(fatalLog, args...)
+func Exitln(args ...any) {
+	exitf(1, lnFormat(args), args...)
 }
 
 // Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
-func Exitf(format string, args ...interface{}) {
-	atomic.StoreUint32(&fatalNoStacks, 1)
-	logging.printf(fatalLog, format, args...)
+func Exitf(format string, args ...any) {
+	exitf(1, format, args...)
 }
diff --git a/vendor/github.com/golang/glog/glog_file.go b/vendor/github.com/golang/glog/glog_file.go
index 65075d281..af1c934b8 100644
--- a/vendor/github.com/golang/glog/glog_file.go
+++ b/vendor/github.com/golang/glog/glog_file.go
@@ -1,6 +1,6 @@
-// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
+// Go support for leveled logs, analogous to https://github.com/google/glog.
 //
-// Copyright 2013 Google Inc. All Rights Reserved.
+// Copyright 2023 Google Inc. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -19,26 +19,34 @@
 package glog
 
 import (
+	"bufio"
+	"bytes"
 	"errors"
 	"flag"
 	"fmt"
+	"io"
 	"os"
 	"os/user"
 	"path/filepath"
+	"runtime"
 	"strings"
 	"sync"
 	"time"
-)
 
-// MaxSize is the maximum size of a log file in bytes.
-var MaxSize uint64 = 1024 * 1024 * 1800
+	"github.com/golang/glog/internal/logsink"
+)
 
 // logDirs lists the candidate directories for new log files.
 var logDirs []string
 
-// If non-empty, overrides the choice of directory in which to write logs.
-// See createLogDirs for the full list of possible destinations.
-var logDir = flag.String("log_dir", "", "If non-empty, write log files in this directory")
+var (
+	// If non-empty, overrides the choice of directory in which to write logs.
+	// See createLogDirs for the full list of possible destinations.
+	logDir      = flag.String("log_dir", "", "If non-empty, write log files in this directory")
+	logLink     = flag.String("log_link", "", "If non-empty, add symbolic links in this directory to the log files")
+	logBufLevel = flag.Int("logbuflevel", int(logsink.Info), "Buffer log messages logged at this level or lower"+
+		" (-1 means don't buffer; 0 means buffer INFO only; ...). Has limited applicability on non-prod platforms.")
+)
 
 func createLogDirs() {
 	if *logDir != "" {
@@ -64,9 +72,17 @@ func init() {
 	if err == nil {
 		userName = current.Username
 	}
-
-	// Sanitize userName since it may contain filepath separators on Windows.
-	userName = strings.Replace(userName, `\`, "_", -1)
+	// Sanitize userName since it is used to construct file paths.
+	userName = strings.Map(func(r rune) rune {
+		switch {
+		case r >= 'a' && r <= 'z':
+		case r >= 'A' && r <= 'Z':
+		case r >= '0' && r <= '9':
+		default:
+			return '_'
+		}
+		return r
+	}, userName)
 }
 
 // shortHostname returns its argument, truncating at the first period.
@@ -122,3 +138,270 @@ func create(tag string, t time.Time) (f *os.File, filename string, err error) {
 	}
 	return nil, "", fmt.Errorf("log: cannot create log: %v", lastErr)
 }
+
+// flushSyncWriter is the interface satisfied by logging destinations.
+type flushSyncWriter interface {
+	Flush() error
+	Sync() error
+	io.Writer
+	filenames() []string
+}
+
+var sinks struct {
+	stderr stderrSink
+	file   fileSink
+}
+
+func init() {
+	sinks.stderr.w = os.Stderr
+
+	// Register stderr first: that way if we crash during file-writing at least
+	// the log will have gone somewhere.
+	logsink.TextSinks = append(logsink.TextSinks, &sinks.stderr, &sinks.file)
+
+	sinks.file.flushChan = make(chan logsink.Severity, 1)
+	go sinks.file.flushDaemon()
+}
+
+// stderrSink is a logsink.Text that writes log entries to stderr
+// if they meet certain conditions.
+type stderrSink struct {
+	mu sync.Mutex
+	w  io.Writer
+}
+
+// Enabled implements logsink.Text.Enabled.  It returns true if any of the
+// various stderr flags are enabled for logs of the given severity, if the log
+// message is from the standard "log" package, or if google.Init has not yet run
+// (and hence file logging is not yet initialized).
+func (s *stderrSink) Enabled(m *logsink.Meta) bool {
+	return toStderr || alsoToStderr || m.Severity >= stderrThreshold.get()
+}
+
+// Emit implements logsink.Text.Emit.
+func (s *stderrSink) Emit(m *logsink.Meta, data []byte) (n int, err error) {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	dn, err := s.w.Write(data)
+	n += dn
+	return n, err
+}
+
+// severityWriters is an array of flushSyncWriter with a value for each
+// logsink.Severity.
+type severityWriters [4]flushSyncWriter
+
+// fileSink is a logsink.Text that prints to a set of Google log files.
+type fileSink struct {
+	mu sync.Mutex
+	// file holds writer for each of the log types.
+	file      severityWriters
+	flushChan chan logsink.Severity
+}
+
+// Enabled implements logsink.Text.Enabled.  It returns true if google.Init
+// has run and both --disable_log_to_disk and --logtostderr are false.
+func (s *fileSink) Enabled(m *logsink.Meta) bool {
+	return !toStderr
+}
+
+// Emit implements logsink.Text.Emit
+func (s *fileSink) Emit(m *logsink.Meta, data []byte) (n int, err error) {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	if err = s.createMissingFiles(m.Severity); err != nil {
+		return 0, err
+	}
+	for sev := m.Severity; sev >= logsink.Info; sev-- {
+		if _, fErr := s.file[sev].Write(data); fErr != nil && err == nil {
+			err = fErr // Take the first error.
+		}
+	}
+	n = len(data)
+	if int(m.Severity) > *logBufLevel {
+		select {
+		case s.flushChan <- m.Severity:
+		default:
+		}
+	}
+
+	return n, err
+}
+
+// syncBuffer joins a bufio.Writer to its underlying file, providing access to the
+// file's Sync method and providing a wrapper for the Write method that provides log
+// file rotation. There are conflicting methods, so the file cannot be embedded.
+// s.mu is held for all its methods.
+type syncBuffer struct {
+	sink *fileSink
+	*bufio.Writer
+	file   *os.File
+	names  []string
+	sev    logsink.Severity
+	nbytes uint64 // The number of bytes written to this file
+}
+
+func (sb *syncBuffer) Sync() error {
+	return sb.file.Sync()
+}
+
+func (sb *syncBuffer) Write(p []byte) (n int, err error) {
+	if sb.nbytes+uint64(len(p)) >= MaxSize {
+		if err := sb.rotateFile(time.Now()); err != nil {
+			return 0, err
+		}
+	}
+	n, err = sb.Writer.Write(p)
+	sb.nbytes += uint64(n)
+	return n, err
+}
+
+func (sb *syncBuffer) filenames() []string {
+	return sb.names
+}
+
+const footer = "\nCONTINUED IN NEXT FILE\n"
+
+// rotateFile closes the syncBuffer's file and starts a new one.
+func (sb *syncBuffer) rotateFile(now time.Time) error {
+	var err error
+	pn := "<none>"
+	file, name, err := create(sb.sev.String(), now)
+
+	if sb.file != nil {
+		// The current log file becomes the previous log at the end of
+		// this block, so save its name for use in the header of the next
+		// file.
+		pn = sb.file.Name()
+		sb.Flush()
+		// If there's an existing file, write a footer with the name of
+		// the next file in the chain, followed by the constant string
+		// \nCONTINUED IN NEXT FILE\n to make continuation detection simple.
+		sb.file.Write([]byte("Next log: "))
+		sb.file.Write([]byte(name))
+		sb.file.Write([]byte(footer))
+		sb.file.Close()
+	}
+
+	sb.file = file
+	sb.names = append(sb.names, name)
+	sb.nbytes = 0
+	if err != nil {
+		return err
+	}
+
+	sb.Writer = bufio.NewWriterSize(sb.file, bufferSize)
+
+	// Write header.
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05"))
+	fmt.Fprintf(&buf, "Running on machine: %s\n", host)
+	fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH)
+	fmt.Fprintf(&buf, "Previous log: %s\n", pn)
+	fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n")
+	n, err := sb.file.Write(buf.Bytes())
+	sb.nbytes += uint64(n)
+	return err
+}
+
+// bufferSize sizes the buffer associated with each log file. It's large
+// so that log records can accumulate without the logging thread blocking
+// on disk I/O. The flushDaemon will block instead.
+const bufferSize = 256 * 1024
+
+// createMissingFiles creates all the log files for severity from infoLog up to
+// upTo that have not already been created.
+// s.mu is held.
+func (s *fileSink) createMissingFiles(upTo logsink.Severity) error {
+	if s.file[upTo] != nil {
+		return nil
+	}
+	now := time.Now()
+	// Files are created in increasing severity order, so we can be assured that
+	// if a high severity logfile exists, then so do all of lower severity.
+	for sev := logsink.Info; sev <= upTo; sev++ {
+		if s.file[sev] != nil {
+			continue
+		}
+		sb := &syncBuffer{
+			sink: s,
+			sev:  sev,
+		}
+		if err := sb.rotateFile(now); err != nil {
+			return err
+		}
+		s.file[sev] = sb
+	}
+	return nil
+}
+
+// flushDaemon periodically flushes the log file buffers.
+func (s *fileSink) flushDaemon() {
+	tick := time.NewTicker(30 * time.Second)
+	defer tick.Stop()
+	for {
+		select {
+		case <-tick.C:
+			s.Flush()
+		case sev := <-s.flushChan:
+			s.flush(sev)
+		}
+	}
+}
+
+// Flush flushes all pending log I/O.
+func Flush() {
+	sinks.file.Flush()
+}
+
+// Flush flushes all the logs and attempts to "sync" their data to disk.
+func (s *fileSink) Flush() error {
+	return s.flush(logsink.Info)
+}
+
+// flush flushes all logs of severity threshold or greater.
+func (s *fileSink) flush(threshold logsink.Severity) error {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	var firstErr error
+	updateErr := func(err error) {
+		if err != nil && firstErr == nil {
+			firstErr = err
+		}
+	}
+
+	// Flush from fatal down, in case there's trouble flushing.
+	for sev := logsink.Fatal; sev >= threshold; sev-- {
+		file := s.file[sev]
+		if file != nil {
+			updateErr(file.Flush())
+			updateErr(file.Sync())
+		}
+	}
+
+	return firstErr
+}
+
+// Names returns the names of the log files holding the FATAL, ERROR,
+// WARNING, or INFO logs. Returns ErrNoLog if the log for the given
+// level doesn't exist (e.g. because no messages of that level have been
+// written). This may return multiple names if the log type requested
+// has rolled over.
+func Names(s string) ([]string, error) {
+	severity, err := logsink.ParseSeverity(s)
+	if err != nil {
+		return nil, err
+	}
+
+	sinks.file.mu.Lock()
+	defer sinks.file.mu.Unlock()
+	f := sinks.file.file[severity]
+	if f == nil {
+		return nil, ErrNoLog
+	}
+
+	return f.filenames(), nil
+}
diff --git a/vendor/github.com/golang/glog/glog_flags.go b/vendor/github.com/golang/glog/glog_flags.go
new file mode 100644
index 000000000..3060e54d9
--- /dev/null
+++ b/vendor/github.com/golang/glog/glog_flags.go
@@ -0,0 +1,395 @@
+// Go support for leveled logs, analogous to https://github.com/google/glog.
+//
+// Copyright 2023 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package glog
+
+import (
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"strings"
+	"sync"
+	"sync/atomic"
+
+	"github.com/golang/glog/internal/logsink"
+)
+
+// modulePat contains a filter for the -vmodule flag.
+// It holds a verbosity level and a file pattern to match.
+type modulePat struct {
+	pattern string
+	literal bool // The pattern is a literal string
+	full    bool // The pattern wants to match the full path
+	level   Level
+}
+
+// match reports whether the file matches the pattern. It uses a string
+// comparison if the pattern contains no metacharacters.
+func (m *modulePat) match(full, file string) bool {
+	if m.literal {
+		if m.full {
+			return full == m.pattern
+		}
+		return file == m.pattern
+	}
+	if m.full {
+		match, _ := filepath.Match(m.pattern, full)
+		return match
+	}
+	match, _ := filepath.Match(m.pattern, file)
+	return match
+}
+
+// isLiteral reports whether the pattern is a literal string, that is, has no metacharacters
+// that require filepath.Match to be called to match the pattern.
+func isLiteral(pattern string) bool {
+	return !strings.ContainsAny(pattern, `\*?[]`)
+}
+
+// isFull reports whether the pattern matches the full file path, that is,
+// whether it contains /.
+func isFull(pattern string) bool {
+	return strings.ContainsRune(pattern, '/')
+}
+
+// verboseFlags represents the setting of the -v and -vmodule flags.
+type verboseFlags struct {
+	// moduleLevelCache is a sync.Map storing the -vmodule Level for each V()
+	// call site, identified by PC. If there is no matching -vmodule filter,
+	// the cached value is exactly v. moduleLevelCache is replaced with a new
+	// Map whenever the -vmodule or -v flag changes state.
+	moduleLevelCache atomic.Value
+
+	// mu guards all fields below.
+	mu sync.Mutex
+
+	// v stores the value of the -v flag.  It may be read safely using
+	// sync.LoadInt32, but is only modified under mu.
+	v Level
+
+	// module stores the parsed -vmodule flag.
+	module []modulePat
+
+	// moduleLength caches len(module).  If greater than zero, it
+	// means vmodule is enabled. It may be read safely using sync.LoadInt32, but
+	// is only modified under mu.
+	moduleLength int32
+}
+
+// NOTE: For compatibility with the open-sourced v1 version of this
+// package (github.com/golang/glog) we need to retain that flag.Level
+// implements the flag.Value interface. See also go/log-vs-glog.
+
+// String is part of the flag.Value interface.
+func (l *Level) String() string {
+	return strconv.FormatInt(int64(l.Get().(Level)), 10)
+}
+
+// Get is part of the flag.Value interface.
+func (l *Level) Get() any {
+	if l == &vflags.v {
+		// l is the value registered for the -v flag.
+		return Level(atomic.LoadInt32((*int32)(l)))
+	}
+	return *l
+}
+
+// Set is part of the flag.Value interface.
+func (l *Level) Set(value string) error {
+	v, err := strconv.Atoi(value)
+	if err != nil {
+		return err
+	}
+	if l == &vflags.v {
+		// l is the value registered for the -v flag.
+		vflags.mu.Lock()
+		defer vflags.mu.Unlock()
+		vflags.moduleLevelCache.Store(&sync.Map{})
+		atomic.StoreInt32((*int32)(l), int32(v))
+		return nil
+	}
+	*l = Level(v)
+	return nil
+}
+
+// vModuleFlag is the flag.Value for the --vmodule flag.
+type vModuleFlag struct{ *verboseFlags }
+
+func (f vModuleFlag) String() string {
+	f.mu.Lock()
+	defer f.mu.Unlock()
+
+	var b bytes.Buffer
+	for i, f := range f.module {
+		if i > 0 {
+			b.WriteRune(',')
+		}
+		fmt.Fprintf(&b, "%s=%d", f.pattern, f.level)
+	}
+	return b.String()
+}
+
+// Get returns nil for this flag type since the struct is not exported.
+func (f vModuleFlag) Get() any { return nil }
+
+var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N")
+
+// Syntax: -vmodule=recordio=2,foo/bar/baz=1,gfs*=3
+func (f vModuleFlag) Set(value string) error {
+	var filter []modulePat
+	for _, pat := range strings.Split(value, ",") {
+		if len(pat) == 0 {
+			// Empty strings such as from a trailing comma can be ignored.
+			continue
+		}
+		patLev := strings.Split(pat, "=")
+		if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 {
+			return errVmoduleSyntax
+		}
+		pattern := patLev[0]
+		v, err := strconv.Atoi(patLev[1])
+		if err != nil {
+			return errors.New("syntax error: expect comma-separated list of filename=N")
+		}
+		// TODO: check syntax of filter?
+		filter = append(filter, modulePat{pattern, isLiteral(pattern), isFull(pattern), Level(v)})
+	}
+
+	f.mu.Lock()
+	defer f.mu.Unlock()
+	f.module = filter
+	atomic.StoreInt32((*int32)(&f.moduleLength), int32(len(f.module)))
+	f.moduleLevelCache.Store(&sync.Map{})
+	return nil
+}
+
+func (f *verboseFlags) levelForPC(pc uintptr) Level {
+	if level, ok := f.moduleLevelCache.Load().(*sync.Map).Load(pc); ok {
+		return level.(Level)
+	}
+
+	f.mu.Lock()
+	defer f.mu.Unlock()
+	level := Level(f.v)
+	fn := runtime.FuncForPC(pc)
+	file, _ := fn.FileLine(pc)
+	// The file is something like /a/b/c/d.go. We want just the d for
+	// regular matches, /a/b/c/d for full matches.
+	if strings.HasSuffix(file, ".go") {
+		file = file[:len(file)-3]
+	}
+	full := file
+	if slash := strings.LastIndex(file, "/"); slash >= 0 {
+		file = file[slash+1:]
+	}
+	for _, filter := range f.module {
+		if filter.match(full, file) {
+			level = filter.level
+			break // Use the first matching level.
+		}
+	}
+	f.moduleLevelCache.Load().(*sync.Map).Store(pc, level)
+	return level
+}
+
+func (f *verboseFlags) enabled(callerDepth int, level Level) bool {
+	if atomic.LoadInt32(&f.moduleLength) == 0 {
+		// No vmodule values specified, so compare against v level.
+		return Level(atomic.LoadInt32((*int32)(&f.v))) >= level
+	}
+
+	pcs := [1]uintptr{}
+	if runtime.Callers(callerDepth+2, pcs[:]) < 1 {
+		return false
+	}
+	frame, _ := runtime.CallersFrames(pcs[:]).Next()
+	return f.levelForPC(frame.Entry) >= level
+}
+
+// traceLocation represents an entry in the -log_backtrace_at flag.
+type traceLocation struct {
+	file string
+	line int
+}
+
+var errTraceSyntax = errors.New("syntax error: expect file.go:234")
+
+func parseTraceLocation(value string) (traceLocation, error) {
+	fields := strings.Split(value, ":")
+	if len(fields) != 2 {
+		return traceLocation{}, errTraceSyntax
+	}
+	file, lineStr := fields[0], fields[1]
+	if !strings.Contains(file, ".") {
+		return traceLocation{}, errTraceSyntax
+	}
+	line, err := strconv.Atoi(lineStr)
+	if err != nil {
+		return traceLocation{}, errTraceSyntax
+	}
+	if line < 0 {
+		return traceLocation{}, errors.New("negative value for line")
+	}
+	return traceLocation{file, line}, nil
+}
+
+// match reports whether the specified file and line matches the trace location.
+// The argument file name is the full path, not the basename specified in the flag.
+func (t traceLocation) match(file string, line int) bool {
+	if t.line != line {
+		return false
+	}
+	if i := strings.LastIndex(file, "/"); i >= 0 {
+		file = file[i+1:]
+	}
+	return t.file == file
+}
+
+func (t traceLocation) String() string {
+	return fmt.Sprintf("%s:%d", t.file, t.line)
+}
+
+// traceLocations represents the -log_backtrace_at flag.
+// Syntax: -log_backtrace_at=recordio.go:234,sstable.go:456
+// Note that unlike vmodule the file extension is included here.
+type traceLocations struct {
+	mu      sync.Mutex
+	locsLen int32 // Safe for atomic read without mu.
+	locs    []traceLocation
+}
+
+func (t *traceLocations) String() string {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+
+	var buf bytes.Buffer
+	for i, tl := range t.locs {
+		if i > 0 {
+			buf.WriteString(",")
+		}
+		buf.WriteString(tl.String())
+	}
+	return buf.String()
+}
+
+// Get always returns nil for this flag type since the struct is not exported
+func (t *traceLocations) Get() any { return nil }
+
+func (t *traceLocations) Set(value string) error {
+	var locs []traceLocation
+	for _, s := range strings.Split(value, ",") {
+		if s == "" {
+			continue
+		}
+		loc, err := parseTraceLocation(s)
+		if err != nil {
+			return err
+		}
+		locs = append(locs, loc)
+	}
+
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	atomic.StoreInt32(&t.locsLen, int32(len(locs)))
+	t.locs = locs
+	return nil
+}
+
+func (t *traceLocations) match(file string, line int) bool {
+	if atomic.LoadInt32(&t.locsLen) == 0 {
+		return false
+	}
+
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	for _, tl := range t.locs {
+		if tl.match(file, line) {
+			return true
+		}
+	}
+	return false
+}
+
+// severityFlag is an atomic flag.Value implementation for logsink.Severity.
+type severityFlag int32
+
+func (s *severityFlag) get() logsink.Severity {
+	return logsink.Severity(atomic.LoadInt32((*int32)(s)))
+}
+func (s *severityFlag) String() string { return strconv.FormatInt(int64(*s), 10) }
+func (s *severityFlag) Get() any       { return s.get() }
+func (s *severityFlag) Set(value string) error {
+	threshold, err := logsink.ParseSeverity(value)
+	if err != nil {
+		// Not a severity name.  Try a raw number.
+		v, err := strconv.Atoi(value)
+		if err != nil {
+			return err
+		}
+		threshold = logsink.Severity(v)
+		if threshold < logsink.Info || threshold > logsink.Fatal {
+			return fmt.Errorf("Severity %d out of range (min %d, max %d).", v, logsink.Info, logsink.Fatal)
+		}
+	}
+	atomic.StoreInt32((*int32)(s), int32(threshold))
+	return nil
+}
+
+var (
+	vflags verboseFlags // The -v and -vmodule flags.
+
+	logBacktraceAt traceLocations // The -log_backtrace_at flag.
+
+	// Boolean flags. Not handled atomically because the flag.Value interface
+	// does not let us avoid the =true, and that shorthand is necessary for
+	// compatibility. TODO: does this matter enough to fix? Seems unlikely.
+	toStderr     bool // The -logtostderr flag.
+	alsoToStderr bool // The -alsologtostderr flag.
+
+	stderrThreshold severityFlag // The -stderrthreshold flag.
+)
+
+// verboseEnabled returns whether the caller at the given depth should emit
+// verbose logs at the given level, with depth 0 identifying the caller of
+// verboseEnabled.
+func verboseEnabled(callerDepth int, level Level) bool {
+	return vflags.enabled(callerDepth+1, level)
+}
+
+// backtraceAt returns whether the logging call at the given function and line
+// should also emit a backtrace of the current call stack.
+func backtraceAt(file string, line int) bool {
+	return logBacktraceAt.match(file, line)
+}
+
+func init() {
+	vflags.moduleLevelCache.Store(&sync.Map{})
+
+	flag.Var(&vflags.v, "v", "log level for V logs")
+	flag.Var(vModuleFlag{&vflags}, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging")
+
+	flag.Var(&logBacktraceAt, "log_backtrace_at", "when logging hits line file:N, emit a stack trace")
+
+	stderrThreshold = severityFlag(logsink.Error)
+
+	flag.BoolVar(&toStderr, "logtostderr", false, "log to standard error instead of files")
+	flag.BoolVar(&alsoToStderr, "alsologtostderr", false, "log to standard error as well as files")
+	flag.Var(&stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr")
+}
diff --git a/vendor/github.com/golang/glog/internal/logsink/logsink.go b/vendor/github.com/golang/glog/internal/logsink/logsink.go
new file mode 100644
index 000000000..53758e1c9
--- /dev/null
+++ b/vendor/github.com/golang/glog/internal/logsink/logsink.go
@@ -0,0 +1,387 @@
+// Copyright 2023 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package logsink
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+
+	"github.com/golang/glog/internal/stackdump"
+)
+
+// MaxLogMessageLen is the limit on length of a formatted log message, including
+// the standard line prefix and trailing newline.
+//
+// Chosen to match C++ glog.
+const MaxLogMessageLen = 15000
+
+// A Severity is a severity at which a message can be logged.
+type Severity int8
+
+// These constants identify the log levels in order of increasing severity.
+// A message written to a high-severity log file is also written to each
+// lower-severity log file.
+const (
+	Info Severity = iota
+	Warning
+	Error
+
+	// Fatal contains logs written immediately before the process terminates.
+	//
+	// Sink implementations should not terminate the process themselves: the log
+	// package will perform any necessary cleanup and terminate the process as
+	// appropriate.
+	Fatal
+)
+
+func (s Severity) String() string {
+	switch s {
+	case Info:
+		return "INFO"
+	case Warning:
+		return "WARNING"
+	case Error:
+		return "ERROR"
+	case Fatal:
+		return "FATAL"
+	}
+	return fmt.Sprintf("%T(%d)", s, s)
+}
+
+// ParseSeverity returns the case-insensitive Severity value for the given string.
+func ParseSeverity(name string) (Severity, error) {
+	name = strings.ToUpper(name)
+	for s := Info; s <= Fatal; s++ {
+		if s.String() == name {
+			return s, nil
+		}
+	}
+	return -1, fmt.Errorf("logsink: invalid severity %q", name)
+}
+
+// Meta is metadata about a logging call.
+type Meta struct {
+	// Time is the time at which the log call was made.
+	Time time.Time
+
+	// File is the source file from which the log entry originates.
+	File string
+	// Line is the line offset within the source file.
+	Line int
+	// Depth is the number of stack frames between the logsink and the log call.
+	Depth int
+
+	Severity Severity
+
+	// Verbose indicates whether the call was made via "log.V".  Log entries below
+	// the current verbosity threshold are not sent to the sink.
+	Verbose bool
+
+	// Thread ID. This can be populated with a thread ID from another source,
+	// such as a system we are importing logs from. In the normal case, this
+	// will be set to the process ID (PID), since Go doesn't have threads.
+	Thread int64
+
+	// Stack trace starting in the logging function. May be nil.
+	// A logsink should implement the StackWanter interface to request this.
+	//
+	// Even if WantStack returns false, this field may be set (e.g. if another
+	// sink wants a stack trace).
+	Stack *stackdump.Stack
+}
+
+// Structured is a logging destination that accepts structured data as input.
+type Structured interface {
+	// Printf formats according to a fmt.Printf format specifier and writes a log
+	// entry.  The precise result of formatting depends on the sink, but should
+	// aim for consistency with fmt.Printf.
+	//
+	// Printf returns the number of bytes occupied by the log entry, which
+	// may not be equal to the total number of bytes written.
+	//
+	// Printf returns any error encountered *if* it is severe enough that the log
+	// package should terminate the process.
+	//
+	// The sink must not modify the *Meta parameter, nor reference it after
+	// Printf has returned: it may be reused in subsequent calls.
+	Printf(meta *Meta, format string, a ...any) (n int, err error)
+}
+
+// StackWanter can be implemented by a logsink.Structured to indicate that it
+// wants a stack trace to accompany at least some of the log messages it receives.
+type StackWanter interface {
+	// WantStack returns true if the sink requires a stack trace for a log message
+	// with this metadata.
+	//
+	// NOTE: Returning true implies that meta.Stack will be non-nil. Returning
+	// false does NOT imply that meta.Stack will be nil.
+	WantStack(meta *Meta) bool
+}
+
+// Text is a logging destination that accepts pre-formatted log lines (instead of
+// structured data).
+type Text interface {
+	// Enabled returns whether this sink should output messages for the given
+	// Meta.  If the sink returns false for a given Meta, the Printf function will
+	// not call Emit on it for the corresponding log message.
+	Enabled(*Meta) bool
+
+	// Emit writes a pre-formatted text log entry (including any applicable
+	// header) to the log.  It returns the number of bytes occupied by the entry
+	// (which may differ from the length of the passed-in slice).
+	//
+	// Emit returns any error encountered *if* it is severe enough that the log
+	// package should terminate the process.
+	//
+	// The sink must not modify the *Meta parameter, nor reference it after
+	// Printf has returned: it may be reused in subsequent calls.
+	//
+	// NOTE: When developing a text sink, keep in mind the surface in which the
+	// logs will be displayed, and whether it's important that the sink be
+	// resistent to tampering in the style of b/211428300. Standard text sinks
+	// (like `stderrSink`) do not protect against this (e.g. by escaping
+	// characters) because the cases where they would show user-influenced bytes
+	// are vanishingly small.
+	Emit(*Meta, []byte) (n int, err error)
+}
+
+// bufs is a pool of *bytes.Buffer used in formatting log entries.
+var bufs sync.Pool // Pool of *bytes.Buffer.
+
+// textPrintf formats a text log entry and emits it to all specified Text sinks.
+//
+// The returned n is the maximum across all Emit calls.
+// The returned err is the first non-nil error encountered.
+// Sinks that are disabled by configuration should return (0, nil).
+func textPrintf(m *Meta, textSinks []Text, format string, args ...any) (n int, err error) {
+	// We expect at most file, stderr, and perhaps syslog.  If there are more,
+	// we'll end up allocating - no big deal.
+	const maxExpectedTextSinks = 3
+	var noAllocSinks [maxExpectedTextSinks]Text
+
+	sinks := noAllocSinks[:0]
+	for _, s := range textSinks {
+		if s.Enabled(m) {
+			sinks = append(sinks, s)
+		}
+	}
+	if len(sinks) == 0 && m.Severity != Fatal {
+		return 0, nil // No TextSinks specified; don't bother formatting.
+	}
+
+	bufi := bufs.Get()
+	var buf *bytes.Buffer
+	if bufi == nil {
+		buf = bytes.NewBuffer(nil)
+		bufi = buf
+	} else {
+		buf = bufi.(*bytes.Buffer)
+		buf.Reset()
+	}
+
+	// Lmmdd hh:mm:ss.uuuuuu PID/GID file:line]
+	//
+	// The "PID" entry arguably ought to be TID for consistency with other
+	// environments, but TID is not meaningful in a Go program due to the
+	// multiplexing of goroutines across threads.
+	//
+	// Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand.
+	// It's worth about 3X. Fprintf is hard.
+	const severityChar = "IWEF"
+	buf.WriteByte(severityChar[m.Severity])
+
+	_, month, day := m.Time.Date()
+	hour, minute, second := m.Time.Clock()
+	twoDigits(buf, int(month))
+	twoDigits(buf, day)
+	buf.WriteByte(' ')
+	twoDigits(buf, hour)
+	buf.WriteByte(':')
+	twoDigits(buf, minute)
+	buf.WriteByte(':')
+	twoDigits(buf, second)
+	buf.WriteByte('.')
+	nDigits(buf, 6, uint64(m.Time.Nanosecond()/1000), '0')
+	buf.WriteByte(' ')
+
+	nDigits(buf, 7, uint64(m.Thread), ' ')
+	buf.WriteByte(' ')
+
+	{
+		file := m.File
+		if i := strings.LastIndex(file, "/"); i >= 0 {
+			file = file[i+1:]
+		}
+		buf.WriteString(file)
+	}
+
+	buf.WriteByte(':')
+	{
+		var tmp [19]byte
+		buf.Write(strconv.AppendInt(tmp[:0], int64(m.Line), 10))
+	}
+	buf.WriteString("] ")
+
+	msgStart := buf.Len()
+	fmt.Fprintf(buf, format, args...)
+	if buf.Len() > MaxLogMessageLen-1 {
+		buf.Truncate(MaxLogMessageLen - 1)
+	}
+	msgEnd := buf.Len()
+	if b := buf.Bytes(); b[len(b)-1] != '\n' {
+		buf.WriteByte('\n')
+	}
+
+	for _, s := range sinks {
+		sn, sErr := s.Emit(m, buf.Bytes())
+		if sn > n {
+			n = sn
+		}
+		if sErr != nil && err == nil {
+			err = sErr
+		}
+	}
+
+	if m.Severity == Fatal {
+		savedM := *m
+		fatalMessageStore(savedEntry{
+			meta: &savedM,
+			msg:  buf.Bytes()[msgStart:msgEnd],
+		})
+	} else {
+		bufs.Put(bufi)
+	}
+	return n, err
+}
+
+const digits = "0123456789"
+
+// twoDigits formats a zero-prefixed two-digit integer to buf.
+func twoDigits(buf *bytes.Buffer, d int) {
+	buf.WriteByte(digits[(d/10)%10])
+	buf.WriteByte(digits[d%10])
+}
+
+// nDigits formats an n-digit integer to buf, padding with pad on the left. It
+// assumes d != 0.
+func nDigits(buf *bytes.Buffer, n int, d uint64, pad byte) {
+	var tmp [20]byte
+
+	cutoff := len(tmp) - n
+	j := len(tmp) - 1
+	for ; d > 0; j-- {
+		tmp[j] = digits[d%10]
+		d /= 10
+	}
+	for ; j >= cutoff; j-- {
+		tmp[j] = pad
+	}
+	j++
+	buf.Write(tmp[j:])
+}
+
+// Printf writes a log entry to all registered TextSinks in this package, then
+// to all registered StructuredSinks.
+//
+// The returned n is the maximum across all Emit and Printf calls.
+// The returned err is the first non-nil error encountered.
+// Sinks that are disabled by configuration should return (0, nil).
+func Printf(m *Meta, format string, args ...any) (n int, err error) {
+	m.Depth++
+	n, err = textPrintf(m, TextSinks, format, args...)
+
+	for _, sink := range StructuredSinks {
+		// TODO: Support TextSinks that implement StackWanter?
+		if sw, ok := sink.(StackWanter); ok && sw.WantStack(m) {
+			if m.Stack == nil {
+				// First, try to find a stacktrace in args, otherwise generate one.
+				for _, arg := range args {
+					if stack, ok := arg.(stackdump.Stack); ok {
+						m.Stack = &stack
+						break
+					}
+				}
+				if m.Stack == nil {
+					stack := stackdump.Caller( /* skipDepth = */ m.Depth)
+					m.Stack = &stack
+				}
+			}
+		}
+		sn, sErr := sink.Printf(m, format, args...)
+		if sn > n {
+			n = sn
+		}
+		if sErr != nil && err == nil {
+			err = sErr
+		}
+	}
+	return n, err
+}
+
+// The sets of sinks to which logs should be written.
+//
+// These must only be modified during package init, and are read-only thereafter.
+var (
+	// StructuredSinks is the set of Structured sink instances to which logs
+	// should be written.
+	StructuredSinks []Structured
+
+	// TextSinks is the set of Text sink instances to which logs should be
+	// written.
+	//
+	// These are registered separately from Structured sink implementations to
+	// avoid the need to repeat the work of formatting a message for each Text
+	// sink that writes it.  The package-level Printf function writes to both sets
+	// independenty, so a given log destination should only register a Structured
+	// *or* a Text sink (not both).
+	TextSinks []Text
+)
+
+type savedEntry struct {
+	meta *Meta
+	msg  []byte
+}
+
+// StructuredTextWrapper is a Structured sink which forwards logs to a set of Text sinks.
+//
+// The purpose of this sink is to allow applications to intercept logging calls before they are
+// serialized and sent to Text sinks. For example, if one needs to redact PII from logging
+// arguments before they reach STDERR, one solution would be to do the redacting in a Structured
+// sink that forwards logs to a StructuredTextWrapper instance, and make STDERR a child of that
+// StructuredTextWrapper instance. This is how one could set this up in their application:
+//
+// func init() {
+//
+//	wrapper := logsink.StructuredTextWrapper{TextSinks: logsink.TextSinks}
+//	// sanitizersink will intercept logs and remove PII
+//	sanitizer := sanitizersink{Sink: &wrapper}
+//	logsink.StructuredSinks = append(logsink.StructuredSinks, &sanitizer)
+//	logsink.TextSinks = nil
+//
+// }
+type StructuredTextWrapper struct {
+	// TextSinks is the set of Text sinks that should receive logs from this
+	// StructuredTextWrapper instance.
+	TextSinks []Text
+}
+
+// Printf forwards logs to all Text sinks registered in the StructuredTextWrapper.
+func (w *StructuredTextWrapper) Printf(meta *Meta, format string, args ...any) (n int, err error) {
+	return textPrintf(meta, w.TextSinks, format, args...)
+}
diff --git a/vendor/github.com/golang/glog/internal/logsink/logsink_fatal.go b/vendor/github.com/golang/glog/internal/logsink/logsink_fatal.go
new file mode 100644
index 000000000..3dc269abc
--- /dev/null
+++ b/vendor/github.com/golang/glog/internal/logsink/logsink_fatal.go
@@ -0,0 +1,35 @@
+package logsink
+
+import (
+	"sync/atomic"
+	"unsafe"
+)
+
+func fatalMessageStore(e savedEntry) {
+	// Only put a new one in if we haven't assigned before.
+	atomic.CompareAndSwapPointer(&fatalMessage, nil, unsafe.Pointer(&e))
+}
+
+var fatalMessage unsafe.Pointer // savedEntry stored with CompareAndSwapPointer
+
+// FatalMessage returns the Meta and message contents of the first message
+// logged with Fatal severity, or false if none has occurred.
+func FatalMessage() (*Meta, []byte, bool) {
+	e := (*savedEntry)(atomic.LoadPointer(&fatalMessage))
+	if e == nil {
+		return nil, nil, false
+	}
+	return e.meta, e.msg, true
+}
+
+// DoNotUseRacyFatalMessage is FatalMessage, but worse.
+//
+//go:norace
+//go:nosplit
+func DoNotUseRacyFatalMessage() (*Meta, []byte, bool) {
+	e := (*savedEntry)(fatalMessage)
+	if e == nil {
+		return nil, nil, false
+	}
+	return e.meta, e.msg, true
+}
diff --git a/vendor/github.com/golang/glog/internal/stackdump/stackdump.go b/vendor/github.com/golang/glog/internal/stackdump/stackdump.go
new file mode 100644
index 000000000..3427c9d6b
--- /dev/null
+++ b/vendor/github.com/golang/glog/internal/stackdump/stackdump.go
@@ -0,0 +1,127 @@
+// Copyright 2023 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package stackdump provides wrappers for runtime.Stack and runtime.Callers
+// with uniform support for skipping caller frames.
+//
+// âš  Unlike the functions in the runtime package, these may allocate a
+// non-trivial quantity of memory: use them with care. âš 
+package stackdump
+
+import (
+	"bytes"
+	"runtime"
+)
+
+// runtimeStackSelfFrames is 1 if runtime.Stack includes the call to
+// runtime.Stack itself or 0 if it does not.
+//
+// As of 2016-04-27, the gccgo compiler includes runtime.Stack but the gc
+// compiler does not.
+var runtimeStackSelfFrames = func() int {
+	for n := 1 << 10; n < 1<<20; n *= 2 {
+		buf := make([]byte, n)
+		n := runtime.Stack(buf, false)
+		if bytes.Contains(buf[:n], []byte("runtime.Stack")) {
+			return 1
+		} else if n < len(buf) || bytes.Count(buf, []byte("\n")) >= 3 {
+			return 0
+		}
+	}
+	return 0
+}()
+
+// Stack is a stack dump for a single goroutine.
+type Stack struct {
+	// Text is a representation of the stack dump in a human-readable format.
+	Text []byte
+
+	// PC is a representation of the stack dump using raw program counter values.
+	PC []uintptr
+}
+
+func (s Stack) String() string { return string(s.Text) }
+
+// Caller returns the Stack dump for the calling goroutine, starting skipDepth
+// frames before the caller of Caller.  (Caller(0) provides a dump starting at
+// the caller of this function.)
+func Caller(skipDepth int) Stack {
+	return Stack{
+		Text: CallerText(skipDepth + 1),
+		PC:   CallerPC(skipDepth + 1),
+	}
+}
+
+// CallerText returns a textual dump of the stack starting skipDepth frames before
+// the caller.  (CallerText(0) provides a dump starting at the caller of this
+// function.)
+func CallerText(skipDepth int) []byte {
+	for n := 1 << 10; ; n *= 2 {
+		buf := make([]byte, n)
+		n := runtime.Stack(buf, false)
+		if n < len(buf) {
+			return pruneFrames(skipDepth+1+runtimeStackSelfFrames, buf[:n])
+		}
+	}
+}
+
+// CallerPC returns a dump of the program counters of the stack starting
+// skipDepth frames before the caller.  (CallerPC(0) provides a dump starting at
+// the caller of this function.)
+func CallerPC(skipDepth int) []uintptr {
+	for n := 1 << 8; ; n *= 2 {
+		buf := make([]uintptr, n)
+		n := runtime.Callers(skipDepth+2, buf)
+		if n < len(buf) {
+			return buf[:n]
+		}
+	}
+}
+
+// pruneFrames removes the topmost skipDepth frames of the first goroutine in a
+// textual stack dump.  It overwrites the passed-in slice.
+//
+// If there are fewer than skipDepth frames in the first goroutine's stack,
+// pruneFrames prunes it to an empty stack and leaves the remaining contents
+// intact.
+func pruneFrames(skipDepth int, stack []byte) []byte {
+	headerLen := 0
+	for i, c := range stack {
+		if c == '\n' {
+			headerLen = i + 1
+			break
+		}
+	}
+	if headerLen == 0 {
+		return stack // No header line - not a well-formed stack trace.
+	}
+
+	skipLen := headerLen
+	skipNewlines := skipDepth * 2
+	for ; skipLen < len(stack) && skipNewlines > 0; skipLen++ {
+		c := stack[skipLen]
+		if c != '\n' {
+			continue
+		}
+		skipNewlines--
+		skipLen++
+		if skipNewlines == 0 || skipLen == len(stack) || stack[skipLen] == '\n' {
+			break
+		}
+	}
+
+	pruned := stack[skipLen-headerLen:]
+	copy(pruned, stack[:headerLen])
+	return pruned
+}
diff --git a/vendor/google.golang.org/grpc/CONTRIBUTING.md b/vendor/google.golang.org/grpc/CONTRIBUTING.md
index 8e001134d..608aa6e1a 100644
--- a/vendor/google.golang.org/grpc/CONTRIBUTING.md
+++ b/vendor/google.golang.org/grpc/CONTRIBUTING.md
@@ -20,10 +20,6 @@ How to get your contributions merged smoothly and quickly.
   both author's & review's time is wasted. Create more PRs to address different
   concerns and everyone will be happy.
 
-- For speculative changes, consider opening an issue and discussing it first. If
-  you are suggesting a behavioral or API change, consider starting with a [gRFC 
-  proposal](https://github.com/grpc/proposal).
-
 - If you are searching for features to work on, issues labeled [Status: Help
   Wanted](https://github.com/grpc/grpc-go/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Status%3A+Help+Wanted%22)
   is a great place to start. These issues are well-documented and usually can be
diff --git a/vendor/google.golang.org/grpc/attributes/attributes.go b/vendor/google.golang.org/grpc/attributes/attributes.go
index 02f5dc531..3efca4591 100644
--- a/vendor/google.golang.org/grpc/attributes/attributes.go
+++ b/vendor/google.golang.org/grpc/attributes/attributes.go
@@ -25,6 +25,11 @@
 // later release.
 package attributes
 
+import (
+	"fmt"
+	"strings"
+)
+
 // Attributes is an immutable struct for storing and retrieving generic
 // key/value pairs.  Keys must be hashable, and users should define their own
 // types for keys.  Values should not be modified after they are added to an
@@ -99,3 +104,27 @@ func (a *Attributes) Equal(o *Attributes) bool {
 	}
 	return true
 }
+
+// String prints the attribute map. If any key or values throughout the map
+// implement fmt.Stringer, it calls that method and appends.
+func (a *Attributes) String() string {
+	var sb strings.Builder
+	sb.WriteString("{")
+	first := true
+	for k, v := range a.m {
+		var key, val string
+		if str, ok := k.(interface{ String() string }); ok {
+			key = str.String()
+		}
+		if str, ok := v.(interface{ String() string }); ok {
+			val = str.String()
+		}
+		if !first {
+			sb.WriteString(", ")
+		}
+		sb.WriteString(fmt.Sprintf("%q: %q, ", key, val))
+		first = false
+	}
+	sb.WriteString("}")
+	return sb.String()
+}
diff --git a/vendor/google.golang.org/grpc/balancer/balancer.go b/vendor/google.golang.org/grpc/balancer/balancer.go
index 09d61dd1b..8f00523c0 100644
--- a/vendor/google.golang.org/grpc/balancer/balancer.go
+++ b/vendor/google.golang.org/grpc/balancer/balancer.go
@@ -286,7 +286,7 @@ type PickResult struct {
 	//
 	// LB policies with child policies are responsible for propagating metadata
 	// injected by their children to the ClientConn, as part of Pick().
-	Metatada metadata.MD
+	Metadata metadata.MD
 }
 
 // TransientFailureError returns e.  It exists for backward compatibility and
diff --git a/vendor/google.golang.org/grpc/balancer_conn_wrappers.go b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go
index 0359956d3..04b9ad411 100644
--- a/vendor/google.golang.org/grpc/balancer_conn_wrappers.go
+++ b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go
@@ -25,14 +25,20 @@ import (
 	"sync"
 
 	"google.golang.org/grpc/balancer"
-	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/connectivity"
 	"google.golang.org/grpc/internal/balancer/gracefulswitch"
-	"google.golang.org/grpc/internal/buffer"
 	"google.golang.org/grpc/internal/channelz"
 	"google.golang.org/grpc/internal/grpcsync"
 	"google.golang.org/grpc/resolver"
-	"google.golang.org/grpc/status"
+)
+
+type ccbMode int
+
+const (
+	ccbModeActive = iota
+	ccbModeIdle
+	ccbModeClosed
+	ccbModeExitingIdle
 )
 
 // ccBalancerWrapper sits between the ClientConn and the Balancer.
@@ -49,192 +55,101 @@ import (
 // It uses the gracefulswitch.Balancer internally to ensure that balancer
 // switches happen in a graceful manner.
 type ccBalancerWrapper struct {
-	cc *ClientConn
-
-	// Since these fields are accessed only from handleXxx() methods which are
-	// synchronized by the watcher goroutine, we do not need a mutex to protect
-	// these fields.
+	// The following fields are initialized when the wrapper is created and are
+	// read-only afterwards, and therefore can be accessed without a mutex.
+	cc   *ClientConn
+	opts balancer.BuildOptions
+
+	// Outgoing (gRPC --> balancer) calls are guaranteed to execute in a
+	// mutually exclusive manner as they are scheduled in the serializer. Fields
+	// accessed *only* in these serializer callbacks, can therefore be accessed
+	// without a mutex.
 	balancer        *gracefulswitch.Balancer
 	curBalancerName string
 
-	updateCh *buffer.Unbounded // Updates written on this channel are processed by watcher().
-	resultCh *buffer.Unbounded // Results of calls to UpdateClientConnState() are pushed here.
-	closed   *grpcsync.Event   // Indicates if close has been called.
-	done     *grpcsync.Event   // Indicates if close has completed its work.
+	// mu guards access to the below fields. Access to the serializer and its
+	// cancel function needs to be mutex protected because they are overwritten
+	// when the wrapper exits idle mode.
+	mu               sync.Mutex
+	serializer       *grpcsync.CallbackSerializer // To serialize all outoing calls.
+	serializerCancel context.CancelFunc           // To close the seralizer at close/enterIdle time.
+	mode             ccbMode                      // Tracks the current mode of the wrapper.
 }
 
 // newCCBalancerWrapper creates a new balancer wrapper. The underlying balancer
 // is not created until the switchTo() method is invoked.
 func newCCBalancerWrapper(cc *ClientConn, bopts balancer.BuildOptions) *ccBalancerWrapper {
+	ctx, cancel := context.WithCancel(context.Background())
 	ccb := &ccBalancerWrapper{
-		cc:       cc,
-		updateCh: buffer.NewUnbounded(),
-		resultCh: buffer.NewUnbounded(),
-		closed:   grpcsync.NewEvent(),
-		done:     grpcsync.NewEvent(),
+		cc:               cc,
+		opts:             bopts,
+		serializer:       grpcsync.NewCallbackSerializer(ctx),
+		serializerCancel: cancel,
 	}
-	go ccb.watcher()
 	ccb.balancer = gracefulswitch.NewBalancer(ccb, bopts)
 	return ccb
 }
 
-// The following xxxUpdate structs wrap the arguments received as part of the
-// corresponding update. The watcher goroutine uses the 'type' of the update to
-// invoke the appropriate handler routine to handle the update.
-
-type ccStateUpdate struct {
-	ccs *balancer.ClientConnState
-}
-
-type scStateUpdate struct {
-	sc    balancer.SubConn
-	state connectivity.State
-	err   error
-}
-
-type exitIdleUpdate struct{}
-
-type resolverErrorUpdate struct {
-	err error
-}
-
-type switchToUpdate struct {
-	name string
-}
-
-type subConnUpdate struct {
-	acbw *acBalancerWrapper
-}
-
-// watcher is a long-running goroutine which reads updates from a channel and
-// invokes corresponding methods on the underlying balancer. It ensures that
-// these methods are invoked in a synchronous fashion. It also ensures that
-// these methods are invoked in the order in which the updates were received.
-func (ccb *ccBalancerWrapper) watcher() {
-	for {
-		select {
-		case u := <-ccb.updateCh.Get():
-			ccb.updateCh.Load()
-			if ccb.closed.HasFired() {
-				break
-			}
-			switch update := u.(type) {
-			case *ccStateUpdate:
-				ccb.handleClientConnStateChange(update.ccs)
-			case *scStateUpdate:
-				ccb.handleSubConnStateChange(update)
-			case *exitIdleUpdate:
-				ccb.handleExitIdle()
-			case *resolverErrorUpdate:
-				ccb.handleResolverError(update.err)
-			case *switchToUpdate:
-				ccb.handleSwitchTo(update.name)
-			case *subConnUpdate:
-				ccb.handleRemoveSubConn(update.acbw)
-			default:
-				logger.Errorf("ccBalancerWrapper.watcher: unknown update %+v, type %T", update, update)
-			}
-		case <-ccb.closed.Done():
-		}
-
-		if ccb.closed.HasFired() {
-			ccb.handleClose()
-			return
-		}
-	}
-}
-
 // updateClientConnState is invoked by grpc to push a ClientConnState update to
 // the underlying balancer.
-//
-// Unlike other methods invoked by grpc to push updates to the underlying
-// balancer, this method cannot simply push the update onto the update channel
-// and return. It needs to return the error returned by the underlying balancer
-// back to grpc which propagates that to the resolver.
 func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error {
-	ccb.updateCh.Put(&ccStateUpdate{ccs: ccs})
-
-	var res interface{}
-	select {
-	case res = <-ccb.resultCh.Get():
-		ccb.resultCh.Load()
-	case <-ccb.closed.Done():
-		// Return early if the balancer wrapper is closed while we are waiting for
-		// the underlying balancer to process a ClientConnState update.
-		return nil
-	}
-	// If the returned error is nil, attempting to type assert to error leads to
-	// panic. So, this needs to handled separately.
-	if res == nil {
-		return nil
-	}
-	return res.(error)
-}
-
-// handleClientConnStateChange handles a ClientConnState update from the update
-// channel and invokes the appropriate method on the underlying balancer.
-//
-// If the addresses specified in the update contain addresses of type "grpclb"
-// and the selected LB policy is not "grpclb", these addresses will be filtered
-// out and ccs will be modified with the updated address list.
-func (ccb *ccBalancerWrapper) handleClientConnStateChange(ccs *balancer.ClientConnState) {
-	if ccb.curBalancerName != grpclbName {
-		// Filter any grpclb addresses since we don't have the grpclb balancer.
-		var addrs []resolver.Address
-		for _, addr := range ccs.ResolverState.Addresses {
-			if addr.Type == resolver.GRPCLB {
-				continue
+	ccb.mu.Lock()
+	errCh := make(chan error, 1)
+	// Here and everywhere else where Schedule() is called, it is done with the
+	// lock held. But the lock guards only the scheduling part. The actual
+	// callback is called asynchronously without the lock being held.
+	ok := ccb.serializer.Schedule(func(_ context.Context) {
+		// If the addresses specified in the update contain addresses of type
+		// "grpclb" and the selected LB policy is not "grpclb", these addresses
+		// will be filtered out and ccs will be modified with the updated
+		// address list.
+		if ccb.curBalancerName != grpclbName {
+			var addrs []resolver.Address
+			for _, addr := range ccs.ResolverState.Addresses {
+				if addr.Type == resolver.GRPCLB {
+					continue
+				}
+				addrs = append(addrs, addr)
 			}
-			addrs = append(addrs, addr)
+			ccs.ResolverState.Addresses = addrs
 		}
-		ccs.ResolverState.Addresses = addrs
+		errCh <- ccb.balancer.UpdateClientConnState(*ccs)
+	})
+	if !ok {
+		// If we are unable to schedule a function with the serializer, it
+		// indicates that it has been closed. A serializer is only closed when
+		// the wrapper is closed or is in idle.
+		ccb.mu.Unlock()
+		return fmt.Errorf("grpc: cannot send state update to a closed or idle balancer")
 	}
-	ccb.resultCh.Put(ccb.balancer.UpdateClientConnState(*ccs))
+	ccb.mu.Unlock()
+
+	// We get here only if the above call to Schedule succeeds, in which case it
+	// is guaranteed that the scheduled function will run. Therefore it is safe
+	// to block on this channel.
+	err := <-errCh
+	if logger.V(2) && err != nil {
+		logger.Infof("error from balancer.UpdateClientConnState: %v", err)
+	}
+	return err
 }
 
 // updateSubConnState is invoked by grpc to push a subConn state update to the
 // underlying balancer.
 func (ccb *ccBalancerWrapper) updateSubConnState(sc balancer.SubConn, s connectivity.State, err error) {
-	// When updating addresses for a SubConn, if the address in use is not in
-	// the new addresses, the old ac will be tearDown() and a new ac will be
-	// created. tearDown() generates a state change with Shutdown state, we
-	// don't want the balancer to receive this state change. So before
-	// tearDown() on the old ac, ac.acbw (acWrapper) will be set to nil, and
-	// this function will be called with (nil, Shutdown). We don't need to call
-	// balancer method in this case.
-	if sc == nil {
-		return
-	}
-	ccb.updateCh.Put(&scStateUpdate{
-		sc:    sc,
-		state: s,
-		err:   err,
+	ccb.mu.Lock()
+	ccb.serializer.Schedule(func(_ context.Context) {
+		ccb.balancer.UpdateSubConnState(sc, balancer.SubConnState{ConnectivityState: s, ConnectionError: err})
 	})
-}
-
-// handleSubConnStateChange handles a SubConnState update from the update
-// channel and invokes the appropriate method on the underlying balancer.
-func (ccb *ccBalancerWrapper) handleSubConnStateChange(update *scStateUpdate) {
-	ccb.balancer.UpdateSubConnState(update.sc, balancer.SubConnState{ConnectivityState: update.state, ConnectionError: update.err})
-}
-
-func (ccb *ccBalancerWrapper) exitIdle() {
-	ccb.updateCh.Put(&exitIdleUpdate{})
-}
-
-func (ccb *ccBalancerWrapper) handleExitIdle() {
-	if ccb.cc.GetState() != connectivity.Idle {
-		return
-	}
-	ccb.balancer.ExitIdle()
+	ccb.mu.Unlock()
 }
 
 func (ccb *ccBalancerWrapper) resolverError(err error) {
-	ccb.updateCh.Put(&resolverErrorUpdate{err: err})
-}
-
-func (ccb *ccBalancerWrapper) handleResolverError(err error) {
-	ccb.balancer.ResolverError(err)
+	ccb.mu.Lock()
+	ccb.serializer.Schedule(func(_ context.Context) {
+		ccb.balancer.ResolverError(err)
+	})
+	ccb.mu.Unlock()
 }
 
 // switchTo is invoked by grpc to instruct the balancer wrapper to switch to the
@@ -248,24 +163,27 @@ func (ccb *ccBalancerWrapper) handleResolverError(err error) {
 // the ccBalancerWrapper keeps track of the current LB policy name, and skips
 // the graceful balancer switching process if the name does not change.
 func (ccb *ccBalancerWrapper) switchTo(name string) {
-	ccb.updateCh.Put(&switchToUpdate{name: name})
+	ccb.mu.Lock()
+	ccb.serializer.Schedule(func(_ context.Context) {
+		// TODO: Other languages use case-sensitive balancer registries. We should
+		// switch as well. See: https://github.com/grpc/grpc-go/issues/5288.
+		if strings.EqualFold(ccb.curBalancerName, name) {
+			return
+		}
+		ccb.buildLoadBalancingPolicy(name)
+	})
+	ccb.mu.Unlock()
 }
 
-// handleSwitchTo handles a balancer switch update from the update channel. It
-// calls the SwitchTo() method on the gracefulswitch.Balancer with a
-// balancer.Builder corresponding to name. If no balancer.Builder is registered
-// for the given name, it uses the default LB policy which is "pick_first".
-func (ccb *ccBalancerWrapper) handleSwitchTo(name string) {
-	// TODO: Other languages use case-insensitive balancer registries. We should
-	// switch as well. See: https://github.com/grpc/grpc-go/issues/5288.
-	if strings.EqualFold(ccb.curBalancerName, name) {
-		return
-	}
-
-	// TODO: Ensure that name is a registered LB policy when we get here.
-	// We currently only validate the `loadBalancingConfig` field. We need to do
-	// the same for the `loadBalancingPolicy` field and reject the service config
-	// if the specified policy is not registered.
+// buildLoadBalancingPolicy performs the following:
+//   - retrieve a balancer builder for the given name. Use the default LB
+//     policy, pick_first, if no LB policy with name is found in the registry.
+//   - instruct the gracefulswitch balancer to switch to the above builder. This
+//     will actually build the new balancer.
+//   - update the `curBalancerName` field
+//
+// Must be called from a serializer callback.
+func (ccb *ccBalancerWrapper) buildLoadBalancingPolicy(name string) {
 	builder := balancer.Get(name)
 	if builder == nil {
 		channelz.Warningf(logger, ccb.cc.channelzID, "Channel switches to new LB policy %q, since the specified LB policy %q was not registered", PickFirstBalancerName, name)
@@ -281,26 +199,114 @@ func (ccb *ccBalancerWrapper) handleSwitchTo(name string) {
 	ccb.curBalancerName = builder.Name()
 }
 
-// handleRemoveSucConn handles a request from the underlying balancer to remove
-// a subConn.
-//
-// See comments in RemoveSubConn() for more details.
-func (ccb *ccBalancerWrapper) handleRemoveSubConn(acbw *acBalancerWrapper) {
-	ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
+func (ccb *ccBalancerWrapper) close() {
+	channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: closing")
+	ccb.closeBalancer(ccbModeClosed)
 }
 
-func (ccb *ccBalancerWrapper) close() {
-	ccb.closed.Fire()
-	<-ccb.done.Done()
+// enterIdleMode is invoked by grpc when the channel enters idle mode upon
+// expiry of idle_timeout. This call blocks until the balancer is closed.
+func (ccb *ccBalancerWrapper) enterIdleMode() {
+	channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: entering idle mode")
+	ccb.closeBalancer(ccbModeIdle)
+}
+
+// closeBalancer is invoked when the channel is being closed or when it enters
+// idle mode upon expiry of idle_timeout.
+func (ccb *ccBalancerWrapper) closeBalancer(m ccbMode) {
+	ccb.mu.Lock()
+	if ccb.mode == ccbModeClosed || ccb.mode == ccbModeIdle {
+		ccb.mu.Unlock()
+		return
+	}
+
+	ccb.mode = m
+	done := ccb.serializer.Done
+	b := ccb.balancer
+	ok := ccb.serializer.Schedule(func(_ context.Context) {
+		// Close the serializer to ensure that no more calls from gRPC are sent
+		// to the balancer.
+		ccb.serializerCancel()
+		// Empty the current balancer name because we don't have a balancer
+		// anymore and also so that we act on the next call to switchTo by
+		// creating a new balancer specified by the new resolver.
+		ccb.curBalancerName = ""
+	})
+	if !ok {
+		ccb.mu.Unlock()
+		return
+	}
+	ccb.mu.Unlock()
+
+	// Give enqueued callbacks a chance to finish.
+	<-done
+	// Spawn a goroutine to close the balancer (since it may block trying to
+	// cleanup all allocated resources) and return early.
+	go b.Close()
 }
 
-func (ccb *ccBalancerWrapper) handleClose() {
-	ccb.balancer.Close()
-	ccb.done.Fire()
+// exitIdleMode is invoked by grpc when the channel exits idle mode either
+// because of an RPC or because of an invocation of the Connect() API. This
+// recreates the balancer that was closed previously when entering idle mode.
+//
+// If the channel is not in idle mode, we know for a fact that we are here as a
+// result of the user calling the Connect() method on the ClientConn. In this
+// case, we can simply forward the call to the underlying balancer, instructing
+// it to reconnect to the backends.
+func (ccb *ccBalancerWrapper) exitIdleMode() {
+	ccb.mu.Lock()
+	if ccb.mode == ccbModeClosed {
+		// Request to exit idle is a no-op when wrapper is already closed.
+		ccb.mu.Unlock()
+		return
+	}
+
+	if ccb.mode == ccbModeIdle {
+		// Recreate the serializer which was closed when we entered idle.
+		ctx, cancel := context.WithCancel(context.Background())
+		ccb.serializer = grpcsync.NewCallbackSerializer(ctx)
+		ccb.serializerCancel = cancel
+	}
+
+	// The ClientConn guarantees that mutual exclusion between close() and
+	// exitIdleMode(), and since we just created a new serializer, we can be
+	// sure that the below function will be scheduled.
+	done := make(chan struct{})
+	ccb.serializer.Schedule(func(_ context.Context) {
+		defer close(done)
+
+		ccb.mu.Lock()
+		defer ccb.mu.Unlock()
+
+		if ccb.mode != ccbModeIdle {
+			ccb.balancer.ExitIdle()
+			return
+		}
+
+		// Gracefulswitch balancer does not support a switchTo operation after
+		// being closed. Hence we need to create a new one here.
+		ccb.balancer = gracefulswitch.NewBalancer(ccb, ccb.opts)
+		ccb.mode = ccbModeActive
+		channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: exiting idle mode")
+
+	})
+	ccb.mu.Unlock()
+
+	<-done
+}
+
+func (ccb *ccBalancerWrapper) isIdleOrClosed() bool {
+	ccb.mu.Lock()
+	defer ccb.mu.Unlock()
+	return ccb.mode == ccbModeIdle || ccb.mode == ccbModeClosed
 }
 
 func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
-	if len(addrs) <= 0 {
+	if ccb.isIdleOrClosed() {
+		return nil, fmt.Errorf("grpc: cannot create SubConn when balancer is closed or idle")
+	}
+
+	if len(addrs) == 0 {
 		return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
 	}
 	ac, err := ccb.cc.newAddrConn(addrs, opts)
@@ -309,31 +315,35 @@ func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer
 		return nil, err
 	}
 	acbw := &acBalancerWrapper{ac: ac, producers: make(map[balancer.ProducerBuilder]*refCountedProducer)}
-	acbw.ac.mu.Lock()
 	ac.acbw = acbw
-	acbw.ac.mu.Unlock()
 	return acbw, nil
 }
 
 func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
-	// Before we switched the ccBalancerWrapper to use gracefulswitch.Balancer, it
-	// was required to handle the RemoveSubConn() method asynchronously by pushing
-	// the update onto the update channel. This was done to avoid a deadlock as
-	// switchBalancer() was holding cc.mu when calling Close() on the old
-	// balancer, which would in turn call RemoveSubConn().
-	//
-	// With the use of gracefulswitch.Balancer in ccBalancerWrapper, handling this
-	// asynchronously is probably not required anymore since the switchTo() method
-	// handles the balancer switch by pushing the update onto the channel.
-	// TODO(easwars): Handle this inline.
+	if ccb.isIdleOrClosed() {
+		// It it safe to ignore this call when the balancer is closed or in idle
+		// because the ClientConn takes care of closing the connections.
+		//
+		// Not returning early from here when the balancer is closed or in idle
+		// leads to a deadlock though, because of the following sequence of
+		// calls when holding cc.mu:
+		// cc.exitIdleMode --> ccb.enterIdleMode --> gsw.Close -->
+		// ccb.RemoveAddrConn --> cc.removeAddrConn
+		return
+	}
+
 	acbw, ok := sc.(*acBalancerWrapper)
 	if !ok {
 		return
 	}
-	ccb.updateCh.Put(&subConnUpdate{acbw: acbw})
+	ccb.cc.removeAddrConn(acbw.ac, errConnDrain)
 }
 
 func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
+	if ccb.isIdleOrClosed() {
+		return
+	}
+
 	acbw, ok := sc.(*acBalancerWrapper)
 	if !ok {
 		return
@@ -342,6 +352,10 @@ func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resol
 }
 
 func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) {
+	if ccb.isIdleOrClosed() {
+		return
+	}
+
 	// Update picker before updating state.  Even though the ordering here does
 	// not matter, it can lead to multiple calls of Pick in the common start-up
 	// case where we wait for ready and then perform an RPC.  If the picker is
@@ -352,6 +366,10 @@ func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) {
 }
 
 func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOptions) {
+	if ccb.isIdleOrClosed() {
+		return
+	}
+
 	ccb.cc.resolveNow(o)
 }
 
@@ -362,71 +380,31 @@ func (ccb *ccBalancerWrapper) Target() string {
 // acBalancerWrapper is a wrapper on top of ac for balancers.
 // It implements balancer.SubConn interface.
 type acBalancerWrapper struct {
+	ac *addrConn // read-only
+
 	mu        sync.Mutex
-	ac        *addrConn
 	producers map[balancer.ProducerBuilder]*refCountedProducer
 }
 
-func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
-	acbw.mu.Lock()
-	defer acbw.mu.Unlock()
-	if len(addrs) <= 0 {
-		acbw.ac.cc.removeAddrConn(acbw.ac, errConnDrain)
-		return
-	}
-	if !acbw.ac.tryUpdateAddrs(addrs) {
-		cc := acbw.ac.cc
-		opts := acbw.ac.scopts
-		acbw.ac.mu.Lock()
-		// Set old ac.acbw to nil so the Shutdown state update will be ignored
-		// by balancer.
-		//
-		// TODO(bar) the state transition could be wrong when tearDown() old ac
-		// and creating new ac, fix the transition.
-		acbw.ac.acbw = nil
-		acbw.ac.mu.Unlock()
-		acState := acbw.ac.getState()
-		acbw.ac.cc.removeAddrConn(acbw.ac, errConnDrain)
-
-		if acState == connectivity.Shutdown {
-			return
-		}
+func (acbw *acBalancerWrapper) String() string {
+	return fmt.Sprintf("SubConn(id:%d)", acbw.ac.channelzID.Int())
+}
 
-		newAC, err := cc.newAddrConn(addrs, opts)
-		if err != nil {
-			channelz.Warningf(logger, acbw.ac.channelzID, "acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err)
-			return
-		}
-		acbw.ac = newAC
-		newAC.mu.Lock()
-		newAC.acbw = acbw
-		newAC.mu.Unlock()
-		if acState != connectivity.Idle {
-			go newAC.connect()
-		}
-	}
+func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
+	acbw.ac.updateAddrs(addrs)
 }
 
 func (acbw *acBalancerWrapper) Connect() {
-	acbw.mu.Lock()
-	defer acbw.mu.Unlock()
 	go acbw.ac.connect()
 }
 
-func (acbw *acBalancerWrapper) getAddrConn() *addrConn {
-	acbw.mu.Lock()
-	defer acbw.mu.Unlock()
-	return acbw.ac
-}
-
-var errSubConnNotReady = status.Error(codes.Unavailable, "SubConn not currently connected")
-
 // NewStream begins a streaming RPC on the addrConn.  If the addrConn is not
-// ready, returns errSubConnNotReady.
+// ready, blocks until it is or ctx expires.  Returns an error when the context
+// expires or the addrConn is shut down.
 func (acbw *acBalancerWrapper) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) {
-	transport := acbw.ac.getReadyTransport()
-	if transport == nil {
-		return nil, errSubConnNotReady
+	transport, err := acbw.ac.getTransport(ctx)
+	if err != nil {
+		return nil, err
 	}
 	return newNonRetryClientStream(ctx, desc, method, transport, acbw.ac, opts...)
 }
diff --git a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
index 8cd89dab9..ec2c2fa14 100644
--- a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
+++ b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
@@ -18,7 +18,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.28.1
+// 	protoc-gen-go v1.30.0
 // 	protoc        v4.22.0
 // source: grpc/binlog/v1/binarylog.proto
 
diff --git a/vendor/google.golang.org/grpc/call.go b/vendor/google.golang.org/grpc/call.go
index 9e20e4d38..e6a1dc5d7 100644
--- a/vendor/google.golang.org/grpc/call.go
+++ b/vendor/google.golang.org/grpc/call.go
@@ -27,6 +27,11 @@ import (
 //
 // All errors returned by Invoke are compatible with the status package.
 func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error {
+	if err := cc.idlenessMgr.onCallBegin(); err != nil {
+		return err
+	}
+	defer cc.idlenessMgr.onCallEnd()
+
 	// allow interceptor to see all applicable call options, which means those
 	// configured as defaults from dial option as well as per-call options
 	opts = combine(cc.dopts.callOptions, opts)
diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go
index b9cc05507..95a7459b0 100644
--- a/vendor/google.golang.org/grpc/clientconn.go
+++ b/vendor/google.golang.org/grpc/clientconn.go
@@ -24,7 +24,6 @@ import (
 	"fmt"
 	"math"
 	"net/url"
-	"reflect"
 	"strings"
 	"sync"
 	"sync/atomic"
@@ -69,6 +68,9 @@ var (
 	errConnDrain = errors.New("grpc: the connection is drained")
 	// errConnClosing indicates that the connection is closing.
 	errConnClosing = errors.New("grpc: the connection is closing")
+	// errConnIdling indicates the the connection is being closed as the channel
+	// is moving to an idle mode due to inactivity.
+	errConnIdling = errors.New("grpc: the connection is closing due to channel idleness")
 	// invalidDefaultServiceConfigErrPrefix is used to prefix the json parsing error for the default
 	// service config.
 	invalidDefaultServiceConfigErrPrefix = "grpc: the provided default service config is invalid"
@@ -134,17 +136,29 @@ func (dcs *defaultConfigSelector) SelectConfig(rpcInfo iresolver.RPCInfo) (*ires
 // e.g. to use dns resolver, a "dns:///" prefix should be applied to the target.
 func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) {
 	cc := &ClientConn{
-		target:            target,
-		csMgr:             &connectivityStateManager{},
-		conns:             make(map[*addrConn]struct{}),
-		dopts:             defaultDialOptions(),
-		blockingpicker:    newPickerWrapper(),
-		czData:            new(channelzData),
-		firstResolveEvent: grpcsync.NewEvent(),
-	}
+		target: target,
+		csMgr:  &connectivityStateManager{},
+		conns:  make(map[*addrConn]struct{}),
+		dopts:  defaultDialOptions(),
+		czData: new(channelzData),
+	}
+
+	// We start the channel off in idle mode, but kick it out of idle at the end
+	// of this method, instead of waiting for the first RPC. Other gRPC
+	// implementations do wait for the first RPC to kick the channel out of
+	// idle. But doing so would be a major behavior change for our users who are
+	// used to seeing the channel active after Dial.
+	//
+	// Taking this approach of kicking it out of idle at the end of this method
+	// allows us to share the code between channel creation and exiting idle
+	// mode. This will also make it easy for us to switch to starting the
+	// channel off in idle, if at all we ever get to do that.
+	cc.idlenessState = ccIdlenessStateIdle
+
 	cc.retryThrottler.Store((*retryThrottler)(nil))
 	cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{nil})
 	cc.ctx, cc.cancel = context.WithCancel(context.Background())
+	cc.exitIdleCond = sync.NewCond(&cc.mu)
 
 	disableGlobalOpts := false
 	for _, opt := range opts {
@@ -173,40 +187,11 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
 		}
 	}()
 
-	pid := cc.dopts.channelzParentID
-	cc.channelzID = channelz.RegisterChannel(&channelzChannel{cc}, pid, target)
-	ted := &channelz.TraceEventDesc{
-		Desc:     "Channel created",
-		Severity: channelz.CtInfo,
-	}
-	if cc.dopts.channelzParentID != nil {
-		ted.Parent = &channelz.TraceEventDesc{
-			Desc:     fmt.Sprintf("Nested Channel(id:%d) created", cc.channelzID.Int()),
-			Severity: channelz.CtInfo,
-		}
-	}
-	channelz.AddTraceEvent(logger, cc.channelzID, 1, ted)
-	cc.csMgr.channelzID = cc.channelzID
+	// Register ClientConn with channelz.
+	cc.channelzRegistration(target)
 
-	if cc.dopts.copts.TransportCredentials == nil && cc.dopts.copts.CredsBundle == nil {
-		return nil, errNoTransportSecurity
-	}
-	if cc.dopts.copts.TransportCredentials != nil && cc.dopts.copts.CredsBundle != nil {
-		return nil, errTransportCredsAndBundle
-	}
-	if cc.dopts.copts.CredsBundle != nil && cc.dopts.copts.CredsBundle.TransportCredentials() == nil {
-		return nil, errNoTransportCredsInBundle
-	}
-	transportCreds := cc.dopts.copts.TransportCredentials
-	if transportCreds == nil {
-		transportCreds = cc.dopts.copts.CredsBundle.TransportCredentials()
-	}
-	if transportCreds.Info().SecurityProtocol == "insecure" {
-		for _, cd := range cc.dopts.copts.PerRPCCredentials {
-			if cd.RequireTransportSecurity() {
-				return nil, errTransportCredentialsMissing
-			}
-		}
+	if err := cc.validateTransportCredentials(); err != nil {
+		return nil, err
 	}
 
 	if cc.dopts.defaultServiceConfigRawJSON != nil {
@@ -244,35 +229,19 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
 		}
 	}()
 
-	scSet := false
-	if cc.dopts.scChan != nil {
-		// Try to get an initial service config.
-		select {
-		case sc, ok := <-cc.dopts.scChan:
-			if ok {
-				cc.sc = &sc
-				cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{&sc})
-				scSet = true
-			}
-		default:
-		}
-	}
 	if cc.dopts.bs == nil {
 		cc.dopts.bs = backoff.DefaultExponential
 	}
 
 	// Determine the resolver to use.
-	resolverBuilder, err := cc.parseTargetAndFindResolver()
-	if err != nil {
+	if err := cc.parseTargetAndFindResolver(); err != nil {
 		return nil, err
 	}
-	cc.authority, err = determineAuthority(cc.parsedTarget.Endpoint(), cc.target, cc.dopts)
-	if err != nil {
+	if err = cc.determineAuthority(); err != nil {
 		return nil, err
 	}
-	channelz.Infof(logger, cc.channelzID, "Channel authority set to %q", cc.authority)
 
-	if cc.dopts.scChan != nil && !scSet {
+	if cc.dopts.scChan != nil {
 		// Blocking wait for the initial service config.
 		select {
 		case sc, ok := <-cc.dopts.scChan:
@@ -288,57 +257,224 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
 		go cc.scWatcher()
 	}
 
+	// This creates the name resolver, load balancer, blocking picker etc.
+	if err := cc.exitIdleMode(); err != nil {
+		return nil, err
+	}
+
+	// Configure idleness support with configured idle timeout or default idle
+	// timeout duration. Idleness can be explicitly disabled by the user, by
+	// setting the dial option to 0.
+	cc.idlenessMgr = newIdlenessManager(cc, cc.dopts.idleTimeout)
+
+	// Return early for non-blocking dials.
+	if !cc.dopts.block {
+		return cc, nil
+	}
+
+	// A blocking dial blocks until the clientConn is ready.
+	for {
+		s := cc.GetState()
+		if s == connectivity.Idle {
+			cc.Connect()
+		}
+		if s == connectivity.Ready {
+			return cc, nil
+		} else if cc.dopts.copts.FailOnNonTempDialError && s == connectivity.TransientFailure {
+			if err = cc.connectionError(); err != nil {
+				terr, ok := err.(interface {
+					Temporary() bool
+				})
+				if ok && !terr.Temporary() {
+					return nil, err
+				}
+			}
+		}
+		if !cc.WaitForStateChange(ctx, s) {
+			// ctx got timeout or canceled.
+			if err = cc.connectionError(); err != nil && cc.dopts.returnLastError {
+				return nil, err
+			}
+			return nil, ctx.Err()
+		}
+	}
+}
+
+// addTraceEvent is a helper method to add a trace event on the channel. If the
+// channel is a nested one, the same event is also added on the parent channel.
+func (cc *ClientConn) addTraceEvent(msg string) {
+	ted := &channelz.TraceEventDesc{
+		Desc:     fmt.Sprintf("Channel %s", msg),
+		Severity: channelz.CtInfo,
+	}
+	if cc.dopts.channelzParentID != nil {
+		ted.Parent = &channelz.TraceEventDesc{
+			Desc:     fmt.Sprintf("Nested channel(id:%d) %s", cc.channelzID.Int(), msg),
+			Severity: channelz.CtInfo,
+		}
+	}
+	channelz.AddTraceEvent(logger, cc.channelzID, 0, ted)
+}
+
+// exitIdleMode moves the channel out of idle mode by recreating the name
+// resolver and load balancer.
+func (cc *ClientConn) exitIdleMode() error {
+	cc.mu.Lock()
+	if cc.conns == nil {
+		cc.mu.Unlock()
+		return errConnClosing
+	}
+	if cc.idlenessState != ccIdlenessStateIdle {
+		cc.mu.Unlock()
+		logger.Info("ClientConn asked to exit idle mode when not in idle mode")
+		return nil
+	}
+
+	defer func() {
+		// When Close() and exitIdleMode() race against each other, one of the
+		// following two can happen:
+		// - Close() wins the race and runs first. exitIdleMode() runs after, and
+		//   sees that the ClientConn is already closed and hence returns early.
+		// - exitIdleMode() wins the race and runs first and recreates the balancer
+		//   and releases the lock before recreating the resolver. If Close() runs
+		//   in this window, it will wait for exitIdleMode to complete.
+		//
+		// We achieve this synchronization using the below condition variable.
+		cc.mu.Lock()
+		cc.idlenessState = ccIdlenessStateActive
+		cc.exitIdleCond.Signal()
+		cc.mu.Unlock()
+	}()
+
+	cc.idlenessState = ccIdlenessStateExitingIdle
+	exitedIdle := false
+	if cc.blockingpicker == nil {
+		cc.blockingpicker = newPickerWrapper()
+	} else {
+		cc.blockingpicker.exitIdleMode()
+		exitedIdle = true
+	}
+
 	var credsClone credentials.TransportCredentials
 	if creds := cc.dopts.copts.TransportCredentials; creds != nil {
 		credsClone = creds.Clone()
 	}
-	cc.balancerWrapper = newCCBalancerWrapper(cc, balancer.BuildOptions{
-		DialCreds:        credsClone,
-		CredsBundle:      cc.dopts.copts.CredsBundle,
-		Dialer:           cc.dopts.copts.Dialer,
-		Authority:        cc.authority,
-		CustomUserAgent:  cc.dopts.copts.UserAgent,
-		ChannelzParentID: cc.channelzID,
-		Target:           cc.parsedTarget,
-	})
+	if cc.balancerWrapper == nil {
+		cc.balancerWrapper = newCCBalancerWrapper(cc, balancer.BuildOptions{
+			DialCreds:        credsClone,
+			CredsBundle:      cc.dopts.copts.CredsBundle,
+			Dialer:           cc.dopts.copts.Dialer,
+			Authority:        cc.authority,
+			CustomUserAgent:  cc.dopts.copts.UserAgent,
+			ChannelzParentID: cc.channelzID,
+			Target:           cc.parsedTarget,
+		})
+	} else {
+		cc.balancerWrapper.exitIdleMode()
+	}
+	cc.firstResolveEvent = grpcsync.NewEvent()
+	cc.mu.Unlock()
 
-	// Build the resolver.
-	rWrapper, err := newCCResolverWrapper(cc, resolverBuilder)
-	if err != nil {
-		return nil, fmt.Errorf("failed to build resolver: %v", err)
+	// This needs to be called without cc.mu because this builds a new resolver
+	// which might update state or report error inline which needs to be handled
+	// by cc.updateResolverState() which also grabs cc.mu.
+	if err := cc.initResolverWrapper(credsClone); err != nil {
+		return err
 	}
+
+	if exitedIdle {
+		cc.addTraceEvent("exiting idle mode")
+	}
+	return nil
+}
+
+// enterIdleMode puts the channel in idle mode, and as part of it shuts down the
+// name resolver, load balancer and any subchannels.
+func (cc *ClientConn) enterIdleMode() error {
 	cc.mu.Lock()
-	cc.resolverWrapper = rWrapper
+	if cc.conns == nil {
+		cc.mu.Unlock()
+		return ErrClientConnClosing
+	}
+	if cc.idlenessState != ccIdlenessStateActive {
+		logger.Error("ClientConn asked to enter idle mode when not active")
+		return nil
+	}
+
+	// cc.conns == nil is a proxy for the ClientConn being closed. So, instead
+	// of setting it to nil here, we recreate the map. This also means that we
+	// don't have to do this when exiting idle mode.
+	conns := cc.conns
+	cc.conns = make(map[*addrConn]struct{})
+
+	// TODO: Currently, we close the resolver wrapper upon entering idle mode
+	// and create a new one upon exiting idle mode. This means that the
+	// `cc.resolverWrapper` field would be overwritten everytime we exit idle
+	// mode. While this means that we need to hold `cc.mu` when accessing
+	// `cc.resolverWrapper`, it makes the code simpler in the wrapper. We should
+	// try to do the same for the balancer and picker wrappers too.
+	cc.resolverWrapper.close()
+	cc.blockingpicker.enterIdleMode()
+	cc.balancerWrapper.enterIdleMode()
+	cc.csMgr.updateState(connectivity.Idle)
+	cc.idlenessState = ccIdlenessStateIdle
 	cc.mu.Unlock()
 
-	// A blocking dial blocks until the clientConn is ready.
-	if cc.dopts.block {
-		for {
-			cc.Connect()
-			s := cc.GetState()
-			if s == connectivity.Ready {
-				break
-			} else if cc.dopts.copts.FailOnNonTempDialError && s == connectivity.TransientFailure {
-				if err = cc.connectionError(); err != nil {
-					terr, ok := err.(interface {
-						Temporary() bool
-					})
-					if ok && !terr.Temporary() {
-						return nil, err
-					}
-				}
-			}
-			if !cc.WaitForStateChange(ctx, s) {
-				// ctx got timeout or canceled.
-				if err = cc.connectionError(); err != nil && cc.dopts.returnLastError {
-					return nil, err
-				}
-				return nil, ctx.Err()
+	go func() {
+		cc.addTraceEvent("entering idle mode")
+		for ac := range conns {
+			ac.tearDown(errConnIdling)
+		}
+	}()
+	return nil
+}
+
+// validateTransportCredentials performs a series of checks on the configured
+// transport credentials. It returns a non-nil error if any of these conditions
+// are met:
+//   - no transport creds and no creds bundle is configured
+//   - both transport creds and creds bundle are configured
+//   - creds bundle is configured, but it lacks a transport credentials
+//   - insecure transport creds configured alongside call creds that require
+//     transport level security
+//
+// If none of the above conditions are met, the configured credentials are
+// deemed valid and a nil error is returned.
+func (cc *ClientConn) validateTransportCredentials() error {
+	if cc.dopts.copts.TransportCredentials == nil && cc.dopts.copts.CredsBundle == nil {
+		return errNoTransportSecurity
+	}
+	if cc.dopts.copts.TransportCredentials != nil && cc.dopts.copts.CredsBundle != nil {
+		return errTransportCredsAndBundle
+	}
+	if cc.dopts.copts.CredsBundle != nil && cc.dopts.copts.CredsBundle.TransportCredentials() == nil {
+		return errNoTransportCredsInBundle
+	}
+	transportCreds := cc.dopts.copts.TransportCredentials
+	if transportCreds == nil {
+		transportCreds = cc.dopts.copts.CredsBundle.TransportCredentials()
+	}
+	if transportCreds.Info().SecurityProtocol == "insecure" {
+		for _, cd := range cc.dopts.copts.PerRPCCredentials {
+			if cd.RequireTransportSecurity() {
+				return errTransportCredentialsMissing
 			}
 		}
 	}
+	return nil
+}
 
-	return cc, nil
+// channelzRegistration registers the newly created ClientConn with channelz and
+// stores the returned identifier in `cc.channelzID` and `cc.csMgr.channelzID`.
+// A channelz trace event is emitted for ClientConn creation. If the newly
+// created ClientConn is a nested one, i.e a valid parent ClientConn ID is
+// specified via a dial option, the trace event is also added to the parent.
+//
+// Doesn't grab cc.mu as this method is expected to be called only at Dial time.
+func (cc *ClientConn) channelzRegistration(target string) {
+	cc.channelzID = channelz.RegisterChannel(&channelzChannel{cc}, cc.dopts.channelzParentID, target)
+	cc.addTraceEvent("created")
+	cc.csMgr.channelzID = cc.channelzID
 }
 
 // chainUnaryClientInterceptors chains all unary client interceptors into one.
@@ -484,7 +620,9 @@ type ClientConn struct {
 	authority       string               // See determineAuthority().
 	dopts           dialOptions          // Default and user specified dial options.
 	channelzID      *channelz.Identifier // Channelz identifier for the channel.
+	resolverBuilder resolver.Builder     // See parseTargetAndFindResolver().
 	balancerWrapper *ccBalancerWrapper   // Uses gracefulswitch.balancer underneath.
+	idlenessMgr     idlenessManager
 
 	// The following provide their own synchronization, and therefore don't
 	// require cc.mu to be held to access them.
@@ -505,11 +643,31 @@ type ClientConn struct {
 	sc              *ServiceConfig             // Latest service config received from the resolver.
 	conns           map[*addrConn]struct{}     // Set to nil on close.
 	mkp             keepalive.ClientParameters // May be updated upon receipt of a GoAway.
+	idlenessState   ccIdlenessState            // Tracks idleness state of the channel.
+	exitIdleCond    *sync.Cond                 // Signalled when channel exits idle.
 
 	lceMu               sync.Mutex // protects lastConnectionError
 	lastConnectionError error
 }
 
+// ccIdlenessState tracks the idleness state of the channel.
+//
+// Channels start off in `active` and move to `idle` after a period of
+// inactivity. When moving back to `active` upon an incoming RPC, they
+// transition through `exiting_idle`. This state is useful for synchronization
+// with Close().
+//
+// This state tracking is mostly for self-protection. The idlenessManager is
+// expected to keep track of the state as well, and is expected not to call into
+// the ClientConn unnecessarily.
+type ccIdlenessState int8
+
+const (
+	ccIdlenessStateActive ccIdlenessState = iota
+	ccIdlenessStateIdle
+	ccIdlenessStateExitingIdle
+)
+
 // WaitForStateChange waits until the connectivity.State of ClientConn changes from sourceState or
 // ctx expires. A true value is returned in former case and false in latter.
 //
@@ -549,7 +707,10 @@ func (cc *ClientConn) GetState() connectivity.State {
 // Notice: This API is EXPERIMENTAL and may be changed or removed in a later
 // release.
 func (cc *ClientConn) Connect() {
-	cc.balancerWrapper.exitIdle()
+	cc.exitIdleMode()
+	// If the ClientConn was not in idle mode, we need to call ExitIdle on the
+	// LB policy so that connections can be created.
+	cc.balancerWrapper.exitIdleMode()
 }
 
 func (cc *ClientConn) scWatcher() {
@@ -718,6 +879,7 @@ func (cc *ClientConn) newAddrConn(addrs []resolver.Address, opts balancer.NewSub
 		dopts:        cc.dopts,
 		czData:       new(channelzData),
 		resetBackoff: make(chan struct{}),
+		stateChan:    make(chan struct{}),
 	}
 	ac.ctx, ac.cancel = context.WithCancel(cc.ctx)
 	// Track ac in cc. This needs to be done before any getTransport(...) is called.
@@ -811,9 +973,6 @@ func (ac *addrConn) connect() error {
 		ac.mu.Unlock()
 		return nil
 	}
-	// Update connectivity state within the lock to prevent subsequent or
-	// concurrent calls from resetting the transport more than once.
-	ac.updateConnectivityState(connectivity.Connecting, nil)
 	ac.mu.Unlock()
 
 	ac.resetTransport()
@@ -832,58 +991,62 @@ func equalAddresses(a, b []resolver.Address) bool {
 	return true
 }
 
-// tryUpdateAddrs tries to update ac.addrs with the new addresses list.
-//
-// If ac is TransientFailure, it updates ac.addrs and returns true. The updated
-// addresses will be picked up by retry in the next iteration after backoff.
-//
-// If ac is Shutdown or Idle, it updates ac.addrs and returns true.
-//
-// If the addresses is the same as the old list, it does nothing and returns
-// true.
-//
-// If ac is Connecting, it returns false. The caller should tear down the ac and
-// create a new one. Note that the backoff will be reset when this happens.
-//
-// If ac is Ready, it checks whether current connected address of ac is in the
-// new addrs list.
-//   - If true, it updates ac.addrs and returns true. The ac will keep using
-//     the existing connection.
-//   - If false, it does nothing and returns false.
-func (ac *addrConn) tryUpdateAddrs(addrs []resolver.Address) bool {
+// updateAddrs updates ac.addrs with the new addresses list and handles active
+// connections or connection attempts.
+func (ac *addrConn) updateAddrs(addrs []resolver.Address) {
 	ac.mu.Lock()
-	defer ac.mu.Unlock()
-	channelz.Infof(logger, ac.channelzID, "addrConn: tryUpdateAddrs curAddr: %v, addrs: %v", ac.curAddr, addrs)
+	channelz.Infof(logger, ac.channelzID, "addrConn: updateAddrs curAddr: %v, addrs: %v", ac.curAddr, addrs)
+
+	if equalAddresses(ac.addrs, addrs) {
+		ac.mu.Unlock()
+		return
+	}
+
+	ac.addrs = addrs
+
 	if ac.state == connectivity.Shutdown ||
 		ac.state == connectivity.TransientFailure ||
 		ac.state == connectivity.Idle {
-		ac.addrs = addrs
-		return true
+		// We were not connecting, so do nothing but update the addresses.
+		ac.mu.Unlock()
+		return
 	}
 
-	if equalAddresses(ac.addrs, addrs) {
-		return true
+	if ac.state == connectivity.Ready {
+		// Try to find the connected address.
+		for _, a := range addrs {
+			a.ServerName = ac.cc.getServerName(a)
+			if a.Equal(ac.curAddr) {
+				// We are connected to a valid address, so do nothing but
+				// update the addresses.
+				ac.mu.Unlock()
+				return
+			}
+		}
 	}
 
-	if ac.state == connectivity.Connecting {
-		return false
-	}
+	// We are either connected to the wrong address or currently connecting.
+	// Stop the current iteration and restart.
 
-	// ac.state is Ready, try to find the connected address.
-	var curAddrFound bool
-	for _, a := range addrs {
-		a.ServerName = ac.cc.getServerName(a)
-		if reflect.DeepEqual(ac.curAddr, a) {
-			curAddrFound = true
-			break
-		}
+	ac.cancel()
+	ac.ctx, ac.cancel = context.WithCancel(ac.cc.ctx)
+
+	// We have to defer here because GracefulClose => Close => onClose, which
+	// requires locking ac.mu.
+	if ac.transport != nil {
+		defer ac.transport.GracefulClose()
+		ac.transport = nil
 	}
-	channelz.Infof(logger, ac.channelzID, "addrConn: tryUpdateAddrs curAddrFound: %v", curAddrFound)
-	if curAddrFound {
-		ac.addrs = addrs
+
+	if len(addrs) == 0 {
+		ac.updateConnectivityState(connectivity.Idle, nil)
 	}
 
-	return curAddrFound
+	ac.mu.Unlock()
+
+	// Since we were connecting/connected, we should start a new connection
+	// attempt.
+	go ac.resetTransport()
 }
 
 // getServerName determines the serverName to be used in the connection
@@ -1036,39 +1199,40 @@ func (cc *ClientConn) Close() error {
 		cc.mu.Unlock()
 		return ErrClientConnClosing
 	}
+
+	for cc.idlenessState == ccIdlenessStateExitingIdle {
+		cc.exitIdleCond.Wait()
+	}
+
 	conns := cc.conns
 	cc.conns = nil
 	cc.csMgr.updateState(connectivity.Shutdown)
 
+	pWrapper := cc.blockingpicker
 	rWrapper := cc.resolverWrapper
-	cc.resolverWrapper = nil
 	bWrapper := cc.balancerWrapper
+	idlenessMgr := cc.idlenessMgr
 	cc.mu.Unlock()
 
 	// The order of closing matters here since the balancer wrapper assumes the
 	// picker is closed before it is closed.
-	cc.blockingpicker.close()
+	if pWrapper != nil {
+		pWrapper.close()
+	}
 	if bWrapper != nil {
 		bWrapper.close()
 	}
 	if rWrapper != nil {
 		rWrapper.close()
 	}
+	if idlenessMgr != nil {
+		idlenessMgr.close()
+	}
 
 	for ac := range conns {
 		ac.tearDown(ErrClientConnClosing)
 	}
-	ted := &channelz.TraceEventDesc{
-		Desc:     "Channel deleted",
-		Severity: channelz.CtInfo,
-	}
-	if cc.dopts.channelzParentID != nil {
-		ted.Parent = &channelz.TraceEventDesc{
-			Desc:     fmt.Sprintf("Nested channel(id:%d) deleted", cc.channelzID.Int()),
-			Severity: channelz.CtInfo,
-		}
-	}
-	channelz.AddTraceEvent(logger, cc.channelzID, 0, ted)
+	cc.addTraceEvent("deleted")
 	// TraceEvent needs to be called before RemoveEntry, as TraceEvent may add
 	// trace reference to the entity being deleted, and thus prevent it from being
 	// deleted right away.
@@ -1098,7 +1262,8 @@ type addrConn struct {
 	addrs   []resolver.Address // All addresses that the resolver resolved to.
 
 	// Use updateConnectivityState for updating addrConn's connectivity state.
-	state connectivity.State
+	state     connectivity.State
+	stateChan chan struct{} // closed and recreated on every state change.
 
 	backoffIdx   int // Needs to be stateful for resetConnectBackoff.
 	resetBackoff chan struct{}
@@ -1112,6 +1277,9 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error)
 	if ac.state == s {
 		return
 	}
+	// When changing states, reset the state change channel.
+	close(ac.stateChan)
+	ac.stateChan = make(chan struct{})
 	ac.state = s
 	if lastErr == nil {
 		channelz.Infof(logger, ac.channelzID, "Subchannel Connectivity change to %v", s)
@@ -1137,7 +1305,8 @@ func (ac *addrConn) adjustParams(r transport.GoAwayReason) {
 
 func (ac *addrConn) resetTransport() {
 	ac.mu.Lock()
-	if ac.state == connectivity.Shutdown {
+	acCtx := ac.ctx
+	if acCtx.Err() != nil {
 		ac.mu.Unlock()
 		return
 	}
@@ -1165,15 +1334,14 @@ func (ac *addrConn) resetTransport() {
 	ac.updateConnectivityState(connectivity.Connecting, nil)
 	ac.mu.Unlock()
 
-	if err := ac.tryAllAddrs(addrs, connectDeadline); err != nil {
+	if err := ac.tryAllAddrs(acCtx, addrs, connectDeadline); err != nil {
 		ac.cc.resolveNow(resolver.ResolveNowOptions{})
 		// After exhausting all addresses, the addrConn enters
 		// TRANSIENT_FAILURE.
-		ac.mu.Lock()
-		if ac.state == connectivity.Shutdown {
-			ac.mu.Unlock()
+		if acCtx.Err() != nil {
 			return
 		}
+		ac.mu.Lock()
 		ac.updateConnectivityState(connectivity.TransientFailure, err)
 
 		// Backoff.
@@ -1188,13 +1356,13 @@ func (ac *addrConn) resetTransport() {
 			ac.mu.Unlock()
 		case <-b:
 			timer.Stop()
-		case <-ac.ctx.Done():
+		case <-acCtx.Done():
 			timer.Stop()
 			return
 		}
 
 		ac.mu.Lock()
-		if ac.state != connectivity.Shutdown {
+		if acCtx.Err() == nil {
 			ac.updateConnectivityState(connectivity.Idle, err)
 		}
 		ac.mu.Unlock()
@@ -1209,14 +1377,13 @@ func (ac *addrConn) resetTransport() {
 // tryAllAddrs tries to creates a connection to the addresses, and stop when at
 // the first successful one. It returns an error if no address was successfully
 // connected, or updates ac appropriately with the new transport.
-func (ac *addrConn) tryAllAddrs(addrs []resolver.Address, connectDeadline time.Time) error {
+func (ac *addrConn) tryAllAddrs(ctx context.Context, addrs []resolver.Address, connectDeadline time.Time) error {
 	var firstConnErr error
 	for _, addr := range addrs {
-		ac.mu.Lock()
-		if ac.state == connectivity.Shutdown {
-			ac.mu.Unlock()
+		if ctx.Err() != nil {
 			return errConnClosing
 		}
+		ac.mu.Lock()
 
 		ac.cc.mu.RLock()
 		ac.dopts.copts.KeepaliveParams = ac.cc.mkp
@@ -1230,7 +1397,7 @@ func (ac *addrConn) tryAllAddrs(addrs []resolver.Address, connectDeadline time.T
 
 		channelz.Infof(logger, ac.channelzID, "Subchannel picks a new address %q to connect", addr.Addr)
 
-		err := ac.createTransport(addr, copts, connectDeadline)
+		err := ac.createTransport(ctx, addr, copts, connectDeadline)
 		if err == nil {
 			return nil
 		}
@@ -1247,19 +1414,20 @@ func (ac *addrConn) tryAllAddrs(addrs []resolver.Address, connectDeadline time.T
 // createTransport creates a connection to addr. It returns an error if the
 // address was not successfully connected, or updates ac appropriately with the
 // new transport.
-func (ac *addrConn) createTransport(addr resolver.Address, copts transport.ConnectOptions, connectDeadline time.Time) error {
+func (ac *addrConn) createTransport(ctx context.Context, addr resolver.Address, copts transport.ConnectOptions, connectDeadline time.Time) error {
 	addr.ServerName = ac.cc.getServerName(addr)
-	hctx, hcancel := context.WithCancel(ac.ctx)
+	hctx, hcancel := context.WithCancel(ctx)
 
 	onClose := func(r transport.GoAwayReason) {
 		ac.mu.Lock()
 		defer ac.mu.Unlock()
 		// adjust params based on GoAwayReason
 		ac.adjustParams(r)
-		if ac.state == connectivity.Shutdown {
-			// Already shut down.  tearDown() already cleared the transport and
-			// canceled hctx via ac.ctx, and we expected this connection to be
-			// closed, so do nothing here.
+		if ctx.Err() != nil {
+			// Already shut down or connection attempt canceled.  tearDown() or
+			// updateAddrs() already cleared the transport and canceled hctx
+			// via ac.ctx, and we expected this connection to be closed, so do
+			// nothing here.
 			return
 		}
 		hcancel()
@@ -1278,7 +1446,7 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
 		ac.updateConnectivityState(connectivity.Idle, nil)
 	}
 
-	connectCtx, cancel := context.WithDeadline(ac.ctx, connectDeadline)
+	connectCtx, cancel := context.WithDeadline(ctx, connectDeadline)
 	defer cancel()
 	copts.ChannelzParentID = ac.channelzID
 
@@ -1295,7 +1463,7 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
 
 	ac.mu.Lock()
 	defer ac.mu.Unlock()
-	if ac.state == connectivity.Shutdown {
+	if ctx.Err() != nil {
 		// This can happen if the subConn was removed while in `Connecting`
 		// state. tearDown() would have set the state to `Shutdown`, but
 		// would not have closed the transport since ac.transport would not
@@ -1307,6 +1475,9 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
 		// The error we pass to Close() is immaterial since there are no open
 		// streams at this point, so no trailers with error details will be sent
 		// out. We just need to pass a non-nil error.
+		//
+		// This can also happen when updateAddrs is called during a connection
+		// attempt.
 		go newTr.Close(transport.ErrConnClosing)
 		return nil
 	}
@@ -1414,6 +1585,29 @@ func (ac *addrConn) getReadyTransport() transport.ClientTransport {
 	return nil
 }
 
+// getTransport waits until the addrconn is ready and returns the transport.
+// If the context expires first, returns an appropriate status.  If the
+// addrConn is stopped first, returns an Unavailable status error.
+func (ac *addrConn) getTransport(ctx context.Context) (transport.ClientTransport, error) {
+	for ctx.Err() == nil {
+		ac.mu.Lock()
+		t, state, sc := ac.transport, ac.state, ac.stateChan
+		ac.mu.Unlock()
+		if state == connectivity.Ready {
+			return t, nil
+		}
+		if state == connectivity.Shutdown {
+			return nil, status.Errorf(codes.Unavailable, "SubConn shutting down")
+		}
+
+		select {
+		case <-ctx.Done():
+		case <-sc:
+		}
+	}
+	return nil, status.FromContextError(ctx.Err()).Err()
+}
+
 // tearDown starts to tear down the addrConn.
 //
 // Note that tearDown doesn't remove ac from ac.cc.conns, so the addrConn struct
@@ -1565,7 +1759,14 @@ func (cc *ClientConn) connectionError() error {
 	return cc.lastConnectionError
 }
 
-func (cc *ClientConn) parseTargetAndFindResolver() (resolver.Builder, error) {
+// parseTargetAndFindResolver parses the user's dial target and stores the
+// parsed target in `cc.parsedTarget`.
+//
+// The resolver to use is determined based on the scheme in the parsed target
+// and the same is stored in `cc.resolverBuilder`.
+//
+// Doesn't grab cc.mu as this method is expected to be called only at Dial time.
+func (cc *ClientConn) parseTargetAndFindResolver() error {
 	channelz.Infof(logger, cc.channelzID, "original dial target is: %q", cc.target)
 
 	var rb resolver.Builder
@@ -1577,7 +1778,8 @@ func (cc *ClientConn) parseTargetAndFindResolver() (resolver.Builder, error) {
 		rb = cc.getResolver(parsedTarget.URL.Scheme)
 		if rb != nil {
 			cc.parsedTarget = parsedTarget
-			return rb, nil
+			cc.resolverBuilder = rb
+			return nil
 		}
 	}
 
@@ -1592,15 +1794,16 @@ func (cc *ClientConn) parseTargetAndFindResolver() (resolver.Builder, error) {
 	parsedTarget, err = parseTarget(canonicalTarget)
 	if err != nil {
 		channelz.Infof(logger, cc.channelzID, "dial target %q parse failed: %v", canonicalTarget, err)
-		return nil, err
+		return err
 	}
 	channelz.Infof(logger, cc.channelzID, "parsed dial target is: %+v", parsedTarget)
 	rb = cc.getResolver(parsedTarget.URL.Scheme)
 	if rb == nil {
-		return nil, fmt.Errorf("could not get resolver for default scheme: %q", parsedTarget.URL.Scheme)
+		return fmt.Errorf("could not get resolver for default scheme: %q", parsedTarget.URL.Scheme)
 	}
 	cc.parsedTarget = parsedTarget
-	return rb, nil
+	cc.resolverBuilder = rb
+	return nil
 }
 
 // parseTarget uses RFC 3986 semantics to parse the given target into a
@@ -1623,7 +1826,15 @@ func parseTarget(target string) (resolver.Target, error) {
 // - user specified authority override using `WithAuthority` dial option
 // - creds' notion of server name for the authentication handshake
 // - endpoint from dial target of the form "scheme://[authority]/endpoint"
-func determineAuthority(endpoint, target string, dopts dialOptions) (string, error) {
+//
+// Stores the determined authority in `cc.authority`.
+//
+// Returns a non-nil error if the authority returned by the transport
+// credentials do not match the authority configured through the dial option.
+//
+// Doesn't grab cc.mu as this method is expected to be called only at Dial time.
+func (cc *ClientConn) determineAuthority() error {
+	dopts := cc.dopts
 	// Historically, we had two options for users to specify the serverName or
 	// authority for a channel. One was through the transport credentials
 	// (either in its constructor, or through the OverrideServerName() method).
@@ -1640,25 +1851,58 @@ func determineAuthority(endpoint, target string, dopts dialOptions) (string, err
 	}
 	authorityFromDialOption := dopts.authority
 	if (authorityFromCreds != "" && authorityFromDialOption != "") && authorityFromCreds != authorityFromDialOption {
-		return "", fmt.Errorf("ClientConn's authority from transport creds %q and dial option %q don't match", authorityFromCreds, authorityFromDialOption)
+		return fmt.Errorf("ClientConn's authority from transport creds %q and dial option %q don't match", authorityFromCreds, authorityFromDialOption)
 	}
 
+	endpoint := cc.parsedTarget.Endpoint()
+	target := cc.target
 	switch {
 	case authorityFromDialOption != "":
-		return authorityFromDialOption, nil
+		cc.authority = authorityFromDialOption
 	case authorityFromCreds != "":
-		return authorityFromCreds, nil
+		cc.authority = authorityFromCreds
 	case strings.HasPrefix(target, "unix:") || strings.HasPrefix(target, "unix-abstract:"):
 		// TODO: remove when the unix resolver implements optional interface to
 		// return channel authority.
-		return "localhost", nil
+		cc.authority = "localhost"
 	case strings.HasPrefix(endpoint, ":"):
-		return "localhost" + endpoint, nil
+		cc.authority = "localhost" + endpoint
 	default:
 		// TODO: Define an optional interface on the resolver builder to return
 		// the channel authority given the user's dial target. For resolvers
 		// which don't implement this interface, we will use the endpoint from
 		// "scheme://authority/endpoint" as the default authority.
-		return endpoint, nil
+		cc.authority = endpoint
+	}
+	channelz.Infof(logger, cc.channelzID, "Channel authority set to %q", cc.authority)
+	return nil
+}
+
+// initResolverWrapper creates a ccResolverWrapper, which builds the name
+// resolver. This method grabs the lock to assign the newly built resolver
+// wrapper to the cc.resolverWrapper field.
+func (cc *ClientConn) initResolverWrapper(creds credentials.TransportCredentials) error {
+	rw, err := newCCResolverWrapper(cc, ccResolverWrapperOpts{
+		target:  cc.parsedTarget,
+		builder: cc.resolverBuilder,
+		bOpts: resolver.BuildOptions{
+			DisableServiceConfig: cc.dopts.disableServiceConfig,
+			DialCreds:            creds,
+			CredsBundle:          cc.dopts.copts.CredsBundle,
+			Dialer:               cc.dopts.copts.Dialer,
+		},
+		channelzID: cc.channelzID,
+	})
+	if err != nil {
+		return fmt.Errorf("failed to build resolver: %v", err)
 	}
+	// Resolver implementations may report state update or error inline when
+	// built (or right after), and this is handled in cc.updateResolverState.
+	// Also, an error from the resolver might lead to a re-resolution request
+	// from the balancer, which is handled in resolveNow() where
+	// `cc.resolverWrapper` is accessed. Hence, we need to hold the lock here.
+	cc.mu.Lock()
+	cc.resolverWrapper = rw
+	cc.mu.Unlock()
+	return nil
 }
diff --git a/vendor/google.golang.org/grpc/dialoptions.go b/vendor/google.golang.org/grpc/dialoptions.go
index e9d6852fd..15a3d5102 100644
--- a/vendor/google.golang.org/grpc/dialoptions.go
+++ b/vendor/google.golang.org/grpc/dialoptions.go
@@ -77,6 +77,7 @@ type dialOptions struct {
 	defaultServiceConfig        *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
 	defaultServiceConfigRawJSON *string
 	resolvers                   []resolver.Builder
+	idleTimeout                 time.Duration
 }
 
 // DialOption configures how we set up the connection.
@@ -295,6 +296,9 @@ func withBackoff(bs internalbackoff.Strategy) DialOption {
 // WithBlock returns a DialOption which makes callers of Dial block until the
 // underlying connection is up. Without this, Dial returns immediately and
 // connecting the server happens in background.
+//
+// Use of this feature is not recommended.  For more information, please see:
+// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
 func WithBlock() DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.block = true
@@ -306,6 +310,9 @@ func WithBlock() DialOption {
 // the context.DeadlineExceeded error.
 // Implies WithBlock()
 //
+// Use of this feature is not recommended.  For more information, please see:
+// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
+//
 // # Experimental
 //
 // Notice: This API is EXPERIMENTAL and may be changed or removed in a
@@ -448,6 +455,9 @@ func withBinaryLogger(bl binarylog.Logger) DialOption {
 // FailOnNonTempDialError only affects the initial dial, and does not do
 // anything useful unless you are also using WithBlock().
 //
+// Use of this feature is not recommended.  For more information, please see:
+// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
+//
 // # Experimental
 //
 // Notice: This API is EXPERIMENTAL and may be changed or removed in a
@@ -646,3 +656,23 @@ func WithResolvers(rs ...resolver.Builder) DialOption {
 		o.resolvers = append(o.resolvers, rs...)
 	})
 }
+
+// WithIdleTimeout returns a DialOption that configures an idle timeout for the
+// channel. If the channel is idle for the configured timeout, i.e there are no
+// ongoing RPCs and no new RPCs are initiated, the channel will enter idle mode
+// and as a result the name resolver and load balancer will be shut down. The
+// channel will exit idle mode when the Connect() method is called or when an
+// RPC is initiated.
+//
+// By default this feature is disabled, which can also be explicitly configured
+// by passing zero to this function.
+//
+// # Experimental
+//
+// Notice: This API is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func WithIdleTimeout(d time.Duration) DialOption {
+	return newFuncDialOption(func(o *dialOptions) {
+		o.idleTimeout = d
+	})
+}
diff --git a/vendor/google.golang.org/grpc/idle.go b/vendor/google.golang.org/grpc/idle.go
new file mode 100644
index 000000000..dc3dc72f6
--- /dev/null
+++ b/vendor/google.golang.org/grpc/idle.go
@@ -0,0 +1,287 @@
+/*
+ *
+ * Copyright 2023 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+	"fmt"
+	"math"
+	"sync"
+	"sync/atomic"
+	"time"
+)
+
+// For overriding in unit tests.
+var timeAfterFunc = func(d time.Duration, f func()) *time.Timer {
+	return time.AfterFunc(d, f)
+}
+
+// idlenessEnforcer is the functionality provided by grpc.ClientConn to enter
+// and exit from idle mode.
+type idlenessEnforcer interface {
+	exitIdleMode() error
+	enterIdleMode() error
+}
+
+// idlenessManager defines the functionality required to track RPC activity on a
+// channel.
+type idlenessManager interface {
+	onCallBegin() error
+	onCallEnd()
+	close()
+}
+
+type noopIdlenessManager struct{}
+
+func (noopIdlenessManager) onCallBegin() error { return nil }
+func (noopIdlenessManager) onCallEnd()         {}
+func (noopIdlenessManager) close()             {}
+
+// idlenessManagerImpl implements the idlenessManager interface. It uses atomic
+// operations to synchronize access to shared state and a mutex to guarantee
+// mutual exclusion in a critical section.
+type idlenessManagerImpl struct {
+	// State accessed atomically.
+	lastCallEndTime           int64 // Unix timestamp in nanos; time when the most recent RPC completed.
+	activeCallsCount          int32 // Count of active RPCs; -math.MaxInt32 means channel is idle or is trying to get there.
+	activeSinceLastTimerCheck int32 // Boolean; True if there was an RPC since the last timer callback.
+	closed                    int32 // Boolean; True when the manager is closed.
+
+	// Can be accessed without atomics or mutex since these are set at creation
+	// time and read-only after that.
+	enforcer idlenessEnforcer // Functionality provided by grpc.ClientConn.
+	timeout  int64            // Idle timeout duration nanos stored as an int64.
+
+	// idleMu is used to guarantee mutual exclusion in two scenarios:
+	// - Opposing intentions:
+	//   - a: Idle timeout has fired and handleIdleTimeout() is trying to put
+	//     the channel in idle mode because the channel has been inactive.
+	//   - b: At the same time an RPC is made on the channel, and onCallBegin()
+	//     is trying to prevent the channel from going idle.
+	// - Competing intentions:
+	//   - The channel is in idle mode and there are multiple RPCs starting at
+	//     the same time, all trying to move the channel out of idle. Only one
+	//     of them should succeed in doing so, while the other RPCs should
+	//     piggyback on the first one and be successfully handled.
+	idleMu       sync.RWMutex
+	actuallyIdle bool
+	timer        *time.Timer
+}
+
+// newIdlenessManager creates a new idleness manager implementation for the
+// given idle timeout.
+func newIdlenessManager(enforcer idlenessEnforcer, idleTimeout time.Duration) idlenessManager {
+	if idleTimeout == 0 {
+		return noopIdlenessManager{}
+	}
+
+	i := &idlenessManagerImpl{
+		enforcer: enforcer,
+		timeout:  int64(idleTimeout),
+	}
+	i.timer = timeAfterFunc(idleTimeout, i.handleIdleTimeout)
+	return i
+}
+
+// resetIdleTimer resets the idle timer to the given duration. This method
+// should only be called from the timer callback.
+func (i *idlenessManagerImpl) resetIdleTimer(d time.Duration) {
+	i.idleMu.Lock()
+	defer i.idleMu.Unlock()
+
+	if i.timer == nil {
+		// Only close sets timer to nil. We are done.
+		return
+	}
+
+	// It is safe to ignore the return value from Reset() because this method is
+	// only ever called from the timer callback, which means the timer has
+	// already fired.
+	i.timer.Reset(d)
+}
+
+// handleIdleTimeout is the timer callback that is invoked upon expiry of the
+// configured idle timeout. The channel is considered inactive if there are no
+// ongoing calls and no RPC activity since the last time the timer fired.
+func (i *idlenessManagerImpl) handleIdleTimeout() {
+	if i.isClosed() {
+		return
+	}
+
+	if atomic.LoadInt32(&i.activeCallsCount) > 0 {
+		i.resetIdleTimer(time.Duration(i.timeout))
+		return
+	}
+
+	// There has been activity on the channel since we last got here. Reset the
+	// timer and return.
+	if atomic.LoadInt32(&i.activeSinceLastTimerCheck) == 1 {
+		// Set the timer to fire after a duration of idle timeout, calculated
+		// from the time the most recent RPC completed.
+		atomic.StoreInt32(&i.activeSinceLastTimerCheck, 0)
+		i.resetIdleTimer(time.Duration(atomic.LoadInt64(&i.lastCallEndTime) + i.timeout - time.Now().UnixNano()))
+		return
+	}
+
+	// This CAS operation is extremely likely to succeed given that there has
+	// been no activity since the last time we were here.  Setting the
+	// activeCallsCount to -math.MaxInt32 indicates to onCallBegin() that the
+	// channel is either in idle mode or is trying to get there.
+	if !atomic.CompareAndSwapInt32(&i.activeCallsCount, 0, -math.MaxInt32) {
+		// This CAS operation can fail if an RPC started after we checked for
+		// activity at the top of this method, or one was ongoing from before
+		// the last time we were here. In both case, reset the timer and return.
+		i.resetIdleTimer(time.Duration(i.timeout))
+		return
+	}
+
+	// Now that we've set the active calls count to -math.MaxInt32, it's time to
+	// actually move to idle mode.
+	if i.tryEnterIdleMode() {
+		// Successfully entered idle mode. No timer needed until we exit idle.
+		return
+	}
+
+	// Failed to enter idle mode due to a concurrent RPC that kept the channel
+	// active, or because of an error from the channel. Undo the attempt to
+	// enter idle, and reset the timer to try again later.
+	atomic.AddInt32(&i.activeCallsCount, math.MaxInt32)
+	i.resetIdleTimer(time.Duration(i.timeout))
+}
+
+// tryEnterIdleMode instructs the channel to enter idle mode. But before
+// that, it performs a last minute check to ensure that no new RPC has come in,
+// making the channel active.
+//
+// Return value indicates whether or not the channel moved to idle mode.
+//
+// Holds idleMu which ensures mutual exclusion with exitIdleMode.
+func (i *idlenessManagerImpl) tryEnterIdleMode() bool {
+	i.idleMu.Lock()
+	defer i.idleMu.Unlock()
+
+	if atomic.LoadInt32(&i.activeCallsCount) != -math.MaxInt32 {
+		// We raced and lost to a new RPC. Very rare, but stop entering idle.
+		return false
+	}
+	if atomic.LoadInt32(&i.activeSinceLastTimerCheck) == 1 {
+		// An very short RPC could have come in (and also finished) after we
+		// checked for calls count and activity in handleIdleTimeout(), but
+		// before the CAS operation. So, we need to check for activity again.
+		return false
+	}
+
+	// No new RPCs have come in since we last set the active calls count value
+	// -math.MaxInt32 in the timer callback. And since we have the lock, it is
+	// safe to enter idle mode now.
+	if err := i.enforcer.enterIdleMode(); err != nil {
+		logger.Errorf("Failed to enter idle mode: %v", err)
+		return false
+	}
+
+	// Successfully entered idle mode.
+	i.actuallyIdle = true
+	return true
+}
+
+// onCallBegin is invoked at the start of every RPC.
+func (i *idlenessManagerImpl) onCallBegin() error {
+	if i.isClosed() {
+		return nil
+	}
+
+	if atomic.AddInt32(&i.activeCallsCount, 1) > 0 {
+		// Channel is not idle now. Set the activity bit and allow the call.
+		atomic.StoreInt32(&i.activeSinceLastTimerCheck, 1)
+		return nil
+	}
+
+	// Channel is either in idle mode or is in the process of moving to idle
+	// mode. Attempt to exit idle mode to allow this RPC.
+	if err := i.exitIdleMode(); err != nil {
+		// Undo the increment to calls count, and return an error causing the
+		// RPC to fail.
+		atomic.AddInt32(&i.activeCallsCount, -1)
+		return err
+	}
+
+	atomic.StoreInt32(&i.activeSinceLastTimerCheck, 1)
+	return nil
+}
+
+// exitIdleMode instructs the channel to exit idle mode.
+//
+// Holds idleMu which ensures mutual exclusion with tryEnterIdleMode.
+func (i *idlenessManagerImpl) exitIdleMode() error {
+	i.idleMu.Lock()
+	defer i.idleMu.Unlock()
+
+	if !i.actuallyIdle {
+		// This can happen in two scenarios:
+		// - handleIdleTimeout() set the calls count to -math.MaxInt32 and called
+		//   tryEnterIdleMode(). But before the latter could grab the lock, an RPC
+		//   came in and onCallBegin() noticed that the calls count is negative.
+		// - Channel is in idle mode, and multiple new RPCs come in at the same
+		//   time, all of them notice a negative calls count in onCallBegin and get
+		//   here. The first one to get the lock would got the channel to exit idle.
+		//
+		// Either way, nothing to do here.
+		return nil
+	}
+
+	if err := i.enforcer.exitIdleMode(); err != nil {
+		return fmt.Errorf("channel failed to exit idle mode: %v", err)
+	}
+
+	// Undo the idle entry process. This also respects any new RPC attempts.
+	atomic.AddInt32(&i.activeCallsCount, math.MaxInt32)
+	i.actuallyIdle = false
+
+	// Start a new timer to fire after the configured idle timeout.
+	i.timer = timeAfterFunc(time.Duration(i.timeout), i.handleIdleTimeout)
+	return nil
+}
+
+// onCallEnd is invoked at the end of every RPC.
+func (i *idlenessManagerImpl) onCallEnd() {
+	if i.isClosed() {
+		return
+	}
+
+	// Record the time at which the most recent call finished.
+	atomic.StoreInt64(&i.lastCallEndTime, time.Now().UnixNano())
+
+	// Decrement the active calls count. This count can temporarily go negative
+	// when the timer callback is in the process of moving the channel to idle
+	// mode, but one or more RPCs come in and complete before the timer callback
+	// can get done with the process of moving to idle mode.
+	atomic.AddInt32(&i.activeCallsCount, -1)
+}
+
+func (i *idlenessManagerImpl) isClosed() bool {
+	return atomic.LoadInt32(&i.closed) == 1
+}
+
+func (i *idlenessManagerImpl) close() {
+	atomic.StoreInt32(&i.closed, 1)
+
+	i.idleMu.Lock()
+	i.timer.Stop()
+	i.timer = nil
+	i.idleMu.Unlock()
+}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go b/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
index af03a40d9..755fdebc1 100644
--- a/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
+++ b/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
@@ -32,6 +32,9 @@ var grpclogLogger = grpclog.Component("binarylog")
 
 // Logger specifies MethodLoggers for method names with a Log call that
 // takes a context.
+//
+// This is used in the 1.0 release of gcp/observability, and thus must not be
+// deleted or changed.
 type Logger interface {
 	GetMethodLogger(methodName string) MethodLogger
 }
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
index 56fcf008d..6c3f63221 100644
--- a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
+++ b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
@@ -49,6 +49,9 @@ func (g *callIDGenerator) reset() {
 var idGen callIDGenerator
 
 // MethodLogger is the sub-logger for each method.
+//
+// This is used in the 1.0 release of gcp/observability, and thus must not be
+// deleted or changed.
 type MethodLogger interface {
 	Log(context.Context, LogEntryConfig)
 }
@@ -65,6 +68,9 @@ type TruncatingMethodLogger struct {
 }
 
 // NewTruncatingMethodLogger returns a new truncating method logger.
+//
+// This is used in the 1.0 release of gcp/observability, and thus must not be
+// deleted or changed.
 func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger {
 	return &TruncatingMethodLogger{
 		headerMaxLen:  h,
@@ -145,6 +151,9 @@ func (ml *TruncatingMethodLogger) truncateMessage(msgPb *binlogpb.Message) (trun
 }
 
 // LogEntryConfig represents the configuration for binary log entry.
+//
+// This is used in the 1.0 release of gcp/observability, and thus must not be
+// deleted or changed.
 type LogEntryConfig interface {
 	toProto() *binlogpb.GrpcLogEntry
 }
diff --git a/vendor/google.golang.org/grpc/internal/buffer/unbounded.go b/vendor/google.golang.org/grpc/internal/buffer/unbounded.go
index 9f6a0c120..81c2f5fd7 100644
--- a/vendor/google.golang.org/grpc/internal/buffer/unbounded.go
+++ b/vendor/google.golang.org/grpc/internal/buffer/unbounded.go
@@ -35,6 +35,7 @@ import "sync"
 // internal/transport/transport.go for an example of this.
 type Unbounded struct {
 	c       chan interface{}
+	closed  bool
 	mu      sync.Mutex
 	backlog []interface{}
 }
@@ -47,16 +48,18 @@ func NewUnbounded() *Unbounded {
 // Put adds t to the unbounded buffer.
 func (b *Unbounded) Put(t interface{}) {
 	b.mu.Lock()
+	defer b.mu.Unlock()
+	if b.closed {
+		return
+	}
 	if len(b.backlog) == 0 {
 		select {
 		case b.c <- t:
-			b.mu.Unlock()
 			return
 		default:
 		}
 	}
 	b.backlog = append(b.backlog, t)
-	b.mu.Unlock()
 }
 
 // Load sends the earliest buffered data, if any, onto the read channel
@@ -64,6 +67,10 @@ func (b *Unbounded) Put(t interface{}) {
 // value from the read channel.
 func (b *Unbounded) Load() {
 	b.mu.Lock()
+	defer b.mu.Unlock()
+	if b.closed {
+		return
+	}
 	if len(b.backlog) > 0 {
 		select {
 		case b.c <- b.backlog[0]:
@@ -72,7 +79,6 @@ func (b *Unbounded) Load() {
 		default:
 		}
 	}
-	b.mu.Unlock()
 }
 
 // Get returns a read channel on which values added to the buffer, via Put(),
@@ -80,6 +86,20 @@ func (b *Unbounded) Load() {
 //
 // Upon reading a value from this channel, users are expected to call Load() to
 // send the next buffered value onto the channel if there is any.
+//
+// If the unbounded buffer is closed, the read channel returned by this method
+// is closed.
 func (b *Unbounded) Get() <-chan interface{} {
 	return b.c
 }
+
+// Close closes the unbounded buffer.
+func (b *Unbounded) Close() {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+	if b.closed {
+		return
+	}
+	b.closed = true
+	close(b.c)
+}
diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
index 5ba9d94d4..80fd5c7d2 100644
--- a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
+++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
@@ -36,6 +36,10 @@ var (
 	// "GRPC_RING_HASH_CAP".  This does not override the default bounds
 	// checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M).
 	RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024)
+	// PickFirstLBConfig is set if we should support configuration of the
+	// pick_first LB policy, which can be enabled by setting the environment
+	// variable "GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG" to "true".
+	PickFirstLBConfig = boolFromEnv("GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG", false)
 )
 
 func boolFromEnv(envVar string, def bool) bool {
diff --git a/vendor/google.golang.org/grpc/internal/envconfig/observability.go b/vendor/google.golang.org/grpc/internal/envconfig/observability.go
index 821dd0a7c..dd314cfb1 100644
--- a/vendor/google.golang.org/grpc/internal/envconfig/observability.go
+++ b/vendor/google.golang.org/grpc/internal/envconfig/observability.go
@@ -28,9 +28,15 @@ const (
 var (
 	// ObservabilityConfig is the json configuration for the gcp/observability
 	// package specified directly in the envObservabilityConfig env var.
+	//
+	// This is used in the 1.0 release of gcp/observability, and thus must not be
+	// deleted or changed.
 	ObservabilityConfig = os.Getenv(envObservabilityConfig)
 	// ObservabilityConfigFile is the json configuration for the
 	// gcp/observability specified in a file with the location specified in
 	// envObservabilityConfigFile env var.
+	//
+	// This is used in the 1.0 release of gcp/observability, and thus must not be
+	// deleted or changed.
 	ObservabilityConfigFile = os.Getenv(envObservabilityConfigFile)
 )
diff --git a/vendor/google.golang.org/grpc/internal/envconfig/xds.go b/vendor/google.golang.org/grpc/internal/envconfig/xds.go
index 04136882c..02b4b6a1c 100644
--- a/vendor/google.golang.org/grpc/internal/envconfig/xds.go
+++ b/vendor/google.golang.org/grpc/internal/envconfig/xds.go
@@ -61,11 +61,10 @@ var (
 	// have a brand new API on the server-side and users explicitly need to use
 	// the new API to get security integration on the server.
 	XDSClientSideSecurity = boolFromEnv("GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT", true)
-	// XDSAggregateAndDNS indicates whether processing of aggregated cluster
-	// and DNS cluster is enabled, which can be enabled by setting the
-	// environment variable
-	// "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER" to
-	// "true".
+	// XDSAggregateAndDNS indicates whether processing of aggregated cluster and
+	// DNS cluster is enabled, which can be disabled by setting the environment
+	// variable "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"
+	// to "false".
 	XDSAggregateAndDNS = boolFromEnv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER", true)
 
 	// XDSRBAC indicates whether xDS configured RBAC HTTP Filter is enabled,
@@ -79,14 +78,18 @@ var (
 	// XDSFederation indicates whether federation support is enabled, which can
 	// be enabled by setting the environment variable
 	// "GRPC_EXPERIMENTAL_XDS_FEDERATION" to "true".
-	XDSFederation = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FEDERATION", false)
+	XDSFederation = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FEDERATION", true)
 
 	// XDSRLS indicates whether processing of Cluster Specifier plugins and
-	// support for the RLS CLuster Specifier is enabled, which can be enabled by
+	// support for the RLS CLuster Specifier is enabled, which can be disabled by
 	// setting the environment variable "GRPC_EXPERIMENTAL_XDS_RLS_LB" to
-	// "true".
-	XDSRLS = boolFromEnv("GRPC_EXPERIMENTAL_XDS_RLS_LB", false)
+	// "false".
+	XDSRLS = boolFromEnv("GRPC_EXPERIMENTAL_XDS_RLS_LB", true)
 
 	// C2PResolverTestOnlyTrafficDirectorURI is the TD URI for testing.
 	C2PResolverTestOnlyTrafficDirectorURI = os.Getenv("GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI")
+	// XDSCustomLBPolicy indicates whether Custom LB Policies are enabled, which
+	// can be disabled by setting the environment variable
+	// "GRPC_EXPERIMENTAL_XDS_CUSTOM_LB_CONFIG" to "false".
+	XDSCustomLBPolicy = boolFromEnv("GRPC_EXPERIMENTAL_XDS_CUSTOM_LB_CONFIG", true)
 )
diff --git a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
index 517ea7064..d08e3e907 100644
--- a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
+++ b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
@@ -72,3 +72,17 @@ func Uint64() uint64 {
 	defer mu.Unlock()
 	return r.Uint64()
 }
+
+// Uint32 implements rand.Uint32 on the grpcrand global source.
+func Uint32() uint32 {
+	mu.Lock()
+	defer mu.Unlock()
+	return r.Uint32()
+}
+
+// Shuffle implements rand.Shuffle on the grpcrand global source.
+var Shuffle = func(n int, f func(int, int)) {
+	mu.Lock()
+	defer mu.Unlock()
+	r.Shuffle(n, f)
+}
diff --git a/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go b/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go
new file mode 100644
index 000000000..37b8d4117
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go
@@ -0,0 +1,119 @@
+/*
+ *
+ * Copyright 2022 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpcsync
+
+import (
+	"context"
+	"sync"
+
+	"google.golang.org/grpc/internal/buffer"
+)
+
+// CallbackSerializer provides a mechanism to schedule callbacks in a
+// synchronized manner. It provides a FIFO guarantee on the order of execution
+// of scheduled callbacks. New callbacks can be scheduled by invoking the
+// Schedule() method.
+//
+// This type is safe for concurrent access.
+type CallbackSerializer struct {
+	// Done is closed once the serializer is shut down completely, i.e all
+	// scheduled callbacks are executed and the serializer has deallocated all
+	// its resources.
+	Done chan struct{}
+
+	callbacks *buffer.Unbounded
+	closedMu  sync.Mutex
+	closed    bool
+}
+
+// NewCallbackSerializer returns a new CallbackSerializer instance. The provided
+// context will be passed to the scheduled callbacks. Users should cancel the
+// provided context to shutdown the CallbackSerializer. It is guaranteed that no
+// callbacks will be added once this context is canceled, and any pending un-run
+// callbacks will be executed before the serializer is shut down.
+func NewCallbackSerializer(ctx context.Context) *CallbackSerializer {
+	t := &CallbackSerializer{
+		Done:      make(chan struct{}),
+		callbacks: buffer.NewUnbounded(),
+	}
+	go t.run(ctx)
+	return t
+}
+
+// Schedule adds a callback to be scheduled after existing callbacks are run.
+//
+// Callbacks are expected to honor the context when performing any blocking
+// operations, and should return early when the context is canceled.
+//
+// Return value indicates if the callback was successfully added to the list of
+// callbacks to be executed by the serializer. It is not possible to add
+// callbacks once the context passed to NewCallbackSerializer is cancelled.
+func (t *CallbackSerializer) Schedule(f func(ctx context.Context)) bool {
+	t.closedMu.Lock()
+	defer t.closedMu.Unlock()
+
+	if t.closed {
+		return false
+	}
+	t.callbacks.Put(f)
+	return true
+}
+
+func (t *CallbackSerializer) run(ctx context.Context) {
+	var backlog []func(context.Context)
+
+	defer close(t.Done)
+	for ctx.Err() == nil {
+		select {
+		case <-ctx.Done():
+			// Do nothing here. Next iteration of the for loop will not happen,
+			// since ctx.Err() would be non-nil.
+		case callback, ok := <-t.callbacks.Get():
+			if !ok {
+				return
+			}
+			t.callbacks.Load()
+			callback.(func(ctx context.Context))(ctx)
+		}
+	}
+
+	// Fetch pending callbacks if any, and execute them before returning from
+	// this method and closing t.Done.
+	t.closedMu.Lock()
+	t.closed = true
+	backlog = t.fetchPendingCallbacks()
+	t.callbacks.Close()
+	t.closedMu.Unlock()
+	for _, b := range backlog {
+		b(ctx)
+	}
+}
+
+func (t *CallbackSerializer) fetchPendingCallbacks() []func(context.Context) {
+	var backlog []func(context.Context)
+	for {
+		select {
+		case b := <-t.callbacks.Get():
+			backlog = append(backlog, b.(func(context.Context)))
+			t.callbacks.Load()
+		default:
+			return backlog
+		}
+	}
+}
diff --git a/vendor/google.golang.org/grpc/internal/internal.go b/vendor/google.golang.org/grpc/internal/internal.go
index 836b6a3b3..42ff39c84 100644
--- a/vendor/google.golang.org/grpc/internal/internal.go
+++ b/vendor/google.golang.org/grpc/internal/internal.go
@@ -60,6 +60,9 @@ var (
 	GetServerCredentials interface{} // func (*grpc.Server) credentials.TransportCredentials
 	// CanonicalString returns the canonical string of the code defined here:
 	// https://github.com/grpc/grpc/blob/master/doc/statuscodes.md.
+	//
+	// This is used in the 1.0 release of gcp/observability, and thus must not be
+	// deleted or changed.
 	CanonicalString interface{} // func (codes.Code) string
 	// DrainServerTransports initiates a graceful close of existing connections
 	// on a gRPC server accepted on the provided listener address. An
@@ -69,20 +72,35 @@ var (
 	// AddGlobalServerOptions adds an array of ServerOption that will be
 	// effective globally for newly created servers. The priority will be: 1.
 	// user-provided; 2. this method; 3. default values.
+	//
+	// This is used in the 1.0 release of gcp/observability, and thus must not be
+	// deleted or changed.
 	AddGlobalServerOptions interface{} // func(opt ...ServerOption)
 	// ClearGlobalServerOptions clears the array of extra ServerOption. This
 	// method is useful in testing and benchmarking.
+	//
+	// This is used in the 1.0 release of gcp/observability, and thus must not be
+	// deleted or changed.
 	ClearGlobalServerOptions func()
 	// AddGlobalDialOptions adds an array of DialOption that will be effective
 	// globally for newly created client channels. The priority will be: 1.
 	// user-provided; 2. this method; 3. default values.
+	//
+	// This is used in the 1.0 release of gcp/observability, and thus must not be
+	// deleted or changed.
 	AddGlobalDialOptions interface{} // func(opt ...DialOption)
 	// DisableGlobalDialOptions returns a DialOption that prevents the
 	// ClientConn from applying the global DialOptions (set via
 	// AddGlobalDialOptions).
+	//
+	// This is used in the 1.0 release of gcp/observability, and thus must not be
+	// deleted or changed.
 	DisableGlobalDialOptions interface{} // func() grpc.DialOption
 	// ClearGlobalDialOptions clears the array of extra DialOption. This
 	// method is useful in testing and benchmarking.
+	//
+	// This is used in the 1.0 release of gcp/observability, and thus must not be
+	// deleted or changed.
 	ClearGlobalDialOptions func()
 	// JoinDialOptions combines the dial options passed as arguments into a
 	// single dial option.
@@ -93,9 +111,15 @@ var (
 
 	// WithBinaryLogger returns a DialOption that specifies the binary logger
 	// for a ClientConn.
+	//
+	// This is used in the 1.0 release of gcp/observability, and thus must not be
+	// deleted or changed.
 	WithBinaryLogger interface{} // func(binarylog.Logger) grpc.DialOption
 	// BinaryLogger returns a ServerOption that can set the binary logger for a
 	// server.
+	//
+	// This is used in the 1.0 release of gcp/observability, and thus must not be
+	// deleted or changed.
 	BinaryLogger interface{} // func(binarylog.Logger) grpc.ServerOption
 
 	// NewXDSResolverWithConfigForTesting creates a new xds resolver builder using
diff --git a/vendor/google.golang.org/grpc/internal/serviceconfig/duration.go b/vendor/google.golang.org/grpc/internal/serviceconfig/duration.go
new file mode 100644
index 000000000..11d82afcc
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/serviceconfig/duration.go
@@ -0,0 +1,130 @@
+/*
+ *
+ * Copyright 2023 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package serviceconfig
+
+import (
+	"encoding/json"
+	"fmt"
+	"math"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// Duration defines JSON marshal and unmarshal methods to conform to the
+// protobuf JSON spec defined [here].
+//
+// [here]: https://protobuf.dev/reference/protobuf/google.protobuf/#duration
+type Duration time.Duration
+
+func (d Duration) String() string {
+	return fmt.Sprint(time.Duration(d))
+}
+
+// MarshalJSON converts from d to a JSON string output.
+func (d Duration) MarshalJSON() ([]byte, error) {
+	ns := time.Duration(d).Nanoseconds()
+	sec := ns / int64(time.Second)
+	ns = ns % int64(time.Second)
+
+	var sign string
+	if sec < 0 || ns < 0 {
+		sign, sec, ns = "-", -1*sec, -1*ns
+	}
+
+	// Generated output always contains 0, 3, 6, or 9 fractional digits,
+	// depending on required precision.
+	str := fmt.Sprintf("%s%d.%09d", sign, sec, ns)
+	str = strings.TrimSuffix(str, "000")
+	str = strings.TrimSuffix(str, "000")
+	str = strings.TrimSuffix(str, ".000")
+	return []byte(fmt.Sprintf("\"%ss\"", str)), nil
+}
+
+// UnmarshalJSON unmarshals b as a duration JSON string into d.
+func (d *Duration) UnmarshalJSON(b []byte) error {
+	var s string
+	if err := json.Unmarshal(b, &s); err != nil {
+		return err
+	}
+	if !strings.HasSuffix(s, "s") {
+		return fmt.Errorf("malformed duration %q: missing seconds unit", s)
+	}
+	neg := false
+	if s[0] == '-' {
+		neg = true
+		s = s[1:]
+	}
+	ss := strings.SplitN(s[:len(s)-1], ".", 3)
+	if len(ss) > 2 {
+		return fmt.Errorf("malformed duration %q: too many decimals", s)
+	}
+	// hasDigits is set if either the whole or fractional part of the number is
+	// present, since both are optional but one is required.
+	hasDigits := false
+	var sec, ns int64
+	if len(ss[0]) > 0 {
+		var err error
+		if sec, err = strconv.ParseInt(ss[0], 10, 64); err != nil {
+			return fmt.Errorf("malformed duration %q: %v", s, err)
+		}
+		// Maximum seconds value per the durationpb spec.
+		const maxProtoSeconds = 315_576_000_000
+		if sec > maxProtoSeconds {
+			return fmt.Errorf("out of range: %q", s)
+		}
+		hasDigits = true
+	}
+	if len(ss) == 2 && len(ss[1]) > 0 {
+		if len(ss[1]) > 9 {
+			return fmt.Errorf("malformed duration %q: too many digits after decimal", s)
+		}
+		var err error
+		if ns, err = strconv.ParseInt(ss[1], 10, 64); err != nil {
+			return fmt.Errorf("malformed duration %q: %v", s, err)
+		}
+		for i := 9; i > len(ss[1]); i-- {
+			ns *= 10
+		}
+		hasDigits = true
+	}
+	if !hasDigits {
+		return fmt.Errorf("malformed duration %q: contains no numbers", s)
+	}
+
+	if neg {
+		sec *= -1
+		ns *= -1
+	}
+
+	// Maximum/minimum seconds/nanoseconds representable by Go's time.Duration.
+	const maxSeconds = math.MaxInt64 / int64(time.Second)
+	const maxNanosAtMaxSeconds = math.MaxInt64 % int64(time.Second)
+	const minSeconds = math.MinInt64 / int64(time.Second)
+	const minNanosAtMinSeconds = math.MinInt64 % int64(time.Second)
+
+	if sec > maxSeconds || (sec == maxSeconds && ns >= maxNanosAtMaxSeconds) {
+		*d = Duration(math.MaxInt64)
+	} else if sec < minSeconds || (sec == minSeconds && ns <= minNanosAtMinSeconds) {
+		*d = Duration(math.MinInt64)
+	} else {
+		*d = Duration(sec*int64(time.Second) + ns)
+	}
+	return nil
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
index c343c23a5..be5a9c81e 100644
--- a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
+++ b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
@@ -30,6 +30,7 @@ import (
 
 	"golang.org/x/net/http2"
 	"golang.org/x/net/http2/hpack"
+	"google.golang.org/grpc/internal/grpclog"
 	"google.golang.org/grpc/internal/grpcutil"
 	"google.golang.org/grpc/status"
 )
@@ -488,12 +489,13 @@ type loopyWriter struct {
 	bdpEst        *bdpEstimator
 	draining      bool
 	conn          net.Conn
+	logger        *grpclog.PrefixLogger
 
 	// Side-specific handlers
 	ssGoAwayHandler func(*goAway) (bool, error)
 }
 
-func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator, conn net.Conn) *loopyWriter {
+func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator, conn net.Conn, logger *grpclog.PrefixLogger) *loopyWriter {
 	var buf bytes.Buffer
 	l := &loopyWriter{
 		side:          s,
@@ -507,6 +509,7 @@ func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimato
 		hEnc:          hpack.NewEncoder(&buf),
 		bdpEst:        bdpEst,
 		conn:          conn,
+		logger:        logger,
 	}
 	return l
 }
@@ -536,8 +539,8 @@ const minBatchSize = 1000
 // left open to allow the I/O error to be encountered by the reader instead.
 func (l *loopyWriter) run() (err error) {
 	defer func() {
-		if logger.V(logLevel) {
-			logger.Infof("transport: loopyWriter exiting with error: %v", err)
+		if l.logger.V(logLevel) {
+			l.logger.Infof("loopyWriter exiting with error: %v", err)
 		}
 		if !isIOError(err) {
 			l.framer.writer.Flush()
@@ -636,8 +639,8 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error {
 	if l.side == serverSide {
 		str, ok := l.estdStreams[h.streamID]
 		if !ok {
-			if logger.V(logLevel) {
-				logger.Warningf("transport: loopy doesn't recognize the stream: %d", h.streamID)
+			if l.logger.V(logLevel) {
+				l.logger.Infof("Unrecognized streamID %d in loopyWriter", h.streamID)
 			}
 			return nil
 		}
@@ -692,8 +695,8 @@ func (l *loopyWriter) writeHeader(streamID uint32, endStream bool, hf []hpack.He
 	l.hBuf.Reset()
 	for _, f := range hf {
 		if err := l.hEnc.WriteField(f); err != nil {
-			if logger.V(logLevel) {
-				logger.Warningf("transport: loopyWriter.writeHeader encountered error while encoding headers: %v", err)
+			if l.logger.V(logLevel) {
+				l.logger.Warningf("Encountered error while encoding headers: %v", err)
 			}
 		}
 	}
diff --git a/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/vendor/google.golang.org/grpc/internal/transport/handler_server.go
index e6626bf96..98f80e3fa 100644
--- a/vendor/google.golang.org/grpc/internal/transport/handler_server.go
+++ b/vendor/google.golang.org/grpc/internal/transport/handler_server.go
@@ -39,6 +39,7 @@ import (
 	"golang.org/x/net/http2"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/credentials"
+	"google.golang.org/grpc/internal/grpclog"
 	"google.golang.org/grpc/internal/grpcutil"
 	"google.golang.org/grpc/metadata"
 	"google.golang.org/grpc/peer"
@@ -83,6 +84,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []s
 		contentSubtype: contentSubtype,
 		stats:          stats,
 	}
+	st.logger = prefixLoggerForServerHandlerTransport(st)
 
 	if v := r.Header.Get("grpc-timeout"); v != "" {
 		to, err := decodeTimeout(v)
@@ -150,13 +152,14 @@ type serverHandlerTransport struct {
 	// TODO make sure this is consistent across handler_server and http2_server
 	contentSubtype string
 
-	stats []stats.Handler
+	stats  []stats.Handler
+	logger *grpclog.PrefixLogger
 }
 
 func (ht *serverHandlerTransport) Close(err error) {
 	ht.closeOnce.Do(func() {
-		if logger.V(logLevel) {
-			logger.Infof("Closing serverHandlerTransport: %v", err)
+		if ht.logger.V(logLevel) {
+			ht.logger.Infof("Closing: %v", err)
 		}
 		close(ht.closedCh)
 	})
@@ -450,7 +453,7 @@ func (ht *serverHandlerTransport) IncrMsgSent() {}
 
 func (ht *serverHandlerTransport) IncrMsgRecv() {}
 
-func (ht *serverHandlerTransport) Drain() {
+func (ht *serverHandlerTransport) Drain(debugData string) {
 	panic("Drain() is not implemented")
 }
 
diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go
index 9826feb8c..326bf0848 100644
--- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go
+++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go
@@ -38,6 +38,7 @@ import (
 	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/internal/channelz"
 	icredentials "google.golang.org/grpc/internal/credentials"
+	"google.golang.org/grpc/internal/grpclog"
 	"google.golang.org/grpc/internal/grpcsync"
 	"google.golang.org/grpc/internal/grpcutil"
 	imetadata "google.golang.org/grpc/internal/metadata"
@@ -145,6 +146,7 @@ type http2Client struct {
 	bufferPool *bufferPool
 
 	connectionID uint64
+	logger       *grpclog.PrefixLogger
 }
 
 func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error), addr resolver.Address, useProxy bool, grpcUA string) (net.Conn, error) {
@@ -244,7 +246,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 		if err := connectCtx.Err(); err != nil {
 			// connectCtx expired before exiting the function.  Hard close the connection.
 			if logger.V(logLevel) {
-				logger.Infof("newClientTransport: aborting due to connectCtx: %v", err)
+				logger.Infof("Aborting due to connect deadline expiring: %v", err)
 			}
 			conn.Close()
 		}
@@ -346,6 +348,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 		bufferPool:            newBufferPool(),
 		onClose:               onClose,
 	}
+	t.logger = prefixLoggerForClientTransport(t)
 	// Add peer information to the http2client context.
 	t.ctx = peer.NewContext(t.ctx, t.getPeer())
 
@@ -444,7 +447,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 		return nil, err
 	}
 	go func() {
-		t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst, t.conn)
+		t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger)
 		t.loopy.run()
 		close(t.writerDone)
 	}()
@@ -782,7 +785,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
 		s.id = h.streamID
 		s.fc = &inFlow{limit: uint32(t.initialWindowSize)}
 		t.mu.Lock()
-		if t.activeStreams == nil { // Can be niled from Close().
+		if t.state == draining || t.activeStreams == nil { // Can be niled from Close().
 			t.mu.Unlock()
 			return false // Don't create a stream if the transport is already closed.
 		}
@@ -859,8 +862,8 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
 		}
 	}
 	if transportDrainRequired {
-		if logger.V(logLevel) {
-			logger.Infof("transport: t.nextID > MaxStreamID. Draining")
+		if t.logger.V(logLevel) {
+			t.logger.Infof("Draining transport: t.nextID > MaxStreamID")
 		}
 		t.GracefulClose()
 	}
@@ -952,8 +955,8 @@ func (t *http2Client) Close(err error) {
 		t.mu.Unlock()
 		return
 	}
-	if logger.V(logLevel) {
-		logger.Infof("transport: closing: %v", err)
+	if t.logger.V(logLevel) {
+		t.logger.Infof("Closing: %v", err)
 	}
 	// Call t.onClose ASAP to prevent the client from attempting to create new
 	// streams.
@@ -1009,8 +1012,8 @@ func (t *http2Client) GracefulClose() {
 		t.mu.Unlock()
 		return
 	}
-	if logger.V(logLevel) {
-		logger.Infof("transport: GracefulClose called")
+	if t.logger.V(logLevel) {
+		t.logger.Infof("GracefulClose called")
 	}
 	t.onClose(GoAwayInvalid)
 	t.state = draining
@@ -1174,8 +1177,8 @@ func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) {
 	}
 	statusCode, ok := http2ErrConvTab[f.ErrCode]
 	if !ok {
-		if logger.V(logLevel) {
-			logger.Warningf("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error: %v", f.ErrCode)
+		if t.logger.V(logLevel) {
+			t.logger.Infof("Received a RST_STREAM frame with code %q, but found no mapped gRPC status", f.ErrCode)
 		}
 		statusCode = codes.Unknown
 	}
@@ -1334,7 +1337,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
 
 // setGoAwayReason sets the value of t.goAwayReason based
 // on the GoAway frame received.
-// It expects a lock on transport's mutext to be held by
+// It expects a lock on transport's mutex to be held by
 // the caller.
 func (t *http2Client) setGoAwayReason(f *http2.GoAwayFrame) {
 	t.goAwayReason = GoAwayNoReason
diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go
index 99ae1a737..ec4eef213 100644
--- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go
+++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go
@@ -35,7 +35,9 @@ import (
 	"github.com/golang/protobuf/proto"
 	"golang.org/x/net/http2"
 	"golang.org/x/net/http2/hpack"
+	"google.golang.org/grpc/internal/grpclog"
 	"google.golang.org/grpc/internal/grpcutil"
+	"google.golang.org/grpc/internal/pretty"
 	"google.golang.org/grpc/internal/syscall"
 
 	"google.golang.org/grpc/codes"
@@ -129,6 +131,8 @@ type http2Server struct {
 	// This lock may not be taken if mu is already held.
 	maxStreamMu sync.Mutex
 	maxStreamID uint32 // max stream ID ever seen
+
+	logger *grpclog.PrefixLogger
 }
 
 // NewServerTransport creates a http2 transport with conn and configuration
@@ -167,15 +171,10 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 		ID:  http2.SettingMaxFrameSize,
 		Val: http2MaxFrameLen,
 	}}
-	// TODO(zhaoq): Have a better way to signal "no limit" because 0 is
-	// permitted in the HTTP2 spec.
-	maxStreams := config.MaxStreams
-	if maxStreams == 0 {
-		maxStreams = math.MaxUint32
-	} else {
+	if config.MaxStreams != math.MaxUint32 {
 		isettings = append(isettings, http2.Setting{
 			ID:  http2.SettingMaxConcurrentStreams,
-			Val: maxStreams,
+			Val: config.MaxStreams,
 		})
 	}
 	dynamicWindow := true
@@ -254,7 +253,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 		framer:            framer,
 		readerDone:        make(chan struct{}),
 		writerDone:        make(chan struct{}),
-		maxStreams:        maxStreams,
+		maxStreams:        config.MaxStreams,
 		inTapHandle:       config.InTapHandle,
 		fc:                &trInFlow{limit: uint32(icwz)},
 		state:             reachable,
@@ -267,6 +266,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 		czData:            new(channelzData),
 		bufferPool:        newBufferPool(),
 	}
+	t.logger = prefixLoggerForServerTransport(t)
 	// Add peer information to the http2server context.
 	t.ctx = peer.NewContext(t.ctx, t.getPeer())
 
@@ -331,7 +331,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 	t.handleSettings(sf)
 
 	go func() {
-		t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn)
+		t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger)
 		t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler
 		t.loopy.run()
 		close(t.writerDone)
@@ -425,8 +425,8 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
 		// "Transports must consider requests containing the Connection header
 		// as malformed." - A41
 		case "connection":
-			if logger.V(logLevel) {
-				logger.Errorf("transport: http2Server.operateHeaders parsed a :connection header which makes a request malformed as per the HTTP/2 spec")
+			if t.logger.V(logLevel) {
+				t.logger.Infof("Received a HEADERS frame with a :connection header which makes the request malformed, as per the HTTP/2 spec")
 			}
 			protocolError = true
 		default:
@@ -436,7 +436,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
 			v, err := decodeMetadataHeader(hf.Name, hf.Value)
 			if err != nil {
 				headerError = status.Newf(codes.Internal, "malformed binary metadata %q in header %q: %v", hf.Value, hf.Name, err)
-				logger.Warningf("Failed to decode metadata header (%q, %q): %v", hf.Name, hf.Value, err)
+				t.logger.Warningf("Failed to decode metadata header (%q, %q): %v", hf.Name, hf.Value, err)
 				break
 			}
 			mdata[hf.Name] = append(mdata[hf.Name], v)
@@ -450,8 +450,8 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
 	// error, this takes precedence over a client not speaking gRPC.
 	if len(mdata[":authority"]) > 1 || len(mdata["host"]) > 1 {
 		errMsg := fmt.Sprintf("num values of :authority: %v, num values of host: %v, both must only have 1 value as per HTTP/2 spec", len(mdata[":authority"]), len(mdata["host"]))
-		if logger.V(logLevel) {
-			logger.Errorf("transport: %v", errMsg)
+		if t.logger.V(logLevel) {
+			t.logger.Infof("Aborting the stream early: %v", errMsg)
 		}
 		t.controlBuf.put(&earlyAbortStream{
 			httpStatus:     http.StatusBadRequest,
@@ -545,9 +545,9 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
 	}
 	if httpMethod != http.MethodPost {
 		t.mu.Unlock()
-		errMsg := fmt.Sprintf("http2Server.operateHeaders parsed a :method field: %v which should be POST", httpMethod)
-		if logger.V(logLevel) {
-			logger.Infof("transport: %v", errMsg)
+		errMsg := fmt.Sprintf("Received a HEADERS frame with :method %q which should be POST", httpMethod)
+		if t.logger.V(logLevel) {
+			t.logger.Infof("Aborting the stream early: %v", errMsg)
 		}
 		t.controlBuf.put(&earlyAbortStream{
 			httpStatus:     405,
@@ -563,8 +563,8 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
 		var err error
 		if s.ctx, err = t.inTapHandle(s.ctx, &tap.Info{FullMethodName: s.method}); err != nil {
 			t.mu.Unlock()
-			if logger.V(logLevel) {
-				logger.Infof("transport: http2Server.operateHeaders got an error from InTapHandle: %v", err)
+			if t.logger.V(logLevel) {
+				t.logger.Infof("Aborting the stream early due to InTapHandle failure: %v", err)
 			}
 			stat, ok := status.FromError(err)
 			if !ok {
@@ -638,8 +638,8 @@ func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context.
 		atomic.StoreInt64(&t.lastRead, time.Now().UnixNano())
 		if err != nil {
 			if se, ok := err.(http2.StreamError); ok {
-				if logger.V(logLevel) {
-					logger.Warningf("transport: http2Server.HandleStreams encountered http2.StreamError: %v", se)
+				if t.logger.V(logLevel) {
+					t.logger.Warningf("Encountered http2.StreamError: %v", se)
 				}
 				t.mu.Lock()
 				s := t.activeStreams[se.StreamID]
@@ -682,8 +682,8 @@ func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context.
 		case *http2.GoAwayFrame:
 			// TODO: Handle GoAway from the client appropriately.
 		default:
-			if logger.V(logLevel) {
-				logger.Errorf("transport: http2Server.HandleStreams found unhandled frame type %v.", frame)
+			if t.logger.V(logLevel) {
+				t.logger.Infof("Received unsupported frame type %T", frame)
 			}
 		}
 	}
@@ -942,8 +942,8 @@ func (t *http2Server) checkForHeaderListSize(it interface{}) bool {
 	var sz int64
 	for _, f := range hdrFrame.hf {
 		if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) {
-			if logger.V(logLevel) {
-				logger.Errorf("header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize)
+			if t.logger.V(logLevel) {
+				t.logger.Infof("Header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize)
 			}
 			return false
 		}
@@ -1056,7 +1056,7 @@ func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error {
 		stBytes, err := proto.Marshal(p)
 		if err != nil {
 			// TODO: return error instead, when callers are able to handle it.
-			logger.Errorf("transport: failed to marshal rpc status: %v, error: %v", p, err)
+			t.logger.Errorf("Failed to marshal rpc status: %s, error: %v", pretty.ToJSON(p), err)
 		} else {
 			headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-status-details-bin", Value: encodeBinHeader(stBytes)})
 		}
@@ -1161,18 +1161,18 @@ func (t *http2Server) keepalive() {
 			if val <= 0 {
 				// The connection has been idle for a duration of keepalive.MaxConnectionIdle or more.
 				// Gracefully close the connection.
-				t.Drain()
+				t.Drain("max_idle")
 				return
 			}
 			idleTimer.Reset(val)
 		case <-ageTimer.C:
-			t.Drain()
+			t.Drain("max_age")
 			ageTimer.Reset(t.kp.MaxConnectionAgeGrace)
 			select {
 			case <-ageTimer.C:
 				// Close the connection after grace period.
-				if logger.V(logLevel) {
-					logger.Infof("transport: closing server transport due to maximum connection age.")
+				if t.logger.V(logLevel) {
+					t.logger.Infof("Closing server transport due to maximum connection age")
 				}
 				t.controlBuf.put(closeConnection{})
 			case <-t.done:
@@ -1223,8 +1223,8 @@ func (t *http2Server) Close(err error) {
 		t.mu.Unlock()
 		return
 	}
-	if logger.V(logLevel) {
-		logger.Infof("transport: closing: %v", err)
+	if t.logger.V(logLevel) {
+		t.logger.Infof("Closing: %v", err)
 	}
 	t.state = closing
 	streams := t.activeStreams
@@ -1232,8 +1232,8 @@ func (t *http2Server) Close(err error) {
 	t.mu.Unlock()
 	t.controlBuf.finish()
 	close(t.done)
-	if err := t.conn.Close(); err != nil && logger.V(logLevel) {
-		logger.Infof("transport: error closing conn during Close: %v", err)
+	if err := t.conn.Close(); err != nil && t.logger.V(logLevel) {
+		t.logger.Infof("Error closing underlying net.Conn during Close: %v", err)
 	}
 	channelz.RemoveEntry(t.channelzID)
 	// Cancel all active streams.
@@ -1313,14 +1313,14 @@ func (t *http2Server) RemoteAddr() net.Addr {
 	return t.remoteAddr
 }
 
-func (t *http2Server) Drain() {
+func (t *http2Server) Drain(debugData string) {
 	t.mu.Lock()
 	defer t.mu.Unlock()
 	if t.drainEvent != nil {
 		return
 	}
 	t.drainEvent = grpcsync.NewEvent()
-	t.controlBuf.put(&goAway{code: http2.ErrCodeNo, debugData: []byte{}, headsUp: true})
+	t.controlBuf.put(&goAway{code: http2.ErrCodeNo, debugData: []byte(debugData), headsUp: true})
 }
 
 var goAwayPing = &ping{data: [8]byte{1, 6, 1, 8, 0, 3, 3, 9}}
@@ -1362,7 +1362,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) {
 	// originated before the GoAway reaches the client.
 	// After getting the ack or timer expiration send out another GoAway this
 	// time with an ID of the max stream server intends to process.
-	if err := t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, []byte{}); err != nil {
+	if err := t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, g.debugData); err != nil {
 		return false, err
 	}
 	if err := t.framer.fr.WritePing(false, goAwayPing.data); err != nil {
diff --git a/vendor/google.golang.org/grpc/internal/transport/http_util.go b/vendor/google.golang.org/grpc/internal/transport/http_util.go
index 8fcae4f4d..19cbb18f5 100644
--- a/vendor/google.golang.org/grpc/internal/transport/http_util.go
+++ b/vendor/google.golang.org/grpc/internal/transport/http_util.go
@@ -38,7 +38,6 @@ import (
 	"golang.org/x/net/http2/hpack"
 	spb "google.golang.org/genproto/googleapis/rpc/status"
 	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/grpclog"
 	"google.golang.org/grpc/status"
 )
 
@@ -86,7 +85,6 @@ var (
 		// 504 Gateway timeout - UNAVAILABLE.
 		http.StatusGatewayTimeout: codes.Unavailable,
 	}
-	logger = grpclog.Component("transport")
 )
 
 // isReservedHeader checks whether hdr belongs to HTTP2 headers
diff --git a/vendor/google.golang.org/grpc/internal/transport/logging.go b/vendor/google.golang.org/grpc/internal/transport/logging.go
new file mode 100644
index 000000000..42ed2b07a
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/logging.go
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright 2023 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package transport
+
+import (
+	"fmt"
+
+	"google.golang.org/grpc/grpclog"
+	internalgrpclog "google.golang.org/grpc/internal/grpclog"
+)
+
+var logger = grpclog.Component("transport")
+
+func prefixLoggerForServerTransport(p *http2Server) *internalgrpclog.PrefixLogger {
+	return internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[server-transport %p] ", p))
+}
+
+func prefixLoggerForServerHandlerTransport(p *serverHandlerTransport) *internalgrpclog.PrefixLogger {
+	return internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[server-handler-transport %p] ", p))
+}
+
+func prefixLoggerForClientTransport(p *http2Client) *internalgrpclog.PrefixLogger {
+	return internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[client-transport %p] ", p))
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go
index 1b7d7fabc..aa1c89659 100644
--- a/vendor/google.golang.org/grpc/internal/transport/transport.go
+++ b/vendor/google.golang.org/grpc/internal/transport/transport.go
@@ -726,7 +726,7 @@ type ServerTransport interface {
 	RemoteAddr() net.Addr
 
 	// Drain notifies the client this ServerTransport stops accepting new RPCs.
-	Drain()
+	Drain(debugData string)
 
 	// IncrMsgSent increments the number of message sent through this transport.
 	IncrMsgSent()
diff --git a/vendor/google.golang.org/grpc/picker_wrapper.go b/vendor/google.golang.org/grpc/picker_wrapper.go
index c525dc070..02f975951 100644
--- a/vendor/google.golang.org/grpc/picker_wrapper.go
+++ b/vendor/google.golang.org/grpc/picker_wrapper.go
@@ -36,6 +36,7 @@ import (
 type pickerWrapper struct {
 	mu         sync.Mutex
 	done       bool
+	idle       bool
 	blockingCh chan struct{}
 	picker     balancer.Picker
 }
@@ -47,7 +48,11 @@ func newPickerWrapper() *pickerWrapper {
 // updatePicker is called by UpdateBalancerState. It unblocks all blocked pick.
 func (pw *pickerWrapper) updatePicker(p balancer.Picker) {
 	pw.mu.Lock()
-	if pw.done {
+	if pw.done || pw.idle {
+		// There is a small window where a picker update from the LB policy can
+		// race with the channel going to idle mode. If the picker is idle here,
+		// it is because the channel asked it to do so, and therefore it is sage
+		// to ignore the update from the LB policy.
 		pw.mu.Unlock()
 		return
 	}
@@ -63,10 +68,8 @@ func (pw *pickerWrapper) updatePicker(p balancer.Picker) {
 //   - wraps the done function in the passed in result to increment the calls
 //     failed or calls succeeded channelz counter before invoking the actual
 //     done function.
-func doneChannelzWrapper(acw *acBalancerWrapper, result *balancer.PickResult) {
-	acw.mu.Lock()
-	ac := acw.ac
-	acw.mu.Unlock()
+func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) {
+	ac := acbw.ac
 	ac.incrCallsStarted()
 	done := result.Done
 	result.Done = func(b balancer.DoneInfo) {
@@ -152,14 +155,14 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 			return nil, balancer.PickResult{}, status.Error(codes.Unavailable, err.Error())
 		}
 
-		acw, ok := pickResult.SubConn.(*acBalancerWrapper)
+		acbw, ok := pickResult.SubConn.(*acBalancerWrapper)
 		if !ok {
 			logger.Errorf("subconn returned from pick is type %T, not *acBalancerWrapper", pickResult.SubConn)
 			continue
 		}
-		if t := acw.getAddrConn().getReadyTransport(); t != nil {
+		if t := acbw.ac.getReadyTransport(); t != nil {
 			if channelz.IsOn() {
-				doneChannelzWrapper(acw, &pickResult)
+				doneChannelzWrapper(acbw, &pickResult)
 				return t, pickResult, nil
 			}
 			return t, pickResult, nil
@@ -187,6 +190,25 @@ func (pw *pickerWrapper) close() {
 	close(pw.blockingCh)
 }
 
+func (pw *pickerWrapper) enterIdleMode() {
+	pw.mu.Lock()
+	defer pw.mu.Unlock()
+	if pw.done {
+		return
+	}
+	pw.idle = true
+}
+
+func (pw *pickerWrapper) exitIdleMode() {
+	pw.mu.Lock()
+	defer pw.mu.Unlock()
+	if pw.done {
+		return
+	}
+	pw.blockingCh = make(chan struct{})
+	pw.idle = false
+}
+
 // dropError is a wrapper error that indicates the LB policy wishes to drop the
 // RPC and not retry it.
 type dropError struct {
diff --git a/vendor/google.golang.org/grpc/pickfirst.go b/vendor/google.golang.org/grpc/pickfirst.go
index fc91b4d26..abe266b02 100644
--- a/vendor/google.golang.org/grpc/pickfirst.go
+++ b/vendor/google.golang.org/grpc/pickfirst.go
@@ -19,11 +19,15 @@
 package grpc
 
 import (
+	"encoding/json"
 	"errors"
 	"fmt"
 
 	"google.golang.org/grpc/balancer"
 	"google.golang.org/grpc/connectivity"
+	"google.golang.org/grpc/internal/envconfig"
+	"google.golang.org/grpc/internal/grpcrand"
+	"google.golang.org/grpc/serviceconfig"
 )
 
 // PickFirstBalancerName is the name of the pick_first balancer.
@@ -43,10 +47,28 @@ func (*pickfirstBuilder) Name() string {
 	return PickFirstBalancerName
 }
 
+type pfConfig struct {
+	serviceconfig.LoadBalancingConfig `json:"-"`
+
+	// If set to true, instructs the LB policy to shuffle the order of the list
+	// of addresses received from the name resolver before attempting to
+	// connect to them.
+	ShuffleAddressList bool `json:"shuffleAddressList"`
+}
+
+func (*pickfirstBuilder) ParseConfig(js json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
+	cfg := &pfConfig{}
+	if err := json.Unmarshal(js, cfg); err != nil {
+		return nil, fmt.Errorf("pickfirst: unable to unmarshal LB policy config: %s, error: %v", string(js), err)
+	}
+	return cfg, nil
+}
+
 type pickfirstBalancer struct {
 	state   connectivity.State
 	cc      balancer.ClientConn
 	subConn balancer.SubConn
+	cfg     *pfConfig
 }
 
 func (b *pickfirstBalancer) ResolverError(err error) {
@@ -69,7 +91,8 @@ func (b *pickfirstBalancer) ResolverError(err error) {
 }
 
 func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState) error {
-	if len(state.ResolverState.Addresses) == 0 {
+	addrs := state.ResolverState.Addresses
+	if len(addrs) == 0 {
 		// The resolver reported an empty address list. Treat it like an error by
 		// calling b.ResolverError.
 		if b.subConn != nil {
@@ -82,12 +105,23 @@ func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState
 		return balancer.ErrBadResolverState
 	}
 
+	if state.BalancerConfig != nil {
+		cfg, ok := state.BalancerConfig.(*pfConfig)
+		if !ok {
+			return fmt.Errorf("pickfirstBalancer: received nil or illegal BalancerConfig (type %T): %v", state.BalancerConfig, state.BalancerConfig)
+		}
+		b.cfg = cfg
+	}
+
+	if envconfig.PickFirstLBConfig && b.cfg != nil && b.cfg.ShuffleAddressList {
+		grpcrand.Shuffle(len(addrs), func(i, j int) { addrs[i], addrs[j] = addrs[j], addrs[i] })
+	}
 	if b.subConn != nil {
-		b.cc.UpdateAddresses(b.subConn, state.ResolverState.Addresses)
+		b.cc.UpdateAddresses(b.subConn, addrs)
 		return nil
 	}
 
-	subConn, err := b.cc.NewSubConn(state.ResolverState.Addresses, balancer.NewSubConnOptions{})
+	subConn, err := b.cc.NewSubConn(addrs, balancer.NewSubConnOptions{})
 	if err != nil {
 		if logger.V(2) {
 			logger.Errorf("pickfirstBalancer: failed to NewSubConn: %v", err)
@@ -119,7 +153,6 @@ func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state b
 		}
 		return
 	}
-	b.state = state.ConnectivityState
 	if state.ConnectivityState == connectivity.Shutdown {
 		b.subConn = nil
 		return
@@ -132,11 +165,21 @@ func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state b
 			Picker:            &picker{result: balancer.PickResult{SubConn: subConn}},
 		})
 	case connectivity.Connecting:
+		if b.state == connectivity.TransientFailure {
+			// We stay in TransientFailure until we are Ready. See A62.
+			return
+		}
 		b.cc.UpdateState(balancer.State{
 			ConnectivityState: state.ConnectivityState,
 			Picker:            &picker{err: balancer.ErrNoSubConnAvailable},
 		})
 	case connectivity.Idle:
+		if b.state == connectivity.TransientFailure {
+			// We stay in TransientFailure until we are Ready. Also kick the
+			// subConn out of Idle into Connecting. See A62.
+			b.subConn.Connect()
+			return
+		}
 		b.cc.UpdateState(balancer.State{
 			ConnectivityState: state.ConnectivityState,
 			Picker:            &idlePicker{subConn: subConn},
@@ -147,6 +190,7 @@ func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state b
 			Picker:            &picker{err: state.ConnectionError},
 		})
 	}
+	b.state = state.ConnectivityState
 }
 
 func (b *pickfirstBalancer) Close() {
diff --git a/vendor/google.golang.org/grpc/resolver/resolver.go b/vendor/google.golang.org/grpc/resolver/resolver.go
index 6215e5ef2..353c10b69 100644
--- a/vendor/google.golang.org/grpc/resolver/resolver.go
+++ b/vendor/google.golang.org/grpc/resolver/resolver.go
@@ -22,13 +22,13 @@ package resolver
 
 import (
 	"context"
+	"fmt"
 	"net"
 	"net/url"
 	"strings"
 
 	"google.golang.org/grpc/attributes"
 	"google.golang.org/grpc/credentials"
-	"google.golang.org/grpc/internal/pretty"
 	"google.golang.org/grpc/serviceconfig"
 )
 
@@ -124,7 +124,7 @@ type Address struct {
 	Attributes *attributes.Attributes
 
 	// BalancerAttributes contains arbitrary data about this address intended
-	// for consumption by the LB policy.  These attribes do not affect SubConn
+	// for consumption by the LB policy.  These attributes do not affect SubConn
 	// creation, connection establishment, handshaking, etc.
 	BalancerAttributes *attributes.Attributes
 
@@ -151,7 +151,17 @@ func (a Address) Equal(o Address) bool {
 
 // String returns JSON formatted string representation of the address.
 func (a Address) String() string {
-	return pretty.ToJSON(a)
+	var sb strings.Builder
+	sb.WriteString(fmt.Sprintf("{Addr: %q, ", a.Addr))
+	sb.WriteString(fmt.Sprintf("ServerName: %q, ", a.ServerName))
+	if a.Attributes != nil {
+		sb.WriteString(fmt.Sprintf("Attributes: %v, ", a.Attributes.String()))
+	}
+	if a.BalancerAttributes != nil {
+		sb.WriteString(fmt.Sprintf("BalancerAttributes: %v", a.BalancerAttributes.String()))
+	}
+	sb.WriteString("}")
+	return sb.String()
 }
 
 // BuildOptions includes additional information for the builder to create
diff --git a/vendor/google.golang.org/grpc/resolver_conn_wrapper.go b/vendor/google.golang.org/grpc/resolver_conn_wrapper.go
index 05a9d4e0b..b408b3688 100644
--- a/vendor/google.golang.org/grpc/resolver_conn_wrapper.go
+++ b/vendor/google.golang.org/grpc/resolver_conn_wrapper.go
@@ -19,11 +19,11 @@
 package grpc
 
 import (
+	"context"
 	"strings"
 	"sync"
 
 	"google.golang.org/grpc/balancer"
-	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/internal/channelz"
 	"google.golang.org/grpc/internal/grpcsync"
 	"google.golang.org/grpc/internal/pretty"
@@ -31,129 +31,192 @@ import (
 	"google.golang.org/grpc/serviceconfig"
 )
 
+// resolverStateUpdater wraps the single method used by ccResolverWrapper to
+// report a state update from the actual resolver implementation.
+type resolverStateUpdater interface {
+	updateResolverState(s resolver.State, err error) error
+}
+
 // ccResolverWrapper is a wrapper on top of cc for resolvers.
 // It implements resolver.ClientConn interface.
 type ccResolverWrapper struct {
-	cc         *ClientConn
-	resolverMu sync.Mutex
-	resolver   resolver.Resolver
-	done       *grpcsync.Event
-	curState   resolver.State
+	// The following fields are initialized when the wrapper is created and are
+	// read-only afterwards, and therefore can be accessed without a mutex.
+	cc                  resolverStateUpdater
+	channelzID          *channelz.Identifier
+	ignoreServiceConfig bool
+	opts                ccResolverWrapperOpts
+	serializer          *grpcsync.CallbackSerializer // To serialize all incoming calls.
+	serializerCancel    context.CancelFunc           // To close the serializer, accessed only from close().
+
+	// All incoming (resolver --> gRPC) calls are guaranteed to execute in a
+	// mutually exclusive manner as they are scheduled on the serializer.
+	// Fields accessed *only* in these serializer callbacks, can therefore be
+	// accessed without a mutex.
+	curState resolver.State
+
+	// mu guards access to the below fields.
+	mu       sync.Mutex
+	closed   bool
+	resolver resolver.Resolver // Accessed only from outgoing calls.
+}
 
-	incomingMu sync.Mutex // Synchronizes all the incoming calls.
+// ccResolverWrapperOpts wraps the arguments to be passed when creating a new
+// ccResolverWrapper.
+type ccResolverWrapperOpts struct {
+	target     resolver.Target       // User specified dial target to resolve.
+	builder    resolver.Builder      // Resolver builder to use.
+	bOpts      resolver.BuildOptions // Resolver build options to use.
+	channelzID *channelz.Identifier  // Channelz identifier for the channel.
 }
 
 // newCCResolverWrapper uses the resolver.Builder to build a Resolver and
 // returns a ccResolverWrapper object which wraps the newly built resolver.
-func newCCResolverWrapper(cc *ClientConn, rb resolver.Builder) (*ccResolverWrapper, error) {
+func newCCResolverWrapper(cc resolverStateUpdater, opts ccResolverWrapperOpts) (*ccResolverWrapper, error) {
+	ctx, cancel := context.WithCancel(context.Background())
 	ccr := &ccResolverWrapper{
-		cc:   cc,
-		done: grpcsync.NewEvent(),
-	}
-
-	var credsClone credentials.TransportCredentials
-	if creds := cc.dopts.copts.TransportCredentials; creds != nil {
-		credsClone = creds.Clone()
-	}
-	rbo := resolver.BuildOptions{
-		DisableServiceConfig: cc.dopts.disableServiceConfig,
-		DialCreds:            credsClone,
-		CredsBundle:          cc.dopts.copts.CredsBundle,
-		Dialer:               cc.dopts.copts.Dialer,
-	}
-
-	var err error
-	// We need to hold the lock here while we assign to the ccr.resolver field
-	// to guard against a data race caused by the following code path,
-	// rb.Build-->ccr.ReportError-->ccr.poll-->ccr.resolveNow, would end up
-	// accessing ccr.resolver which is being assigned here.
-	ccr.resolverMu.Lock()
-	defer ccr.resolverMu.Unlock()
-	ccr.resolver, err = rb.Build(cc.parsedTarget, ccr, rbo)
+		cc:                  cc,
+		channelzID:          opts.channelzID,
+		ignoreServiceConfig: opts.bOpts.DisableServiceConfig,
+		opts:                opts,
+		serializer:          grpcsync.NewCallbackSerializer(ctx),
+		serializerCancel:    cancel,
+	}
+
+	// Cannot hold the lock at build time because the resolver can send an
+	// update or error inline and these incoming calls grab the lock to schedule
+	// a callback in the serializer.
+	r, err := opts.builder.Build(opts.target, ccr, opts.bOpts)
 	if err != nil {
+		cancel()
 		return nil, err
 	}
+
+	// Any error reported by the resolver at build time that leads to a
+	// re-resolution request from the balancer is dropped by grpc until we
+	// return from this function. So, we don't have to handle pending resolveNow
+	// requests here.
+	ccr.mu.Lock()
+	ccr.resolver = r
+	ccr.mu.Unlock()
+
 	return ccr, nil
 }
 
 func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOptions) {
-	ccr.resolverMu.Lock()
-	if !ccr.done.HasFired() {
-		ccr.resolver.ResolveNow(o)
+	ccr.mu.Lock()
+	defer ccr.mu.Unlock()
+
+	// ccr.resolver field is set only after the call to Build() returns. But in
+	// the process of building, the resolver may send an error update which when
+	// propagated to the balancer may result in a re-resolution request.
+	if ccr.closed || ccr.resolver == nil {
+		return
 	}
-	ccr.resolverMu.Unlock()
+	ccr.resolver.ResolveNow(o)
 }
 
 func (ccr *ccResolverWrapper) close() {
-	ccr.resolverMu.Lock()
-	ccr.resolver.Close()
-	ccr.done.Fire()
-	ccr.resolverMu.Unlock()
+	ccr.mu.Lock()
+	if ccr.closed {
+		ccr.mu.Unlock()
+		return
+	}
+
+	channelz.Info(logger, ccr.channelzID, "Closing the name resolver")
+
+	// Close the serializer to ensure that no more calls from the resolver are
+	// handled, before actually closing the resolver.
+	ccr.serializerCancel()
+	ccr.closed = true
+	r := ccr.resolver
+	ccr.mu.Unlock()
+
+	// Give enqueued callbacks a chance to finish.
+	<-ccr.serializer.Done
+
+	// Spawn a goroutine to close the resolver (since it may block trying to
+	// cleanup all allocated resources) and return early.
+	go r.Close()
+}
+
+// serializerScheduleLocked is a convenience method to schedule a function to be
+// run on the serializer while holding ccr.mu.
+func (ccr *ccResolverWrapper) serializerScheduleLocked(f func(context.Context)) {
+	ccr.mu.Lock()
+	ccr.serializer.Schedule(f)
+	ccr.mu.Unlock()
 }
 
+// UpdateState is called by resolver implementations to report new state to gRPC
+// which includes addresses and service config.
 func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error {
-	ccr.incomingMu.Lock()
-	defer ccr.incomingMu.Unlock()
-	if ccr.done.HasFired() {
+	errCh := make(chan error, 1)
+	ok := ccr.serializer.Schedule(func(context.Context) {
+		ccr.addChannelzTraceEvent(s)
+		ccr.curState = s
+		if err := ccr.cc.updateResolverState(ccr.curState, nil); err == balancer.ErrBadResolverState {
+			errCh <- balancer.ErrBadResolverState
+			return
+		}
+		errCh <- nil
+	})
+	if !ok {
+		// The only time when Schedule() fail to add the callback to the
+		// serializer is when the serializer is closed, and this happens only
+		// when the resolver wrapper is closed.
 		return nil
 	}
-	ccr.addChannelzTraceEvent(s)
-	ccr.curState = s
-	if err := ccr.cc.updateResolverState(ccr.curState, nil); err == balancer.ErrBadResolverState {
-		return balancer.ErrBadResolverState
-	}
-	return nil
+	return <-errCh
 }
 
+// ReportError is called by resolver implementations to report errors
+// encountered during name resolution to gRPC.
 func (ccr *ccResolverWrapper) ReportError(err error) {
-	ccr.incomingMu.Lock()
-	defer ccr.incomingMu.Unlock()
-	if ccr.done.HasFired() {
-		return
-	}
-	channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: reporting error to cc: %v", err)
-	ccr.cc.updateResolverState(resolver.State{}, err)
+	ccr.serializerScheduleLocked(func(_ context.Context) {
+		channelz.Warningf(logger, ccr.channelzID, "ccResolverWrapper: reporting error to cc: %v", err)
+		ccr.cc.updateResolverState(resolver.State{}, err)
+	})
 }
 
-// NewAddress is called by the resolver implementation to send addresses to gRPC.
+// NewAddress is called by the resolver implementation to send addresses to
+// gRPC.
 func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
-	ccr.incomingMu.Lock()
-	defer ccr.incomingMu.Unlock()
-	if ccr.done.HasFired() {
-		return
-	}
-	ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig})
-	ccr.curState.Addresses = addrs
-	ccr.cc.updateResolverState(ccr.curState, nil)
+	ccr.serializerScheduleLocked(func(_ context.Context) {
+		ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig})
+		ccr.curState.Addresses = addrs
+		ccr.cc.updateResolverState(ccr.curState, nil)
+	})
 }
 
 // NewServiceConfig is called by the resolver implementation to send service
 // configs to gRPC.
 func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
-	ccr.incomingMu.Lock()
-	defer ccr.incomingMu.Unlock()
-	if ccr.done.HasFired() {
-		return
-	}
-	channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: got new service config: %s", sc)
-	if ccr.cc.dopts.disableServiceConfig {
-		channelz.Info(logger, ccr.cc.channelzID, "Service config lookups disabled; ignoring config")
-		return
-	}
-	scpr := parseServiceConfig(sc)
-	if scpr.Err != nil {
-		channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: error parsing service config: %v", scpr.Err)
-		return
-	}
-	ccr.addChannelzTraceEvent(resolver.State{Addresses: ccr.curState.Addresses, ServiceConfig: scpr})
-	ccr.curState.ServiceConfig = scpr
-	ccr.cc.updateResolverState(ccr.curState, nil)
+	ccr.serializerScheduleLocked(func(_ context.Context) {
+		channelz.Infof(logger, ccr.channelzID, "ccResolverWrapper: got new service config: %s", sc)
+		if ccr.ignoreServiceConfig {
+			channelz.Info(logger, ccr.channelzID, "Service config lookups disabled; ignoring config")
+			return
+		}
+		scpr := parseServiceConfig(sc)
+		if scpr.Err != nil {
+			channelz.Warningf(logger, ccr.channelzID, "ccResolverWrapper: error parsing service config: %v", scpr.Err)
+			return
+		}
+		ccr.addChannelzTraceEvent(resolver.State{Addresses: ccr.curState.Addresses, ServiceConfig: scpr})
+		ccr.curState.ServiceConfig = scpr
+		ccr.cc.updateResolverState(ccr.curState, nil)
+	})
 }
 
+// ParseServiceConfig is called by resolver implementations to parse a JSON
+// representation of the service config.
 func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult {
 	return parseServiceConfig(scJSON)
 }
 
+// addChannelzTraceEvent adds a channelz trace event containing the new
+// state received from resolver implementations.
 func (ccr *ccResolverWrapper) addChannelzTraceEvent(s resolver.State) {
 	var updates []string
 	var oldSC, newSC *ServiceConfig
@@ -172,5 +235,5 @@ func (ccr *ccResolverWrapper) addChannelzTraceEvent(s resolver.State) {
 	} else if len(ccr.curState.Addresses) == 0 && len(s.Addresses) > 0 {
 		updates = append(updates, "resolver returned new addresses")
 	}
-	channelz.Infof(logger, ccr.cc.channelzID, "Resolver state updated: %s (%v)", pretty.ToJSON(s), strings.Join(updates, "; "))
+	channelz.Infof(logger, ccr.channelzID, "Resolver state updated: %s (%v)", pretty.ToJSON(s), strings.Join(updates, "; "))
 }
diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go
index 087b9ad7c..8869cc906 100644
--- a/vendor/google.golang.org/grpc/server.go
+++ b/vendor/google.golang.org/grpc/server.go
@@ -43,7 +43,6 @@ import (
 	"google.golang.org/grpc/internal"
 	"google.golang.org/grpc/internal/binarylog"
 	"google.golang.org/grpc/internal/channelz"
-	"google.golang.org/grpc/internal/grpcrand"
 	"google.golang.org/grpc/internal/grpcsync"
 	"google.golang.org/grpc/internal/grpcutil"
 	"google.golang.org/grpc/internal/transport"
@@ -116,12 +115,6 @@ type serviceInfo struct {
 	mdata       interface{}
 }
 
-type serverWorkerData struct {
-	st     transport.ServerTransport
-	wg     *sync.WaitGroup
-	stream *transport.Stream
-}
-
 // Server is a gRPC server to serve RPC requests.
 type Server struct {
 	opts serverOptions
@@ -146,7 +139,7 @@ type Server struct {
 	channelzID *channelz.Identifier
 	czData     *channelzData
 
-	serverWorkerChannels []chan *serverWorkerData
+	serverWorkerChannel chan func()
 }
 
 type serverOptions struct {
@@ -178,6 +171,7 @@ type serverOptions struct {
 }
 
 var defaultServerOptions = serverOptions{
+	maxConcurrentStreams:  math.MaxUint32,
 	maxReceiveMessageSize: defaultServerMaxReceiveMessageSize,
 	maxSendMessageSize:    defaultServerMaxSendMessageSize,
 	connectionTimeout:     120 * time.Second,
@@ -388,6 +382,9 @@ func MaxSendMsgSize(m int) ServerOption {
 // MaxConcurrentStreams returns a ServerOption that will apply a limit on the number
 // of concurrent streams to each ServerTransport.
 func MaxConcurrentStreams(n uint32) ServerOption {
+	if n == 0 {
+		n = math.MaxUint32
+	}
 	return newFuncServerOption(func(o *serverOptions) {
 		o.maxConcurrentStreams = n
 	})
@@ -561,40 +558,33 @@ func NumStreamWorkers(numServerWorkers uint32) ServerOption {
 const serverWorkerResetThreshold = 1 << 16
 
 // serverWorkers blocks on a *transport.Stream channel forever and waits for
-// data to be fed by serveStreams. This allows different requests to be
+// data to be fed by serveStreams. This allows multiple requests to be
 // processed by the same goroutine, removing the need for expensive stack
 // re-allocations (see the runtime.morestack problem [1]).
 //
 // [1] https://github.com/golang/go/issues/18138
-func (s *Server) serverWorker(ch chan *serverWorkerData) {
-	// To make sure all server workers don't reset at the same time, choose a
-	// random number of iterations before resetting.
-	threshold := serverWorkerResetThreshold + grpcrand.Intn(serverWorkerResetThreshold)
-	for completed := 0; completed < threshold; completed++ {
-		data, ok := <-ch
+func (s *Server) serverWorker() {
+	for completed := 0; completed < serverWorkerResetThreshold; completed++ {
+		f, ok := <-s.serverWorkerChannel
 		if !ok {
 			return
 		}
-		s.handleStream(data.st, data.stream, s.traceInfo(data.st, data.stream))
-		data.wg.Done()
+		f()
 	}
-	go s.serverWorker(ch)
+	go s.serverWorker()
 }
 
-// initServerWorkers creates worker goroutines and channels to process incoming
+// initServerWorkers creates worker goroutines and a channel to process incoming
 // connections to reduce the time spent overall on runtime.morestack.
 func (s *Server) initServerWorkers() {
-	s.serverWorkerChannels = make([]chan *serverWorkerData, s.opts.numServerWorkers)
+	s.serverWorkerChannel = make(chan func())
 	for i := uint32(0); i < s.opts.numServerWorkers; i++ {
-		s.serverWorkerChannels[i] = make(chan *serverWorkerData)
-		go s.serverWorker(s.serverWorkerChannels[i])
+		go s.serverWorker()
 	}
 }
 
 func (s *Server) stopServerWorkers() {
-	for i := uint32(0); i < s.opts.numServerWorkers; i++ {
-		close(s.serverWorkerChannels[i])
-	}
+	close(s.serverWorkerChannel)
 }
 
 // NewServer creates a gRPC server which has no service registered and has not
@@ -898,7 +888,7 @@ func (s *Server) drainServerTransports(addr string) {
 	s.mu.Lock()
 	conns := s.conns[addr]
 	for st := range conns {
-		st.Drain()
+		st.Drain("")
 	}
 	s.mu.Unlock()
 }
@@ -946,26 +936,26 @@ func (s *Server) serveStreams(st transport.ServerTransport) {
 	defer st.Close(errors.New("finished serving streams for the server transport"))
 	var wg sync.WaitGroup
 
-	var roundRobinCounter uint32
+	streamQuota := newHandlerQuota(s.opts.maxConcurrentStreams)
 	st.HandleStreams(func(stream *transport.Stream) {
 		wg.Add(1)
+
+		streamQuota.acquire()
+		f := func() {
+			defer streamQuota.release()
+			defer wg.Done()
+			s.handleStream(st, stream, s.traceInfo(st, stream))
+		}
+
 		if s.opts.numServerWorkers > 0 {
-			data := &serverWorkerData{st: st, wg: &wg, stream: stream}
 			select {
-			case s.serverWorkerChannels[atomic.AddUint32(&roundRobinCounter, 1)%s.opts.numServerWorkers] <- data:
+			case s.serverWorkerChannel <- f:
+				return
 			default:
 				// If all stream workers are busy, fallback to the default code path.
-				go func() {
-					s.handleStream(st, stream, s.traceInfo(st, stream))
-					wg.Done()
-				}()
 			}
-		} else {
-			go func() {
-				defer wg.Done()
-				s.handleStream(st, stream, s.traceInfo(st, stream))
-			}()
 		}
+		go f()
 	}, func(ctx context.Context, method string) context.Context {
 		if !EnableTracing {
 			return ctx
@@ -1054,7 +1044,7 @@ func (s *Server) addConn(addr string, st transport.ServerTransport) bool {
 	if s.drain {
 		// Transport added after we drained our existing conns: drain it
 		// immediately.
-		st.Drain()
+		st.Drain("")
 	}
 
 	if s.conns[addr] == nil {
@@ -1864,7 +1854,7 @@ func (s *Server) GracefulStop() {
 	if !s.drain {
 		for _, conns := range s.conns {
 			for st := range conns {
-				st.Drain()
+				st.Drain("graceful_stop")
 			}
 		}
 		s.drain = true
@@ -2060,3 +2050,32 @@ func validateSendCompressor(name, clientCompressors string) error {
 	}
 	return fmt.Errorf("client does not support compressor %q", name)
 }
+
+// atomicSemaphore implements a blocking, counting semaphore. acquire should be
+// called synchronously; release may be called asynchronously.
+type atomicSemaphore struct {
+	n    int64
+	wait chan struct{}
+}
+
+func (q *atomicSemaphore) acquire() {
+	if atomic.AddInt64(&q.n, -1) < 0 {
+		// We ran out of quota.  Block until a release happens.
+		<-q.wait
+	}
+}
+
+func (q *atomicSemaphore) release() {
+	// N.B. the "<= 0" check below should allow for this to work with multiple
+	// concurrent calls to acquire, but also note that with synchronous calls to
+	// acquire, as our system does, n will never be less than -1.  There are
+	// fairness issues (queuing) to consider if this was to be generalized.
+	if atomic.AddInt64(&q.n, 1) <= 0 {
+		// An acquire was waiting on us.  Unblock it.
+		q.wait <- struct{}{}
+	}
+}
+
+func newHandlerQuota(n uint32) *atomicSemaphore {
+	return &atomicSemaphore{n: int64(n), wait: make(chan struct{}, 1)}
+}
diff --git a/vendor/google.golang.org/grpc/service_config.go b/vendor/google.golang.org/grpc/service_config.go
index f22acace4..0df11fc09 100644
--- a/vendor/google.golang.org/grpc/service_config.go
+++ b/vendor/google.golang.org/grpc/service_config.go
@@ -23,8 +23,6 @@ import (
 	"errors"
 	"fmt"
 	"reflect"
-	"strconv"
-	"strings"
 	"time"
 
 	"google.golang.org/grpc/codes"
@@ -106,8 +104,8 @@ type healthCheckConfig struct {
 
 type jsonRetryPolicy struct {
 	MaxAttempts          int
-	InitialBackoff       string
-	MaxBackoff           string
+	InitialBackoff       internalserviceconfig.Duration
+	MaxBackoff           internalserviceconfig.Duration
 	BackoffMultiplier    float64
 	RetryableStatusCodes []codes.Code
 }
@@ -129,50 +127,6 @@ type retryThrottlingPolicy struct {
 	TokenRatio float64
 }
 
-func parseDuration(s *string) (*time.Duration, error) {
-	if s == nil {
-		return nil, nil
-	}
-	if !strings.HasSuffix(*s, "s") {
-		return nil, fmt.Errorf("malformed duration %q", *s)
-	}
-	ss := strings.SplitN((*s)[:len(*s)-1], ".", 3)
-	if len(ss) > 2 {
-		return nil, fmt.Errorf("malformed duration %q", *s)
-	}
-	// hasDigits is set if either the whole or fractional part of the number is
-	// present, since both are optional but one is required.
-	hasDigits := false
-	var d time.Duration
-	if len(ss[0]) > 0 {
-		i, err := strconv.ParseInt(ss[0], 10, 32)
-		if err != nil {
-			return nil, fmt.Errorf("malformed duration %q: %v", *s, err)
-		}
-		d = time.Duration(i) * time.Second
-		hasDigits = true
-	}
-	if len(ss) == 2 && len(ss[1]) > 0 {
-		if len(ss[1]) > 9 {
-			return nil, fmt.Errorf("malformed duration %q", *s)
-		}
-		f, err := strconv.ParseInt(ss[1], 10, 64)
-		if err != nil {
-			return nil, fmt.Errorf("malformed duration %q: %v", *s, err)
-		}
-		for i := 9; i > len(ss[1]); i-- {
-			f *= 10
-		}
-		d += time.Duration(f)
-		hasDigits = true
-	}
-	if !hasDigits {
-		return nil, fmt.Errorf("malformed duration %q", *s)
-	}
-
-	return &d, nil
-}
-
 type jsonName struct {
 	Service string
 	Method  string
@@ -201,7 +155,7 @@ func (j jsonName) generatePath() (string, error) {
 type jsonMC struct {
 	Name                    *[]jsonName
 	WaitForReady            *bool
-	Timeout                 *string
+	Timeout                 *internalserviceconfig.Duration
 	MaxRequestMessageBytes  *int64
 	MaxResponseMessageBytes *int64
 	RetryPolicy             *jsonRetryPolicy
@@ -252,15 +206,10 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult {
 		if m.Name == nil {
 			continue
 		}
-		d, err := parseDuration(m.Timeout)
-		if err != nil {
-			logger.Warningf("grpc: unmarshaling service config %s: %v", js, err)
-			return &serviceconfig.ParseResult{Err: err}
-		}
 
 		mc := MethodConfig{
 			WaitForReady: m.WaitForReady,
-			Timeout:      d,
+			Timeout:      (*time.Duration)(m.Timeout),
 		}
 		if mc.RetryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil {
 			logger.Warningf("grpc: unmarshaling service config %s: %v", js, err)
@@ -312,18 +261,10 @@ func convertRetryPolicy(jrp *jsonRetryPolicy) (p *internalserviceconfig.RetryPol
 	if jrp == nil {
 		return nil, nil
 	}
-	ib, err := parseDuration(&jrp.InitialBackoff)
-	if err != nil {
-		return nil, err
-	}
-	mb, err := parseDuration(&jrp.MaxBackoff)
-	if err != nil {
-		return nil, err
-	}
 
 	if jrp.MaxAttempts <= 1 ||
-		*ib <= 0 ||
-		*mb <= 0 ||
+		jrp.InitialBackoff <= 0 ||
+		jrp.MaxBackoff <= 0 ||
 		jrp.BackoffMultiplier <= 0 ||
 		len(jrp.RetryableStatusCodes) == 0 {
 		logger.Warningf("grpc: ignoring retry policy %v due to illegal configuration", jrp)
@@ -332,8 +273,8 @@ func convertRetryPolicy(jrp *jsonRetryPolicy) (p *internalserviceconfig.RetryPol
 
 	rp := &internalserviceconfig.RetryPolicy{
 		MaxAttempts:          jrp.MaxAttempts,
-		InitialBackoff:       *ib,
-		MaxBackoff:           *mb,
+		InitialBackoff:       time.Duration(jrp.InitialBackoff),
+		MaxBackoff:           time.Duration(jrp.MaxBackoff),
 		BackoffMultiplier:    jrp.BackoffMultiplier,
 		RetryableStatusCodes: make(map[codes.Code]bool),
 	}
diff --git a/vendor/google.golang.org/grpc/status/status.go b/vendor/google.golang.org/grpc/status/status.go
index 623be39f2..bcf2e4d81 100644
--- a/vendor/google.golang.org/grpc/status/status.go
+++ b/vendor/google.golang.org/grpc/status/status.go
@@ -77,9 +77,18 @@ func FromProto(s *spb.Status) *Status {
 // FromError returns a Status representation of err.
 //
 //   - If err was produced by this package or implements the method `GRPCStatus()
-//     *Status`, the appropriate Status is returned.
+//     *Status` and `GRPCStatus()` does not return nil, or if err wraps a type
+//     satisfying this, the Status from `GRPCStatus()` is returned.  For wrapped
+//     errors, the message returned contains the entire err.Error() text and not
+//     just the wrapped status. In that case, ok is true.
 //
-//   - If err is nil, a Status is returned with codes.OK and no message.
+//   - If err is nil, a Status is returned with codes.OK and no message, and ok
+//     is true.
+//
+//   - If err implements the method `GRPCStatus() *Status` and `GRPCStatus()`
+//     returns nil (which maps to Codes.OK), or if err wraps a type
+//     satisfying this, a Status is returned with codes.Unknown and err's
+//     Error() message, and ok is false.
 //
 //   - Otherwise, err is an error not compatible with this package.  In this
 //     case, a Status is returned with codes.Unknown and err's Error() message,
@@ -88,10 +97,29 @@ func FromError(err error) (s *Status, ok bool) {
 	if err == nil {
 		return nil, true
 	}
-	if se, ok := err.(interface {
-		GRPCStatus() *Status
-	}); ok {
-		return se.GRPCStatus(), true
+	type grpcstatus interface{ GRPCStatus() *Status }
+	if gs, ok := err.(grpcstatus); ok {
+		if gs.GRPCStatus() == nil {
+			// Error has status nil, which maps to codes.OK. There
+			// is no sensible behavior for this, so we turn it into
+			// an error with codes.Unknown and discard the existing
+			// status.
+			return New(codes.Unknown, err.Error()), false
+		}
+		return gs.GRPCStatus(), true
+	}
+	var gs grpcstatus
+	if errors.As(err, &gs) {
+		if gs.GRPCStatus() == nil {
+			// Error wraps an error that has status nil, which maps
+			// to codes.OK.  There is no sensible behavior for this,
+			// so we turn it into an error with codes.Unknown and
+			// discard the existing status.
+			return New(codes.Unknown, err.Error()), false
+		}
+		p := gs.GRPCStatus().Proto()
+		p.Message = err.Error()
+		return status.FromProto(p), true
 	}
 	return New(codes.Unknown, err.Error()), false
 }
@@ -103,19 +131,16 @@ func Convert(err error) *Status {
 	return s
 }
 
-// Code returns the Code of the error if it is a Status error, codes.OK if err
-// is nil, or codes.Unknown otherwise.
+// Code returns the Code of the error if it is a Status error or if it wraps a
+// Status error. If that is not the case, it returns codes.OK if err is nil, or
+// codes.Unknown otherwise.
 func Code(err error) codes.Code {
 	// Don't use FromError to avoid allocation of OK status.
 	if err == nil {
 		return codes.OK
 	}
-	if se, ok := err.(interface {
-		GRPCStatus() *Status
-	}); ok {
-		return se.GRPCStatus().Code()
-	}
-	return codes.Unknown
+
+	return Convert(err).Code()
 }
 
 // FromContextError converts a context error or wrapped context error into a
diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go
index d1226a412..10092685b 100644
--- a/vendor/google.golang.org/grpc/stream.go
+++ b/vendor/google.golang.org/grpc/stream.go
@@ -123,6 +123,9 @@ type ClientStream interface {
 	// calling RecvMsg on the same stream at the same time, but it is not safe
 	// to call SendMsg on the same stream in different goroutines. It is also
 	// not safe to call CloseSend concurrently with SendMsg.
+	//
+	// It is not safe to modify the message after calling SendMsg. Tracing
+	// libraries and stats handlers may use the message lazily.
 	SendMsg(m interface{}) error
 	// RecvMsg blocks until it receives a message into m or the stream is
 	// done. It returns io.EOF when the stream completes successfully. On
@@ -152,6 +155,11 @@ type ClientStream interface {
 // If none of the above happen, a goroutine and a context will be leaked, and grpc
 // will not call the optionally-configured stats handler with a stats.End message.
 func (cc *ClientConn) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) {
+	if err := cc.idlenessMgr.onCallBegin(); err != nil {
+		return nil, err
+	}
+	defer cc.idlenessMgr.onCallEnd()
+
 	// allow interceptor to see all applicable call options, which means those
 	// configured as defaults from dial option as well as per-call options
 	opts = combine(cc.dopts.callOptions, opts)
@@ -469,7 +477,7 @@ func (a *csAttempt) newStream() error {
 	// It is safe to overwrite the csAttempt's context here, since all state
 	// maintained in it are local to the attempt. When the attempt has to be
 	// retried, a new instance of csAttempt will be created.
-	if a.pickResult.Metatada != nil {
+	if a.pickResult.Metadata != nil {
 		// We currently do not have a function it the metadata package which
 		// merges given metadata with existing metadata in a context. Existing
 		// function `AppendToOutgoingContext()` takes a variadic argument of key
@@ -479,7 +487,7 @@ func (a *csAttempt) newStream() error {
 		// in a form passable to AppendToOutgoingContext(), or create a version
 		// of AppendToOutgoingContext() that accepts a metadata.MD.
 		md, _ := metadata.FromOutgoingContext(a.ctx)
-		md = metadata.Join(md, a.pickResult.Metatada)
+		md = metadata.Join(md, a.pickResult.Metadata)
 		a.ctx = metadata.NewOutgoingContext(a.ctx, md)
 	}
 
@@ -1265,14 +1273,19 @@ func newNonRetryClientStream(ctx context.Context, desc *StreamDesc, method strin
 	as.p = &parser{r: s}
 	ac.incrCallsStarted()
 	if desc != unaryStreamDesc {
-		// Listen on cc and stream contexts to cleanup when the user closes the
-		// ClientConn or cancels the stream context.  In all other cases, an error
-		// should already be injected into the recv buffer by the transport, which
-		// the client will eventually receive, and then we will cancel the stream's
-		// context in clientStream.finish.
+		// Listen on stream context to cleanup when the stream context is
+		// canceled.  Also listen for the addrConn's context in case the
+		// addrConn is closed or reconnects to a different address.  In all
+		// other cases, an error should already be injected into the recv
+		// buffer by the transport, which the client will eventually receive,
+		// and then we will cancel the stream's context in
+		// addrConnStream.finish.
 		go func() {
+			ac.mu.Lock()
+			acCtx := ac.ctx
+			ac.mu.Unlock()
 			select {
-			case <-ac.ctx.Done():
+			case <-acCtx.Done():
 				as.finish(status.Error(codes.Canceled, "grpc: the SubConn is closing"))
 			case <-ctx.Done():
 				as.finish(toRPCErr(ctx.Err()))
diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go
index 3c6e3c911..3cc754062 100644
--- a/vendor/google.golang.org/grpc/version.go
+++ b/vendor/google.golang.org/grpc/version.go
@@ -19,4 +19,4 @@
 package grpc
 
 // Version is the current grpc version.
-const Version = "1.54.0"
+const Version = "1.56.3"
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 7ac34b8ba..a7692a179 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -166,9 +166,11 @@ github.com/gogo/protobuf/gogoproto
 github.com/gogo/protobuf/proto
 github.com/gogo/protobuf/protoc-gen-gogo/descriptor
 github.com/gogo/protobuf/sortkeys
-# github.com/golang/glog v1.0.0
-## explicit; go 1.11
+# github.com/golang/glog v1.1.0
+## explicit; go 1.18
 github.com/golang/glog
+github.com/golang/glog/internal/logsink
+github.com/golang/glog/internal/stackdump
 # github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
 ## explicit
 github.com/golang/groupcache/lru
@@ -597,7 +599,7 @@ google.golang.org/appengine/urlfetch
 # google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19
 ## explicit; go 1.19
 google.golang.org/genproto/googleapis/rpc/status
-# google.golang.org/grpc v1.54.0
+# google.golang.org/grpc v1.56.3
 ## explicit; go 1.17
 google.golang.org/grpc
 google.golang.org/grpc/attributes