Skip to content

Commit

Permalink
Reduce the number of times env.Processes gets called (#482)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhurley authored Sep 28, 2023
1 parent ab04cf2 commit df8cf6e
Show file tree
Hide file tree
Showing 29 changed files with 280 additions and 175 deletions.
16 changes: 8 additions & 8 deletions Makefile.packaging
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ package: gpg-key $(PACKAGES_DIR) $(GITHUB_PACKAGES_DIR) $(AZURE_PACKAGES_DIR) ##
# Create deb packages

@for arch in $(DEB_ARCHS); do \
GOWORK=off CGO_ENABLED=0 GOARCH=$${arch} GOOS=linux go build -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${arch} GOOS=linux go build -pgo=auto -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
for distro in $(DEB_DISTROS); do \
deb_codename=`echo $$distro | cut -d- -f 2`; \
VERSION=$(shell echo ${VERSION} | tr -d 'v')~$${deb_codename} ARCH=$${arch} nfpm pkg --config .nfpm.yaml --packager deb --target ${PACKAGES_DIR}/deb/${PACKAGE_PREFIX}_$(shell echo ${VERSION} | tr -d 'v')~$${deb_codename}_$${arch}.deb; \
Expand All @@ -59,7 +59,7 @@ package: gpg-key $(PACKAGES_DIR) $(GITHUB_PACKAGES_DIR) $(AZURE_PACKAGES_DIR) ##

# Create rpm packages

@GOWORK=off CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -ldflags=${LDFLAGS} -o ./build/nginx-agent
@GOWORK=off CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -pgo=auto -ldflags=${LDFLAGS} -o ./build/nginx-agent
@for distro in $(RPM_DISTROS); do \
rpm_distro=`echo $$distro | cut -d- -f 1`; \
rpm_major=`echo $$distro | cut -d- -f 2`; \
Expand All @@ -82,7 +82,7 @@ package: gpg-key $(PACKAGES_DIR) $(GITHUB_PACKAGES_DIR) $(AZURE_PACKAGES_DIR) ##
@for arch in $(REDHAT_ARCHS); do \
goarch=amd64; \
if [ "$$arch" = "aarch64" ]; then goarch="arm64"; fi; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${goarch} GOOS=linux go build -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${goarch} GOOS=linux go build -pgo=auto -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
for distro in $(REDHAT_VERSIONS); do \
rpm_distro=`echo $$distro | cut -d- -f 1`; \
rpm_major=`echo $$distro | cut -d- -f 2`; \
Expand All @@ -99,7 +99,7 @@ package: gpg-key $(PACKAGES_DIR) $(GITHUB_PACKAGES_DIR) $(AZURE_PACKAGES_DIR) ##
@for arch in $(ALMA_ARCHS); do \
goarch=amd64; \
if [ "$$arch" = "aarch64" ]; then goarch="arm64"; fi; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${goarch} GOOS=linux go build -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${goarch} GOOS=linux go build -pgo=auto -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
for distro in $(ALMA_VERSIONS); do \
rpm_distro=`echo $$distro | cut -d- -f 1`; \
rpm_major=`echo $$distro | cut -d- -f 2`; \
Expand All @@ -116,7 +116,7 @@ package: gpg-key $(PACKAGES_DIR) $(GITHUB_PACKAGES_DIR) $(AZURE_PACKAGES_DIR) ##
@for arch in $(ROCKY_ARCHS); do \
goarch=amd64; \
if [ "$$arch" = "aarch64" ]; then goarch="arm64"; fi; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${goarch} GOOS=linux go build -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${goarch} GOOS=linux go build -pgo=auto -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
for distro in $(ROCKY_VERSIONS); do \
rpm_distro=`echo $$distro | cut -d- -f 1`; \
rpm_major=`echo $$distro | cut -d- -f 2`; \
Expand All @@ -134,7 +134,7 @@ package: gpg-key $(PACKAGES_DIR) $(GITHUB_PACKAGES_DIR) $(AZURE_PACKAGES_DIR) ##
@for arch in $(AMAZON_ARCHS); do \
goarch=amd64; \
if [ "$$arch" = "aarch64" ]; then goarch="arm64"; fi; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${goarch} GOOS=linux go build -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${goarch} GOOS=linux go build -pgo=auto -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
for version in $(AMAZON_VERSIONS); do \
rpm_major=`echo $$version | cut -d- -f 2`; \
rpm_codename="amzn$$rpm_major";\
Expand All @@ -150,7 +150,7 @@ package: gpg-key $(PACKAGES_DIR) $(GITHUB_PACKAGES_DIR) $(AZURE_PACKAGES_DIR) ##
@for arch in $(APK_ARCHS); do \
goarch=amd64; \
if [ "$$arch" = "aarch64" ]; then goarch="arm64"; fi; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${goarch} GOOS=linux go build -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
GOWORK=off CGO_ENABLED=0 GOARCH=$${goarch} GOOS=linux go build -pgo=auto -ldflags=${LDFLAGS} -o ./build/nginx-agent; \
for version in $(APK_VERSIONS); do \
if [ ! -d "$(PACKAGES_DIR)/apk/v$${version}/$${arch}" ]; then mkdir -p $(PACKAGES_DIR)/apk/v$${version}/$${arch}; fi; \
VERSION=$(shell echo ${VERSION} | tr -d 'v') ARCH=$${arch} nfpm pkg --config .nfpm.yaml --packager apk --target $(PACKAGES_DIR)/apk/v$${version}/$${arch}/${PACKAGE_PREFIX}-$(shell echo ${VERSION} | tr -d 'v').apk; \
Expand All @@ -163,7 +163,7 @@ package: gpg-key $(PACKAGES_DIR) $(GITHUB_PACKAGES_DIR) $(AZURE_PACKAGES_DIR) ##
# Create txz packages

rm -rf ./build/nginx-agent
@GOWORK=off CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags=${LDFLAGS} -o ./build/nginx-agent
@GOWORK=off CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -pgo=auto -ldflags=${LDFLAGS} -o ./build/nginx-agent

docker run -v ${PWD}:/nginx-agent/ build-signed-packager:1.0.0

Expand Down
2 changes: 1 addition & 1 deletion nginx-agent.conf
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ config_dirs: "/etc/nginx:/usr/local/etc/nginx:/usr/share/nginx/modules:/etc/nms"
# host: 127.0.0.1
#
# Set this value to a secure port number to prevent information leaks.
# port: 8038
# port: 8038
Binary file modified profile.cgo
Binary file not shown.
28 changes: 26 additions & 2 deletions src/plugins/agent_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"net/http"
"os"
"regexp"
"sync"
"time"

"github.com/nginx/agent/v2/src/core/metrics"
Expand Down Expand Up @@ -60,6 +61,7 @@ type AgentAPI struct {
nginxBinary core.NginxBinary
nginxHandler *NginxHandler
exporter *prometheus_metrics.Exporter
processes []*core.Process
}

type NginxHandler struct {
Expand All @@ -69,6 +71,8 @@ type NginxHandler struct {
nginxBinary core.NginxBinary
responseChannel chan *proto.Command_NginxConfigResponse
configResponseStatuses map[string]*proto.NginxConfigStatus
processesMutex sync.RWMutex
processes []*core.Process
}

// swagger:parameters apply-nginx-config
Expand Down Expand Up @@ -133,12 +137,13 @@ const (
jsonMimeType = "application/json"
)

func NewAgentAPI(config *config.Config, env core.Environment, nginxBinary core.NginxBinary) *AgentAPI {
func NewAgentAPI(config *config.Config, env core.Environment, nginxBinary core.NginxBinary, processes []*core.Process) *AgentAPI {
return &AgentAPI{
config: config,
env: env,
nginxBinary: nginxBinary,
exporter: prometheus_metrics.NewExporter(&proto.MetricsReport{}),
processes: processes,
}
}

Expand Down Expand Up @@ -181,6 +186,11 @@ func (a *AgentAPI) Process(message *core.Message) {
default:
log.Errorf("Expected the type %T but got %T", &proto.AgentActivityStatus{}, response)
}
case core.NginxDetailProcUpdate:
a.processes = message.Data().([]*core.Process)
if a.nginxHandler != nil {
a.nginxHandler.syncProcessInfo(a.processes)
}
}
}

Expand All @@ -195,6 +205,7 @@ func (a *AgentAPI) Subscriptions() []string {
core.NginxConfigValidationPending,
core.NginxConfigApplyFailed,
core.NginxConfigApplySucceeded,
core.NginxDetailProcUpdate,
}
}

Expand All @@ -206,6 +217,7 @@ func (a *AgentAPI) createHttpServer() {
nginxBinary: a.nginxBinary,
responseChannel: make(chan *proto.Command_NginxConfigResponse),
configResponseStatuses: make(map[string]*proto.NginxConfigStatus),
processes: a.processes,
}

mux := http.NewServeMux()
Expand Down Expand Up @@ -462,7 +474,7 @@ func readFileFromRequest(r *http.Request) (*bytes.Buffer, error) {
func (h *NginxHandler) getNginxDetails() []*proto.NginxDetails {
var nginxDetails []*proto.NginxDetails

for _, proc := range h.env.Processes() {
for _, proc := range h.getNginxProccessInfo() {
if proc.IsMaster {
nginxDetails = append(nginxDetails, h.nginxBinary.GetNginxDetailsFromProcess(proc))
}
Expand Down Expand Up @@ -581,6 +593,18 @@ func (h *NginxHandler) getConfigStatus(w http.ResponseWriter, r *http.Request) e
return writeObjectToResponseBody(w, agentAPIConfigApplyStatusResponse)
}

func (h *NginxHandler) getNginxProccessInfo() []*core.Process {
h.processesMutex.RLock()
defer h.processesMutex.RUnlock()
return h.processes
}

func (h *NginxHandler) syncProcessInfo(processInfo []*core.Process) {
h.processesMutex.Lock()
defer h.processesMutex.Unlock()
h.processes = processInfo
}

func writeObjectToResponseBody(w http.ResponseWriter, response any) error {
respBody := new(bytes.Buffer)
err := json.NewEncoder(respBody).Encode(response)
Expand Down
18 changes: 9 additions & 9 deletions src/plugins/agent_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func TestAgentAPI_Subscriptions(t *testing.T) {
core.NginxConfigValidationPending,
core.NginxConfigApplyFailed,
core.NginxConfigApplySucceeded,
core.NginxDetailProcUpdate,
}

agentAPI := AgentAPI{}
Expand Down Expand Up @@ -122,9 +123,7 @@ func TestNginxHandler_sendInstanceDetailsPayload(t *testing.T) {
processes = append(processes, &core.Process{Pid: 1, Name: "12345", IsMaster: true})
}

env.On("Processes").Return(processes)

nginxHandler := NginxHandler{env: env, nginxBinary: mockNginxBinary}
nginxHandler := NginxHandler{env: env, nginxBinary: mockNginxBinary, processes: processes}
err := nginxHandler.sendInstanceDetailsPayload(respRec, req)
assert.NoError(t, err)

Expand Down Expand Up @@ -266,12 +265,12 @@ func TestNginxHandler_updateConfig(t *testing.T) {
ConfigureArgs: []string{},
}

var env *tutils.MockEnvironment
env := tutils.GetMockEnv()
var processes []*core.Process
if tt.nginxInstancesPresent {
env = tutils.GetMockEnvWithProcess()
processes = tutils.GetProcesses()
} else {
env = tutils.GetMockEnv()
env.On("Processes", mock.Anything).Return([]*core.Process{})
processes = []*core.Process{}
}
env.On("WriteFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)

Expand All @@ -287,6 +286,7 @@ func TestNginxHandler_updateConfig(t *testing.T) {
pipeline: pipeline,
nginxBinary: mockNginxBinary,
responseChannel: make(chan *proto.Command_NginxConfigResponse),
processes: processes,
}

if tt.response != nil {
Expand Down Expand Up @@ -412,7 +412,7 @@ func TestProcess_metricReport(t *testing.T) {
metricReport := &proto.MetricsReport{Meta: &proto.Metadata{MessageId: "123"}}
metricReportBundle := &metrics.MetricsReportBundle{Data: []*proto.MetricsReport{metricReport}}

agentAPI := NewAgentAPI(conf, mockEnvironment, mockNginxBinary)
agentAPI := NewAgentAPI(conf, mockEnvironment, mockNginxBinary, []*core.Process{})

// Check that latest metric report isn't set
assert.NotEqual(t, metricReport, agentAPI.exporter.GetLatestMetricReports()[0])
Expand Down Expand Up @@ -493,7 +493,7 @@ func TestMtls_forApi(t *testing.T) {
client.SetTransport(transport)
}

pluginUnderTest := NewAgentAPI(tt.conf, tutils.GetMockEnvWithProcess(), tutils.GetMockNginxBinary())
pluginUnderTest := NewAgentAPI(tt.conf, tutils.GetMockEnvWithProcess(), tutils.GetMockNginxBinary(), tutils.GetProcesses())
pluginUnderTest.Init(core.NewMockMessagePipe(ctx))

client.SetRetryCount(3).SetRetryWaitTime(50 * time.Millisecond).SetRetryMaxWaitTime(200 * time.Millisecond)
Expand Down
16 changes: 9 additions & 7 deletions src/plugins/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ func LoadPlugins(commander client.Commander, binary core.NginxBinary, env core.E
var corePlugins []core.Plugin
var extensionPlugins []core.ExtensionPlugin

processes := env.Processes()

if commander != nil {
corePlugins = append(corePlugins,
NewCommander(commander, loadedConfig),
Expand All @@ -40,38 +42,38 @@ func LoadPlugins(commander client.Commander, binary core.NginxBinary, env core.E

corePlugins = append(corePlugins,
NewConfigReader(loadedConfig),
NewNginx(commander, binary, env, loadedConfig),
NewNginx(commander, binary, env, loadedConfig, processes),
NewExtensions(loadedConfig, env),
NewFeatures(commander, loadedConfig, env, binary, loadedConfig.Version, agentEventsMeta),
NewFeatures(commander, loadedConfig, env, binary, loadedConfig.Version, processes, agentEventsMeta),
)

if loadedConfig.IsFeatureEnabled(agent_config.FeatureRegistration) {
corePlugins = append(corePlugins, NewOneTimeRegistration(loadedConfig, binary, env, sdkGRPC.NewMessageMeta(uuid.NewString())))
corePlugins = append(corePlugins, NewOneTimeRegistration(loadedConfig, binary, env, sdkGRPC.NewMessageMeta(uuid.NewString()), processes))
}

if loadedConfig.IsFeatureEnabled(agent_config.FeatureMetrics) || loadedConfig.IsFeatureEnabled(agent_config.FeatureMetricsCollection) ||
(len(loadedConfig.Nginx.NginxCountingSocket) > 0 && loadedConfig.IsFeatureEnabled(agent_config.FeatureNginxCounting)) {
corePlugins = append(corePlugins, NewMetrics(loadedConfig, env, binary))
corePlugins = append(corePlugins, NewMetrics(loadedConfig, env, binary, processes))
}

if loadedConfig.IsFeatureEnabled(agent_config.FeatureMetrics) || loadedConfig.IsFeatureEnabled(agent_config.FeatureMetricsThrottle) {
corePlugins = append(corePlugins, NewMetricsThrottle(loadedConfig, env))
}

if loadedConfig.IsFeatureEnabled(agent_config.FeatureDataPlaneStatus) {
corePlugins = append(corePlugins, NewDataPlaneStatus(loadedConfig, sdkGRPC.NewMessageMeta(uuid.NewString()), binary, env))
corePlugins = append(corePlugins, NewDataPlaneStatus(loadedConfig, sdkGRPC.NewMessageMeta(uuid.NewString()), binary, env, processes))
}

if loadedConfig.IsFeatureEnabled(agent_config.FeatureProcessWatcher) {
corePlugins = append(corePlugins, NewProcessWatcher(env, binary))
corePlugins = append(corePlugins, NewProcessWatcher(env, binary, processes))
}

if loadedConfig.IsFeatureEnabled(agent_config.FeatureActivityEvents) {
corePlugins = append(corePlugins, NewEvents(loadedConfig, env, sdkGRPC.NewMessageMeta(uuid.NewString()), binary, agentEventsMeta))
}

if loadedConfig.AgentAPI.Port != 0 && loadedConfig.IsFeatureEnabled(agent_config.FeatureAgentAPI) {
corePlugins = append(corePlugins, NewAgentAPI(loadedConfig, env, binary))
corePlugins = append(corePlugins, NewAgentAPI(loadedConfig, env, binary, processes))
} else {
log.Info("Agent API not configured")
}
Expand Down
12 changes: 8 additions & 4 deletions src/plugins/dataplane_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ type DataPlaneStatus struct {
softwareDetails map[string]*proto.DataplaneSoftwareDetails
nginxConfigActivityStatuses map[string]*proto.AgentActivityStatus
softwareDetailsMutex sync.RWMutex
processes []*core.Process
}

const (
defaultMinInterval = time.Second * 30
)

func NewDataPlaneStatus(config *config.Config, meta *proto.Metadata, binary core.NginxBinary, env core.Environment) *DataPlaneStatus {
func NewDataPlaneStatus(config *config.Config, meta *proto.Metadata, binary core.NginxBinary, env core.Environment, processes []*core.Process) *DataPlaneStatus {
log.Tracef("Dataplane status interval %s", config.Dataplane.Status.PollInterval)
pollInt := config.Dataplane.Status.PollInterval
if pollInt < defaultMinInterval {
Expand All @@ -69,6 +70,7 @@ func NewDataPlaneStatus(config *config.Config, meta *proto.Metadata, binary core
softwareDetailsMutex: sync.RWMutex{},
nginxConfigActivityStatuses: make(map[string]*proto.AgentActivityStatus),
softwareDetails: make(map[string]*proto.DataplaneSoftwareDetails),
processes: processes,
}
}

Expand Down Expand Up @@ -129,6 +131,8 @@ func (dps *DataPlaneStatus) Process(msg *core.Message) {
default:
log.Errorf("Expected the type %T but got %T", &proto.AgentActivityStatus{}, data)
}
case msg.Exact(core.NginxDetailProcUpdate):
dps.processes = msg.Data().([]*core.Process)
}
}

Expand All @@ -139,6 +143,7 @@ func (dps *DataPlaneStatus) Subscriptions() []string {
core.NginxConfigValidationPending,
core.NginxConfigApplyFailed,
core.NginxConfigApplySucceeded,
core.NginxDetailProcUpdate,
}
}

Expand Down Expand Up @@ -182,7 +187,6 @@ func (dps *DataPlaneStatus) healthGoRoutine(pipeline core.MessagePipeInterface)
}

func (dps *DataPlaneStatus) dataplaneStatus(forceDetails bool) *proto.DataplaneStatus {
processes := dps.env.Processes()
forceDetails = forceDetails || time.Now().UTC().Add(-dps.reportInterval).After(dps.lastSendDetails)

agentActivityStatuses := []*proto.AgentActivityStatus{}
Expand All @@ -200,8 +204,8 @@ func (dps *DataPlaneStatus) dataplaneStatus(forceDetails bool) *proto.DataplaneS

dataplaneStatus := &proto.DataplaneStatus{
Host: dps.hostInfo(forceDetails),
Details: dps.detailsForProcess(processes, forceDetails),
Healths: dps.healthForProcess(processes),
Details: dps.detailsForProcess(dps.processes, forceDetails),
Healths: dps.healthForProcess(dps.processes),
DataplaneSoftwareDetails: dataplaneSoftwareDetails,
AgentActivityStatus: agentActivityStatuses,
}
Expand Down
Loading

0 comments on commit df8cf6e

Please sign in to comment.