Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
type Config struct {
confighttp.ClientConfig `mapstructure:",squash"`
APIDetails APIDetails `mapstructure:"api_details"`
InstanceID string `mapstructure:"instance_id"`
AccessLogs []AccessLog `mapstructure:"access_logs"`
MetricsBuilderConfig metadata.MetricsBuilderConfig `mapstructure:",squash"`
scraperhelper.ControllerConfig `mapstructure:",squash"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ func (nls *NginxLogScraper) Scrape(_ context.Context) (pmetric.Metrics, error) {
nls.entries = make([]*entry.Entry, 0)
timeNow := pcommon.NewTimestampFromTime(time.Now())

nls.rb.SetInstanceID(nls.settings.ID.Name())
nls.rb.SetInstanceID(nls.cfg.InstanceID)
nls.rb.SetInstanceType("nginx")
nls.logger.Debug("NGINX OSS access log resource info", zap.Any("resource", nls.rb))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func (s *NginxStubStatusScraper) Scrape(context.Context) (pmetric.Metrics, error
return pmetric.Metrics{}, err
}

s.rb.SetInstanceID(s.settings.ID.Name())
s.rb.SetInstanceID(s.cfg.InstanceID)
s.rb.SetInstanceType("nginx")
s.settings.Logger.Debug("NGINX OSS stub status resource info", zap.Any("resource", s.rb))

Expand Down
1 change: 1 addition & 0 deletions internal/collector/nginxplusreceiver/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const defaultCollectInterval = 10 * time.Second
type Config struct {
confighttp.ClientConfig `mapstructure:",squash"`
APIDetails APIDetails `mapstructure:"api_details"`
InstanceID string `mapstructure:"instance_id"`
MetricsBuilderConfig metadata.MetricsBuilderConfig `mapstructure:",squash"`
scraperhelper.ControllerConfig `mapstructure:",squash"`
}
Expand Down
2 changes: 1 addition & 1 deletion internal/collector/nginxplusreceiver/scraper.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (nps *NginxPlusScraper) Scrape(ctx context.Context) (pmetric.Metrics, error
return pmetric.Metrics{}, fmt.Errorf("failed to get stats from plus API: %w", err)
}

nps.rb.SetInstanceID(nps.settings.ID.Name())
nps.rb.SetInstanceID(nps.cfg.InstanceID)
nps.rb.SetInstanceType("nginxplus")
nps.logger.Debug("NGINX Plus resource info", zap.Any("resource", nps.rb))

Expand Down
35 changes: 35 additions & 0 deletions internal/collector/otel_collector_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import (
"sync"
"time"

"github.com/goccy/go-yaml"
pkgConfig "github.com/nginx/agent/v3/pkg/config"
"go.opentelemetry.io/collector/confmap"

"github.com/nginx/agent/v3/api/grpc/mpi/v1"
"github.com/nginx/agent/v3/internal/backoff"
Expand Down Expand Up @@ -384,6 +386,31 @@ func (oc *Collector) updateHeadersSetterExtension(
return headersSetterExtensionUpdated
}

func (oc *Collector) writeRunningConfig(ctx context.Context, settings otelcol.CollectorSettings) error {
slog.DebugContext(ctx, "Writing running OTel collector config", "path",
"/var/lib/nginx-agent/opentelemetry-collector-agent-debug.yaml")
resolver, err := confmap.NewResolver(settings.ConfigProviderSettings.ResolverSettings)
if err != nil {
return fmt.Errorf("unable to create resolver: %w", err)
}

con, err := resolver.Resolve(ctx)
if err != nil {
return fmt.Errorf("error while resolving config: %w", err)
}
b, err := yaml.Marshal(con.ToStringMap())
if err != nil {
return fmt.Errorf("error while marshaling to YAML: %w", err)
}

writeErr := os.WriteFile("/var/lib/nginx-agent/opentelemetry-collector-agent-debug.yaml", b, filePermission)
if writeErr != nil {
return fmt.Errorf("error while writing debug config: %w", err)
}

return nil
}

func (oc *Collector) restartCollector(ctx context.Context) {
err := oc.Close(ctx)
if err != nil {
Expand All @@ -392,6 +419,14 @@ func (oc *Collector) restartCollector(ctx context.Context) {
}

settings := OTelCollectorSettings(oc.config)

if strings.ToLower(oc.config.Log.Level) == "debug" {
writeErr := oc.writeRunningConfig(ctx, settings)
if writeErr != nil {
slog.ErrorContext(ctx, "Failed to write debug OTel Collector config", "error", writeErr)
}
}

oTelCollector, err := otelcol.NewCollector(settings)
if err != nil {
slog.ErrorContext(ctx, "Failed to create OTel Collector", "error", err)
Expand Down
26 changes: 22 additions & 4 deletions internal/collector/otelcol.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@ receivers:
{{- end }}

{{- range .Receivers.NginxReceivers }}
{{- if gt (len $.Receivers.NginxReceivers) 1 }}
nginx/{{- .InstanceID -}}:
{{- else }}
nginx:
{{- end}}
instance_id: "{{- .InstanceID -}}"
api_details:
url: "{{- .StubStatus.URL -}}"
listen: "{{- .StubStatus.Listen -}}"
Expand All @@ -98,12 +103,17 @@ receivers:
{{- end }}

{{- range .Receivers.NginxPlusReceivers }}
{{- if gt (len $.Receivers.NginxPlusReceivers) 1 }}
nginxplus/{{- .InstanceID -}}:
{{- else }}
nginxplus:
{{- end}}
instance_id: "{{- .InstanceID -}}"
api_details:
url: "{{- .PlusAPI.URL -}}"
listen: "{{- .PlusAPI.Listen -}}"
location: "{{- .PlusAPI.Location -}}"
ca: "{{- .PlusAPI.Ca -}}"
url: "{{- .PlusAPI.URL -}}"
listen: "{{- .PlusAPI.Listen -}}"
location: "{{- .PlusAPI.Location -}}"
ca: "{{- .PlusAPI.Ca -}}"
{{- if .CollectionInterval }}
collection_interval: {{ .CollectionInterval }}
{{- end }}
Expand Down Expand Up @@ -274,10 +284,18 @@ service:
{{- end }}
{{- else if eq $receiver "nginx_metrics" }}
{{- range $.Receivers.NginxReceivers }}
{{- if gt (len $.Receivers.NginxReceivers) 1 }}
- nginx/{{- .InstanceID -}}
{{- else }}
- nginx
{{- end }}
{{- end }}
{{- range $.Receivers.NginxPlusReceivers }}
{{- if gt (len $.Receivers.NginxReceivers) 1 }}
- nginxplus/{{- .InstanceID -}}
{{- else }}
- nginxplus
{{- end }}
{{- end }}
{{- else }}
- {{ $receiver }}
Expand Down
6 changes: 5 additions & 1 deletion internal/collector/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ func createConverterFactories() []confmap.ConverterFactory {
}

func createURIs(cfg *config.Config) []string {
return []string{cfg.Collector.ConfigPath}
configFiles := []string{cfg.Collector.ConfigPath}
configFiles = slices.Concat(configFiles, cfg.Collector.AdditionalPaths)
slog.Info("Additional config files:", "", configFiles)

return configFiles
}

func createFile(confPath string) error {
Expand Down
28 changes: 27 additions & 1 deletion internal/collector/settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package collector
import (
"os"
"path/filepath"
"slices"
"testing"
"time"

Expand Down Expand Up @@ -107,6 +108,28 @@ func TestTemplateWrite(t *testing.T) {
},
},
})

cfg.Collector.Receivers.NginxPlusReceivers = slices.Concat(cfg.Collector.Receivers.NginxPlusReceivers,
[]config.NginxPlusReceiver{
{
InstanceID: "456",
PlusAPI: config.APIDetails{
URL: "http://localhost:80/api",
Listen: "",
Location: "",
},
CollectionInterval: 20 * time.Second,
},
{
InstanceID: "789",
PlusAPI: config.APIDetails{
URL: "http://localhost:90/api",
Listen: "",
Location: "",
},
CollectionInterval: 20 * time.Second,
},
})
// Clear default config and test collector with TLS enabled
cfg.Collector.Receivers.OtlpReceivers["default"] = &config.OtlpReceiver{
Server: &config.ServerConfig{
Expand Down Expand Up @@ -165,7 +188,10 @@ func TestTemplateWrite(t *testing.T) {

cfg.Collector.Pipelines.Metrics = make(map[string]*config.Pipeline)
cfg.Collector.Pipelines.Metrics["default"] = &config.Pipeline{
Receivers: []string{"hostmetrics", "containermetrics", "otlp/default", "nginx/123"},
Receivers: []string{
"hostmetrics", "containermetrics",
"otlp/default", "nginx", "nginxplus/456", "nginxplus/789",
},
Processors: []string{"resource/default", "batch/default"},
Exporters: []string{"otlp/default", "prometheus", "debug"},
}
Expand Down
23 changes: 16 additions & 7 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,14 @@ func registerCollectorFlags(fs *flag.FlagSet) {
"The path to the Opentelemetry Collector configuration file.",
)

fs.StringSlice(
CollectorAdditionalConfigPathsKey,
[]string{},
"Paths to additional OpenTelemetry Collector configuration files. The order of the configuration files"+
" determines which config file takes priority. The last config file will take precedent over other files "+
"if they have the same setting. Paths to configuration files must be absolute",
)

fs.String(
CollectorLogLevelKey,
DefCollectorLogLevel,
Expand Down Expand Up @@ -1053,13 +1061,14 @@ func resolveCollector(allowedDirs []string) (*Collector, error) {
}

col := &Collector{
ConfigPath: viperInstance.GetString(CollectorConfigPathKey),
Exporters: exporters,
Processors: resolveProcessors(),
Receivers: receivers,
Extensions: resolveExtensions(),
Log: resolveCollectorLog(),
Pipelines: resolvePipelines(),
ConfigPath: viperInstance.GetString(CollectorConfigPathKey),
AdditionalPaths: viperInstance.GetStringSlice(CollectorAdditionalConfigPathsKey),
Exporters: exporters,
Processors: resolveProcessors(),
Receivers: receivers,
Extensions: resolveExtensions(),
Log: resolveCollectorLog(),
Pipelines: resolvePipelines(),
}

// Check for self-signed certificate true in Agent conf
Expand Down
6 changes: 4 additions & 2 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func TestResolveConfig(t *testing.T) {

actual, err := ResolveConfig()
require.NoError(t, err)
t.Logf("Actual: %+v", actual.AllowedDirectories)
sort.Slice(actual.Collector.Extensions.HeadersSetter.Headers, func(i, j int) bool {
headers := actual.Collector.Extensions.HeadersSetter.Headers
return headers[i].Key < headers[j].Key
Expand Down Expand Up @@ -1094,7 +1095,7 @@ func createConfig() *Config {
},
AllowedDirectories: []string{
"/etc/nginx-agent", "/etc/nginx", "/usr/local/etc/nginx", "/var/run/nginx",
"/usr/share/nginx/modules", "/var/log/nginx",
"/usr/share/nginx/modules", "/var/log/nginx", "/configs",
},
DataPlaneConfig: &DataPlaneConfig{
Nginx: &NginxDataPlaneConfig{
Expand All @@ -1111,7 +1112,8 @@ func createConfig() *Config {
},
},
Collector: &Collector{
ConfigPath: "/etc/nginx-agent/nginx-agent-otelcol.yaml",
ConfigPath: "/etc/nginx-agent/nginx-agent-otelcol.yaml",
AdditionalPaths: []string{"/configs/my_config.yaml", "/etc/nginx-agent/nginx-agent-otelcol.yaml"},
Exporters: Exporters{
OtlpExporters: map[string]*OtlpExporter{
"default": {
Expand Down
1 change: 1 addition & 0 deletions internal/config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ var (
ClientBackoffMultiplierKey = pre(ClientRootKey) + "backoff_multiplier"

CollectorConfigPathKey = pre(CollectorRootKey) + "config_path"
CollectorAdditionalConfigPathsKey = pre(CollectorRootKey) + "additional_config_paths"
CollectorExportersKey = pre(CollectorRootKey) + "exporters"
CollectorDebugExporterKey = pre(CollectorExportersKey) + "debug"
CollectorPrometheusExporterKey = pre(CollectorExportersKey) + "prometheus"
Expand Down
4 changes: 4 additions & 0 deletions internal/config/testdata/nginx-agent.conf
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ allowed_directories:
- /var/run/nginx
- /usr/share/nginx/modules
- /var/log/nginx
- /configs

command:
server:
Expand Down Expand Up @@ -94,6 +95,9 @@ auxiliary_command:

collector:
config_path: "/etc/nginx-agent/nginx-agent-otelcol.yaml"
additional_config_paths:
- "/configs/my_config.yaml"
- /etc/nginx-agent/nginx-agent-otelcol.yaml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be commented?

Suggested change
- /etc/nginx-agent/nginx-agent-otelcol.yaml
- "/etc/nginx-agent/nginx-agent-otelcol.yaml"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's without the quotes because I wanted to check it would work with and without the quotes

receivers:
otlp:
"default":
Expand Down
23 changes: 16 additions & 7 deletions internal/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,14 @@ type (
}

Collector struct {
ConfigPath string `yaml:"config_path" mapstructure:"config_path"`
Log *Log `yaml:"log" mapstructure:"log"`
Exporters Exporters `yaml:"exporters" mapstructure:"exporters"`
Extensions Extensions `yaml:"extensions" mapstructure:"extensions"`
Processors Processors `yaml:"processors" mapstructure:"processors"`
Pipelines Pipelines `yaml:"pipelines" mapstructure:"pipelines"`
Receivers Receivers `yaml:"receivers" mapstructure:"receivers"`
ConfigPath string `yaml:"config_path" mapstructure:"config_path"`
AdditionalPaths []string `yaml:"additional_config_paths" mapstructure:"additional_config_paths"`
Log *Log `yaml:"log" mapstructure:"log"`
Exporters Exporters `yaml:"exporters" mapstructure:"exporters"`
Extensions Extensions `yaml:"extensions" mapstructure:"extensions"`
Processors Processors `yaml:"processors" mapstructure:"processors"`
Pipelines Pipelines `yaml:"pipelines" mapstructure:"pipelines"`
Receivers Receivers `yaml:"receivers" mapstructure:"receivers"`
}

Pipelines struct {
Expand Down Expand Up @@ -364,6 +365,14 @@ func (col *Collector) Validate(allowedDirectories []string) error {
err = errors.Join(err, nginxReceiver.Validate(allowedDirectories))
}

for _, path := range col.AdditionalPaths {
cleanPath := filepath.Clean(path)
pathAllowed := isAllowedDir(cleanPath, allowedDirectories)
if !pathAllowed {
err = errors.Join(err, fmt.Errorf("additional config path %s not in allowed directories", path))
}
}

return err
}

Expand Down
23 changes: 21 additions & 2 deletions test/config/collector/test-opentelemetry-collector-agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ receivers:
cert_file: /tmp/cert.pem
key_file: /tmp/key.pem
ca_file: /tmp/ca.pem
nginx/123:
nginx:
instance_id: "123"
api_details:
url: "http://localhost:80/status"
listen: ""
Expand All @@ -36,6 +37,22 @@ receivers:
access_logs:
- log_format: "$remote_addr - $remote_user [$time_local] \"$request\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\" \"$http_x_forwarded_for\"\"$upstream_cache_status\""
file_path: "/var/log/nginx/access-custom.conf"
nginxplus/456:
instance_id: "456"
api_details:
url: "http://localhost:80/api"
listen: ""
location: ""
ca: ""
collection_interval: 20s
nginxplus/789:
instance_id: "789"
api_details:
url: "http://localhost:90/api"
listen: ""
location: ""
ca: ""
collection_interval: 20s
tcplog/default:
listen_address: "localhost:151"
operators:
Expand Down Expand Up @@ -108,7 +125,9 @@ service:
- hostmetrics
- containermetrics
- otlp/default
- nginx/123
- nginx
- nginxplus/456
- nginxplus/789
processors:
- resource/default
- batch/default
Expand Down
Loading