Skip to content

Commit

Permalink
Merge branch 'main' into codeboten/add-tls-support-grpc
Browse files Browse the repository at this point in the history
  • Loading branch information
codeboten authored Dec 12, 2024
2 parents 0e82d09 + 0c0b385 commit a6fed29
Show file tree
Hide file tree
Showing 31 changed files with 361 additions and 63 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- The `go.opentelemetry.io/contrib/bridges/otellogr` module.
This module provides an OpenTelemetry logging bridge for `github.com/go-logr/logr`. (#6386)
- Added SNS instrumentation in `go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws`. (#6388)
- Use a `sync.Pool` for metric options in `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp`. (#6394)
- Added support for configuring `Certificate` field when configuring OTLP exporters in `go.opentelemetry.io/contrib/config`. (#6376)

### Changed
Expand All @@ -30,6 +31,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Allow marshaling types in `go.opentelemetry.io/contrib/config`. (#6347)
- Removed the redundant handling of panic from the `HTML` function in `go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin`. (#6373)
- The `code.function` attribute emitted by `go.opentelemetry.io/contrib/bridges/otelslog` now stores just the function name instead the package path-qualified function name. The `code.namespace` attribute now stores the package path. (#6415)
- The `code.function` attribute emitted by `go.opentelemetry.io/contrib/bridges/otelzap` now stores just the function name instead the package path-qualified function name. The `code.namespace` attribute now stores the package path. (#6423)
- Return an error for `nil` values when unmarshaling `NameStringValuePair` in `go.opentelemetry.io/contrib/config`. (#6425)

<!-- Released section -->
<!-- Don't change this section unless doing release -->
Expand Down
6 changes: 6 additions & 0 deletions bridges/otelslog/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,12 @@ func TestSplitFuncName(t *testing.T) {
wantFuncName: "foo",
wantNamespace: "github.com/my/repo/pkg",
},
{
// anonymous function
fullFuncName: "github.com/my/repo/pkg.foo.func5",
wantFuncName: "func5",
wantNamespace: "github.com/my/repo/pkg.foo",
},
{
fullFuncName: "net/http.Get",
wantFuncName: "Get",
Expand Down
17 changes: 16 additions & 1 deletion bridges/otelzap/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ package otelzap // import "go.opentelemetry.io/contrib/bridges/otelzap"
import (
"context"
"slices"
"strings"

"go.uber.org/zap/zapcore"

Expand Down Expand Up @@ -202,10 +203,12 @@ func (o *Core) Write(ent zapcore.Entry, fields []zapcore.Field) error {

r.AddAttributes(o.attr...)
if ent.Caller.Defined {
funcName, namespace := splitFuncName(ent.Caller.Function)
r.AddAttributes(
log.String(string(semconv.CodeFilepathKey), ent.Caller.File),
log.Int(string(semconv.CodeLineNumberKey), ent.Caller.Line),
log.String(string(semconv.CodeFunctionKey), ent.Caller.Function),
log.String(string(semconv.CodeFunctionKey), funcName),
log.String(string(semconv.CodeNamespaceKey), namespace),
)
}
if ent.Stack != "" {
Expand Down Expand Up @@ -262,3 +265,15 @@ func convertLevel(level zapcore.Level) log.Severity {
return log.SeverityUndefined
}
}

// splitFuncName splits package path-qualified function name into
// function name and package full name (namespace). E.g. it splits
// "github.com/my/repo/pkg.foo" into
// "foo" and "github.com/my/repo/pkg".
func splitFuncName(f string) (string, string) {
i := strings.LastIndexByte(f, '.')
if i < 0 {
return "", ""
}
return f[i+1:], f[:i]
}
48 changes: 46 additions & 2 deletions bridges/otelzap/core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,17 @@ func TestCoreWithCaller(t *testing.T) {
assert.Equal(t, testMessage, got.Body().AsString())
assert.Equal(t, log.SeverityInfo, got.Severity())
assert.Equal(t, zap.InfoLevel.String(), got.SeverityText())
assert.Equal(t, 3, got.AttributesLen())
assert.Equal(t, 4, got.AttributesLen())
got.WalkAttributes(func(kv log.KeyValue) bool {
switch kv.Key {
case string(semconv.CodeFilepathKey):
assert.Contains(t, kv.Value.AsString(), "core_test.go")
case string(semconv.CodeLineNumberKey):
assert.Positive(t, kv.Value.AsInt64())
case string(semconv.CodeFunctionKey):
assert.Contains(t, kv.Value.AsString(), "TestCoreWithCaller")
assert.Equal(t, t.Name(), kv.Value.AsString())
case string(semconv.CodeNamespaceKey):
assert.Equal(t, "go.opentelemetry.io/contrib/bridges/otelzap", kv.Value.AsString())
default:
assert.Fail(t, "unexpected attribute key", kv.Key)
}
Expand Down Expand Up @@ -269,6 +271,48 @@ func TestConvertLevel(t *testing.T) {
}
}

func TestSplitFuncName(t *testing.T) {
testCases := []struct {
fullFuncName string
wantFuncName string
wantNamespace string
}{
{
fullFuncName: "github.com/my/repo/pkg.foo",
wantFuncName: "foo",
wantNamespace: "github.com/my/repo/pkg",
},
{
// anonymous function
fullFuncName: "github.com/my/repo/pkg.foo.func5",
wantFuncName: "func5",
wantNamespace: "github.com/my/repo/pkg.foo",
},
{
fullFuncName: "net/http.Get",
wantFuncName: "Get",
wantNamespace: "net/http",
},
{
fullFuncName: "invalid",
wantFuncName: "",
wantNamespace: "",
},
{
fullFuncName: ".",
wantFuncName: "",
wantNamespace: "",
},
}
for _, tc := range testCases {
t.Run(tc.fullFuncName, func(t *testing.T) {
gotFuncName, gotNamespace := splitFuncName(tc.fullFuncName)
assert.Equal(t, tc.wantFuncName, gotFuncName)
assert.Equal(t, tc.wantNamespace, gotNamespace)
})
}
}

func BenchmarkCoreWrite(b *testing.B) {
benchmarks := []struct {
name string
Expand Down
49 changes: 49 additions & 0 deletions config/testdata/invalid_nil_name.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"file_format": "0.3",
"disabled": false,
"logger_provider": {
"processors": [
{
"batch": {
"schedule_delay": 5000,
"export_timeout": 30000,
"max_queue_size": 2048,
"max_export_batch_size": 512,
"exporter": {
"otlp": {
"protocol": "http/protobuf",
"endpoint": "http://localhost:4318/v1/logs",
"certificate": "/app/cert.pem",
"client_key": "/app/cert.pem",
"client_certificate": "/app/cert.pem",
"headers": [
{
"name": "api-key",
"value": "1234"
},
{
"value": "nil-name"
}
],
"headers_list": "api-key=1234",
"compression": "gzip",
"timeout": 10000,
"insecure": false
}
}
}
},
{
"simple": {
"exporter": {
"console": {}
}
}
}
],
"limits": {
"attribute_value_length_limit": 4096,
"attribute_count_limit": 128
}
}
}
13 changes: 13 additions & 0 deletions config/testdata/invalid_nil_name.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
file_format: "0.3"
disabled: false
logger_provider:
processors:
- batch:
exporter:
otlp:
protocol: http/protobuf
endpoint: http://localhost:4318/v1/logs
headers:
- name: api-key
value: "1234"
- value: nil-name
49 changes: 49 additions & 0 deletions config/testdata/invalid_nil_value.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"file_format": "0.3",
"disabled": false,
"logger_provider": {
"processors": [
{
"batch": {
"schedule_delay": 5000,
"export_timeout": 30000,
"max_queue_size": 2048,
"max_export_batch_size": 512,
"exporter": {
"otlp": {
"protocol": "http/protobuf",
"endpoint": "http://localhost:4318/v1/logs",
"certificate": "/app/cert.pem",
"client_key": "/app/cert.pem",
"client_certificate": "/app/cert.pem",
"headers": [
{
"name": "api-key",
"value": "1234"
},
{
"name": "nil-value"
}
],
"headers_list": "api-key=1234",
"compression": "gzip",
"timeout": 10000,
"insecure": false
}
}
}
},
{
"simple": {
"exporter": {
"console": {}
}
}
}
],
"limits": {
"attribute_value_length_limit": 4096,
"attribute_count_limit": 128
}
}
}
13 changes: 13 additions & 0 deletions config/testdata/invalid_nil_value.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
file_format: "0.3"
disabled: false
logger_provider:
processors:
- batch:
exporter:
otlp:
protocol: http/protobuf
endpoint: http://localhost:4318/v1/logs
headers:
- name: api-key
value: "1234"
- name: nil-value
25 changes: 16 additions & 9 deletions config/v0.3.0/config_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,25 @@ func (j *NameStringValuePair) UnmarshalJSON(b []byte) error {
if err := json.Unmarshal(b, &raw); err != nil {
return err
}
if _, ok := raw["name"]; raw != nil && !ok {
return errors.New("field name in NameStringValuePair: required")
if _, ok := raw["name"]; !ok {
return errors.New("json: cannot unmarshal field name in NameStringValuePair required")
}
if _, ok := raw["value"]; raw != nil && !ok {
return errors.New("field value in NameStringValuePair: required")
if _, ok := raw["value"]; !ok {
return errors.New("json: cannot unmarshal field value in NameStringValuePair required")
}
type Plain NameStringValuePair
var plain Plain
if err := json.Unmarshal(b, &plain); err != nil {
return err
var name, value string
var ok bool
if name, ok = raw["name"].(string); !ok {
return errors.New("yaml: cannot unmarshal field name in NameStringValuePair must be string")
}
if value, ok = raw["value"].(string); !ok {
return errors.New("yaml: cannot unmarshal field value in NameStringValuePair must be string")
}

*j = NameStringValuePair{
Name: name,
Value: &value,
}
*j = NameStringValuePair(plain)
return nil
}

Expand Down
22 changes: 22 additions & 0 deletions config/v0.3.0/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,16 @@ func TestParseYAML(t *testing.T) {
wantErr: errors.New(`yaml: unmarshal errors:
line 2: cannot unmarshal !!str ` + "`notabool`" + ` into bool`),
},
{
name: "invalid nil name",
input: "invalid_nil_name.yaml",
wantErr: errors.New(`yaml: cannot unmarshal field name in NameStringValuePair required`),
},
{
name: "invalid nil value",
input: "invalid_nil_value.yaml",
wantErr: errors.New(`yaml: cannot unmarshal field value in NameStringValuePair required`),
},
{
name: "valid v0.2 config",
input: "v0.2.yaml",
Expand All @@ -429,6 +439,7 @@ func TestParseYAML(t *testing.T) {

got, err := ParseYAML(b)
if tt.wantErr != nil {
require.Error(t, err)
require.Equal(t, tt.wantErr.Error(), err.Error())
} else {
require.NoError(t, err)
Expand Down Expand Up @@ -459,6 +470,16 @@ func TestSerializeJSON(t *testing.T) {
input: "invalid_bool.json",
wantErr: errors.New(`json: cannot unmarshal string into Go struct field Plain.disabled of type bool`),
},
{
name: "invalid nil name",
input: "invalid_nil_name.json",
wantErr: errors.New(`json: cannot unmarshal field name in NameStringValuePair required`),
},
{
name: "invalid nil value",
input: "invalid_nil_value.json",
wantErr: errors.New(`json: cannot unmarshal field value in NameStringValuePair required`),
},
{
name: "valid v0.2 config",
input: "v0.2.json",
Expand All @@ -480,6 +501,7 @@ func TestSerializeJSON(t *testing.T) {
err = json.Unmarshal(b, &got)

if tt.wantErr != nil {
require.Error(t, err)
require.Equal(t, tt.wantErr.Error(), err.Error())
} else {
require.NoError(t, err)
Expand Down
28 changes: 28 additions & 0 deletions config/v0.3.0/config_yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package config // import "go.opentelemetry.io/contrib/config/v0.3.0"

import (
"errors"
"fmt"
"reflect"
)
Expand All @@ -30,6 +31,33 @@ func (j *AttributeNameValueType) UnmarshalYAML(unmarshal func(interface{}) error
return nil
}

// UnmarshalYAML implements yaml.Unmarshaler.
func (j *NameStringValuePair) UnmarshalYAML(unmarshal func(interface{}) error) error {
var raw map[string]interface{}
if err := unmarshal(&raw); err != nil {
return err
}
if _, ok := raw["name"]; !ok {
return errors.New("yaml: cannot unmarshal field name in NameStringValuePair required")
}
if _, ok := raw["value"]; !ok {
return errors.New("yaml: cannot unmarshal field value in NameStringValuePair required")
}
var name, value string
var ok bool
if name, ok = raw["name"].(string); !ok {
return errors.New("yaml: cannot unmarshal field name in NameStringValuePair must be string")
}
if value, ok = raw["value"].(string); !ok {
return errors.New("yaml: cannot unmarshal field value in NameStringValuePair must be string")
}
*j = NameStringValuePair{
Name: name,
Value: &value,
}
return nil
}

// UnmarshalYAML implements yaml.Unmarshaler.
func (j *LanguageSpecificInstrumentation) UnmarshalYAML(unmarshal func(interface{}) error) error {
var raw map[string]interface{}
Expand Down
Loading

0 comments on commit a6fed29

Please sign in to comment.