From 5ea3c4ace67a5d2eae0c6868560cec4a13f4ea15 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Sep 2025 08:36:18 +0000 Subject: [PATCH] feat: Upgrade to OpenTelemetry v1.38.0 with independent OTEL configuration parameters Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> --- OTEL_V2.8_EXAMPLE.md | 177 ++++++++++++++---- database/gdb/gdb_core_config.go | 18 ++ database/gdb/gdb_core_trace.go | 2 +- .../gdb_z_unit_feature_otel_tracing_test.go | 47 +++-- go.mod | 8 +- go.sum | 22 ++- internal/otel/otel_config.go | 44 +++++ net/ghttp/ghttp_middleware_tracing.go | 4 +- net/ghttp/ghttp_server_config.go | 36 ++++ .../ghttp_z_unit_feature_otel_tracing_test.go | 117 ++++++++++++ 10 files changed, 408 insertions(+), 67 deletions(-) create mode 100644 internal/otel/otel_config.go diff --git a/OTEL_V2.8_EXAMPLE.md b/OTEL_V2.8_EXAMPLE.md index 8abc9ab59..b454ad7cb 100644 --- a/OTEL_V2.8_EXAMPLE.md +++ b/OTEL_V2.8_EXAMPLE.md @@ -2,33 +2,44 @@ This example demonstrates the new configurable OpenTelemetry tracing features for SQL, HTTP requests, and HTTP responses. +**Updated to OpenTelemetry v1.38.0 with Independent OTEL Parameters** + ## HTTP Server Configuration -### Enable Request Parameter Tracing +### New Independent OTEL Configuration (Recommended) ```yaml server: address: ":8080" - otelTraceRequestEnabled: true # Enable HTTP request parameter tracing + otel: + traceRequestEnabled: true # Enable HTTP request parameter tracing + traceResponseEnabled: true # Enable HTTP response body tracing ``` -### Enable Response Body Tracing +### Legacy Configuration (Still Supported) ```yaml server: address: ":8080" - otelTraceResponseEnabled: true # Enable HTTP response body tracing -``` - -### Enable Both Request and Response Tracing -```yaml -server: - address: ":8080" - otelTraceRequestEnabled: true # Enable HTTP request parameter tracing + otelTraceRequestEnabled: true # Enable HTTP request parameter tracing otelTraceResponseEnabled: true # Enable HTTP response body tracing ``` ## Database Configuration -### Enable SQL Statement Tracing +### New Independent OTEL Configuration (Recommended) +```yaml +database: + default: + type: "mysql" + host: "127.0.0.1" + port: "3306" + user: "your_user" + pass: "your_password" + name: "your_database" + otel: + traceSQLEnabled: true # Enable SQL statement tracing +``` + +### Legacy Configuration (Still Supported) ```yaml database: default: @@ -43,23 +54,27 @@ database: ## Programmatic Configuration -### HTTP Server +### HTTP Server - New Independent OTEL Configuration ```go package main import ( "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/internal/otel" "github.com/gogf/gf/v2/net/ghttp" ) func main() { s := g.Server() - // Enable tracing via configuration map - s.SetConfigWithMap(g.Map{ - "OtelTraceRequestEnabled": true, - "OtelTraceResponseEnabled": true, - }) + // Configure using new independent OTEL configuration + config := ghttp.NewConfig() + config.Address = ":8080" + config.Otel = otel.Config{ + TraceRequestEnabled: true, + TraceResponseEnabled: true, + } + s.SetConfig(config) s.BindHandler("/api/test", func(r *ghttp.Request) { // This handler will have its request parameters and response traced @@ -73,18 +88,47 @@ func main() { } ``` -### Database +### HTTP Server - Legacy Configuration (Still Supported) ```go package main import ( - "context" - "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" ) func main() { - // Configure database with SQL tracing enabled + s := g.Server() + + // Enable tracing via configuration map (legacy approach) + s.SetConfigWithMap(g.Map{ + "OtelTraceRequestEnabled": true, + "OtelTraceResponseEnabled": true, + }) + + s.BindHandler("/api/test", func(r *ghttp.Request) { + // This handler will have its request parameters and response traced + r.Response.WriteJson(g.Map{ + "message": "Hello World", + "input": r.Get("input"), + }) + }) + + s.Run() +} +``` + +### Database - New Independent OTEL Configuration +```go +package main + +import ( + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/internal/otel" +) + +func main() { + // Configure database with new independent OTEL configuration config := gdb.ConfigNode{ Type: "mysql", Host: "127.0.0.1", @@ -92,23 +136,50 @@ func main() { User: "your_user", Pass: "your_password", Name: "your_database", - OtelTraceSQLEnabled: true, // Enable SQL tracing + Otel: otel.Config{ + TraceSQLEnabled: true, + }, } db, err := gdb.New(config) if err != nil { - g.Log().Fatal(context.TODO(), err) + panic(err) } - defer db.Close(context.TODO()) - // SQL queries will now be traced - result, err := db.GetOne(context.TODO(), "SELECT * FROM users WHERE id = ?", 1) + // SQL statements will now be traced + result, err := db.Query("SELECT * FROM users WHERE id = ?", 1) + // ... handle result +} +``` + +### Database - Legacy Configuration (Still Supported) +```go +package main + +import ( + "github.com/gogf/gf/v2/database/gdb" +) + +func main() { + // Configure database with legacy OTEL configuration + config := gdb.ConfigNode{ + Type: "mysql", + Host: "127.0.0.1", + Port: "3306", + User: "your_user", + Pass: "your_password", + Name: "your_database", + OtelTraceSQLEnabled: true, // Legacy field + } + + db, err := gdb.New(config) if err != nil { - g.Log().Error(context.TODO(), err) - return + panic(err) } - g.Log().Info(context.TODO(), "User:", result) + // SQL statements will now be traced + result, err := db.Query("SELECT * FROM users WHERE id = ?", 1) + // ... handle result } ``` @@ -154,8 +225,44 @@ All HTTP requests now include the HTTP method in traces: ## Benefits -1. **Configurable**: All new tracing features are opt-in via configuration -2. **Performance**: Only enabled features add overhead -3. **Backward Compatible**: Existing tracing continues to work unchanged -4. **Comprehensive**: Covers SQL, HTTP requests, and HTTP responses -5. **Size Aware**: Respects content size limits to prevent memory issues \ No newline at end of file +1. **OpenTelemetry v1.38.0**: Updated to the latest OpenTelemetry version with improved performance and features +2. **Independent Configuration**: New modular OTEL configuration structure for better organization +3. **Configurable**: All new tracing features are opt-in via configuration +4. **Performance**: Only enabled features add overhead +5. **Backward Compatible**: Legacy configuration fields still work alongside new structure +6. **Comprehensive**: Covers SQL, HTTP requests, and HTTP responses +7. **Size Aware**: Respects content size limits to prevent memory issues + +## Migration Guide + +### From Legacy to New Configuration + +#### HTTP Server +```go +// Legacy (still works) +s.SetConfigWithMap(g.Map{ + "OtelTraceRequestEnabled": true, +}) + +// New (recommended) +config := ghttp.NewConfig() +config.Otel.TraceRequestEnabled = true +s.SetConfig(config) +``` + +#### Database +```go +// Legacy (still works) +config := gdb.ConfigNode{ + OtelTraceSQLEnabled: true, +} + +// New (recommended) +config := gdb.ConfigNode{ + Otel: otel.Config{ + TraceSQLEnabled: true, + }, +} +``` + +The new configuration provides better organization and allows for future OTEL features to be grouped logically while maintaining full backward compatibility. \ No newline at end of file diff --git a/database/gdb/gdb_core_config.go b/database/gdb/gdb_core_config.go index 185485046..c73680829 100644 --- a/database/gdb/gdb_core_config.go +++ b/database/gdb/gdb_core_config.go @@ -13,6 +13,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/internal/otel" "github.com/gogf/gf/v2/os/gcache" "github.com/gogf/gf/v2/os/glog" "github.com/gogf/gf/v2/text/gregex" @@ -66,7 +67,12 @@ type ConfigNode struct { // Optional field Debug bool `json:"debug"` + // Otel specifies the OpenTelemetry tracing configuration + // Optional field + Otel otel.Config `json:"otel"` + // OtelTraceSQLEnabled enables OpenTelemetry tracing for SQL operations + // Deprecated: Use Otel.TraceSQLEnabled instead. This field is kept for backward compatibility. // Optional field OtelTraceSQLEnabled bool `json:"otelTraceSQLEnabled"` @@ -440,3 +446,15 @@ func parseConfigNodeLink(node *ConfigNode) (*ConfigNode, error) { } return node, nil } + +// IsOtelTraceSQLEnabled returns whether SQL tracing is enabled for this configuration. +// It checks both the new Otel.TraceSQLEnabled field and the deprecated OtelTraceSQLEnabled field +// for backward compatibility. +func (node *ConfigNode) IsOtelTraceSQLEnabled() bool { + // Check new configuration first + if node.Otel.TraceSQLEnabled { + return true + } + // Fall back to deprecated field for backward compatibility + return node.OtelTraceSQLEnabled +} diff --git a/database/gdb/gdb_core_trace.go b/database/gdb/gdb_core_trace.go index 7a2bc9ec9..cd6429674 100644 --- a/database/gdb/gdb_core_trace.go +++ b/database/gdb/gdb_core_trace.go @@ -83,7 +83,7 @@ func (c *Core) traceSpanEnd(ctx context.Context, span trace.Span, sql *Sql) { events = append(events, attribute.String(traceEventDbExecutionType, string(sql.Type))) // Add SQL statement to tracing if enabled - if c.db.GetConfig().OtelTraceSQLEnabled { + if c.db.GetConfig().IsOtelTraceSQLEnabled() { events = append(events, attribute.String(traceEventDbExecutionSQL, sql.Format)) } diff --git a/database/gdb/gdb_z_unit_feature_otel_tracing_test.go b/database/gdb/gdb_z_unit_feature_otel_tracing_test.go index 861f0eebe..13101723c 100644 --- a/database/gdb/gdb_z_unit_feature_otel_tracing_test.go +++ b/database/gdb/gdb_z_unit_feature_otel_tracing_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/internal/otel" "github.com/gogf/gf/v2/test/gtest" ) @@ -21,7 +22,9 @@ func Test_OTEL_SQLTracing_Default(t *testing.T) { } // By default, SQL tracing should be disabled + t.Assert(config.IsOtelTraceSQLEnabled(), false) t.Assert(config.OtelTraceSQLEnabled, false) + t.Assert(config.Otel.TraceSQLEnabled, false) }) } @@ -33,8 +36,27 @@ func Test_OTEL_SQLTracing_Configuration(t *testing.T) { OtelTraceSQLEnabled: true, } - // SQL tracing should be configurable + // SQL tracing should be configurable using legacy field + t.Assert(config.IsOtelTraceSQLEnabled(), true) t.Assert(config.OtelTraceSQLEnabled, true) + t.Assert(config.Otel.TraceSQLEnabled, false) + }) +} + +func Test_OTEL_SQLTracing_NewConfiguration(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + config := gdb.ConfigNode{ + Type: "sqlite", + Name: ":memory:", + Otel: otel.Config{ + TraceSQLEnabled: true, + }, + } + + // SQL tracing should be configurable using new configuration + t.Assert(config.IsOtelTraceSQLEnabled(), true) + t.Assert(config.OtelTraceSQLEnabled, false) + t.Assert(config.Otel.TraceSQLEnabled, true) }) } @@ -46,28 +68,23 @@ func Test_OTEL_SQLTracing_Enabled(t *testing.T) { OtelTraceSQLEnabled: true, } - // Test that the configuration field can be set and retrieved - t.Assert(config.OtelTraceSQLEnabled, true) - - // Test that the field is preserved during configuration operations - configGroup := gdb.ConfigGroup{config} - t.Assert(configGroup[0].OtelTraceSQLEnabled, true) + // Test that the configuration field can be set and retrieved using legacy field + t.Assert(config.IsOtelTraceSQLEnabled(), true) }) } -func Test_OTEL_SQLTracing_Disabled(t *testing.T) { +func Test_OTEL_SQLTracing_BothFieldsEnabled(t *testing.T) { gtest.C(t, func(t *gtest.T) { config := gdb.ConfigNode{ - Type: "mysql", + Type: "mysql", Name: "test_db", OtelTraceSQLEnabled: false, + Otel: otel.Config{ + TraceSQLEnabled: true, + }, } - // Test that the configuration field can be set and retrieved - t.Assert(config.OtelTraceSQLEnabled, false) - - // Test that the field is preserved during configuration operations - configGroup := gdb.ConfigGroup{config} - t.Assert(configGroup[0].OtelTraceSQLEnabled, false) + // New field should take precedence over legacy field + t.Assert(config.IsOtelTraceSQLEnabled(), true) }) } \ No newline at end of file diff --git a/go.mod b/go.mod index de9b455f0..47b97253a 100644 --- a/go.mod +++ b/go.mod @@ -12,9 +12,9 @@ require ( github.com/grokify/html-strip-tags-go v0.1.0 github.com/magiconair/properties v1.8.10 github.com/olekukonko/tablewriter v1.0.9 - go.opentelemetry.io/otel v1.37.0 - go.opentelemetry.io/otel/sdk v1.37.0 - go.opentelemetry.io/otel/trace v1.37.0 + go.opentelemetry.io/otel v1.38.0 + go.opentelemetry.io/otel/sdk v1.38.0 + go.opentelemetry.io/otel/trace v1.38.0 golang.org/x/net v0.43.0 golang.org/x/text v0.28.0 gopkg.in/yaml.v3 v3.0.1 @@ -32,6 +32,6 @@ require ( github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel/metric v1.37.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect golang.org/x/sys v0.35.0 // indirect ) diff --git a/go.sum b/go.sum index e58d3957d..b9d2b7217 100644 --- a/go.sum +++ b/go.sum @@ -48,18 +48,20 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= diff --git a/internal/otel/otel_config.go b/internal/otel/otel_config.go new file mode 100644 index 000000000..9fd11ec5b --- /dev/null +++ b/internal/otel/otel_config.go @@ -0,0 +1,44 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// Package otel provides OpenTelemetry configurations and utilities. +package otel + +// Config holds OpenTelemetry configuration options. +type Config struct { + // TraceSQLEnabled enables OpenTelemetry tracing for SQL operations. + TraceSQLEnabled bool `json:"traceSQLEnabled"` + + // TraceRequestEnabled enables tracing of HTTP request parameters. + TraceRequestEnabled bool `json:"traceRequestEnabled"` + + // TraceResponseEnabled enables tracing of HTTP response parameters. + TraceResponseEnabled bool `json:"traceResponseEnabled"` +} + +// NewConfig creates and returns a new OTEL configuration with default settings. +func NewConfig() *Config { + return &Config{ + TraceSQLEnabled: false, + TraceRequestEnabled: false, + TraceResponseEnabled: false, + } +} + +// IsTracingSQLEnabled returns whether SQL tracing is enabled. +func (c *Config) IsTracingSQLEnabled() bool { + return c.TraceSQLEnabled +} + +// IsTracingRequestEnabled returns whether HTTP request tracing is enabled. +func (c *Config) IsTracingRequestEnabled() bool { + return c.TraceRequestEnabled +} + +// IsTracingResponseEnabled returns whether HTTP response tracing is enabled. +func (c *Config) IsTracingResponseEnabled() bool { + return c.TraceResponseEnabled +} \ No newline at end of file diff --git a/net/ghttp/ghttp_middleware_tracing.go b/net/ghttp/ghttp_middleware_tracing.go index 59ace2eea..c056bd8fc 100644 --- a/net/ghttp/ghttp_middleware_tracing.go +++ b/net/ghttp/ghttp_middleware_tracing.go @@ -88,7 +88,7 @@ func internalMiddlewareServerTracing(r *Request) { } // Add request parameters if configured - if r.Server != nil && r.Server.config.OtelTraceRequestEnabled { + if r.Server != nil && r.Server.config.IsOtelTraceRequestEnabled() { // Get all request parameters (query + form + body) requestParams := make(map[string]any) @@ -140,7 +140,7 @@ func internalMiddlewareServerTracing(r *Request) { } // Add response body if configured - if r.Server != nil && r.Server.config.OtelTraceResponseEnabled { + if r.Server != nil && r.Server.config.IsOtelTraceResponseEnabled() { if r.Response.BufferLength() > 0 { responseBody := r.Response.BufferString() // Limit response body size for tracing to avoid memory issues diff --git a/net/ghttp/ghttp_server_config.go b/net/ghttp/ghttp_server_config.go index 2c365e28b..41c5b08d3 100644 --- a/net/ghttp/ghttp_server_config.go +++ b/net/ghttp/ghttp_server_config.go @@ -19,6 +19,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/intlog" + "github.com/gogf/gf/v2/internal/otel" "github.com/gogf/gf/v2/net/gsvc" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/glog" @@ -247,10 +248,15 @@ type ServerConfig struct { // OpenTelemetry Tracing. // ====================================================================================================== + // Otel specifies the OpenTelemetry tracing configuration + Otel otel.Config `json:"otel"` + // OtelTraceRequestEnabled enables tracing of HTTP request parameters. + // Deprecated: Use Otel.TraceRequestEnabled instead. This field is kept for backward compatibility. OtelTraceRequestEnabled bool `json:"otelTraceRequestEnabled"` // OtelTraceResponseEnabled enables tracing of HTTP response parameters. + // Deprecated: Use Otel.TraceResponseEnabled instead. This field is kept for backward compatibility. OtelTraceResponseEnabled bool `json:"otelTraceResponseEnabled"` // ====================================================================================================== @@ -316,6 +322,7 @@ func NewConfig() ServerConfig { ErrorLogPattern: "error-{Ymd}.log", AccessLogEnabled: false, AccessLogPattern: "access-{Ymd}.log", + Otel: *otel.NewConfig(), OtelTraceRequestEnabled: false, OtelTraceResponseEnabled: false, DumpRouterMap: true, @@ -585,3 +592,32 @@ func (s *Server) SetRegistrar(registrar gsvc.Registrar) { func (s *Server) GetRegistrar() gsvc.Registrar { return s.registrar } + +// GetConfig returns the configuration of current server. +func (s *Server) GetConfig() ServerConfig { + return s.config +} + +// IsOtelTraceRequestEnabled returns whether HTTP request tracing is enabled. +// It checks both the new Otel.TraceRequestEnabled field and the deprecated OtelTraceRequestEnabled field +// for backward compatibility. +func (c ServerConfig) IsOtelTraceRequestEnabled() bool { + // Check new configuration first + if c.Otel.TraceRequestEnabled { + return true + } + // Fall back to deprecated field for backward compatibility + return c.OtelTraceRequestEnabled +} + +// IsOtelTraceResponseEnabled returns whether HTTP response tracing is enabled. +// It checks both the new Otel.TraceResponseEnabled field and the deprecated OtelTraceResponseEnabled field +// for backward compatibility. +func (c ServerConfig) IsOtelTraceResponseEnabled() bool { + // Check new configuration first + if c.Otel.TraceResponseEnabled { + return true + } + // Fall back to deprecated field for backward compatibility + return c.OtelTraceResponseEnabled +} diff --git a/net/ghttp/ghttp_z_unit_feature_otel_tracing_test.go b/net/ghttp/ghttp_z_unit_feature_otel_tracing_test.go index 9483c0e4e..6c1ce2aaa 100644 --- a/net/ghttp/ghttp_z_unit_feature_otel_tracing_test.go +++ b/net/ghttp/ghttp_z_unit_feature_otel_tracing_test.go @@ -7,16 +7,20 @@ package ghttp_test import ( + "context" "fmt" "testing" "time" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/internal/otel" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/util/guid" ) +var testCtx = context.Background() + func Test_OTEL_RequestTracing_Disabled(t *testing.T) { s := g.Server(guid.S()) s.BindHandler("/test", func(r *ghttp.Request) { @@ -134,4 +138,117 @@ func Test_OTEL_BothTracingEnabled(t *testing.T) { t.Assert(res.StatusCode, 200) // Test passes if no errors occurred during both request and response tracing }) +} + +func Test_OTEL_NewConfiguration_RequestTracing(t *testing.T) { + s := g.Server(guid.S()) + + // Enable request tracing using new independent OTEL configuration + config := ghttp.NewConfig() + config.Otel.TraceRequestEnabled = true + err := s.SetConfig(config) + gtest.AssertNil(err) + + s.BindHandler("/test", func(r *ghttp.Request) { + r.Response.WriteJson(g.Map{"result": "ok"}) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + gtest.C(t, func(t *gtest.T) { + prefix := fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()) + client := g.Client() + client.SetPrefix(prefix) + res, err := client.Post(ctx, "/test?query1=qvalue1", g.Map{"param1": "value1"}) + t.AssertNil(err) + defer res.Close() + + t.Assert(res.StatusCode, 200) + // Test configuration helper methods + t.Assert(s.GetConfig().IsOtelTraceRequestEnabled(), true) + t.Assert(s.GetConfig().IsOtelTraceResponseEnabled(), false) + }) +} + +func Test_OTEL_NewConfiguration_ResponseTracing(t *testing.T) { + s := g.Server(guid.S()) + + // Enable response tracing using new independent OTEL configuration + config := ghttp.NewConfig() + config.Otel.TraceResponseEnabled = true + err := s.SetConfig(config) + gtest.AssertNil(err) + + s.BindHandler("/test", func(r *ghttp.Request) { + r.Response.WriteJson(g.Map{"result": "success", "data": "test data"}) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + gtest.C(t, func(t *gtest.T) { + prefix := fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()) + client := g.Client() + client.SetPrefix(prefix) + res, err := client.Get(ctx, "/test") + t.AssertNil(err) + defer res.Close() + + t.Assert(res.StatusCode, 200) + // Test configuration helper methods + t.Assert(s.GetConfig().IsOtelTraceRequestEnabled(), false) + t.Assert(s.GetConfig().IsOtelTraceResponseEnabled(), true) + }) +} + +func Test_OTEL_BackwardCompatibility(t *testing.T) { + s := g.Server(guid.S()) + + // Test that legacy configuration still works alongside new configuration + config := ghttp.NewConfig() + config.OtelTraceRequestEnabled = true // Legacy field + config.Otel.TraceResponseEnabled = true // New field + err := s.SetConfig(config) + gtest.AssertNil(err) + + s.BindHandler("/test", func(r *ghttp.Request) { + r.Response.WriteJson(g.Map{"result": "backward_compatible"}) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + gtest.C(t, func(t *gtest.T) { + prefix := fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()) + client := g.Client() + client.SetPrefix(prefix) + res, err := client.Post(ctx, "/test?query=test", g.Map{"param": "test"}) + t.AssertNil(err) + defer res.Close() + + t.Assert(res.StatusCode, 200) + // Test that both legacy and new configuration work together + t.Assert(s.GetConfig().IsOtelTraceRequestEnabled(), true) + t.Assert(s.GetConfig().IsOtelTraceResponseEnabled(), true) + }) +} + +func Test_OTEL_Configuration_Helpers(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + // Test new OTEL config helpers + otelConfig := otel.NewConfig() + t.Assert(otelConfig.IsTracingSQLEnabled(), false) + t.Assert(otelConfig.IsTracingRequestEnabled(), false) + t.Assert(otelConfig.IsTracingResponseEnabled(), false) + + otelConfig.TraceSQLEnabled = true + otelConfig.TraceRequestEnabled = true + t.Assert(otelConfig.IsTracingSQLEnabled(), true) + t.Assert(otelConfig.IsTracingRequestEnabled(), true) + t.Assert(otelConfig.IsTracingResponseEnabled(), false) + }) } \ No newline at end of file