Skip to content

Commit 32c6f74

Browse files
committed
Merge branch 'v3' into add-nginx-plus-api-actions
2 parents aadb015 + 9b1bc5b commit 32c6f74

32 files changed

+995
-205
lines changed

Makefile.packaging

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ BINARY_PATH := $(BUILD_DIR)/$(BINARY_NAME)
1010
GPG_PUBLIC_KEY := .key
1111
PACKAGE_BUILD ?= 1
1212
PACKAGE_VERSION := $(shell echo ${VERSION} | tr -d 'v')-$(PACKAGE_BUILD)
13-
APK_PACKAGE_VERSION := $(shell echo ${VERSION} | tr -d 'v')_$(PACKAGE_BUILD)
13+
APK_PACKAGE_VERSION := $(shell echo ${VERSION} | tr -d 'v').$(PACKAGE_BUILD)
1414
TARBALL_NAME := $(PACKAGE_PREFIX)v3.tar.gz
1515

1616
DEB_DISTROS ?= ubuntu-noble-24.04 ubuntu-jammy-22.04 ubuntu-focal-20.04 debian-bookworm-12 debian-bullseye-11

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ require (
3333
github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.114.0
3434
github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor v0.114.0
3535
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver v0.114.0
36+
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/tcplogreceiver v0.114.0
3637
github.com/open-telemetry/opentelemetry-collector-contrib/testbed v0.114.0
3738
github.com/shirou/gopsutil/v4 v4.24.10
3839
github.com/spf13/pflag v1.0.5

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusrec
474474
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver v0.114.0/go.mod h1:T1p6ShTr8farkE4qUB2TyGUIvRSN3s17D0qY7rMqCRM=
475475
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/syslogreceiver v0.114.0 h1:chiIs7XGNSoptd0VgVR912NFogB8srpuVzgeVM9xW0w=
476476
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/syslogreceiver v0.114.0/go.mod h1:cHIBJ01AgmkTUN2FgXz9NU8LbnLGUR2uxssCdiqwV4w=
477+
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/tcplogreceiver v0.114.0 h1:C1487YIMVBuJ8ixBLChyIl8VHlF8Ir6l2hfeYNNPPLM=
478+
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/tcplogreceiver v0.114.0/go.mod h1:+SvBS7Xu+pI67e5outljqWDMt+bIu9B6XON0nM4PIhY=
477479
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver v0.114.0 h1:E686MeQcQ+a3Q47A/xAc3Nk6Qdz8wHcBLMJ3Y8bNKi0=
478480
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver v0.114.0/go.mod h1:zkQAapuNRobj7GY8kKRal+2EYkAMWmZ1KMysUrQI48A=
479481
github.com/open-telemetry/opentelemetry-collector-contrib/testbed v0.114.0 h1:/4hKXCQaD78y6cFA4xXMfZhh86/RNwrjyr6xnhFs5AA=

internal/backoff/backoff.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import (
4848
// Information from https://pkg.go.dev/github.com/cenkalti/backoff/v4#section-readme
4949
func WaitUntil(
5050
ctx context.Context,
51-
backoffSettings *config.CommonSettings,
51+
backoffSettings *config.BackOff,
5252
operation backoff.Operation,
5353
) error {
5454
eb := backoff.NewExponentialBackOff()
@@ -68,7 +68,7 @@ func WaitUntil(
6868
// nolint: ireturn
6969
func WaitUntilWithData[T any](
7070
ctx context.Context,
71-
backoffSettings *config.CommonSettings,
71+
backoffSettings *config.BackOff,
7272
operation backoff.OperationWithData[T],
7373
) (T, error) {
7474
backoffWithContext := Context(ctx, backoffSettings)
@@ -77,7 +77,7 @@ func WaitUntilWithData[T any](
7777
}
7878

7979
// nolint: ireturn
80-
func Context(ctx context.Context, backoffSettings *config.CommonSettings) backoff.BackOffContext {
80+
func Context(ctx context.Context, backoffSettings *config.BackOff) backoff.BackOffContext {
8181
eb := backoff.NewExponentialBackOff()
8282
eb.InitialInterval = backoffSettings.InitialInterval
8383
eb.MaxInterval = backoffSettings.MaxInterval

internal/backoff/backoff_test.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,16 @@ func TestWaitUntil(t *testing.T) {
8282

8383
for _, test := range tests {
8484
invocations = 0
85-
settings := &config.CommonSettings{
86-
InitialInterval: test.initialInterval,
87-
MaxInterval: test.maxInterval,
88-
MaxElapsedTime: test.maxElapsedTime,
89-
RandomizationFactor: config.DefBackoffRandomizationFactor,
90-
Multiplier: config.DefBackoffMultiplier,
85+
settings := &config.Client{
86+
Backoff: &config.BackOff{
87+
InitialInterval: test.initialInterval,
88+
MaxInterval: test.maxInterval,
89+
MaxElapsedTime: test.maxElapsedTime,
90+
RandomizationFactor: config.DefBackoffRandomizationFactor,
91+
Multiplier: config.DefBackoffMultiplier,
92+
},
9193
}
92-
result := WaitUntil(test.context, settings, test.operation)
94+
result := WaitUntil(test.context, settings.Backoff, test.operation)
9395

9496
if test.expectedError {
9597
assert.Errorf(t, result, test.name)
@@ -164,7 +166,7 @@ func TestWaitUntilWithData(t *testing.T) {
164166
}
165167

166168
for _, test := range tests {
167-
settings := &config.CommonSettings{
169+
settings := &config.BackOff{
168170
InitialInterval: test.initialInterval,
169171
MaxInterval: test.maxInterval,
170172
MaxElapsedTime: test.maxElapsedTime,
@@ -185,7 +187,7 @@ func TestWaitUntilWithData(t *testing.T) {
185187
}
186188

187189
func TestContext(t *testing.T) {
188-
settings := &config.CommonSettings{
190+
settings := &config.BackOff{
189191
InitialInterval: 10 * time.Millisecond,
190192
MaxInterval: 10 * time.Millisecond,
191193
MaxElapsedTime: 10 * time.Millisecond,

internal/collector/factories.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor"
2121
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor"
2222
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver"
23+
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/tcplogreceiver"
2324
"go.opentelemetry.io/collector/component"
2425
"go.opentelemetry.io/collector/connector"
2526
"go.opentelemetry.io/collector/exporter"
@@ -98,6 +99,7 @@ func createReceiverFactories() (map[component.Type]receiver.Factory, error) {
9899
hostmetricsreceiver.NewFactory(),
99100
nginxreceiver.NewFactory(),
100101
nginxplusreceiver.NewFactory(),
102+
tcplogreceiver.NewFactory(),
101103
}
102104

103105
return receiver.MakeFactoryMap(receiverList...)

internal/collector/factories_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func TestOTelComponentFactoriesDefault(t *testing.T) {
1818
require.NoError(t, err, "OTelComponentFactories should not return an error")
1919
assert.NotNil(t, factories, "factories should not be nil")
2020

21-
assert.Len(t, factories.Receivers, 4)
21+
assert.Len(t, factories.Receivers, 5)
2222
assert.Len(t, factories.Processors, 8)
2323
assert.Len(t, factories.Exporters, 4)
2424
assert.Len(t, factories.Extensions, 3)

internal/collector/otel_collector_plugin.go

Lines changed: 123 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ import (
2626
const (
2727
maxTimeToWaitForShutdown = 30 * time.Second
2828
filePermission = 0o600
29+
// To conform to the rfc3164 spec the timestamp in the logs need to be formatted correctly.
30+
// Here are some examples of what the timestamp conversions look like.
31+
// Notice how if the day begins with a zero that the zero is replaced with an empty space.
32+
33+
// 2024-11-06T17:19:24+00:00 ---> Nov 6 17:19:24
34+
// 2024-11-16T17:19:24+00:00 ---> Nov 16 17:19:24
35+
timestampConversionExpression = `'EXPR(let timestamp = split(split(body, ">")[1], " ")[0]; ` +
36+
`let newTimestamp = timestamp matches "(\\d{4})-(\\d{2})-(0\\d{1})T(\\d{2}):(\\d{2}):(\\d{2}).*" ` +
37+
`? date(timestamp).Format("Jan 2 15:04:05") : date(timestamp).Format("Jan 02 15:04:05"); ` +
38+
`split(body, ">")[0] + ">" + newTimestamp + " " + split(body, " ", 2)[1])'`
2939
)
3040

3141
type (
@@ -193,9 +203,9 @@ func (oc *Collector) Close(ctx context.Context) error {
193203
oc.service.Shutdown()
194204
oc.cancel()
195205

196-
settings := oc.config.Common
206+
settings := oc.config.Client.Backoff
197207
settings.MaxElapsedTime = maxTimeToWaitForShutdown
198-
err := backoff.WaitUntil(ctx, oc.config.Common, func() error {
208+
err := backoff.WaitUntil(ctx, settings, func() error {
199209
if oc.service.GetState() == otelcol.StateClosed {
200210
return nil
201211
}
@@ -243,7 +253,7 @@ func (oc *Collector) handleNginxConfigUpdate(ctx context.Context, msg *bus.Messa
243253
return
244254
}
245255

246-
reloadCollector := oc.checkForNewNginxReceivers(nginxConfigContext)
256+
reloadCollector := oc.checkForNewReceivers(nginxConfigContext)
247257

248258
if reloadCollector {
249259
slog.InfoContext(ctx, "Reloading OTel collector config")
@@ -368,7 +378,7 @@ func (oc *Collector) restartCollector(ctx context.Context) {
368378
}
369379
}
370380

371-
func (oc *Collector) checkForNewNginxReceivers(nginxConfigContext *model.NginxConfigContext) bool {
381+
func (oc *Collector) checkForNewReceivers(nginxConfigContext *model.NginxConfigContext) bool {
372382
nginxReceiverFound, reloadCollector := oc.updateExistingNginxPlusReceiver(nginxConfigContext)
373383

374384
if !nginxReceiverFound && nginxConfigContext.PlusAPI.URL != "" {
@@ -406,6 +416,11 @@ func (oc *Collector) checkForNewNginxReceivers(nginxConfigContext *model.NginxCo
406416
}
407417
}
408418

419+
tcplogReceiversFound := oc.updateTcplogReceivers(nginxConfigContext)
420+
if tcplogReceiversFound {
421+
reloadCollector = true
422+
}
423+
409424
return reloadCollector
410425
}
411426

@@ -476,6 +491,110 @@ func (oc *Collector) updateExistingNginxOSSReceiver(
476491
return nginxReceiverFound, reloadCollector
477492
}
478493

494+
func (oc *Collector) updateTcplogReceivers(nginxConfigContext *model.NginxConfigContext) bool {
495+
newTcplogReceiverAdded := false
496+
if nginxConfigContext.NAPSysLogServers != nil {
497+
napLoop:
498+
for _, napSysLogServer := range nginxConfigContext.NAPSysLogServers {
499+
if oc.doesTcplogReceiverAlreadyExist(napSysLogServer) {
500+
continue napLoop
501+
}
502+
503+
oc.config.Collector.Receivers.TcplogReceivers = append(
504+
oc.config.Collector.Receivers.TcplogReceivers,
505+
config.TcplogReceiver{
506+
ListenAddress: napSysLogServer,
507+
Operators: []config.Operator{
508+
{
509+
Type: "add",
510+
Fields: map[string]string{
511+
"field": "body",
512+
"value": timestampConversionExpression,
513+
},
514+
},
515+
{
516+
Type: "syslog_parser",
517+
Fields: map[string]string{
518+
"protocol": "rfc3164",
519+
},
520+
},
521+
{
522+
Type: "remove",
523+
Fields: map[string]string{
524+
"field": "attributes.message",
525+
},
526+
},
527+
{
528+
Type: "add",
529+
Fields: map[string]string{
530+
"field": "resource[\"instance.id\"]",
531+
"value": nginxConfigContext.InstanceID,
532+
},
533+
},
534+
},
535+
},
536+
)
537+
538+
newTcplogReceiverAdded = true
539+
}
540+
}
541+
542+
tcplogReceiverDeleted := oc.areNapReceiversDeleted(nginxConfigContext)
543+
544+
return newTcplogReceiverAdded || tcplogReceiverDeleted
545+
}
546+
547+
func (oc *Collector) areNapReceiversDeleted(nginxConfigContext *model.NginxConfigContext) bool {
548+
listenAddressesToBeDeleted := oc.getConfigDeletedNapReceivers(nginxConfigContext)
549+
if len(listenAddressesToBeDeleted) != 0 {
550+
oc.deleteNapReceivers(listenAddressesToBeDeleted)
551+
return true
552+
}
553+
554+
return false
555+
}
556+
557+
func (oc *Collector) deleteNapReceivers(listenAddressesToBeDeleted map[string]bool) {
558+
filteredReceivers := (oc.config.Collector.Receivers.TcplogReceivers)[:0]
559+
for _, receiver := range oc.config.Collector.Receivers.TcplogReceivers {
560+
if !listenAddressesToBeDeleted[receiver.ListenAddress] {
561+
filteredReceivers = append(filteredReceivers, receiver)
562+
}
563+
}
564+
oc.config.Collector.Receivers.TcplogReceivers = filteredReceivers
565+
}
566+
567+
func (oc *Collector) getConfigDeletedNapReceivers(nginxConfigContext *model.NginxConfigContext) map[string]bool {
568+
elements := make(map[string]bool)
569+
570+
for _, tcplogReceiver := range oc.config.Collector.Receivers.TcplogReceivers {
571+
elements[tcplogReceiver.ListenAddress] = true
572+
}
573+
574+
if nginxConfigContext.NAPSysLogServers != nil {
575+
addressesToDelete := make(map[string]bool)
576+
for _, napAddress := range nginxConfigContext.NAPSysLogServers {
577+
if !elements[napAddress] {
578+
addressesToDelete[napAddress] = true
579+
}
580+
}
581+
582+
return addressesToDelete
583+
}
584+
585+
return elements
586+
}
587+
588+
func (oc *Collector) doesTcplogReceiverAlreadyExist(listenAddress string) bool {
589+
for _, tcplogReceiver := range oc.config.Collector.Receivers.TcplogReceivers {
590+
if listenAddress == tcplogReceiver.ListenAddress {
591+
return true
592+
}
593+
}
594+
595+
return false
596+
}
597+
479598
// nolint: revive
480599
func (oc *Collector) updateResourceAttributes(
481600
attributesToAdd []config.ResourceAttribute,

internal/collector/otel_collector_plugin_test.go

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"context"
1010
"errors"
1111
"fmt"
12+
"path/filepath"
1213
"testing"
1314

1415
"github.com/nginx/agent/v3/test/protos"
@@ -26,6 +27,8 @@ import (
2627
)
2728

2829
func TestCollector_New(t *testing.T) {
30+
tmpDir := t.TempDir()
31+
2932
tests := []struct {
3033
config *config.Config
3134
expectedError error
@@ -56,7 +59,7 @@ func TestCollector_New(t *testing.T) {
5659
name: "Successful initialization",
5760
config: &config.Config{
5861
Collector: &config.Collector{
59-
Log: &config.Log{Path: "/tmp/test.log"},
62+
Log: &config.Log{Path: filepath.Join(tmpDir, "test.log")},
6063
},
6164
},
6265
expectedError: nil,
@@ -79,6 +82,8 @@ func TestCollector_New(t *testing.T) {
7982
}
8083

8184
func TestCollector_Init(t *testing.T) {
85+
tmpDir := t.TempDir()
86+
8287
tests := []struct {
8388
name string
8489
expectedLog string
@@ -104,7 +109,7 @@ func TestCollector_Init(t *testing.T) {
104109
logBuf := &bytes.Buffer{}
105110
stub.StubLoggerWith(logBuf)
106111

107-
conf.Collector.Log = &config.Log{Path: "/tmp/test.log"}
112+
conf.Collector.Log = &config.Log{Path: filepath.Join(tmpDir, "test.log")}
108113

109114
if tt.expectedError {
110115
conf.Collector.Receivers = config.Receivers{}
@@ -714,6 +719,60 @@ func TestCollector_updateResourceAttributes(t *testing.T) {
714719
}
715720
}
716721

722+
func TestCollector_updateTcplogReceivers(t *testing.T) {
723+
conf := types.OTelConfig(t)
724+
conf.Collector.Log.Path = ""
725+
conf.Collector.Processors.Batch = nil
726+
conf.Collector.Processors.Attribute = nil
727+
conf.Collector.Processors.Resource = nil
728+
729+
collector, err := New(conf)
730+
require.NoError(t, err)
731+
732+
nginxConfigContext := &model.NginxConfigContext{
733+
NAPSysLogServers: []string{
734+
"localhost:151",
735+
},
736+
}
737+
738+
assert.Empty(t, conf.Collector.Receivers.TcplogReceivers)
739+
740+
t.Run("Test 1: New TcplogReceiver added", func(tt *testing.T) {
741+
tcplogReceiverAdded := collector.updateTcplogReceivers(nginxConfigContext)
742+
743+
assert.True(tt, tcplogReceiverAdded)
744+
assert.Len(tt, conf.Collector.Receivers.TcplogReceivers, 1)
745+
assert.Equal(tt, "localhost:151", conf.Collector.Receivers.TcplogReceivers[0].ListenAddress)
746+
assert.Len(tt, conf.Collector.Receivers.TcplogReceivers[0].Operators, 4)
747+
})
748+
749+
// Calling updateTcplogReceivers shouldn't update the TcplogReceivers slice
750+
// since there is already a receiver with the same ListenAddress
751+
t.Run("Test 2: TcplogReceiver already exists", func(tt *testing.T) {
752+
tcplogReceiverAdded := collector.updateTcplogReceivers(nginxConfigContext)
753+
assert.False(t, tcplogReceiverAdded)
754+
assert.Len(t, conf.Collector.Receivers.TcplogReceivers, 1)
755+
assert.Equal(t, "localhost:151", conf.Collector.Receivers.TcplogReceivers[0].ListenAddress)
756+
assert.Len(t, conf.Collector.Receivers.TcplogReceivers[0].Operators, 4)
757+
})
758+
759+
t.Run("Test 3: TcplogReceiver deleted", func(tt *testing.T) {
760+
tcplogReceiverDeleted := collector.updateTcplogReceivers(&model.NginxConfigContext{})
761+
assert.True(t, tcplogReceiverDeleted)
762+
assert.Empty(t, conf.Collector.Receivers.TcplogReceivers)
763+
})
764+
765+
t.Run("Test 4: New tcplogReceiver added and deleted another", func(tt *testing.T) {
766+
tcplogReceiverDeleted := collector.updateTcplogReceivers(&model.NginxConfigContext{NAPSysLogServers: []string{
767+
"localhost:152",
768+
}})
769+
assert.True(t, tcplogReceiverDeleted)
770+
assert.Len(t, conf.Collector.Receivers.TcplogReceivers, 1)
771+
assert.Equal(t, "localhost:152", conf.Collector.Receivers.TcplogReceivers[0].ListenAddress)
772+
assert.Len(t, conf.Collector.Receivers.TcplogReceivers[0].Operators, 4)
773+
})
774+
}
775+
717776
func createFakeCollector() *typesfakes.FakeCollectorInterface {
718777
fakeCollector := &typesfakes.FakeCollectorInterface{}
719778
fakeCollector.RunStub = func(ctx context.Context) error { return nil }

0 commit comments

Comments
 (0)