Skip to content

Commit ec8461d

Browse files
authored
Merge branch 'coder:main' into main
2 parents d7fa089 + 47199ab commit ec8461d

138 files changed

Lines changed: 6814 additions & 3682 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.claude/docs/GO.md‎

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
# Modern Go (1.18–1.26)
2+
3+
Reference for writing idiomatic Go. Covers what changed, what it
4+
replaced, and what to reach for. Respect the project's `go.mod` `go`
5+
line: don't emit features from a version newer than what the module
6+
declares. Check `go.mod` before writing code.
7+
8+
## How modern Go thinks differently
9+
10+
**Generics** (1.18): Design reusable code with type parameters instead
11+
of `interface{}` casts, code generation, or the `sort.Interface`
12+
pattern. Use `any` for unconstrained types, `comparable` for map keys
13+
and equality, `cmp.Ordered` for sortable types. Type inference usually
14+
makes explicit type arguments unnecessary (improved in 1.21).
15+
16+
**Per-iteration loop variables** (1.22): Each loop iteration gets its
17+
own variable copy. Closures inside loops capture the correct value. The
18+
`v := v` shadow trick is dead. Remove it when you see it.
19+
20+
**Iterators** (1.23): `iter.Seq[V]` and `iter.Seq2[K,V]` are the
21+
standard iterator types. Containers expose `.All()` methods returning
22+
these. Combined with `slices.Collect`, `slices.Sorted`, `maps.Keys`,
23+
etc., they replace ad-hoc "loop and append" code with composable,
24+
lazy pipelines. When a sequence is consumed only once, prefer an
25+
iterator over materializing a slice.
26+
27+
**Error trees** (1.20–1.26): Errors compose as trees, not chains.
28+
`errors.Join` aggregates multiple errors. `fmt.Errorf` accepts multiple
29+
`%w` verbs. `errors.Is`/`As` traverse the full tree. Custom error
30+
types that wrap multiple causes must implement `Unwrap() []error` (the
31+
slice form), not `Unwrap() error`, or tree traversal won't find the
32+
children. `errors.AsType[T]` (1.26) is the type-safe way to match
33+
error types. Propagate cancellation reasons with
34+
`context.WithCancelCause`.
35+
36+
**Structured logging** (1.21): `log/slog` is the standard structured
37+
logger. This project uses `cdr.dev/slog/v3` instead, which has a
38+
different API. Do not use `log/slog` directly.
39+
40+
## Replace these patterns
41+
42+
The left column reflects common patterns from pre-1.22 Go. Write the
43+
right column instead. The "Since" column tells you the minimum `go`
44+
directive version required in `go.mod`.
45+
46+
| Old pattern | Modern replacement | Since |
47+
|---|---|---|
48+
| `interface{}` | `any` | 1.18 |
49+
| `v := v` inside loops | remove it | 1.22 |
50+
| `for i := 0; i < n; i++` | `for i := range n` | 1.22 |
51+
| `for i := 0; i < b.N; i++` (benchmarks) | `for b.Loop()` (correct timing, future-proof) | 1.24 |
52+
| `sort.Slice(s, func(i,j int) bool{…})` | `slices.SortFunc(s, cmpFn)` | 1.21 |
53+
| `wg.Add(1); go func(){ defer wg.Done(); … }()` | `wg.Go(func(){…})` | 1.25 |
54+
| `func ptr[T any](v T) *T { return &v }` | `new(expr)` e.g. `new(time.Now())` | 1.26 |
55+
| `var target *E; errors.As(err, &target)` | `t, ok := errors.AsType[*E](err)` | 1.26 |
56+
| Custom multi-error type | `errors.Join(err1, err2, …)` | 1.20 |
57+
| Single `%w` for multiple causes | `fmt.Errorf("…: %w, %w", e1, e2)` | 1.20 |
58+
| `rand.Seed(time.Now().UnixNano())` | delete it (auto-seeded); prefer `math/rand/v2` | 1.20/1.22 |
59+
| `sync.Once` + captured variable | `sync.OnceValue(func() T {…})` / `OnceValues` | 1.21 |
60+
| Custom `min`/`max` helpers | `min(a, b)` / `max(a, b)` builtins (any ordered type) | 1.21 |
61+
| `for k := range m { delete(m, k) }` | `clear(m)` (also zeroes slices) | 1.21 |
62+
| Index+slice or `SplitN(s, sep, 2)` | `strings.Cut(s, sep)` / `bytes.Cut` | 1.18 |
63+
| `TrimPrefix` + check if anything was trimmed | `strings.CutPrefix` / `CutSuffix` (returns ok bool) | 1.20 |
64+
| `strings.Split` + loop when no slice is needed | `strings.SplitSeq` / `Lines` / `FieldsSeq` (iterator, no alloc) | 1.24 |
65+
| `"2006-01-02"` / `"2006-01-02 15:04:05"` / `"15:04:05"` | `time.DateOnly` / `time.DateTime` / `time.TimeOnly` | 1.20 |
66+
| Manual `Before`/`After`/`Equal` chains for comparison | `time.Time.Compare` (returns -1/0/+1; works with `slices.SortFunc`) | 1.20 |
67+
| Loop collecting map keys into slice | `slices.Sorted(maps.Keys(m))` | 1.23 |
68+
| `fmt.Sprintf` + append to `[]byte` | `fmt.Appendf(buf, …)` (also `Append`, `Appendln`) | 1.18 |
69+
| `reflect.TypeOf((*T)(nil)).Elem()` | `reflect.TypeFor[T]()` | 1.22 |
70+
| `*(*[4]byte)(slice)` unsafe cast | `[4]byte(slice)` direct conversion | 1.20 |
71+
| `atomic.LoadInt64` / `StoreInt64` | `atomic.Int64` (also `Bool`, `Uint64`, `Pointer[T]`) | 1.19 |
72+
| `crypto/rand.Read(buf)` + hex/base64 encode | `crypto/rand.Text()` (one call) | 1.24 |
73+
| Checking `crypto/rand.Read` error | don't: return is always nil | 1.24 |
74+
| `time.Sleep` in tests | `testing/synctest` (deterministic fake clock) | 1.24/1.25 |
75+
| `json:",omitempty"` on zero-value structs like `time.Time{}` | `json:",omitzero"` (uses `IsZero()` method) | 1.24 |
76+
| `strings.Title` | `golang.org/x/text/cases` | 1.18 |
77+
| `net.IP` in new code | `net/netip.Addr` (immutable, comparable, lighter) | 1.18 |
78+
| `tools.go` with blank imports | `tool` directive in `go.mod` | 1.24 |
79+
| `runtime.SetFinalizer` | `runtime.AddCleanup` (multiple per object, no pointer cycles) | 1.24 |
80+
| `httputil.ReverseProxy.Director` | `.Rewrite` hook + `ProxyRequest` (Director deprecated in 1.26) | 1.20 |
81+
| `sql.NullString`, `sql.NullInt64`, etc. | `sql.Null[T]` | 1.22 |
82+
| Manual `ctx, cancel := context.WithCancel(…)` + `t.Cleanup(cancel)` | `t.Context()` (auto-canceled when test ends) | 1.24 |
83+
| `if d < 0 { d = -d }` on durations | `d.Abs()` (handles `math.MinInt64`) | 1.19 |
84+
| Implement only `TextMarshaler` | also implement `TextAppender` for alloc-free marshaling | 1.24 |
85+
| Custom `Unwrap() error` on multi-cause errors | `Unwrap() []error` (slice form; required for tree traversal) | 1.20 |
86+
87+
## New capabilities
88+
89+
These enable things that weren't practical before. Reach for them in the
90+
described situations.
91+
92+
| What | Since | When to use it |
93+
|---|---|---|
94+
| `cmp.Or(a, b, c)` | 1.22 | Defaults/fallback chains: returns first non-zero value. Replaces verbose `if a != "" { return a }` cascades. |
95+
| `context.WithoutCancel(ctx)` | 1.21 | Background work that must outlive the request (e.g. async cleanup after HTTP response). Derived context keeps parent's values but ignores cancellation. |
96+
| `context.AfterFunc(ctx, fn)` | 1.21 | Register cleanup that fires on context cancellation without spawning a goroutine that blocks on `<-ctx.Done()`. |
97+
| `context.WithCancelCause` / `Cause` | 1.20 | When callers need to know WHY a context was canceled, not just that it was. Retrieve cause with `context.Cause(ctx)`. |
98+
| `context.WithDeadlineCause` / `WithTimeoutCause` | 1.21 | Attach a domain-specific error to deadline/timeout expiry (e.g. distinguish "DB query timed out" from "HTTP request timed out"). |
99+
| `errors.ErrUnsupported` | 1.21 | Standard sentinel for "not supported." Use instead of per-package custom sentinels. Check with `errors.Is`. |
100+
| `http.ResponseController` | 1.20 | Per-request flush, hijack, and deadline control without type-asserting `ResponseWriter` to `http.Flusher` or `http.Hijacker`. |
101+
| Enhanced `ServeMux` routing | 1.22 | `"GET /items/{id}"` patterns in `http.ServeMux`. Access with `r.PathValue("id")`. Wildcards: `{name}`, catch-all: `{path...}`, exact: `{$}`. Eliminates many third-party router dependencies. |
102+
| `os.Root` / `OpenRoot` | 1.24 | Confined directory access that prevents symlink escape. 1.25 adds `MkdirAll`, `ReadFile`, `WriteFile` for real use. |
103+
| `os.CopyFS` | 1.23 | Copy an entire `fs.FS` to local filesystem in one call. |
104+
| `os/signal.NotifyContext` with cause | 1.26 | Cancellation cause identifies which signal (SIGTERM vs SIGINT) triggered shutdown. |
105+
| `io/fs.SkipAll` / `filepath.SkipAll` | 1.20 | Return from `WalkDir` callback to stop walking entirely. Cleaner than a sentinel error. |
106+
| `GOMEMLIMIT` env / `debug.SetMemoryLimit` | 1.19 | Soft memory limit for GC. Use alongside or instead of `GOGC` in memory-constrained containers. |
107+
| `net/url.JoinPath` | 1.19 | Join URL path segments correctly. Replaces error-prone string concatenation. |
108+
| `go test -skip` | 1.20 | Skip tests matching a pattern. Useful when running a subset of a large test suite. |
109+
110+
## Key packages
111+
112+
### `slices` (1.21, iterators added 1.23)
113+
114+
Replaces `sort.Slice`, manual search loops, and manual contains checks.
115+
116+
Search: `Contains`, `ContainsFunc`, `Index`, `IndexFunc`,
117+
`BinarySearch`, `BinarySearchFunc`.
118+
119+
Sort: `Sort`, `SortFunc`, `SortStableFunc`, `IsSorted`, `IsSortedFunc`,
120+
`Min`, `MinFunc`, `Max`, `MaxFunc`.
121+
122+
Transform: `Clone`, `Compact`, `CompactFunc`, `Grow`, `Clip`,
123+
`Concat` (1.22), `Repeat` (1.23), `Reverse`, `Insert`, `Delete`,
124+
`Replace`.
125+
126+
Compare: `Equal`, `EqualFunc`, `Compare`.
127+
128+
Iterators (1.23): `All`, `Values`, `Backward`, `Collect`, `AppendSeq`,
129+
`Sorted`, `SortedFunc`, `SortedStableFunc`, `Chunk`.
130+
131+
### `maps` (1.21, iterators added 1.23)
132+
133+
Core: `Clone`, `Copy`, `Equal`, `EqualFunc`, `DeleteFunc`.
134+
135+
Iterators (1.23): `All`, `Keys`, `Values`, `Insert`, `Collect`.
136+
137+
### `cmp` (1.21, `Or` added 1.22)
138+
139+
`Ordered` constraint for any ordered type. `Compare(a, b)` returns
140+
-1/0/+1. `Less(a, b)` returns bool. `Or(vals...)` returns first
141+
non-zero value.
142+
143+
### `iter` (1.23)
144+
145+
`Seq[V]` is `func(yield func(V) bool)`. `Seq2[K,V]` is
146+
`func(yield func(K, V) bool)`. Return these from your container's
147+
`.All()` methods. Consume with `for v := range seq` or pass to
148+
`slices.Collect`, `slices.Sorted`, `maps.Collect`, etc.
149+
150+
### `math/rand/v2` (1.22)
151+
152+
Replaces `math/rand`. `IntN` not `Intn`. Generic `N[T]()` for any
153+
integer type. Default source is `ChaCha8` (crypto-quality). No global
154+
`Seed`. Use `rand.New(source)` for reproducible sequences.
155+
156+
### `log/slog` (1.21)
157+
158+
`slog.Info`, `slog.Warn`, `slog.Error`, `slog.Debug` with key-value
159+
pairs. `slog.With(attrs...)` for logger with preset fields.
160+
`slog.GroupAttrs` (1.25) for clean group creation. Implement
161+
`slog.Handler` for custom backends.
162+
163+
**Note:** This project uses `cdr.dev/slog/v3`, not `log/slog`. The
164+
API is different. Read existing code for usage patterns.
165+
166+
## Pitfalls
167+
168+
Things that are easy to get wrong, even when you know the modern API
169+
exists. Check your output against these.
170+
171+
**Version misuse.** The replacement table has a "Since" column. If the
172+
project's `go.mod` says `go 1.22`, you cannot use `wg.Go` (1.25),
173+
`errors.AsType` (1.26), `new(expr)` (1.26), `b.Loop()` (1.24), or
174+
`testing/synctest` (1.24). Fall back to the older pattern. Always
175+
check before reaching for a replacement.
176+
177+
**`slices.Sort` vs `slices.SortFunc`.** `slices.Sort` requires
178+
`cmp.Ordered` types (int, string, float64, etc.). For structs, custom
179+
types, or multi-field sorting, use `slices.SortFunc` with a comparator
180+
function. Using `slices.Sort` on a non-ordered type is a compile error.
181+
182+
**`for range n` still binds the index.** `for range n` discards the
183+
index. If you need it, write `for i := range n`. Writing
184+
`for range n` and then trying to use `i` inside the loop is a compile
185+
error.
186+
187+
**Don't hand-roll iterators when the stdlib returns one.** Functions
188+
like `maps.Keys`, `slices.Values`, `strings.SplitSeq`, and
189+
`strings.Lines` already return `iter.Seq` or `iter.Seq2`. Don't
190+
reimplement them. Compose with `slices.Collect`, `slices.Sorted`, etc.
191+
192+
**Don't mix `math/rand` and `math/rand/v2`.** They have different
193+
function names (`Intn` vs `IntN`) and different default sources. Pick
194+
one per package. Prefer v2 for new code. The v1 global source is
195+
auto-seeded since 1.20, so delete `rand.Seed` calls either way.
196+
197+
**Iterator protocol.** When implementing `iter.Seq`, you must respect
198+
the `yield` return value. If `yield` returns `false`, stop iteration
199+
immediately and return. Ignoring it violates the contract and causes
200+
panics when consumers break out of `for range` loops early.
201+
202+
**`errors.Join` with nil.** `errors.Join` skips nil arguments. This is
203+
intentional and useful for aggregating optional errors, but don't
204+
assume the result is always non-nil. `errors.Join(nil, nil)` returns
205+
nil.
206+
207+
**`cmp.Or` evaluates all arguments.** Unlike a chain of `if`
208+
statements, `cmp.Or(a(), b(), c())` calls all three functions. If any
209+
have side effects or are expensive, use `if`/`else` instead.
210+
211+
**Timer channel semantics changed in 1.23.** Code that checks
212+
`len(timer.C)` to see if a value is pending no longer works (channel
213+
capacity is 0). Use a non-blocking `select` receive instead:
214+
`select { case <-timer.C: default: }`.
215+
216+
**`context.WithoutCancel` still propagates values.** The derived
217+
context inherits all values from the parent. If any middleware stores
218+
request-scoped state (deadlines, trace IDs) via `context.WithValue`,
219+
the background work sees it. This is usually desired but can be
220+
surprising if the values hold references that should not outlive the
221+
request.
222+
223+
## Behavioral changes that affect code
224+
225+
- **Timers** (1.23): unstopped `Timer`/`Ticker` are GC'd immediately.
226+
Channels are unbuffered: no stale values after `Reset`/`Stop`. You no
227+
longer need `defer t.Stop()` to prevent leaks.
228+
- **Error tree traversal** (1.20): `errors.Is`/`As` follow
229+
`Unwrap() []error`, not just `Unwrap() error`. Multi-error types must
230+
expose the slice form for child errors to be found.
231+
- **`math/rand` auto-seeded** (1.20): the global RNG is auto-seeded.
232+
`rand.Seed` is a no-op in 1.24+. Don't call it.
233+
- **GODEBUG compat** (1.21): behavioral changes are gated by `go.mod`'s
234+
`go` line. Upgrading the version opts into new defaults.
235+
- **Build tags** (1.18): `//go:build` is the only syntax. `// +build`
236+
is gone.
237+
- **Tool install** (1.18): `go get` no longer builds. Use
238+
`go install pkg@version`.
239+
- **Doc comments** (1.19): support `[links]`, lists, and headings.
240+
- **`go test -skip`** (1.20): skip tests by name pattern from the
241+
command line.
242+
- **`go fix ./...` modernizers** (1.26): auto-rewrites code to use
243+
newer idioms. Run after Go version upgrades.
244+
245+
## Transparent improvements (no code changes)
246+
247+
Swiss Tables maps, Green Tea GC, PGO, faster `io.ReadAll`,
248+
stack-allocated slices, reduced cgo overhead, container-aware
249+
GOMAXPROCS. Free on upgrade.

‎.github/workflows/deploy-docs.yaml‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# This workflow triggers a Vercel deploy hook which builds+deploys coder.com
2+
# (a Next.js app), to keep coder.com/docs URLs in sync with docs/manifest.json
3+
#
4+
# https://vercel.com/docs/deploy-hooks#triggering-a-deploy-hook
5+
6+
name: Update coder.com/docs
7+
8+
on:
9+
push:
10+
branches:
11+
- main
12+
paths:
13+
- "docs/manifest.json"
14+
15+
jobs:
16+
deploy-docs:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Deploy docs site
20+
run: |
21+
curl -X POST "${{ secrets.DEPLOY_DOCS_VERCEL_WEBHOOK }}"

‎.github/workflows/release.yaml‎

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -955,35 +955,3 @@ jobs:
955955
# different repo.
956956
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }}
957957
VERSION: ${{ needs.release.outputs.version }}
958-
959-
# publish-sqlc pushes the latest schema to sqlc cloud.
960-
# At present these pushes cannot be tagged, so the last push is always the latest.
961-
publish-sqlc:
962-
name: "Publish to schema sqlc cloud"
963-
runs-on: "ubuntu-latest"
964-
needs: release
965-
if: ${{ !inputs.dry_run }}
966-
steps:
967-
- name: Harden Runner
968-
uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2
969-
with:
970-
egress-policy: audit
971-
972-
- name: Checkout
973-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
974-
with:
975-
fetch-depth: 1
976-
persist-credentials: false
977-
978-
# We need golang to run the migration main.go
979-
- name: Setup Go
980-
uses: ./.github/actions/setup-go
981-
982-
- name: Setup sqlc
983-
uses: ./.github/actions/setup-sqlc
984-
985-
- name: Push schema to sqlc cloud
986-
# Don't block a release on this
987-
continue-on-error: true
988-
run: |
989-
make sqlc-push

‎AGENTS.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ comments preserve important context about why code works a certain way.
203203
## Detailed Development Guides
204204

205205
@.claude/docs/ARCHITECTURE.md
206+
@.claude/docs/GO.md
206207
@.claude/docs/OAUTH2.md
207208
@.claude/docs/TESTING.md
208209
@.claude/docs/TROUBLESHOOTING.md

‎Makefile‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ SITE_GEN_FILES := \
427427
site/src/api/typesGenerated.ts \
428428
site/src/api/rbacresourcesGenerated.ts \
429429
site/src/api/countriesGenerated.ts \
430+
site/src/api/chatModelOptionsGenerated.json \
430431
site/src/theme/icons.json
431432

432433
site/out/index.html: \
@@ -654,6 +655,7 @@ GEN_FILES := \
654655
tailnet/proto/tailnet.pb.go \
655656
agent/proto/agent.pb.go \
656657
agent/agentsocket/proto/agentsocket.pb.go \
658+
agent/boundarylogproxy/codec/boundary.pb.go \
657659
provisionersdk/proto/provisioner.pb.go \
658660
provisionerd/proto/provisionerd.pb.go \
659661
vpn/vpn.pb.go \
@@ -709,6 +711,7 @@ gen/mark-fresh:
709711
provisionersdk/proto/provisioner.pb.go \
710712
provisionerd/proto/provisionerd.pb.go \
711713
agent/agentsocket/proto/agentsocket.pb.go \
714+
agent/boundarylogproxy/codec/boundary.pb.go \
712715
vpn/vpn.pb.go \
713716
enterprise/aibridged/proto/aibridged.pb.go \
714717
coderd/database/dump.sql \
@@ -719,6 +722,7 @@ gen/mark-fresh:
719722
coderd/rbac/scopes_constants_gen.go \
720723
site/src/api/rbacresourcesGenerated.ts \
721724
site/src/api/countriesGenerated.ts \
725+
site/src/api/chatModelOptionsGenerated.json \
722726
docs/admin/integrations/prometheus.md \
723727
docs/reference/cli/index.md \
724728
docs/admin/security/audit-logs.md \
@@ -843,6 +847,12 @@ vpn/vpn.pb.go: vpn/vpn.proto
843847
--go_opt=paths=source_relative \
844848
./vpn/vpn.proto
845849

850+
agent/boundarylogproxy/codec/boundary.pb.go: agent/boundarylogproxy/codec/boundary.proto agent/proto/agent.proto
851+
protoc \
852+
--go_out=. \
853+
--go_opt=paths=source_relative \
854+
./agent/boundarylogproxy/codec/boundary.proto
855+
846856
enterprise/aibridged/proto/aibridged.pb.go: enterprise/aibridged/proto/aibridged.proto
847857
protoc \
848858
--go_out=. \
@@ -909,6 +919,10 @@ site/src/api/countriesGenerated.ts: site/node_modules/.installed scripts/typegen
909919
./scripts/biome_format.sh src/api/countriesGenerated.ts
910920
touch "$@"
911921

922+
site/src/api/chatModelOptionsGenerated.json: scripts/modeloptionsgen/main.go codersdk/chats.go
923+
go run ./scripts/modeloptionsgen/main.go | tail -n +2 > "$@"
924+
cd site && pnpm biome format --write src/api/chatModelOptionsGenerated.json
925+
912926
scripts/metricsdocgen/generated_metrics: $(GO_SRC_FILES)
913927
go run ./scripts/metricsdocgen/scanner > $@
914928

‎agent/agent.go‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ func (a *agent) initSocketServer() {
410410
agentsocket.WithPath(a.socketPath),
411411
)
412412
if err != nil {
413-
a.logger.Warn(a.hardCtx, "failed to create socket server", slog.Error(err), slog.F("path", a.socketPath))
413+
a.logger.Error(a.hardCtx, "failed to create socket server", slog.Error(err), slog.F("path", a.socketPath))
414414
return
415415
}
416416

@@ -420,7 +420,12 @@ func (a *agent) initSocketServer() {
420420

421421
// startBoundaryLogProxyServer starts the boundary log proxy socket server.
422422
func (a *agent) startBoundaryLogProxyServer() {
423-
proxy := boundarylogproxy.NewServer(a.logger, a.boundaryLogProxySocketPath)
423+
if a.boundaryLogProxySocketPath == "" {
424+
a.logger.Warn(a.hardCtx, "boundary log proxy socket path not defined; not starting proxy")
425+
return
426+
}
427+
428+
proxy := boundarylogproxy.NewServer(a.logger, a.boundaryLogProxySocketPath, a.prometheusRegistry)
424429
if err := proxy.Start(); err != nil {
425430
a.logger.Warn(a.hardCtx, "failed to start boundary log proxy", slog.Error(err))
426431
return

0 commit comments

Comments
 (0)