You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2026-06-03 18:35:08 +02:00
a18614cbc2
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [github.com/securego/gosec/v2](https://redirect.github.com/securego/gosec) | `v2.23.0` → `v2.24.7` |  |  | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](../issues/5322) for more information. --- ### Release Notes <details> <summary>securego/gosec (github.com/securego/gosec/v2)</summary> ### [`v2.24.7`](https://redirect.github.com/securego/gosec/releases/tag/v2.24.7) [Compare Source](https://redirect.github.com/securego/gosec/compare/v2.24.6...v2.24.7) #### Changelog - [`bb17e42`](https://redirect.github.com/securego/gosec/commit/bb17e422fc34bf4c0a2e5cab9d07dc45a68c040c) Ignore nosec comments in action integration workflow to generate some warnings ([#​1573](https://redirect.github.com/securego/gosec/issues/1573)) - [`e1502ad`](https://redirect.github.com/securego/gosec/commit/e1502ad21653d1c6717e33f1221c3ce2d5c8581f) Add a workflow for action integration test ([#​1571](https://redirect.github.com/securego/gosec/issues/1571)) - [`f8691bd`](https://redirect.github.com/securego/gosec/commit/f8691bd77bab5430ccb538e6f253275e82577afc) fix(sarif): avoid invalid null relationships in SARIF output ([#​1569](https://redirect.github.com/securego/gosec/issues/1569)) - [`ade1d0e`](https://redirect.github.com/securego/gosec/commit/ade1d0e0a04ec8ae98da98614d42524621d40df2) chore: migrate gosec container image references to GHCR ([#​1567](https://redirect.github.com/securego/gosec/issues/1567)) ### [`v2.24.6`](https://redirect.github.com/securego/gosec/releases/tag/v2.24.6) [Compare Source](https://redirect.github.com/securego/gosec/compare/v2.24.5...v2.24.6) #### Changelog - [`88835e8`](https://redirect.github.com/securego/gosec/commit/88835e86bba381290c2f60a1c73610995b1502eb) Update gorelease to use the latest cosign bundle argument ([#​1565](https://redirect.github.com/securego/gosec/issues/1565)) ### [`v2.24.5`](https://redirect.github.com/securego/gosec/compare/v2.24.4...v2.24.5) [Compare Source](https://redirect.github.com/securego/gosec/compare/v2.24.4...v2.24.5) ### [`v2.24.4`](https://redirect.github.com/securego/gosec/compare/v2.24.3...v2.24.4) [Compare Source](https://redirect.github.com/securego/gosec/compare/v2.24.3...v2.24.4) ### [`v2.24.3`](https://redirect.github.com/securego/gosec/compare/v2.24.2...v2.24.3) [Compare Source](https://redirect.github.com/securego/gosec/compare/v2.24.2...v2.24.3) ### [`v2.24.2`](https://redirect.github.com/securego/gosec/compare/v2.24.1...v2.24.2) [Compare Source](https://redirect.github.com/securego/gosec/compare/v2.24.1...v2.24.2) ### [`v2.24.1`](https://redirect.github.com/securego/gosec/compare/v2.24.0...v2.24.1) [Compare Source](https://redirect.github.com/securego/gosec/compare/v2.24.0...v2.24.1) ### [`v2.24.0`](https://redirect.github.com/securego/gosec/releases/tag/v2.24.0) [Compare Source](https://redirect.github.com/securego/gosec/compare/v2.23.0...v2.24.0) #### Changelog - [`271492b`](https://redirect.github.com/securego/gosec/commit/271492bcd930ef72dfb9d00e5bb9544b3b407fb5) fix: G704 false positive on const URL ([#​1551](https://redirect.github.com/securego/gosec/issues/1551)) - [`1341aea`](https://redirect.github.com/securego/gosec/commit/1341aeadb4c334014c4834c745344edb9dcf85b0) fix(G705): eliminate false positive for non-HTTP io.Writer ([#​1550](https://redirect.github.com/securego/gosec/issues/1550)) - [`f2262c8`](https://redirect.github.com/securego/gosec/commit/f2262c88ffdfc9eb7be8444db19caa17cc71810f) G120: avoid false positive when MaxBytesReader is applied in middleware ([#​1547](https://redirect.github.com/securego/gosec/issues/1547)) - [`5b580c7`](https://redirect.github.com/securego/gosec/commit/5b580c76e4714fa553b2ceb8169a071e45bf6428) Fix G602 regression coverage for issue [#​1545](https://redirect.github.com/securego/gosec/issues/1545) and stabilize G117 TOML test dependency ([#​1546](https://redirect.github.com/securego/gosec/issues/1546)) - [`eba2d15`](https://redirect.github.com/securego/gosec/commit/eba2d1582b13e37d5b6c991b643827bc60e58156) taint: skip `context.Context` arguments during taint propagation to fix false positives ([#​1543](https://redirect.github.com/securego/gosec/issues/1543)) - [`a6381c1`](https://redirect.github.com/securego/gosec/commit/a6381c1e2fe9a9a33ef105c76bea3191402ea4b3) test: add missing rules to formatter report tests ([#​1540](https://redirect.github.com/securego/gosec/issues/1540)) - [`fea9725`](https://redirect.github.com/securego/gosec/commit/fea9725934065d3dd5c96352f89f75d117ac12f6) chore(deps): update all dependencies ([#​1541](https://redirect.github.com/securego/gosec/issues/1541)) - [`f3e2fac`](https://redirect.github.com/securego/gosec/commit/f3e2fac4d58b7eca54307cd40ce2a836a12e4d95) Regenrate the TLS config rule ([#​1539](https://redirect.github.com/securego/gosec/issues/1539)) - [`200461f`](https://redirect.github.com/securego/gosec/commit/200461fcf74ed836305bf95f72568c20925730c5) Improve documentation ([#​1538](https://redirect.github.com/securego/gosec/issues/1538)) - [`078a62a`](https://redirect.github.com/securego/gosec/commit/078a62afc3331206fec1cd9a03637983ec4f9fc8) Expand analyzer-core test coverage for orchestration, go/analysis adapter logic, and taint integration ([#​1537](https://redirect.github.com/securego/gosec/issues/1537)) - [`ffdc620`](https://redirect.github.com/securego/gosec/commit/ffdc6205c82278cee0b62923814141923794219e) Add unit tests for CLI orchestration, TLS config generation, and SSA cache behavior ([#​1536](https://redirect.github.com/securego/gosec/issues/1536)) - [`c13a486`](https://redirect.github.com/securego/gosec/commit/c13a48626bc160ef1caa293679044b5667d4d8ef) Add G707 taint analyzer for SMTP command/header injection ([#​1535](https://redirect.github.com/securego/gosec/issues/1535)) - [`f61ed31`](https://redirect.github.com/securego/gosec/commit/f61ed314c2467116ec3a5126150cb2b29a623406) Add G123 analyzer for tls.VerifyPeerCertificate resumption bypass risk ([#​1534](https://redirect.github.com/securego/gosec/issues/1534)) - [`b568aa1`](https://redirect.github.com/securego/gosec/commit/b568aa1445e110ed12abe5c2433b3cfbcd0a5935) Add G122 SSA analyzer for filepath.Walk/WalkDir symlink TOCTOU race risks ([#​1532](https://redirect.github.com/securego/gosec/issues/1532)) - [`1735e5a`](https://redirect.github.com/securego/gosec/commit/1735e5a9acd155702b8c6137d323df886c0252b5) fix(G602): avoid false positives for range-over-array indexing ([#​1531](https://redirect.github.com/securego/gosec/issues/1531)) - [`caf93d0`](https://redirect.github.com/securego/gosec/commit/caf93d07f10ef7d07006011b17f1d9bd218b5a9d) Improve taint analyzer performance with shared SSA cache, parallel analyzer execution, and CI regression guard ([#​1530](https://redirect.github.com/securego/gosec/issues/1530)) - [`bd11fbe`](https://redirect.github.com/securego/gosec/commit/bd11fbe2bacb0abf1e541df8b6ec6b040bbe2723) fix: taint analysis false positives with G703,G705 ([#​1522](https://redirect.github.com/securego/gosec/issues/1522)) - [`e34e8dd`](https://redirect.github.com/securego/gosec/commit/e34e8dd8e880694cfa801d79977e2d9973df3fa1) Extend the G117 rule to cover other types of serialization such as yaml/xml/toml ([#​1529](https://redirect.github.com/securego/gosec/issues/1529)) - [`b940702`](https://redirect.github.com/securego/gosec/commit/b940702d5e385d1a68def10326b1658e780655fe) Fix the G117 rule to take the JSON serialization into account ([#​1528](https://redirect.github.com/securego/gosec/issues/1528)) - [`4f84627`](https://redirect.github.com/securego/gosec/commit/4f846273804abaf7e040f77b26bf2866336e8af9) (docs) fix justification format ([#​1524](https://redirect.github.com/securego/gosec/issues/1524)) - [`36ba72b`](https://redirect.github.com/securego/gosec/commit/36ba72bb7f91306f5210a821f409696c03dcbf2b) Add G121 analyzer for unsafe CORS bypass patterns in CrossOriginProtection ([#​1521](https://redirect.github.com/securego/gosec/issues/1521)) - [`238f982`](https://redirect.github.com/securego/gosec/commit/238f9823256b1c4a6d7b0ccd7fa0f2ce1123c820) Add G120 SSA analyzer for unbounded form parsing in HTTP handlers ([#​1520](https://redirect.github.com/securego/gosec/issues/1520)) - [`89cde27`](https://redirect.github.com/securego/gosec/commit/89cde277b5e2b4a5dc47eb710911c51a0cb33b63) Add G119 analyzer for unsafe redirect header propagation in CheckRedirect callbacks ([#​1519](https://redirect.github.com/securego/gosec/issues/1519)) - [`14fdd9c`](https://redirect.github.com/securego/gosec/commit/14fdd9cb07c02ab1506fcc336f49c84bf27a5c2d) Fix G115 false positives and negatives (Issue [#​1501](https://redirect.github.com/securego/gosec/issues/1501)) ([#​1518](https://redirect.github.com/securego/gosec/issues/1518)) - [`cec54ec`](https://redirect.github.com/securego/gosec/commit/cec54ec685eda3083e2ab1adf72b6b7ec6cfdb6e) chore(deps): update all dependencies ([#​1517](https://redirect.github.com/securego/gosec/issues/1517)) - [`2b2077e`](https://redirect.github.com/securego/gosec/commit/2b2077e921b56c7ce6545cccceea0556ff8d5d91) Add G118 SSA analyzer for context propagation failures that can cause goroutine/resource leaks ([#​1516](https://redirect.github.com/securego/gosec/issues/1516)) - [`a7666f3`](https://redirect.github.com/securego/gosec/commit/a7666f3c70c94d07dfb03e81613fed34bccc89ae) Add G113: Detect HTTP Request Smuggling via conflicting headers (CVE-2025-22891, CWE-444) ([#​1515](https://redirect.github.com/securego/gosec/issues/1515)) - [`47f8b52`](https://redirect.github.com/securego/gosec/commit/47f8b52fb8700c7ba017ffcc0ea6a32c83e33115) Add G408: SSH PublicKeyCallback Authentication Bypass Analyzer ([#​1513](https://redirect.github.com/securego/gosec/issues/1513)) - [`4f1f362`](https://redirect.github.com/securego/gosec/commit/4f1f362671654660f7145c3c8655ffeaed037d55) Add more unit tests to improve coverage ([#​1512](https://redirect.github.com/securego/gosec/issues/1512)) - [`9344582`](https://redirect.github.com/securego/gosec/commit/9344582ee4bd87b8fa5bc2e483d90fa661f8aa71) Improve test coverage in various areas ([#​1511](https://redirect.github.com/securego/gosec/issues/1511)) - [`8d1b2c6`](https://redirect.github.com/securego/gosec/commit/8d1b2c63ae44e315fb0232813e535891ff0568fc) Imprve the test coverage ([#​1510](https://redirect.github.com/securego/gosec/issues/1510)) - [`993c1c4`](https://redirect.github.com/securego/gosec/commit/993c1c4da2d4426f7567591e23f53ee9f613d07c) Fix incorrect detection of fixed iv in G407 ([#​1509](https://redirect.github.com/securego/gosec/issues/1509)) - [`8668b74`](https://redirect.github.com/securego/gosec/commit/8668b748925d8995cf7712d22bde62cbc96f2304) Add support for go 1.26.x and removed support for go 1.24.x ([#​1508](https://redirect.github.com/securego/gosec/issues/1508)) - [`514225c`](https://redirect.github.com/securego/gosec/commit/514225c8cb01a6bab714db1dd557aeb0d7ab9dc9) Fix the sonar report to follow the latest schema ([#​1507](https://redirect.github.com/securego/gosec/issues/1507)) - [`000384e`](https://redirect.github.com/securego/gosec/commit/000384e510a84a1e2a1118e0fbc56518d290113d) fix: broken taint analysis causing false positives ([#​1506](https://redirect.github.com/securego/gosec/issues/1506)) - [`616192c`](https://redirect.github.com/securego/gosec/commit/616192c9d92792998e2ff38530c080cd0fe293a8) fix: panic on float constants in overflow analyzer ([#​1505](https://redirect.github.com/securego/gosec/issues/1505)) - [`79956a3`](https://redirect.github.com/securego/gosec/commit/79956a3b4cdedc9a4cde5f567c57fc8b367448cf) fix: panic when scanning multi-module repos from root ([#​1504](https://redirect.github.com/securego/gosec/issues/1504)) - [`5736e8b`](https://redirect.github.com/securego/gosec/commit/5736e8b88b6ca97fc7e09ef1bf24b205ab35fd9c) fix: G602 false positive for array element access ([#​1499](https://redirect.github.com/securego/gosec/issues/1499)) - [`1b7e1e9`](https://redirect.github.com/securego/gosec/commit/1b7e1e94bc2077fc1adccfc1358399fad2958d5a) Update gosec to version v2.23.0 in the Github action ([#​1496](https://redirect.github.com/securego/gosec/issues/1496)) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/open-telemetry/opentelemetry-go). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40OC4xIiwidXBkYXRlZEluVmVyIjoiNDMuNDguMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiU2tpcCBDaGFuZ2Vsb2ciLCJkZXBlbmRlbmNpZXMiXX0=--> --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Tyler Yahn <codingalias@gmail.com> Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
334 lines
8.9 KiB
Go
334 lines
8.9 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package trace // import "go.opentelemetry.io/otel/trace"
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
maxListMembers = 32
|
|
|
|
listDelimiters = ","
|
|
memberDelimiter = "="
|
|
|
|
errInvalidKey errorConst = "invalid tracestate key"
|
|
errInvalidValue errorConst = "invalid tracestate value"
|
|
errInvalidMember errorConst = "invalid tracestate list-member"
|
|
errMemberNumber errorConst = "too many list-members in tracestate"
|
|
errDuplicate errorConst = "duplicate list-member in tracestate"
|
|
)
|
|
|
|
type member struct {
|
|
Key string
|
|
Value string
|
|
}
|
|
|
|
// according to (chr = %x20 / (nblk-char = %x21-2B / %x2D-3C / %x3E-7E) )
|
|
// means (chr = %x20-2B / %x2D-3C / %x3E-7E) .
|
|
func checkValueChar(v byte) bool {
|
|
return v >= '\x20' && v <= '\x7e' && v != '\x2c' && v != '\x3d'
|
|
}
|
|
|
|
// according to (nblk-chr = %x21-2B / %x2D-3C / %x3E-7E) .
|
|
func checkValueLast(v byte) bool {
|
|
return v >= '\x21' && v <= '\x7e' && v != '\x2c' && v != '\x3d'
|
|
}
|
|
|
|
// based on the W3C Trace Context specification
|
|
//
|
|
// value = (0*255(chr)) nblk-chr
|
|
// nblk-chr = %x21-2B / %x2D-3C / %x3E-7E
|
|
// chr = %x20 / nblk-chr
|
|
//
|
|
// see https://www.w3.org/TR/trace-context-1/#value
|
|
func checkValue(val string) bool {
|
|
n := len(val)
|
|
if n == 0 || n > 256 {
|
|
return false
|
|
}
|
|
for i := 0; i < n-1; i++ {
|
|
if !checkValueChar(val[i]) {
|
|
return false
|
|
}
|
|
}
|
|
return checkValueLast(val[n-1])
|
|
}
|
|
|
|
func checkKeyRemain(key string) bool {
|
|
// ( lcalpha / DIGIT / "_" / "-"/ "*" / "/" )
|
|
for _, v := range key {
|
|
if v > 127 {
|
|
return false
|
|
}
|
|
if isAlphaNumASCII(v) {
|
|
continue
|
|
}
|
|
switch v {
|
|
case '_', '-', '*', '/':
|
|
continue
|
|
}
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// according to
|
|
//
|
|
// simple-key = lcalpha (0*255( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ))
|
|
// system-id = lcalpha (0*13( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ))
|
|
//
|
|
// param n is remain part length, should be 255 in simple-key or 13 in system-id.
|
|
func checkKeyPart(key string, n int) bool {
|
|
if key == "" {
|
|
return false
|
|
}
|
|
first := key[0] // key's first char
|
|
ret := len(key[1:]) <= n
|
|
ret = ret && first >= 'a' && first <= 'z'
|
|
return ret && checkKeyRemain(key[1:])
|
|
}
|
|
|
|
func isAlphaNumASCII[T rune | byte](c T) bool {
|
|
if c >= 'a' && c <= 'z' {
|
|
return true
|
|
}
|
|
return c >= '0' && c <= '9'
|
|
}
|
|
|
|
// according to
|
|
//
|
|
// tenant-id = ( lcalpha / DIGIT ) 0*240( lcalpha / DIGIT / "_" / "-"/ "*" / "/" )
|
|
//
|
|
// param n is remain part length, should be 240 exactly.
|
|
func checkKeyTenant(key string, n int) bool {
|
|
if key == "" {
|
|
return false
|
|
}
|
|
return isAlphaNumASCII(key[0]) && len(key[1:]) <= n && checkKeyRemain(key[1:])
|
|
}
|
|
|
|
// based on the W3C Trace Context specification
|
|
//
|
|
// key = simple-key / multi-tenant-key
|
|
// simple-key = lcalpha (0*255( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ))
|
|
// multi-tenant-key = tenant-id "@" system-id
|
|
// tenant-id = ( lcalpha / DIGIT ) (0*240( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ))
|
|
// system-id = lcalpha (0*13( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ))
|
|
// lcalpha = %x61-7A ; a-z
|
|
//
|
|
// see https://www.w3.org/TR/trace-context-1/#tracestate-header.
|
|
func checkKey(key string) bool {
|
|
tenant, system, ok := strings.Cut(key, "@")
|
|
if !ok {
|
|
return checkKeyPart(key, 255)
|
|
}
|
|
return checkKeyTenant(tenant, 240) && checkKeyPart(system, 13)
|
|
}
|
|
|
|
func newMember(key, value string) (member, error) {
|
|
if !checkKey(key) {
|
|
return member{}, errInvalidKey
|
|
}
|
|
if !checkValue(value) {
|
|
return member{}, errInvalidValue
|
|
}
|
|
return member{Key: key, Value: value}, nil
|
|
}
|
|
|
|
func parseMember(m string) (member, error) {
|
|
key, val, ok := strings.Cut(m, memberDelimiter)
|
|
if !ok {
|
|
return member{}, fmt.Errorf("%w: %s", errInvalidMember, m)
|
|
}
|
|
key = strings.TrimLeft(key, " \t")
|
|
val = strings.TrimRight(val, " \t")
|
|
result, e := newMember(key, val)
|
|
if e != nil {
|
|
return member{}, fmt.Errorf("%w: %s", errInvalidMember, m)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// String encodes member into a string compliant with the W3C Trace Context
|
|
// specification.
|
|
func (m member) String() string {
|
|
return m.Key + "=" + m.Value
|
|
}
|
|
|
|
// TraceState provides additional vendor-specific trace identification
|
|
// information across different distributed tracing systems. It represents an
|
|
// immutable list consisting of key/value pairs, each pair is referred to as a
|
|
// list-member.
|
|
//
|
|
// TraceState conforms to the W3C Trace Context specification
|
|
// (https://www.w3.org/TR/trace-context-1). All operations that create or copy
|
|
// a TraceState do so by validating all input and will only produce TraceState
|
|
// that conform to the specification. Specifically, this means that all
|
|
// list-member's key/value pairs are valid, no duplicate list-members exist,
|
|
// and the maximum number of list-members (32) is not exceeded.
|
|
type TraceState struct { //nolint:revive // revive complains about stutter of `trace.TraceState`
|
|
// list is the members in order.
|
|
list []member
|
|
}
|
|
|
|
var _ json.Marshaler = TraceState{}
|
|
|
|
// ParseTraceState attempts to decode a TraceState from the passed
|
|
// string. It returns an error if the input is invalid according to the W3C
|
|
// Trace Context specification.
|
|
func ParseTraceState(ts string) (TraceState, error) {
|
|
if ts == "" {
|
|
return TraceState{}, nil
|
|
}
|
|
|
|
wrapErr := func(err error) error {
|
|
return fmt.Errorf("failed to parse tracestate: %w", err)
|
|
}
|
|
|
|
var members []member
|
|
found := make(map[string]struct{})
|
|
for ts != "" {
|
|
var memberStr string
|
|
memberStr, ts, _ = strings.Cut(ts, listDelimiters)
|
|
if memberStr == "" {
|
|
continue
|
|
}
|
|
|
|
m, err := parseMember(memberStr)
|
|
if err != nil {
|
|
return TraceState{}, wrapErr(err)
|
|
}
|
|
|
|
if _, ok := found[m.Key]; ok {
|
|
return TraceState{}, wrapErr(errDuplicate)
|
|
}
|
|
found[m.Key] = struct{}{}
|
|
|
|
members = append(members, m)
|
|
if n := len(members); n > maxListMembers {
|
|
return TraceState{}, wrapErr(errMemberNumber)
|
|
}
|
|
}
|
|
|
|
return TraceState{list: members}, nil
|
|
}
|
|
|
|
// MarshalJSON marshals the TraceState into JSON.
|
|
func (ts TraceState) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(ts.String())
|
|
}
|
|
|
|
// String encodes the TraceState into a string compliant with the W3C
|
|
// Trace Context specification. The returned string will be invalid if the
|
|
// TraceState contains any invalid members.
|
|
func (ts TraceState) String() string {
|
|
if len(ts.list) == 0 {
|
|
return ""
|
|
}
|
|
var n int
|
|
n += len(ts.list) // member delimiters: '='
|
|
n += len(ts.list) - 1 // list delimiters: ','
|
|
for _, mem := range ts.list {
|
|
n += len(mem.Key)
|
|
n += len(mem.Value)
|
|
}
|
|
|
|
var sb strings.Builder
|
|
sb.Grow(n)
|
|
_, _ = sb.WriteString(ts.list[0].Key)
|
|
_ = sb.WriteByte('=')
|
|
_, _ = sb.WriteString(ts.list[0].Value)
|
|
for i := 1; i < len(ts.list); i++ {
|
|
_ = sb.WriteByte(listDelimiters[0])
|
|
_, _ = sb.WriteString(ts.list[i].Key)
|
|
_ = sb.WriteByte('=')
|
|
_, _ = sb.WriteString(ts.list[i].Value)
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
// Get returns the value paired with key from the corresponding TraceState
|
|
// list-member if it exists, otherwise an empty string is returned.
|
|
func (ts TraceState) Get(key string) string {
|
|
for _, member := range ts.list {
|
|
if member.Key == key {
|
|
return member.Value
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// Walk walks all key value pairs in the TraceState by calling f
|
|
// Iteration stops if f returns false.
|
|
func (ts TraceState) Walk(f func(key, value string) bool) {
|
|
for _, m := range ts.list {
|
|
if !f(m.Key, m.Value) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// Insert adds a new list-member defined by the key/value pair to the
|
|
// TraceState. If a list-member already exists for the given key, that
|
|
// list-member's value is updated. The new or updated list-member is always
|
|
// moved to the beginning of the TraceState as specified by the W3C Trace
|
|
// Context specification.
|
|
//
|
|
// If key or value are invalid according to the W3C Trace Context
|
|
// specification an error is returned with the original TraceState.
|
|
//
|
|
// If adding a new list-member means the TraceState would have more members
|
|
// then is allowed, the new list-member will be inserted and the right-most
|
|
// list-member will be dropped in the returned TraceState.
|
|
func (ts TraceState) Insert(key, value string) (TraceState, error) {
|
|
m, err := newMember(key, value)
|
|
if err != nil {
|
|
return ts, err
|
|
}
|
|
n := len(ts.list)
|
|
found := n
|
|
for i := range ts.list {
|
|
if ts.list[i].Key == key {
|
|
found = i
|
|
}
|
|
}
|
|
cTS := TraceState{}
|
|
if found == n && n < maxListMembers {
|
|
cTS.list = make([]member, n+1)
|
|
} else {
|
|
cTS.list = make([]member, n)
|
|
}
|
|
cTS.list[0] = m
|
|
// When the number of members exceeds capacity, drop the "right-most".
|
|
copy(cTS.list[1:], ts.list[0:found])
|
|
if found < n {
|
|
copy(cTS.list[1+found:], ts.list[found+1:])
|
|
}
|
|
return cTS, nil
|
|
}
|
|
|
|
// Delete returns a copy of the TraceState with the list-member identified by
|
|
// key removed.
|
|
func (ts TraceState) Delete(key string) TraceState {
|
|
members := make([]member, ts.Len())
|
|
copy(members, ts.list)
|
|
for i, member := range ts.list {
|
|
if member.Key == key {
|
|
members = append(members[:i], members[i+1:]...)
|
|
// TraceState should contain no duplicate members.
|
|
break
|
|
}
|
|
}
|
|
return TraceState{list: members}
|
|
}
|
|
|
|
// Len returns the number of list-members in the TraceState.
|
|
func (ts TraceState) Len() int {
|
|
return len(ts.list)
|
|
}
|