mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 17:51:57 +00:00
This will be my last PR related to the backend tracing work I've been doing. This is a set of small cleanups to the `trace` package that I've collecting as I have worked on tracing and used tracing. Following this PR, the `trace` package is just a very lightweight wrapper around the standard OpenTelemetry APIs. I think it's best to keep the package around rather than using opentelemetry directly because it easy to add convenience methods (which I would be sad to lose). Each commit is self-contained and has a descriptive message. If anyone wants to pick up where I'm leaving off, here are a few things left undone: - Convert Zoekt to use OpenTelemetry rather than OpenTracing - Add OpenTelemetry support to other services like syntect-server - Merge the `internal/trace` and `internal/tracer` packages - Consider adding a type that conforms to the OpenTelemetry `Span` interface but also writes to `x/net/trace` that can be enabled when tracing is not available. - Remove unrelated code from the `trace` and `tracer` package (see [here](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@a6759b95dbd8e5e3a604f7fd452b0b85f37091d9/-/blob/internal/tracer/tracer.go?L75-83) and [here](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@769fbbf5008e8decc63967dbff53f26333620265/-/blob/internal/trace/buckets.go?L3-7)) - Noodle on a `Traceable` interface (one that impls `Attr()` or `Attrs()`) so types can be easily added with `SetAttributes()` - Experiment with sampling - Experiment with replacing `policy.ShouldTrace` with native opentelemetry tools ## Test plan Tested manually that tracing still looks good locally. Will test on other instances when it rolls out. <!-- All pull requests REQUIRE a test plan: https://docs.sourcegraph.com/dev/background-information/testing_principles -->
61 lines
1.4 KiB
Go
61 lines
1.4 KiB
Go
package trace
|
|
|
|
import (
|
|
"fmt"
|
|
"unicode/utf8"
|
|
|
|
"go.opentelemetry.io/otel/attribute"
|
|
)
|
|
|
|
// Scoped wraps a set of opentelemetry attributes with a prefixed key.
|
|
func Scoped(scope string, kvs ...attribute.KeyValue) []attribute.KeyValue {
|
|
res := make([]attribute.KeyValue, len(kvs))
|
|
for i, kv := range kvs {
|
|
res[i] = attribute.KeyValue{
|
|
Key: attribute.Key(fmt.Sprintf("%s.%s", scope, kv.Key)),
|
|
Value: kv.Value,
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
|
|
// Stringers creates a set of key values from a slice of elements that implement Stringer.
|
|
func Stringers[T fmt.Stringer](key string, values []T) attribute.KeyValue {
|
|
strs := make([]string, 0, len(values))
|
|
for _, value := range values {
|
|
strs = append(strs, value.String())
|
|
}
|
|
return attribute.StringSlice(key, strs)
|
|
}
|
|
|
|
func Error(err error) attribute.KeyValue {
|
|
err = truncateError(err, defaultErrorRuneLimit)
|
|
if err != nil {
|
|
return attribute.String("error", err.Error())
|
|
}
|
|
return attribute.String("error", "<nil>")
|
|
}
|
|
|
|
const defaultErrorRuneLimit = 512
|
|
|
|
func truncateError(err error, maxRunes int) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
return truncatedError{err, maxRunes}
|
|
}
|
|
|
|
type truncatedError struct {
|
|
err error
|
|
maxRunes int
|
|
}
|
|
|
|
func (e truncatedError) Error() string {
|
|
errString := e.err.Error()
|
|
if utf8.RuneCountInString(errString) > e.maxRunes {
|
|
runes := []rune(errString)
|
|
errString = string(runes[:e.maxRunes/2]) + " ...truncated... " + string(runes[len(runes)-e.maxRunes/2:])
|
|
}
|
|
return errString
|
|
}
|