Skip to content

Commit 5e31e7b

Browse files
committed
docs: address PR opensearch-project#812 review feedback
- guides/metrics.md: fix nonexistent opensearchtransport.WithObserver() reference; describe Observer field on opensearch.Config instead - guides/metrics.md: hoist safeFloat helper out of for-loop body so the polling example is parseable Go - guides/metrics.md: align aggregate tables to Field (Go name) + JSON (tag) layout matching ConnectionMetric/PolicySnapshot/RouterSnapshot - guides/error_handling.md, v5preview/opensearchapi/README.md: drop *PartialBulkError and *ShardFailureError from MSearch switch examples (MSearch never returns them); fix the duplicate pre-existing example in v5preview README - guides/error_handling.md: qualify "folded into err" claim with the v4-vs-v5preview default-mask caveat - CHANGELOG.md: rewrite "prefer for/switch pattern over Errors(err)" bullet to recommend the pattern over per-Resp helpers, not over Errors(err) Signed-off-by: Sean Chittenden <sean.chittenden@crowdstrike.com>
1 parent d87bb6e commit 5e31e7b

4 files changed

Lines changed: 36 additions & 46 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
102102
- `opensearchapi.Errors(err) []error` package-level helper that flattens single- and multi-wrapper errors into a uniform slice; recommended call-site pattern is a `for`/`switch` over the result (not `errors.As` against a specific type)
103103
- Helper functions: `IsPartialFailure`, `ToleratePartialFailures`, `RequireSuccessRate` for threshold-based error tolerance
104104
- Operation constants: `OperationIndex`, `OperationCreate`, `OperationUpdate`, `OperationDelete`
105-
- Per-Resp helper methods (`BulkItemFailures`, `SearchShardFailures`, `WriteShardFailures`, `MultiSearchItemFailures`, `PartialFailures(mask)`) exist on the response types as engine machinery for the dispatch; new code should prefer the `for`/`switch` pattern over `opensearchapi.Errors(err)` for forward compatibility
105+
- Per-Resp helper methods (`BulkItemFailures`, `SearchShardFailures`, `WriteShardFailures`, `MultiSearchItemFailures`, `PartialFailures(mask)`) exist on the response types as engine machinery for the dispatch; new code should prefer a `for`/`switch` over `opensearchapi.Errors(err)` rather than the per-Resp helpers, for forward compatibility
106106
- `Config.Errors *errmask.ErrorMask` replaces a single boolean: each bit suppresses one wrapper category. v4 defaults to `errmask.All` (mask everything, preserves pre-bitfield behavior); v5+ defaults to `errmask.Empty` (report everything)
107107
- `OPENSEARCH_GO_ERROR_MASK` environment variable overrides `Config.Errors` at runtime via comma-separated `+`/`-` tokens (lowercase snake_case wrapper names; unknown tokens silently dropped, debug-logged)
108108
- Both `(resp, error)` are non-nil on partial failure -- response is fully populated

guides/error_handling.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,9 @@ resp, err := client.Bulk(ctx, req)
219219
if err != nil {
220220
return err
221221
}
222-
// resp is fully populated; partial failures (if any) are folded into err.
222+
// resp is fully populated; partial failures (if any) are folded into err
223+
// when the wrapper bits are unmasked (the v5preview default, or v4 with
224+
// Config.Errors: errmask.New()).
223225
```
224226

225227
**Inspect categories with a `for`/`switch`** -- when partial error handling is appropriate. Partial error handling lets the client and its application recover from known failure modes they can tolerate (e.g. continue serving a search with a few failed shards, or retry only the bulk items the server rejected) instead of failing the whole operation. The `default` arm catches transport / HTTP / decode errors and any partial-failure category added in a future release:
@@ -228,14 +230,10 @@ if err != nil {
228230
resp, err := client.MSearch(ctx, req)
229231
for _, sub := range opensearchapi.Errors(err) {
230232
switch e := sub.(type) {
231-
case *opensearchapi.PartialBulkError:
232-
log.Printf("%d items failed", len(e.FailedItems))
233233
case *opensearchapi.PartialSearchError:
234234
log.Printf("%d/%d shards failed", e.FailedShards, e.TotalShards)
235235
case *opensearchapi.MultiSearchItemError:
236236
log.Printf("%d sub-queries failed", len(e.Items))
237-
case *opensearchapi.ShardFailureError:
238-
log.Printf("%s: %d/%d shards failed", e.Operation, e.FailedShards, e.TotalShards)
239237
default:
240238
return err
241239
}

guides/metrics.md

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -34,39 +34,39 @@ The top-level `Metrics` struct contains aggregate counters, per-connection detai
3434

3535
### Request Counters
3636

37-
| Field | Type | Description |
38-
| ----------- | ------------- | ----------------------------------------- |
39-
| `requests` | `int` | Total requests performed by the transport |
40-
| `failures` | `int` | Total request failures |
41-
| `responses` | `map[int]int` | Response count by HTTP status code |
37+
| Field | JSON | Type | Description |
38+
| ----------- | ----------- | ------------- | ----------------------------------------- |
39+
| `Requests` | `requests` | `int` | Total requests performed by the transport |
40+
| `Failures` | `failures` | `int` | Total request failures |
41+
| `Responses` | `responses` | `map[int]int` | Response count by HTTP status code |
4242

4343
### Connection Pool State
4444

45-
| Field | Type | Description |
46-
| --------------------- | ----- | ------------------------------------------- |
47-
| `live_connections` | `int` | Non-dead connections (active + standby) |
48-
| `dead_connections` | `int` | Connections in the dead list |
49-
| `standby_connections` | `int` | Connections in the standby partition |
50-
| `overloaded_servers` | `int` | Connections the client considers overloaded |
45+
| Field | JSON | Type | Description |
46+
| -------------------- | --------------------- | ----- | ------------------------------------------- |
47+
| `LiveConnections` | `live_connections` | `int` | Non-dead connections (active + standby) |
48+
| `DeadConnections` | `dead_connections` | `int` | Connections in the dead list |
49+
| `StandbyConnections` | `standby_connections` | `int` | Connections in the standby partition |
50+
| `OverloadedServers` | `overloaded_servers` | `int` | Connections the client considers overloaded |
5151

5252
### Connection Lifecycle Counters
5353

54-
| Field | Type | Description |
55-
| ---------------------- | ----- | ---------------------------------------------------- |
56-
| `connections_promoted` | `int` | Dead to ready transitions (successful resurrections) |
57-
| `connections_demoted` | `int` | Ready to dead transitions |
58-
| `zombie_connections` | `int` | Dead connections forcibly retried |
59-
| `standby_promotions` | `int` | Standby to active transitions |
60-
| `standby_demotions` | `int` | Active to standby transitions |
54+
| Field | JSON | Type | Description |
55+
| --------------------- | ---------------------- | ----- | ---------------------------------------------------- |
56+
| `ConnectionsPromoted` | `connections_promoted` | `int` | Dead to ready transitions (successful resurrections) |
57+
| `ConnectionsDemoted` | `connections_demoted` | `int` | Ready to dead transitions |
58+
| `ZombieConnections` | `zombie_connections` | `int` | Dead connections forcibly retried |
59+
| `StandbyPromotions` | `standby_promotions` | `int` | Standby to active transitions |
60+
| `StandbyDemotions` | `standby_demotions` | `int` | Active to standby transitions |
6161

6262
### Health Check Counters
6363

64-
| Field | Type | Description |
65-
| ----------------------- | ----- | -------------------------------------------------- |
66-
| `health_checks` | `int` | Baseline `GET /` health checks performed |
67-
| `cluster_health_checks` | `int` | `GET /_cluster/health?local=true` checks performed |
68-
| `health_checks_success` | `int` | Successful health check outcomes |
69-
| `health_checks_failed` | `int` | Failed health check outcomes |
64+
| Field | JSON | Type | Description |
65+
| --------------------- | ----------------------- | ----- | -------------------------------------------------- |
66+
| `HealthChecks` | `health_checks` | `int` | Baseline `GET /` health checks performed |
67+
| `ClusterHealthChecks` | `cluster_health_checks` | `int` | `GET /_cluster/health?local=true` checks performed |
68+
| `HealthChecksSuccess` | `health_checks_success` | `int` | Successful health check outcomes |
69+
| `HealthChecksFailed` | `health_checks_failed` | `int` | Failed health check outcomes |
7070

7171
---
7272

@@ -169,6 +169,13 @@ Each index with an active routing slot produces an entry in `Router.Indexes`.
169169
Poll metrics on a timer for logging or export to an external monitoring system.
170170

171171
```go
172+
func safeFloat(f *float64) float64 {
173+
if f == nil {
174+
return 0
175+
}
176+
return *f
177+
}
178+
172179
ticker := time.NewTicker(30 * time.Second)
173180
defer ticker.Stop()
174181

@@ -207,13 +214,6 @@ for range ticker.C {
207214
}
208215
}
209216
}
210-
211-
func safeFloat(f *float64) float64 {
212-
if f == nil {
213-
return 0
214-
}
215-
return *f
216-
}
217217
```
218218

219219
## JSON Export
@@ -249,6 +249,6 @@ The metrics API is pull-based: call `client.Metrics()` inside your collector's `
249249

250250
## Observer API
251251

252-
For event-driven observability (as opposed to polling), implement the `ConnectionObserver` interface and pass it via `opensearchtransport.WithObserver()`. The observer receives callbacks for connection lifecycle events (promote, demote, overload), routing decisions, health checks, and shard map invalidations. See the [routing guide](routing.md) for details on observer events.
252+
For event-driven observability (as opposed to polling), implement the `opensearchtransport.ConnectionObserver` interface and set it on the `Observer` field of `opensearch.Config`. The observer receives callbacks for connection lifecycle events (promote, demote, overload), routing decisions, health checks, and shard map invalidations. See the [routing guide](routing.md) for details on observer events.
253253

254254
The metrics API and observer API are complementary: metrics give you aggregate snapshots for dashboards, while the observer gives you per-event detail for tracing and debugging.

v5preview/opensearchapi/README.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,10 +238,6 @@ for _, sub := range opensearchapi.Errors(err) {
238238
log.Printf("shard agg: %d/%d shards failed", e.FailedShards, e.TotalShards)
239239
case *opensearchapi.MultiSearchItemError:
240240
log.Printf("%d sub-queries failed", len(e.Items))
241-
case *opensearchapi.PartialBulkError:
242-
log.Printf("%d items failed", len(e.FailedItems))
243-
case *opensearchapi.ShardFailureError:
244-
log.Printf("%s: %d/%d shards failed", e.Operation, e.FailedShards, e.TotalShards)
245241
default:
246242
return err // transport / HTTP / decoding error
247243
}
@@ -284,14 +280,10 @@ if err != nil {
284280
resp, err := client.MSearch(ctx, req)
285281
for _, sub := range opensearchapi.Errors(err) {
286282
switch e := sub.(type) {
287-
case *opensearchapi.PartialBulkError:
288-
log.Printf("%d items failed", len(e.FailedItems))
289283
case *opensearchapi.PartialSearchError:
290284
log.Printf("%d/%d shards failed", e.FailedShards, e.TotalShards)
291285
case *opensearchapi.MultiSearchItemError:
292286
log.Printf("%d sub-queries failed", len(e.Items))
293-
case *opensearchapi.ShardFailureError:
294-
log.Printf("%s: %d/%d shards failed", e.Operation, e.FailedShards, e.TotalShards)
295287
default:
296288
return err
297289
}

0 commit comments

Comments
 (0)