-
Notifications
You must be signed in to change notification settings - Fork 576
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move convert values to internal/shared/logutil
- Loading branch information
Showing
17 changed files
with
1,518 additions
and
132 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
// Code created by gotmpl. DO NOT MODIFY. | ||
// source: internal/shared/logutil/convert.go.tmpl | ||
|
||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package logutil // import "go.opentelemetry.io/contrib/bridges/otellogr/internal/logutil" | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"math" | ||
"reflect" | ||
"strconv" | ||
"time" | ||
|
||
"go.opentelemetry.io/otel/log" | ||
) | ||
|
||
// convertKVs converts a list of key-value pairs to a list of [log.KeyValue]. | ||
// The last [context.Context] value is returned as the context. | ||
// If no context is found, the original context is returned. | ||
func ConvertKVs(ctx context.Context, keysAndValues ...any) (context.Context, []log.KeyValue) { | ||
if len(keysAndValues) == 0 { | ||
return ctx, nil | ||
} | ||
if len(keysAndValues)%2 != 0 { | ||
// Ensure an odd number of items here does not corrupt the list. | ||
keysAndValues = append(keysAndValues, nil) | ||
} | ||
|
||
kvs := make([]log.KeyValue, 0, len(keysAndValues)/2) | ||
for i := 0; i < len(keysAndValues); i += 2 { | ||
k, ok := keysAndValues[i].(string) | ||
if !ok { | ||
// Ensure that the key is a string. | ||
k = fmt.Sprintf("%v", keysAndValues[i]) | ||
} | ||
|
||
v := keysAndValues[i+1] | ||
if vCtx, ok := v.(context.Context); ok { | ||
// Special case when a field is of context.Context type. | ||
ctx = vCtx | ||
continue | ||
} | ||
|
||
kvs = append(kvs, log.KeyValue{ | ||
Key: k, | ||
Value: ConvertValue(v), | ||
}) | ||
} | ||
|
||
return ctx, kvs | ||
} | ||
|
||
func ConvertValue(v any) log.Value { | ||
// Handling the most common types without reflect is a small perf win. | ||
switch val := v.(type) { | ||
case bool: | ||
return log.BoolValue(val) | ||
case string: | ||
return log.StringValue(val) | ||
case int: | ||
return log.Int64Value(int64(val)) | ||
case int8: | ||
return log.Int64Value(int64(val)) | ||
case int16: | ||
return log.Int64Value(int64(val)) | ||
case int32: | ||
return log.Int64Value(int64(val)) | ||
case int64: | ||
return log.Int64Value(val) | ||
case uint: | ||
return ConvertUintValue(uint64(val)) | ||
case uint8: | ||
return log.Int64Value(int64(val)) | ||
case uint16: | ||
return log.Int64Value(int64(val)) | ||
case uint32: | ||
return log.Int64Value(int64(val)) | ||
case uint64: | ||
return ConvertUintValue(val) | ||
case uintptr: | ||
return ConvertUintValue(uint64(val)) | ||
case float32: | ||
return log.Float64Value(float64(val)) | ||
case float64: | ||
return log.Float64Value(val) | ||
case time.Duration: | ||
return log.Int64Value(val.Nanoseconds()) | ||
case complex64: | ||
r := log.Float64("r", real(complex128(val))) | ||
i := log.Float64("i", imag(complex128(val))) | ||
return log.MapValue(r, i) | ||
case complex128: | ||
r := log.Float64("r", real(val)) | ||
i := log.Float64("i", imag(val)) | ||
return log.MapValue(r, i) | ||
case time.Time: | ||
return log.Int64Value(val.UnixNano()) | ||
case []byte: | ||
return log.BytesValue(val) | ||
case error: | ||
return log.StringValue(val.Error()) | ||
} | ||
|
||
t := reflect.TypeOf(v) | ||
if t == nil { | ||
return log.Value{} | ||
} | ||
val := reflect.ValueOf(v) | ||
switch t.Kind() { | ||
case reflect.Struct: | ||
return log.StringValue(fmt.Sprintf("%+v", v)) | ||
case reflect.Slice, reflect.Array: | ||
items := make([]log.Value, 0, val.Len()) | ||
for i := 0; i < val.Len(); i++ { | ||
items = append(items, ConvertValue(val.Index(i).Interface())) | ||
} | ||
return log.SliceValue(items...) | ||
case reflect.Map: | ||
kvs := make([]log.KeyValue, 0, val.Len()) | ||
for _, k := range val.MapKeys() { | ||
var key string | ||
switch k.Kind() { | ||
case reflect.String: | ||
key = k.String() | ||
default: | ||
key = fmt.Sprintf("%+v", k.Interface()) | ||
} | ||
kvs = append(kvs, log.KeyValue{ | ||
Key: key, | ||
Value: ConvertValue(val.MapIndex(k).Interface()), | ||
}) | ||
} | ||
return log.MapValue(kvs...) | ||
case reflect.Ptr, reflect.Interface: | ||
if val.IsNil() { | ||
return log.Value{} | ||
} | ||
return ConvertValue(val.Elem().Interface()) | ||
} | ||
|
||
// Try to handle this as gracefully as possible. | ||
// | ||
// Don't panic here. it is preferable to have user's open issue | ||
// asking why their attributes have a "unhandled: " prefix than | ||
// say that their code is panicking. | ||
return log.StringValue(fmt.Sprintf("unhandled: (%s) %+v", t, v)) | ||
} | ||
|
||
// ConvertUintValue converts a uint64 to a log.Value. | ||
// If the value is too large to fit in an int64, it is converted to a string. | ||
func ConvertUintValue(v uint64) log.Value { | ||
if v > math.MaxInt64 { | ||
return log.StringValue(strconv.FormatUint(v, 10)) | ||
} | ||
return log.Int64Value(int64(v)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package logutil // import "go.opentelemetry.io/contrib/bridges/otellogr/internal/logutil" | ||
|
||
// Generate logutil package: | ||
//go:generate gotmpl --body=../../../../internal/shared/logutil/convert_test.go.tmpl "--data={}" --out=convert_test.go | ||
//go:generate gotmpl --body=../../../../internal/shared/logutil/convert.go.tmpl "--data={}" --out=convert.go |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.