Skip to content

Commit

Permalink
Merge pull request newrelic#228 from newrelic/develop
Browse files Browse the repository at this point in the history
Release v3.9.0
  • Loading branch information
newrelic-eheinlein authored Sep 3, 2020
2 parents 34da20d + 523fc73 commit a213648
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 48 deletions.
66 changes: 34 additions & 32 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,107 +103,109 @@ jobs:
- go-version: 1.13.x
dirs: v3/newrelic,v3/internal,v3/examples
- go-version: 1.14.x
dirs: v3/newrelic,v3/internal,v3/examples
- go-version: 1.15.x
dirs: v3/newrelic,v3/internal,v3/examples,v3/integrations/logcontext

# v3 integrations
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/logcontext/nrlogrusplugin
extratesting: go get -u github.com/sirupsen/logrus@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrawssdk-v1
extratesting: go get -u github.com/aws/aws-sdk-go@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrawssdk-v2
extratesting: go get -u github.com/aws/aws-sdk-go-v2@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrecho-v3
# Test against the latest v3 Echo:
extratesting: go get -u github.com/labstack/echo@v3
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrecho-v4
extratesting: go get -u github.com/labstack/echo/v4@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrelasticsearch-v7
extratesting: go get -u github.com/elastic/go-elasticsearch/[email protected]
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrgin
extratesting: go get -u github.com/gin-gonic/gin@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrgorilla
extratesting: go get -u github.com/gorilla/mux@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrgraphgophers
extratesting: go get -u github.com/graph-gophers/graphql-go@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrlogrus
extratesting: go get -u github.com/sirupsen/logrus@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrlogxi
extratesting: go get -u github.com/mgutz/logxi@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrpkgerrors
extratesting: go get -u github.com/pkg/errors@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrlambda
extratesting: go get -u github.com/aws/aws-lambda-go@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrmysql
extratesting: go get -u github.com/go-sql-driver/mysql@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrpq
extratesting: go get -u github.com/lib/pq@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrpq/example/sqlx
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrredis-v7
extratesting: go get -u github.com/go-redis/redis/v7@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrsqlite3
extratesting: go get -u github.com/mattn/go-sqlite3@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrsnowflake
extratesting: go get -u github.com/snowflakedb/gosnowflake@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrgrpc
extratesting: go get -u google.golang.org/grpc@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrmicro
# As of Dec 2019, there is a race condition in when using go-micro@master
# in their logging system. Instead, we'll test against the latest
# released version.
# As of Jan 2019, it is impossible to go get the latest micro version.
# As of June 2020, confirmed errors still result
# extratesting: go get -u github.com/micro/go-micro@latest
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrnats
extratesting: go get -u github.com/nats-io/nats.go/@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrnats/test
extratesting: go get -u github.com/nats-io/nats.go/@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrstan
extratesting: go get -u github.com/nats-io/stan.go/@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrstan/test
extratesting: go get -u github.com/nats-io/stan.go/@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrstan/examples
extratesting: go get -u github.com/nats-io/stan.go/@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/logcontext
extratesting: go get -u github.com/sirupsen/logrus@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrzap
extratesting: go get -u go.uber.org/zap@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrhttprouter
extratesting: go get -u github.com/julienschmidt/httprouter@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrb3
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrmongo
extratesting: go get -u go.mongodb.org/mongo-driver@master
- go-version: 1.14.x
- go-version: 1.15.x
dirs: v3/integrations/nrgraphqlgo,v3/integrations/nrgraphqlgo/example
extratesting: go get -u github.com/graphql-go/graphql@master

Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# ChangeLog

## 3.9.0

### Changes
* When sending Serverless telemetry using the `nrlambda` integration, support an externally-managed named pipe.

## 3.8.1

### Bug Fixes
Expand Down
13 changes: 12 additions & 1 deletion build-script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
set -x
set -e

LATEST_VERSION="go1.14"
LATEST_VERSION="go1.15"

# NOTE: Once we get rid of travis for good, this whole section can be removed
# along with the .travis.yml file.
Expand Down Expand Up @@ -40,8 +40,19 @@ for dir in $DIRS; do
VERSION=$(go version)
V17="1.7"
V18="1.8"
V19="1.9"
if [[ "$VERSION" =~ .*"$V17".* || "$VERSION" =~ .*"$V18".* ]]; then
echo "Not installing GRPC for old versions"
elif [[ "$VERSION" =~ .*"$V19" ]]; then
# install v3 dependencies that support this go version
set +e
go get -u google.golang.org/grpc # this go get will fail to build
set -e
cd $GOPATH/src/google.golang.org/grpc
git checkout v1.31.0
cd -

go get -u github.com/golang/protobuf/protoc-gen-go
else
go get -u github.com/golang/protobuf/protoc-gen-go
go get -u google.golang.org/grpc
Expand Down
36 changes: 30 additions & 6 deletions v3/integrations/nrlambda/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
"github.com/aws/aws-lambda-go/lambdacontext"
"github.com/newrelic/go-agent/v3/internal"
"github.com/newrelic/go-agent/v3/internal/integrationsupport"
newrelic "github.com/newrelic/go-agent/v3/newrelic"
"github.com/newrelic/go-agent/v3/newrelic"
)

type response struct {
Expand Down Expand Up @@ -67,14 +67,37 @@ func responseEvent(ctx context.Context, event interface{}) {
}
}

type writerProvider interface {
borrowWriter(needsWriter func(writer io.Writer))
}

type defaultWriterProvider struct {
}

const telemetryNamedPipe = "/tmp/newrelic-telemetry"

func (wp *defaultWriterProvider) borrowWriter(needsWriter func(io.Writer)) {
// If the telemetry named pipe exists and is writable, use it instead of stdout
pipeFile, err := os.OpenFile(telemetryNamedPipe, os.O_WRONLY, 0)
if err != nil {
needsWriter(os.Stdout)
return
}
//We need to close the pipe; of course we don't close stdout
defer pipeFile.Close()
needsWriter(pipeFile)
}

func (h *wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, error) {
var arn, requestID string
if lctx, ok := lambdacontext.FromContext(ctx); ok {
arn = lctx.InvokedFunctionArn
requestID = lctx.AwsRequestID
}

defer internal.ServerlessWrite(h.app.Private, arn, h.writer)
defer h.hasWriter.borrowWriter(func(writer io.Writer) {
internal.ServerlessWrite(h.app.Private, arn, writer)
})

txn := h.app.StartTransaction(h.functionName)
defer txn.End()
Expand Down Expand Up @@ -110,9 +133,10 @@ type wrappedHandler struct {
// a time, we use a synchronization primitive to determine if this is
// the first transaction for defensiveness in case of future changes.
firstTransaction sync.Once
// writer is used to log the data JSON at the end of each transaction.
// This field exists (rather than hardcoded os.Stdout) for testing.
writer io.Writer
// hasWriter is used to log the data JSON at the end of each transaction.
// The writerProvider manages the lifecycle of the file handle being written
// to, similar to the Loan pattern. This field exists mostly for testing.
hasWriter writerProvider
}

// WrapHandler wraps the provided handler and returns a new handler with
Expand All @@ -127,7 +151,7 @@ func WrapHandler(handler lambda.Handler, app *newrelic.Application) lambda.Handl
original: handler,
app: app,
functionName: lambdacontext.FunctionName,
writer: os.Stdout,
hasWriter: &defaultWriterProvider{},
}
}

Expand Down
54 changes: 46 additions & 8 deletions v3/integrations/nrlambda/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"context"
"encoding/json"
"errors"
"io"
"net/http"
"os"
"strings"
"testing"

Expand Down Expand Up @@ -45,14 +47,23 @@ func distributedTracingEnabled(key string) string {
}
}

// bufWriterProvider is a testing implementation of writerProvider
type bufWriterProvider struct {
buf io.Writer
}

func (bw bufWriterProvider) borrowWriter(needsWriter func(writer io.Writer)) {
needsWriter(bw.buf)
}

func TestColdStart(t *testing.T) {
originalHandler := func(c context.Context) {}
app := testApp(nil, t)
wrapped := Wrap(originalHandler, app)
w := wrapped.(*wrappedHandler)
w.functionName = "functionName"
buf := &bytes.Buffer{}
w.writer = buf
w.hasWriter = bufWriterProvider{buf}

ctx := context.Background()
lctx := &lambdacontext.LambdaContext{
Expand Down Expand Up @@ -104,7 +115,7 @@ func TestColdStart(t *testing.T) {

// Invoke the handler again to test the cold-start attribute absence.
buf = &bytes.Buffer{}
w.writer = buf
w.hasWriter = bufWriterProvider{buf}
internal.HarvestTesting(app.Private, nil)
resp, err = wrapped.Invoke(ctx, nil)
if nil != err || string(resp) != "null" {
Expand Down Expand Up @@ -154,7 +165,7 @@ func TestErrorCapture(t *testing.T) {
w := wrapped.(*wrappedHandler)
w.functionName = "functionName"
buf := &bytes.Buffer{}
w.writer = buf
w.hasWriter = bufWriterProvider{buf}

resp, err := wrapped.Invoke(context.Background(), nil)
if err != returnError || string(resp) != "" {
Expand Down Expand Up @@ -229,7 +240,7 @@ func TestSetWebRequest(t *testing.T) {
w := wrapped.(*wrappedHandler)
w.functionName = "functionName"
buf := &bytes.Buffer{}
w.writer = buf
w.hasWriter = bufWriterProvider{buf}

req := events.APIGatewayProxyRequest{
Headers: map[string]string{
Expand Down Expand Up @@ -301,7 +312,7 @@ func TestDistributedTracing(t *testing.T) {
w := wrapped.(*wrappedHandler)
w.functionName = "functionName"
buf := &bytes.Buffer{}
w.writer = buf
w.hasWriter = bufWriterProvider{buf}

dtHdr := http.Header{}
app.StartTransaction("hello").InsertDistributedTraceHeaders(dtHdr)
Expand Down Expand Up @@ -396,7 +407,7 @@ func TestEventARN(t *testing.T) {
w := wrapped.(*wrappedHandler)
w.functionName = "functionName"
buf := &bytes.Buffer{}
w.writer = buf
w.hasWriter = bufWriterProvider{buf}

req := events.DynamoDBEvent{
Records: []events.DynamoDBEventRecord{{
Expand Down Expand Up @@ -473,7 +484,7 @@ func TestAPIGatewayProxyResponse(t *testing.T) {
w := wrapped.(*wrappedHandler)
w.functionName = "functionName"
buf := &bytes.Buffer{}
w.writer = buf
w.hasWriter = bufWriterProvider{buf}

resp, err := wrapped.Invoke(context.Background(), nil)
if nil != err {
Expand Down Expand Up @@ -535,7 +546,7 @@ func TestCustomEvent(t *testing.T) {
w := wrapped.(*wrappedHandler)
w.functionName = "functionName"
buf := &bytes.Buffer{}
w.writer = buf
w.hasWriter = bufWriterProvider{buf}

resp, err := wrapped.Invoke(context.Background(), nil)
if nil != err || string(resp) != "null" {
Expand All @@ -555,3 +566,30 @@ func TestCustomEvent(t *testing.T) {
t.Error("no output written")
}
}

func TestDefaultWriterProvider(t *testing.T) {
dwp := defaultWriterProvider{}
dwp.borrowWriter(func(writer io.Writer) {
if writer != os.Stdout {
t.Error("Expected stdout")
}
})

const telemetryFile = "/tmp/newrelic-telemetry"
defer os.Remove(telemetryFile)
file, err := os.Create(telemetryFile)
if err != nil {
t.Error("Unexpected error creating telemetry file", err)
}

err = file.Close()
if err != nil {
t.Error("Error closing telemetry file", err)
}

dwp.borrowWriter(func(writer io.Writer) {
if writer == os.Stdout {
t.Error("Expected telemetry file, got stdout")
}
})
}
2 changes: 1 addition & 1 deletion v3/newrelic/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

const (
// Version is the full string version of this Go Agent.
Version = "3.8.1"
Version = "3.9.0"
)

var (
Expand Down

0 comments on commit a213648

Please sign in to comment.