* update github.com/blevesearch/bleve v2.0.2 -> v2.0.3 * github.com/denisenkom/go-mssqldb v0.9.0 -> v0.10.0 * github.com/editorconfig/editorconfig-core-go v2.4.1 -> v2.4.2 * github.com/go-chi/cors v1.1.1 -> v1.2.0 * github.com/go-git/go-billy v5.0.0 -> v5.1.0 * github.com/go-git/go-git v5.2.0 -> v5.3.0 * github.com/go-ldap/ldap v3.2.4 -> v3.3.0 * github.com/go-redis/redis v8.6.0 -> v8.8.2 * github.com/go-sql-driver/mysql v1.5.0 -> v1.6.0 * github.com/go-swagger/go-swagger v0.26.1 -> v0.27.0 * github.com/lib/pq v1.9.0 -> v1.10.1 * github.com/mattn/go-sqlite3 v1.14.6 -> v1.14.7 * github.com/go-testfixtures/testfixtures v3.5.0 -> v3.6.0 * github.com/issue9/identicon v1.0.1 -> v1.2.0 * github.com/klauspost/compress v1.11.8 -> v1.12.1 * github.com/mgechev/revive v1.0.3 -> v1.0.6 * github.com/microcosm-cc/bluemonday v1.0.7 -> v1.0.8 * github.com/niklasfasching/go-org v1.4.0 -> v1.5.0 * github.com/olivere/elastic v7.0.22 -> v7.0.24 * github.com/pelletier/go-toml v1.8.1 -> v1.9.0 * github.com/prometheus/client_golang v1.9.0 -> v1.10.0 * github.com/xanzy/go-gitlab v0.44.0 -> v0.48.0 * github.com/yuin/goldmark v1.3.3 -> v1.3.5 * github.com/6543/go-version v1.2.4 -> v1.3.1 * do github.com/lib/pq v1.10.0 -> v1.10.1 again ...
		
			
				
	
	
		
			150 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			150 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| // Copyright The OpenTelemetry 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 attribute // import "go.opentelemetry.io/otel/attribute"
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"sync"
 | |
| 	"sync/atomic"
 | |
| )
 | |
| 
 | |
| type (
 | |
| 	// Encoder is a mechanism for serializing a label set into a
 | |
| 	// specific string representation that supports caching, to
 | |
| 	// avoid repeated serialization. An example could be an
 | |
| 	// exporter encoding the label set into a wire representation.
 | |
| 	Encoder interface {
 | |
| 		// Encode returns the serialized encoding of the label
 | |
| 		// set using its Iterator.  This result may be cached
 | |
| 		// by a attribute.Set.
 | |
| 		Encode(iterator Iterator) string
 | |
| 
 | |
| 		// ID returns a value that is unique for each class of
 | |
| 		// label encoder.  Label encoders allocate these using
 | |
| 		// `NewEncoderID`.
 | |
| 		ID() EncoderID
 | |
| 	}
 | |
| 
 | |
| 	// EncoderID is used to identify distinct Encoder
 | |
| 	// implementations, for caching encoded results.
 | |
| 	EncoderID struct {
 | |
| 		value uint64
 | |
| 	}
 | |
| 
 | |
| 	// defaultLabelEncoder uses a sync.Pool of buffers to reduce
 | |
| 	// the number of allocations used in encoding labels.  This
 | |
| 	// implementation encodes a comma-separated list of key=value,
 | |
| 	// with '/'-escaping of '=', ',', and '\'.
 | |
| 	defaultLabelEncoder struct {
 | |
| 		// pool is a pool of labelset builders.  The buffers in this
 | |
| 		// pool grow to a size that most label encodings will not
 | |
| 		// allocate new memory.
 | |
| 		pool sync.Pool // *bytes.Buffer
 | |
| 	}
 | |
| )
 | |
| 
 | |
| // escapeChar is used to ensure uniqueness of the label encoding where
 | |
| // keys or values contain either '=' or ','.  Since there is no parser
 | |
| // needed for this encoding and its only requirement is to be unique,
 | |
| // this choice is arbitrary.  Users will see these in some exporters
 | |
| // (e.g., stdout), so the backslash ('\') is used as a conventional choice.
 | |
| const escapeChar = '\\'
 | |
| 
 | |
| var (
 | |
| 	_ Encoder = &defaultLabelEncoder{}
 | |
| 
 | |
| 	// encoderIDCounter is for generating IDs for other label
 | |
| 	// encoders.
 | |
| 	encoderIDCounter uint64
 | |
| 
 | |
| 	defaultEncoderOnce     sync.Once
 | |
| 	defaultEncoderID       = NewEncoderID()
 | |
| 	defaultEncoderInstance *defaultLabelEncoder
 | |
| )
 | |
| 
 | |
| // NewEncoderID returns a unique label encoder ID. It should be
 | |
| // called once per each type of label encoder. Preferably in init() or
 | |
| // in var definition.
 | |
| func NewEncoderID() EncoderID {
 | |
| 	return EncoderID{value: atomic.AddUint64(&encoderIDCounter, 1)}
 | |
| }
 | |
| 
 | |
| // DefaultEncoder returns a label encoder that encodes labels
 | |
| // in such a way that each escaped label's key is followed by an equal
 | |
| // sign and then by an escaped label's value. All key-value pairs are
 | |
| // separated by a comma.
 | |
| //
 | |
| // Escaping is done by prepending a backslash before either a
 | |
| // backslash, equal sign or a comma.
 | |
| func DefaultEncoder() Encoder {
 | |
| 	defaultEncoderOnce.Do(func() {
 | |
| 		defaultEncoderInstance = &defaultLabelEncoder{
 | |
| 			pool: sync.Pool{
 | |
| 				New: func() interface{} {
 | |
| 					return &bytes.Buffer{}
 | |
| 				},
 | |
| 			},
 | |
| 		}
 | |
| 	})
 | |
| 	return defaultEncoderInstance
 | |
| }
 | |
| 
 | |
| // Encode is a part of an implementation of the LabelEncoder
 | |
| // interface.
 | |
| func (d *defaultLabelEncoder) Encode(iter Iterator) string {
 | |
| 	buf := d.pool.Get().(*bytes.Buffer)
 | |
| 	defer d.pool.Put(buf)
 | |
| 	buf.Reset()
 | |
| 
 | |
| 	for iter.Next() {
 | |
| 		i, keyValue := iter.IndexedLabel()
 | |
| 		if i > 0 {
 | |
| 			_, _ = buf.WriteRune(',')
 | |
| 		}
 | |
| 		copyAndEscape(buf, string(keyValue.Key))
 | |
| 
 | |
| 		_, _ = buf.WriteRune('=')
 | |
| 
 | |
| 		if keyValue.Value.Type() == STRING {
 | |
| 			copyAndEscape(buf, keyValue.Value.AsString())
 | |
| 		} else {
 | |
| 			_, _ = buf.WriteString(keyValue.Value.Emit())
 | |
| 		}
 | |
| 	}
 | |
| 	return buf.String()
 | |
| }
 | |
| 
 | |
| // ID is a part of an implementation of the LabelEncoder interface.
 | |
| func (*defaultLabelEncoder) ID() EncoderID {
 | |
| 	return defaultEncoderID
 | |
| }
 | |
| 
 | |
| // copyAndEscape escapes `=`, `,` and its own escape character (`\`),
 | |
| // making the default encoding unique.
 | |
| func copyAndEscape(buf *bytes.Buffer, val string) {
 | |
| 	for _, ch := range val {
 | |
| 		switch ch {
 | |
| 		case '=', ',', escapeChar:
 | |
| 			buf.WriteRune(escapeChar)
 | |
| 		}
 | |
| 		buf.WriteRune(ch)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Valid returns true if this encoder ID was allocated by
 | |
| // `NewEncoderID`.  Invalid encoder IDs will not be cached.
 | |
| func (id EncoderID) Valid() bool {
 | |
| 	return id.value != 0
 | |
| }
 |