diff --git a/.chloggen/zpagesextension-add-expvar.yaml b/.chloggen/zpagesextension-add-expvar.yaml new file mode 100644 index 00000000000..06556c241df --- /dev/null +++ b/.chloggen/zpagesextension-add-expvar.yaml @@ -0,0 +1,25 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: zpagesextension + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add expvar handler to zpages extension. + +# One or more tracking issues or pull requests related to the change +issues: [11081] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/extension/zpagesextension/README.md b/extension/zpagesextension/README.md index 859df8227ec..5a2961878d4 100644 --- a/extension/zpagesextension/README.md +++ b/extension/zpagesextension/README.md @@ -27,6 +27,10 @@ The following settings are required: zPages. Use localhost: to make it available only locally, or ":" to make it available on all network interfaces. +The following settings can be optionally configured: + +- `enable_expvar` (default = false): Enable the expvar services. For detail see [ExpvarZ](#expvarz). + Example: ```yaml extensions: @@ -78,6 +82,12 @@ They also allow you to quickly examine error samples Example URL: http://localhost:55679/debug/tracez +### ExpvarZ + +The ExpvarZ exposes the useful information about Go runtime, OTEL components could leverage [expvar](https://pkg.go.dev/expvar) library to expose their own state. + +Example URL: http://localhost:55679/debug/expvarz + ## Warnings This extension registers a SpanProcessor to record all the spans created inside diff --git a/extension/zpagesextension/config.go b/extension/zpagesextension/config.go index 7375f225ff8..4fe97147fb8 100644 --- a/extension/zpagesextension/config.go +++ b/extension/zpagesextension/config.go @@ -13,6 +13,10 @@ import ( // Config has the configuration for the extension enabling the zPages extension. type Config struct { confighttp.ServerConfig `mapstructure:",squash"` + + // EnableExpvar indicates whether to enable expvar service. + // (default = false) + EnableExpvar bool `mapstructure:"enable_expvar"` } var _ component.Config = (*Config)(nil) diff --git a/extension/zpagesextension/zpagesextension.go b/extension/zpagesextension/zpagesextension.go index 000022689cc..26dca09727a 100644 --- a/extension/zpagesextension/zpagesextension.go +++ b/extension/zpagesextension/zpagesextension.go @@ -6,6 +6,7 @@ package zpagesextension // import "go.opentelemetry.io/collector/extension/zpage import ( "context" "errors" + "expvar" "net/http" "path" @@ -18,7 +19,8 @@ import ( ) const ( - tracezPath = "tracez" + tracezPath = "tracez" + expvarzPath = "expvarz" ) type zpagesExtension struct { @@ -56,6 +58,11 @@ func (zpe *zpagesExtension) Start(ctx context.Context, host component.Host) erro zpe.telemetry.Logger.Warn("zPages span processor registration is not available") } + if zpe.config.EnableExpvar { + zPagesMux.Handle(path.Join("/debug", expvarzPath), expvar.Handler()) + zpe.telemetry.Logger.Info("Registered zPages expvar handler") + } + hostZPages, ok := host.(interface { RegisterZPages(mux *http.ServeMux, pathPrefix string) }) diff --git a/extension/zpagesextension/zpagesextension_test.go b/extension/zpagesextension/zpagesextension_test.go index 21b8df5f8ca..b89bc2b8670 100644 --- a/extension/zpagesextension/zpagesextension_test.go +++ b/extension/zpagesextension/zpagesextension_test.go @@ -51,7 +51,7 @@ func newZpagesTelemetrySettings() component.TelemetrySettings { func TestZPagesExtensionUsage(t *testing.T) { cfg := &Config{ - confighttp.ServerConfig{ + ServerConfig: confighttp.ServerConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, } @@ -78,7 +78,7 @@ func TestZPagesExtensionUsage(t *testing.T) { func TestZPagesExtensionBadAuthExtension(t *testing.T) { cfg := &Config{ - confighttp.ServerConfig{ + ServerConfig: confighttp.ServerConfig{ Endpoint: "localhost:0", Auth: &confighttp.AuthConfig{ Authentication: configauth.Authentication{ @@ -98,7 +98,7 @@ func TestZPagesExtensionPortAlreadyInUse(t *testing.T) { defer ln.Close() cfg := &Config{ - confighttp.ServerConfig{ + ServerConfig: confighttp.ServerConfig{ Endpoint: endpoint, }, } @@ -110,7 +110,7 @@ func TestZPagesExtensionPortAlreadyInUse(t *testing.T) { func TestZPagesMultipleStarts(t *testing.T) { cfg := &Config{ - confighttp.ServerConfig{ + ServerConfig: confighttp.ServerConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, } @@ -127,7 +127,7 @@ func TestZPagesMultipleStarts(t *testing.T) { func TestZPagesMultipleShutdowns(t *testing.T) { cfg := &Config{ - confighttp.ServerConfig{ + ServerConfig: confighttp.ServerConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, } @@ -142,7 +142,7 @@ func TestZPagesMultipleShutdowns(t *testing.T) { func TestZPagesShutdownWithoutStart(t *testing.T) { cfg := &Config{ - confighttp.ServerConfig{ + ServerConfig: confighttp.ServerConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, } @@ -152,3 +152,31 @@ func TestZPagesShutdownWithoutStart(t *testing.T) { require.NoError(t, zpagesExt.Shutdown(context.Background())) } + +func TestZPagesEnableExpvar(t *testing.T) { + cfg := &Config{ + ServerConfig: confighttp.ServerConfig{ + Endpoint: testutil.GetAvailableLocalAddress(t), + }, + EnableExpvar: true, + } + + zpagesExt := newServer(cfg, newZpagesTelemetrySettings()) + require.NotNil(t, zpagesExt) + + require.NoError(t, zpagesExt.Start(context.Background(), newZPagesHost())) + t.Cleanup(func() { require.NoError(t, zpagesExt.Shutdown(context.Background())) }) + + // Give a chance for the server goroutine to run. + runtime.Gosched() + + _, zpagesPort, err := net.SplitHostPort(cfg.ServerConfig.Endpoint) + require.NoError(t, err) + + client := &http.Client{} + resp, err := client.Get("http://localhost:" + zpagesPort + "/debug/expvarz") + require.NoError(t, err) + defer resp.Body.Close() + + require.Equal(t, http.StatusOK, resp.StatusCode) +}