Skip to content

Commit

Permalink
Merge pull request #644 from newrelic/dev
Browse files Browse the repository at this point in the history
Release 10.8
  • Loading branch information
ZNeumann authored Mar 20, 2023
2 parents 1cc9448 + 0b73ba6 commit 839e2c3
Show file tree
Hide file tree
Showing 14 changed files with 148 additions and 37 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
10.7.0
10.8.0
7 changes: 6 additions & 1 deletion agent/newrelic-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -335,8 +335,13 @@ if [ -z "${ispkg}" ]; then
check_file "${ilibdir}/scripts/newrelic-daemon.logrotate"
fi
check_file "${ilibdir}/scripts/newrelic.ini.template"
# Check that exxtension artifacts exist for all supported PHP versions
# MAKE SURE TO UPDATE THIS LIST WHENEVER SUPPORT IS ADDED OR REMOVED
# FOR A PHP VERSION
# Currently supported versions:
# (5.5, 5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2)
for pmv in "20121212" "20131226" "20151012" "20160303" "20170718" \
"20180731" "20190902" "20200930" "20210902"; do
"20180731" "20190902" "20200930" "20210902" "20220829"; do
check_file "${ilibdir}/agent/${arch}/newrelic-${pmv}.so"
# remove following line when ZTS removed from releases
check_file "${ilibdir}/agent/${arch}/newrelic-${pmv}-zts.so"
Expand Down
4 changes: 2 additions & 2 deletions agent/php_internal_instrument.c
Original file line number Diff line number Diff line change
Expand Up @@ -2714,11 +2714,11 @@ NR_INNER_WRAPPER(curl_multi_exec) {

#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO /* PHP 8.0+ */
rv = zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "ol", &curlres,
ZEND_NUM_ARGS() TSRMLS_CC, "oz", &curlres,
&still_running);
#else
rv = zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "rl", &curlres,
ZEND_NUM_ARGS() TSRMLS_CC, "rz", &curlres,
&still_running);
#endif /* PHP 8.0+ */

Expand Down
2 changes: 1 addition & 1 deletion agent/scripts/newrelic.ini.template
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ newrelic.daemon.logfile = "/var/log/newrelic/newrelic-daemon.log"
; rarely need to change this from the default, and usually only under
; the guidance of technical support.
; Must be one of the following values:
; always, error, warning, info, debug
; always, error, warning, info, healthcheck, debug
;
; The values verbose and verbosedebug are deprecated aliases for debug.
;
Expand Down
3 changes: 2 additions & 1 deletion axiom/nr_version.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@
* goldenrod 12Dec2022 (10.4)
* hydrangea 18Jan2023 (10.5)
* impatiens 13Feb2023 (10.6)
* jasmine 08Mar2023 (10.7)
*/
#define NR_CODENAME "jasmine"
#define NR_CODENAME "kalmia"

const char* nr_version(void) {
return NR_STR2(NR_VERSION);
Expand Down
23 changes: 21 additions & 2 deletions make/release.mk
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,23 @@ else
endif


release: Makefile release-daemon release-installer release-agent release-docs release-scripts | releases/$(RELEASE_OS)/
.PHONY: release
release: Makefile release-version release-daemon release-installer release-agent release-docs release-scripts | releases/$(RELEASE_OS)/

release-version: releases/$(RELEASE_OS)/
printf '%s\n' "$(AGENT_VERSION)" > releases/$(RELEASE_OS)/VERSION
printf '%s\n' "$(GIT_COMMIT)" > releases/$(RELEASE_OS)/COMMIT

release-daemon: Makefile daemon | releases/$(RELEASE_OS)/daemon/
cp bin/daemon releases/$(RELEASE_OS)/daemon/newrelic-daemon.$(RELEASE_ARCH)

release-installer: Makefile bin/newrelic-install bin/newrelic-iutil | releases/$(RELEASE_OS)/ releases/$(RELEASE_OS)/scripts/
.PHONY: release-installer
release-installer: Makefile release-installer-script release-installer-iutil

release-installer-script: bin/newrelic-install | releases/$(RELEASE_OS)/
cp bin/newrelic-install releases/$(RELEASE_OS)

release-installer-iutil: bin/newrelic-iutil | releases/$(RELEASE_OS)/scripts/
cp bin/newrelic-iutil releases/$(RELEASE_OS)/scripts/newrelic-iutil.$(RELEASE_ARCH)

release-docs: Makefile | releases/$(RELEASE_OS)/
Expand Down Expand Up @@ -112,6 +120,17 @@ release-agent: Makefile | releases/$(RELEASE_OS)/agent/$(RELEASE_ARCH)/
#
define RELEASE_AGENT_TARGET

#
# Target for building the agent for a given PHP version. Works well
# when building agent using containers. This is useful not only in
# GitHub Actions workflows, but also in a day to day development,
# because it allows to preserve agent between PHP version switches.
#
agent-for-php-$1: PHP_CONFIG := /usr/local/bin/php-config
agent-for-php-$1: Makefile agent | releases/$$(RELEASE_OS)/agent/$$(RELEASE_ARCH)/
@cp agent/modules/newrelic.so "releases/$$(RELEASE_OS)/agent/$$(RELEASE_ARCH)/newrelic-$2.so"
@test -e agent/newrelic.map && cp agent/newrelic.map "releases/$$(RELEASE_OS)/agent/$$(RELEASE_ARCH)/newrelic-$2.map" || true

#
# Target for non-zts GHA releases.
#
Expand Down
2 changes: 1 addition & 1 deletion src/daemon/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func TestParseConfigFile(t *testing.T) {

cfgExpected := &Config{
ConfigFile: "../newrelic/sample_config/config1.cfg",
LogLevel: 4,
LogLevel: 5,
LogFile: "/var/log/newrelic/newrelic-daemon.log",
}

Expand Down
4 changes: 2 additions & 2 deletions src/integration_runner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -650,8 +650,8 @@ func deleteSockfile(network, address string) {
if network == "unix" && !(address[0] == '@') {
err := os.Remove(address)
if err != nil && !os.IsNotExist(err) {
fmt.Fprintln(os.Stderr, "unable to remove stale sock file: %v"+
" - another daemon may already be running?", err)
fmt.Fprintf(os.Stderr, "unable to remove stale sock file: %v"+
" - another daemon may already be running?\n", err)
}
}
}
Expand Down
14 changes: 10 additions & 4 deletions src/newrelic/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
LogError
LogWarning
LogInfo
LogHealthCheck
LogDebug
)

Expand All @@ -46,10 +47,11 @@ func Init(level Level, location string) error {
return nil
}

func Errorf(format string, a ...interface{}) { logf(LogError, format, a...) }
func Warnf(format string, a ...interface{}) { logf(LogWarning, format, a...) }
func Infof(format string, a ...interface{}) { logf(LogInfo, format, a...) }
func Debugf(format string, a ...interface{}) { logf(LogDebug, format, a...) }
func Errorf(format string, a ...interface{}) { logf(LogError, format, a...) }
func Warnf(format string, a ...interface{}) { logf(LogWarning, format, a...) }
func Healthf(format string, a ...interface{}) { logf(LogHealthCheck, format, a...) }
func Infof(format string, a ...interface{}) { logf(LogInfo, format, a...) }
func Debugf(format string, a ...interface{}) { logf(LogDebug, format, a...) }

func logf(level Level, format string, a ...interface{}) {
maxLevel := atomic.LoadInt32((*int32)(&daemonLevel))
Expand Down Expand Up @@ -114,6 +116,8 @@ func (level Level) String() string {
return "Error"
case LogWarning:
return "Warning"
case LogHealthCheck:
return "HealthCheck"
case LogInfo:
return "Info"
case LogDebug:
Expand Down Expand Up @@ -198,6 +202,8 @@ func parseLevel(s string) (Level, error) {
return LogError, nil
case "warning":
return LogWarning, nil
case "healthcheck":
return LogHealthCheck, nil
case "info", "":
return LogInfo, nil
// verbose and verbosedebug kept for historical compatibility
Expand Down
1 change: 1 addition & 0 deletions src/newrelic/log/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func TestParseLevel(t *testing.T) {
{LogDebug, "debug"},
{LogDebug, "verbose"},
{LogDebug, "verbosedebug"},
{LogHealthCheck, "healthcheck"},
}

for i := range tests {
Expand Down
18 changes: 13 additions & 5 deletions src/newrelic/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,17 +368,22 @@ func (p *Processor) processAppInfo(m AppInfoMessage) {
}

numapps := len(p.apps)
if numapps > limits.AppLimit {
if numapps >= limits.AppLimit {
log.Errorf("unable to add app '%s', limit of %d applications reached",
m.Info, limits.AppLimit)
return
} else if numapps == limits.AppLimitNotifyHigh {
log.Infof("approaching app limit of %d, current number of apps is %d",
limits.AppLimit, limits.AppLimitNotifyHigh)
}

app = NewApp(m.Info)
p.apps[key] = app
numapps = len(p.apps)
log.Healthf("current number of apps is %d of a max of %d",
numapps, limits.AppLimit)
if numapps == limits.AppLimitNotifyHigh {
log.Infof("approaching app limit of %d, current number of apps is %d",
limits.AppLimit, limits.AppLimitNotifyHigh)
}

}

func processConnectMessages(reply collector.RPMResponse) {
Expand Down Expand Up @@ -818,10 +823,13 @@ func (p *Processor) doHarvest(ph ProcessorHarvest) {
if p.cfg.AppTimeout > 0 && app.Inactive(p.cfg.AppTimeout) {
log.Infof("removing %q with run id %q for lack of activity within %v",
app, id, p.cfg.AppTimeout)
if len(p.apps) == limits.AppLimitNotifyLow {
numapps := len(p.apps)
if numapps == limits.AppLimitNotifyLow {
log.Infof("current number of apps is %d",
limits.AppLimitNotifyLow)
}
log.Healthf("current number of apps is %d of a max of %d",
numapps, limits.AppLimit)
p.shutdownAppHarvest(id)
delete(p.apps, app.Key())

Expand Down
40 changes: 24 additions & 16 deletions src/newrelic/processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,9 @@ func TestProcessorHarvestDefaultData(t *testing.T) {
t.Fatal(string(append(cp.data, cp2.data...)))
}
}
time := strings.Split(string(cp3.data), ",")[1]
usageMetrics := `["one",` + time + `,` + time + `,` +
time1 := strings.Split(string(cp3.data), ",")[1]
time2 := strings.Split(string(cp3.data), ",")[2]
usageMetrics := `["one",` + time1 + `,` + time2 + `,` +
`[[{"name":"Supportability/C/Collector/Output/Bytes"},[2,1333,0,0,0,0]],` +
`[{"name":"Supportability/C/Collector/metric_data/Output/Bytes"},[1,1253,0,0,0,0]],` +
`[{"name":"Supportability/C/Collector/transaction_sample_data/Output/Bytes"},[1,80,0,0,0,0]]]]`
Expand Down Expand Up @@ -358,8 +359,9 @@ func TestProcessorHarvestCleanExit(t *testing.T) {
t.Fatalf("expected: %s \ngot: %s", expected, string(cp.data))
}

time := strings.Split(string(cp2.data), ",")[1]
usageMetrics := `["one",` + time + `,` + time + `,` +
time1 := strings.Split(string(cp2.data), ",")[1]
time2 := strings.Split(string(cp2.data), ",")[2]
usageMetrics := `["one",` + time1 + `,` + time2 + `,` +
`[[{"name":"Supportability/C/Collector/Output/Bytes"},[2,1313,0,0,0,0]],` +
`[{"name":"Supportability/C/Collector/custom_event_data/Output/Bytes"},[1,60,0,0,0,0]],` +
`[{"name":"Supportability/C/Collector/metric_data/Output/Bytes"},[1,1253,0,0,0,0]]]]`
Expand Down Expand Up @@ -394,8 +396,9 @@ func TestUsageHarvest(t *testing.T) {

// Because MockedProcessor wraps a real processor, we have no way to directly set the time
// of harvests. So we extract the time from what we receive
time := strings.Split(string(cp1.data), ",")[1]
var expectedJSON1 = `["one",` + time + `,` + time + `,` +
time1 := strings.Split(string(cp1.data), ",")[1]
time2 := strings.Split(string(cp1.data), ",")[2]
var expectedJSON1 = `["one",` + time1 + `,` + time2 + `,` +
`[[{"name":"Instance/Reporting"},[1,0,0,0,0,0]],` +
`[{"name":"Supportability/AnalyticsEvents/TotalEventsSeen"},[0,0,0,0,0,0]],` +
`[{"name":"Supportability/AnalyticsEvents/TotalEventsSent"},[0,0,0,0,0,0]],` +
Expand All @@ -413,8 +416,9 @@ func TestUsageHarvest(t *testing.T) {
`[{"name":"Supportability/Logging/Forwarding/Sent"},[0,0,0,0,0,0]],` +
`[{"name":"Supportability/SpanEvent/TotalEventsSeen"},[0,0,0,0,0,0]],` +
`[{"name":"Supportability/SpanEvent/TotalEventsSent"},[0,0,0,0,0,0]]]]`
time = strings.Split(string(cp2.data), ",")[1]
var expectedJSON2 = `["one",` + time + `,` + time + `,` +
time1 = strings.Split(string(cp2.data), ",")[1]
time2 = strings.Split(string(cp2.data), ",")[2]
var expectedJSON2 = `["one",` + time1 + `,` + time2 + `,` +
`[[{"name":"Supportability/C/Collector/Output/Bytes"},[1,1253,0,0,0,0]],` +
`[{"name":"Supportability/C/Collector/metric_data/Output/Bytes"},[1,1253,0,0,0,0]]]]`

Expand Down Expand Up @@ -467,9 +471,10 @@ func TestUsageHarvestExceedChannel(t *testing.T) {

<-m.p.trackProgress // unblock processor after harvest

time := strings.Split(string(cp.data), ",")[1]
time1 := strings.Split(string(cp.data), ",")[1]
time2 := strings.Split(string(cp.data), ",")[2]
// The data usage channel only holds 25 points until dropping data
var expectedJSON = `["one",` + time + `,` + time + `,` +
var expectedJSON = `["one",` + time1 + `,` + time2 + `,` +
`[[{"name":"Supportability/C/Collector/Output/Bytes"},[25,5275,0,0,0,0]],` +
`[{"name":"Supportability/C/Collector/analytic_event_data/Output/Bytes"},[25,5275,0,0,0,0]]]]`

Expand Down Expand Up @@ -527,8 +532,9 @@ func TestSupportabilityHarvest(t *testing.T) {

// Because MockedProcessor wraps a real processor, we have no way to directly set the time
// of harvests. So we extract the time from what we receive
time := strings.Split(string(cp1.data), ",")[1]
var expectedJSON = `["one",` + time + `,` + time + `,` +
time1 := strings.Split(string(cp1.data), ",")[1]
time2 := strings.Split(string(cp1.data), ",")[2]
var expectedJSON = `["one",` + time1 + `,` + time2 + `,` +
`[[{"name":"Instance/Reporting"},[2,0,0,0,0,0]],` +
`[{"name":"Supportability/Agent/Collector/HTTPError/408"},[1,0,0,0,0,0]],` + // Check for HTTPError Supportability metric
`[{"name":"Supportability/Agent/Collector/metric_data/Attempts"},[1,0,0,0,0,0]],` + // Metrics were sent first when the 408 error occurred, so check for the metric failure.
Expand All @@ -548,9 +554,10 @@ func TestSupportabilityHarvest(t *testing.T) {
`[{"name":"Supportability/Logging/Forwarding/Sent"},[0,0,0,0,0,0]],` +
`[{"name":"Supportability/SpanEvent/TotalEventsSeen"},[0,0,0,0,0,0]],` +
`[{"name":"Supportability/SpanEvent/TotalEventsSent"},[0,0,0,0,0,0]]]]`
time = strings.Split(string(cp2.data), ",")[1]
time1 = strings.Split(string(cp2.data), ",")[1]
time2 = strings.Split(string(cp2.data), ",")[2]
// includes usage of the first data usage metrics sent
var expectedJSON2 = `["one",` + time + `,` + time + `,` +
var expectedJSON2 = `["one",` + time1 + `,` + time2 + `,` +
`[[{"name":"Supportability/C/Collector/Output/Bytes"},[2,1584,0,0,0,0]],` +
`[{"name":"Supportability/C/Collector/metric_data/Output/Bytes"},[2,1584,0,0,0,0]]]]`

Expand Down Expand Up @@ -878,8 +885,9 @@ func TestProcessorHarvestSplitTxnEvents(t *testing.T) {
t.Fatal("Payload sum of 8001 events expected, got ", cp1Events, " and ", cp2Events)
}
// usage metrics comparison
time := strings.Split(string(cp3.data), ",")[1]
var expectedJSON = `["one",` + time + `,` + time + `,` +
time1 := strings.Split(string(cp3.data), ",")[1]
time2 := strings.Split(string(cp3.data), ",")[2]
var expectedJSON = `["one",` + time1 + `,` + time2 + `,` +
`[[{"name":"Supportability/C/Collector/Output/Bytes"},[6,289520,0,0,0,0]],` +
`[{"name":"Supportability/C/Collector/analytic_event_data/Output/Bytes"},[5,288261,0,0,0,0]],` +
`[{"name":"Supportability/C/Collector/metric_data/Output/Bytes"},[1,1259,0,0,0,0]]]]`
Expand Down
2 changes: 1 addition & 1 deletion src/stressor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ func reportDaemonStats(stats *MemStats, numMsg uint64, lifespan time.Duration) {
}

func main() {
flag.Usage = func() { fmt.Fprintln(os.Stderr, helpMessage) }
flag.Usage = func() { fmt.Fprint(os.Stderr, helpMessage, '\n') }
flag.Parse()

if *flagCPUProfile != "" {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php
/*
* Copyright 2020 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

/*DESCRIPTION
The agent should not throw a warning if the second arg to curl_multi_exec is NULL
*/

/*SKIPIF
<?php
if (!extension_loaded("curl")) {
die("skip: curl extension required");
}
*/

/*INI
*/

/*EXPECT_METRICS
[
"?? agent run id",
"?? start time",
"?? stop time",
[
[{"name": "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all"},[1,"??","??","??","??","??"]],
[{"name": "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allOther"},[1,"??","??","??","??","??"]],
[{"name": "External/all"},[1,"??","??","??","??","??"]],
[{"name": "External/allOther"},[1,"??","??","??","??","??"]],
[{"name": "External/127.0.0.1/all"},[1,"??","??","??","??","??"]],
[{"name": "OtherTransaction/all"},[1,"??","??","??","??","??"]],
[{"name": "OtherTransaction/php__FILE__"},[1,"??","??","??","??","??"]],
[{"name": "OtherTransactionTotalTime"},[1,"??","??","??","??","??"]],
[{"name": "OtherTransactionTotalTime/php__FILE__"},[1,"??","??","??","??","??"]],
[{"name": "Supportability/DistributedTrace/CreatePayload/Success"},[1,"??","??","??","??","??"]],
[{"name": "Supportability/Logging/Forwarding/PHP/enabled"},[1,"??","??","??","??","??"]],
[{"name": "Supportability/Logging/Metrics/PHP/enabled"},[1,"??","??","??","??","??"]],
[{"name": "Supportability/TraceContext/Create/Success"},[1,"??","??","??","??","??"]],
[{"name": "External/127.0.0.1/all","scope": "OtherTransaction/php__FILE__"},[1,"??","??","??","??","??"]]
]
]
*/

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

function req($url) {
$curl = curl_init($url);

curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);

return $curl;
}

$multi = curl_multi_init();
curl_multi_add_handle($multi, req('127.0.0.1'));

$active = null;
curl_multi_exec($multi, $active);

0 comments on commit 839e2c3

Please sign in to comment.