Skip to content

Commit

Permalink
[mq] working branch - merge 9c4ba04 on top of main at fec0279
Browse files Browse the repository at this point in the history
{"baseBranch":"main","baseCommit":"fec0279bf16165ce57f6a5c62feb16ab81c5c287","createdAt":"2025-02-07T16:02:18.102740Z","headSha":"9c4ba04558deee740658b7353f447424b899b292","id":"a98d0ba7-79ba-46af-82be-1c72fd21d28b","priority":"200","pullRequestNumber":"33556","queuedAt":"2025-02-07T16:02:18.090674Z","status":"STATUS_QUEUED"}
  • Loading branch information
dd-mergequeue[bot] authored Feb 7, 2025
2 parents fb3c503 + 9c4ba04 commit a13051b
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 5 deletions.
2 changes: 2 additions & 0 deletions cmd/otel-agent/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

"github.com/DataDog/datadog-agent/cmd/otel-agent/subcommands"
"github.com/DataDog/datadog-agent/cmd/otel-agent/subcommands/run"
"github.com/DataDog/datadog-agent/cmd/otel-agent/subcommands/status"
"github.com/DataDog/datadog-agent/pkg/cli/subcommands/version"
"go.opentelemetry.io/collector/featuregate"
)
Expand Down Expand Up @@ -49,6 +50,7 @@ func makeCommands(globalParams *subcommands.GlobalParams) *cobra.Command {
commands := []*cobra.Command{
run.MakeCommand(globalConfGetter),
version.MakeCommand("otel-agent"),
status.MakeCommand(globalConfGetter),
}

otelAgentCmd := *commands[0] // root cmd is `run()`; indexed at 0
Expand Down
72 changes: 72 additions & 0 deletions cmd/otel-agent/subcommands/status/command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2025-present Datadog, Inc.

// Package status implements the core status component information provider interface
package status

import (
"os"

"github.com/spf13/cobra"
"go.uber.org/fx"

"github.com/DataDog/datadog-agent/cmd/otel-agent/subcommands"
"github.com/DataDog/datadog-agent/comp/api/authtoken/fetchonlyimpl"
coreconfig "github.com/DataDog/datadog-agent/comp/core/config"
log "github.com/DataDog/datadog-agent/comp/core/log/def"
logfx "github.com/DataDog/datadog-agent/comp/core/log/fx"
"github.com/DataDog/datadog-agent/comp/core/secrets"
"github.com/DataDog/datadog-agent/comp/core/secrets/secretsimpl"
status "github.com/DataDog/datadog-agent/comp/otelcol/status/def"
otelagentStatusfx "github.com/DataDog/datadog-agent/comp/otelcol/status/fx"
"github.com/DataDog/datadog-agent/pkg/util/fxutil"
"github.com/DataDog/datadog-agent/pkg/util/option"
)

type dependencies struct {
fx.In

Status status.Component
}

const headerText = "==========\nOTel Agent\n==========\n"

// MakeCommand returns a `status` command to be used by agent binaries.
func MakeCommand(globalConfGetter func() *subcommands.GlobalParams) *cobra.Command {
cmd := &cobra.Command{
Use: "status",
Short: "Print the current status",
Long: ``,
RunE: func(*cobra.Command, []string) error {
globalParams := globalConfGetter()
return fxutil.OneShot(
runStatus,
fx.Supply(coreconfig.NewAgentParams(globalParams.CoreConfPath, coreconfig.WithExtraConfFiles(globalParams.ConfPaths))),
fx.Supply(option.None[secrets.Component]()),
fx.Supply(secrets.NewEnabledParams()),
fx.Supply(log.ForOneShot(globalParams.LoggerName, "off", true)),
coreconfig.Module(),
secretsimpl.Module(),
logfx.Module(),
fetchonlyimpl.Module(),
otelagentStatusfx.Module(),
)
},
}

return cmd
}

func runStatus(deps dependencies) error {
statusText, err := deps.Status.GetStatus()
if err != nil {
return err
}
_, err = os.Stdout.Write([]byte(headerText + statusText))
if err != nil {
return err
}
return nil
}
40 changes: 40 additions & 0 deletions cmd/otel-agent/subcommands/status/command_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2025-present Datadog, Inc.

package status

import (
"os"
"path"
"testing"

"github.com/spf13/cobra"
"github.com/stretchr/testify/require"

"github.com/DataDog/datadog-agent/cmd/otel-agent/subcommands"
"github.com/DataDog/datadog-agent/pkg/util/fxutil"
)

func newGlobalParamsTest(t *testing.T) *subcommands.GlobalParams {
config := path.Join(t.TempDir(), "datadog.yaml")
err := os.WriteFile(config, []byte("hostname: test"), 0644)
require.NoError(t, err)
return &subcommands.GlobalParams{
CoreConfPath: config,
ConfPaths: []string{"test_config.yaml"},
}
}

func TestStatusCommand(t *testing.T) {
globalConfGetter := func() *subcommands.GlobalParams {
return newGlobalParamsTest(t)
}
fxutil.TestOneShotSubcommand(t,
[]*cobra.Command{MakeCommand(globalConfGetter)},
[]string{"status"},
runStatus,
func() {},
)
}
21 changes: 21 additions & 0 deletions cmd/otel-agent/subcommands/status/test_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
receivers:
otlp:
protocols:
http:
endpoint: "localhost:4318"
grpc:
endpoint: "localhost:4317"

exporters:
datadog:
api:
key: "abc"

service:
pipelines:
traces:
receivers: [otlp]
exporters: [datadog]
telemetry:
metrics:
address: 127.0.0.1:8888
2 changes: 2 additions & 0 deletions comp/otelcol/status/def/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ package status

// Component is the status interface.
type Component interface {
// GetStatus returns the OTel Agent status in string form
GetStatus() (string, error)
}
27 changes: 23 additions & 4 deletions comp/otelcol/status/impl/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
package statusimpl

import (
"bytes"
"embed"
"encoding/json"
"fmt"
"gopkg.in/yaml.v3"
"io"
"net/http"

"github.com/DataDog/datadog-agent/comp/api/authtoken"
"github.com/DataDog/datadog-agent/comp/core/config"
statusComponent "github.com/DataDog/datadog-agent/comp/core/status"
ddflareextension "github.com/DataDog/datadog-agent/comp/otelcol/ddflareextension/def"
Expand All @@ -27,7 +29,8 @@ var templatesFS embed.FS

// Requires defines the dependencies of the status component.
type Requires struct {
Config config.Component
Config config.Component
Authtoken authtoken.Component
}

// Provides contains components provided by status constructor.
Expand All @@ -39,6 +42,7 @@ type Provides struct {
type statusProvider struct {
Config config.Component
client *http.Client
authToken authtoken.Component
receiverStatus map[string]interface{}
exporterStatus map[string]interface{}
}
Expand All @@ -65,8 +69,9 @@ type prometheusRuntimeConfig struct {
// NewComponent creates a new status component.
func NewComponent(reqs Requires) Provides {
comp := statusProvider{
Config: reqs.Config,
client: apiutil.GetClient(false),
Config: reqs.Config,
client: apiutil.GetClient(false),
authToken: reqs.Authtoken,
receiverStatus: map[string]interface{}{
"spans": 0.0,
"metrics": 0.0,
Expand Down Expand Up @@ -100,6 +105,16 @@ func (s statusProvider) Section() string {
return "OTel Agent"
}

// GetStatus returns the OTel Agent status in string form
func (s statusProvider) GetStatus() (string, error) {
buf := new(bytes.Buffer)
err := s.Text(false, buf)
if err != nil {
return "", err
}
return buf.String(), nil
}

func (s statusProvider) getStatusInfo() map[string]interface{} {
statusInfo := make(map[string]interface{})

Expand Down Expand Up @@ -172,7 +187,11 @@ func (s statusProvider) populatePrometheusStatus(prometheusURL string) error {

func (s statusProvider) populateStatus() map[string]interface{} {
extensionURL := s.Config.GetString("otelcollector.extension_url")
resp, err := apiutil.DoGet(s.client, extensionURL, apiutil.CloseConnection)
options := apiutil.ReqOptions{
Conn: apiutil.CloseConnection,
Authtoken: s.authToken.Get(),
}
resp, err := apiutil.DoGetWithOptions(s.client, extensionURL, &options)
if err != nil {
return map[string]interface{}{
"url": extensionURL,
Expand Down
5 changes: 4 additions & 1 deletion comp/otelcol/status/impl/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (

"github.com/stretchr/testify/assert"

"github.com/DataDog/datadog-agent/comp/api/authtoken"
"github.com/DataDog/datadog-agent/comp/api/authtoken/fetchonlyimpl"
"github.com/DataDog/datadog-agent/comp/core/config"
"github.com/DataDog/datadog-agent/comp/core/status"
)
Expand Down Expand Up @@ -47,7 +49,8 @@ func TestStatusOut(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
provides := NewComponent(Requires{
Config: config.NewMock(t),
Config: config.NewMock(t),
Authtoken: authtoken.Component(&fetchonlyimpl.MockFetchOnly{}),
})
headerProvider := provides.StatusProvider.Provider
test.assertFunc(t, headerProvider)
Expand Down
8 changes: 8 additions & 0 deletions test/new-e2e/tests/otel/otel-agent/minimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,11 @@ func (s *minimalTestSuite) TestOTelFlareFiles() {
func (s *minimalTestSuite) TestOTelRemoteConfigPayload() {
utils.TestOTelRemoteConfigPayload(s, minimalProvidedConfig, minimalFullConfig)
}

func (s *minimalTestSuite) TestCoreAgentStatus() {
utils.TestCoreAgentStatusCmd(s)
}

func (s *minimalTestSuite) TestOTelAgentStatus() {
utils.TestOTelAgentStatusCmd(s)
}
40 changes: 40 additions & 0 deletions test/new-e2e/tests/otel/utils/config_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,43 @@ func validateConfigs(t *testing.T, expectedCfg string, actualCfg string) {

assert.YAMLEq(t, expectedCfg, actualCfg)
}

// TestCoreAgentStatusCmd tests the core agent status command contains the OTel Agent status as expected
func TestCoreAgentStatusCmd(s OTelTestSuite) {
err := s.Env().FakeIntake.Client().FlushServerAndResetAggregators()
require.NoError(s.T(), err)
agent := getAgentPod(s)

s.T().Log("Calling status command in core agent")
stdout, stderr, err := s.Env().KubernetesCluster.KubernetesClient.PodExec("datadog", agent.Name, "agent", []string{"agent", "status", "otel agent"})
require.NoError(s.T(), err, "Failed to execute config")
require.Empty(s.T(), stderr)
validateStatus(s.T(), stdout)
}

// TestOTelAgentStatusCmd tests the OTel Agent status subcommand returns as expected
func TestOTelAgentStatusCmd(s OTelTestSuite) {
err := s.Env().FakeIntake.Client().FlushServerAndResetAggregators()
require.NoError(s.T(), err)
agent := getAgentPod(s)

s.T().Log("Calling status command in otel agent")
stdout, stderr, err := s.Env().KubernetesCluster.KubernetesClient.PodExec("datadog", agent.Name, "otel-agent", []string{"otel-agent", "status"})
require.NoError(s.T(), err, "Failed to execute config")
require.Empty(s.T(), stderr)
validateStatus(s.T(), stdout)
}

func validateStatus(t *testing.T, status string) {
require.NotNil(t, status)
require.Contains(t, status, "OTel Agent")
require.Contains(t, status, "Status: Running")
require.Contains(t, status, "Agent Version:")
require.Contains(t, status, "Collector Version:")
require.Contains(t, status, "Spans Accepted:")
require.Contains(t, status, "Metric Points Accepted:")
require.Contains(t, status, "Log Records Accepted:")
require.Contains(t, status, "Spans Sent:")
require.Contains(t, status, "Metric Points Sent:")
require.Contains(t, status, "Log Records Sent:")
}

0 comments on commit a13051b

Please sign in to comment.