From 1aba0544d646f69daaaad03585833fcb9c87d19f Mon Sep 17 00:00:00 2001 From: Imran Shahid Date: Mon, 20 Dec 2021 14:12:20 +0400 Subject: [PATCH 1/5] Added intergation for ms sql server with newrelic Added intergation for ms sql server --- v3/go.mod | 1 + v3/integrations/nrmssql/README.md | 8 +++ v3/integrations/nrmssql/example/main.go | 42 +++++++++++++ v3/integrations/nrmssql/nrmssql.go | 83 +++++++++++++++++++++++++ v3/integrations/nrmssql/nrmssql_test.go | 67 ++++++++++++++++++++ 5 files changed, 201 insertions(+) create mode 100644 v3/integrations/nrmssql/README.md create mode 100644 v3/integrations/nrmssql/example/main.go create mode 100644 v3/integrations/nrmssql/nrmssql.go create mode 100644 v3/integrations/nrmssql/nrmssql_test.go diff --git a/v3/go.mod b/v3/go.mod index 2ada3801e..6c1741b32 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -3,6 +3,7 @@ module github.com/newrelic/go-agent/v3 go 1.7 require ( + github.com/denisenkom/go-mssqldb v0.11.0 github.com/golang/protobuf v1.3.3 google.golang.org/grpc v1.27.0 ) diff --git a/v3/integrations/nrmssql/README.md b/v3/integrations/nrmssql/README.md new file mode 100644 index 000000000..6b58c772d --- /dev/null +++ b/v3/integrations/nrmssql/README.md @@ -0,0 +1,8 @@ +# v3/integrations/nrmssql [![GoDoc](https://godoc.org/github.com/newrelic/go-agent/v3/integrations/nrmysql?status.svg)](https://godoc.org/github.com/newrelic/go-agent/v3/integrations/nrmysql) + +Package `nrmssql` instruments github.com/denisenkom/go-mssqldb. + +```go +import "github.com/newrelic/go-agent/v3/integrations/nrmssql" +``` + diff --git a/v3/integrations/nrmssql/example/main.go b/v3/integrations/nrmssql/example/main.go new file mode 100644 index 000000000..b0e7c1409 --- /dev/null +++ b/v3/integrations/nrmssql/example/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "context" + "database/sql" + "fmt" + "os" + "time" + + _ "github.com/newrelic/go-agent/v3/integrations/nrmssql" + "github.com/newrelic/go-agent/v3/newrelic" +) + +func main() { + // Set up a local ms sql docker + + db, err := sql.Open("nrmssql", "server=localhost;user id=sa;database=master;app name=MyAppName") + if nil != err { + panic(err) + } + + app, err := newrelic.NewApplication( + newrelic.ConfigAppName("MSSQL App"), + newrelic.ConfigLicense(os.Getenv("NEW_RELIC_LICENSE_KEY")), + newrelic.ConfigDebugLogger(os.Stdout), + ) + if nil != err { + panic(err) + } + app.WaitForConnection(5 * time.Second) + txn := app.StartTransaction("mssqlQuery") + + ctx := newrelic.NewContext(context.Background(), txn) + row := db.QueryRowContext(ctx, "SELECT count(*) from tables") + var count int + row.Scan(&count) + + txn.End() + app.Shutdown(5 * time.Second) + + fmt.Println("number of tables in information_schema", count) +} diff --git a/v3/integrations/nrmssql/nrmssql.go b/v3/integrations/nrmssql/nrmssql.go new file mode 100644 index 000000000..75c6e9e7f --- /dev/null +++ b/v3/integrations/nrmssql/nrmssql.go @@ -0,0 +1,83 @@ +// Copyright 2020 New Relic Corporation. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +// +build go1.10 + +// Package nrmssql instruments github.com/denisenkom/go-mssqldb. +// +// Use this package to instrument your MSSQL calls without having to manually +// create DatastoreSegments. This is done in a two step process: +// +// 1. Use this package's driver in place of the mssql driver. +// +// If your code is using sql.Open like this: +// +// import ( +// _ "github.com/denisenkom/go-mssqldb" +// ) +// +// func main() { +// db, err := sql.Open("mssql", "server=localhost;user id=sa;database=master;app name=MyAppName") +// } +// +// Then change the side-effect import to this package, and open "nrmssql" instead: +// +// import ( +// _ "github.com/newrelic/go-agent/v3/integrations/nrmssql" +// ) +// +// func main() { +// db, err := sql.Open("nrmssql", "server=localhost;user id=sa;database=master;app name=MyAppName") +// } +// +// 2. Provide a context containing a newrelic.Transaction to all exec and query +// methods on sql.DB, sql.Conn, sql.Tx, and sql.Stmt. This requires using the +// context methods ExecContext, QueryContext, and QueryRowContext in place of +// Exec, Query, and QueryRow respectively. For example, instead of the +// following: +// +// row := db.QueryRow("SELECT count(*) from tables") +// +// Do this: +// +// ctx := newrelic.NewContext(context.Background(), txn) +// row := db.QueryRowContext(ctx, "SELECT count(*) from tables") + +package nrmssql + +import ( + "database/sql" + "fmt" + "github.com/denisenkom/go-mssqldb/msdsn" + + "github.com/denisenkom/go-mssqldb" + "github.com/newrelic/go-agent/v3/internal" + "github.com/newrelic/go-agent/v3/newrelic" + "github.com/newrelic/go-agent/v3/newrelic/sqlparse" +) + +var ( + baseBuilder = newrelic.SQLDriverSegmentBuilder{ + BaseSegment: newrelic.DatastoreSegment{ + Product: newrelic.DatastoreMSSQL, + }, + ParseQuery: sqlparse.ParseQuery, + ParseDSN: parseDSN, + } +) + +func init() { + sql.Register("nrmssql", newrelic.InstrumentSQLDriver(&mssql.Driver{}, baseBuilder)) + internal.TrackUsage("integration", "driver", "mssql") +} + +func parseDSN(s *newrelic.DatastoreSegment, dsn string) { + cfg, _, err := msdsn.Parse(dsn) + if nil != err { + return + } + + s.DatabaseName = cfg.Database + s.Host = cfg.Host + s.PortPathOrID = fmt.Sprint(cfg.Port) +} diff --git a/v3/integrations/nrmssql/nrmssql_test.go b/v3/integrations/nrmssql/nrmssql_test.go new file mode 100644 index 000000000..e7ba90789 --- /dev/null +++ b/v3/integrations/nrmssql/nrmssql_test.go @@ -0,0 +1,67 @@ +package nrmssql + +import ( + "github.com/newrelic/go-agent/v3/newrelic" + "testing" +) + +func TestParseDSN(t *testing.T) { + testcases := []struct { + dsn string + expHost string + expPortPathOrID string + expDatabaseName string + }{ + // examples from https://github.com/denisenkom/go-mssqldb/blob/master/msdsn/conn_str_test.go + { + dsn: "server=server\\instance;database=testdb;user id=tester;password=pwd", + expHost: "server", + expPortPathOrID: "0", + expDatabaseName: "testdb", + }, + { + dsn: "server=(local)", + expHost: "localhost", + expPortPathOrID: "0", + expDatabaseName: "", + }, + { + dsn: "sqlserver://someuser@somehost?connection+timeout=30", + expHost: "somehost", + expPortPathOrID: "0", + expDatabaseName: "", + }, + { + dsn: "sqlserver://someuser:foo%3A%2F%5C%21~%40;bar@somehost:1434?connection+timeout=30", + expHost: "somehost", + expPortPathOrID: "1434", + expDatabaseName: "", + }, + { + dsn: "Server=mssql.test.local; Initial Catalog=test; User ID=xxxxxxx; Password=abccxxxxxx;", + expHost: "mssql.test.local", + expPortPathOrID: "0", + expDatabaseName: "test", + }, + { + dsn: "sport=invalid", + expHost: "localhost", + expPortPathOrID: "0", + expDatabaseName: "", + }, + } + + for _, test := range testcases { + s := &newrelic.DatastoreSegment{} + parseDSN(s, test.dsn) + if test.expHost != s.Host { + t.Errorf(`incorrect host, expected="%s", actual="%s"`, test.expHost, s.Host) + } + if test.expPortPathOrID != s.PortPathOrID { + t.Errorf(`incorrect port path or id, expected="%s", actual="%s"`, test.expPortPathOrID, s.PortPathOrID) + } + if test.expDatabaseName != s.DatabaseName { + t.Errorf(`incorrect database name, expected="%s", actual="%s"`, test.expDatabaseName, s.DatabaseName) + } + } +} From b19f097a0e44de3ce9693c72e1c2640c9109f5c7 Mon Sep 17 00:00:00 2001 From: Imran Shahid Date: Mon, 20 Dec 2021 15:15:32 +0400 Subject: [PATCH 2/5] formatting --- v3/integrations/nrmssql/nrmssql_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/v3/integrations/nrmssql/nrmssql_test.go b/v3/integrations/nrmssql/nrmssql_test.go index e7ba90789..5b871311c 100644 --- a/v3/integrations/nrmssql/nrmssql_test.go +++ b/v3/integrations/nrmssql/nrmssql_test.go @@ -32,19 +32,19 @@ func TestParseDSN(t *testing.T) { expDatabaseName: "", }, { - dsn: "sqlserver://someuser:foo%3A%2F%5C%21~%40;bar@somehost:1434?connection+timeout=30", + dsn: "sqlserver://someuser:foo%3A%2F%5C%21~%40;bar@somehost:1434?connection+timeout=30", expHost: "somehost", expPortPathOrID: "1434", expDatabaseName: "", }, { - dsn: "Server=mssql.test.local; Initial Catalog=test; User ID=xxxxxxx; Password=abccxxxxxx;", + dsn: "Server=mssql.test.local; Initial Catalog=test; User ID=xxxxxxx; Password=abccxxxxxx;", expHost: "mssql.test.local", expPortPathOrID: "0", expDatabaseName: "test", }, { - dsn: "sport=invalid", + dsn: "sport=invalid", expHost: "localhost", expPortPathOrID: "0", expDatabaseName: "", From e7f00b9afcea66605d40ba0a346eec99615b7fed Mon Sep 17 00:00:00 2001 From: Imran Shahid Date: Mon, 20 Dec 2021 15:40:07 +0400 Subject: [PATCH 3/5] updated ci workflow --- .github/workflows/ci.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4c559b834..9247371a1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -86,6 +86,8 @@ jobs: dirs: _integrations/nrb3 - go-version: 1.13.x dirs: _integrations/nrmongo + - go-version: 1.13.x + dirs: _integrations/nrmssql # v3 agent - go-version: 1.7.x @@ -208,6 +210,9 @@ jobs: - go-version: 1.15.x dirs: v3/integrations/nrgraphqlgo,v3/integrations/nrgraphqlgo/example extratesting: go get -u github.com/graphql-go/graphql@master + - go-version: 1.15.x + dirs: v3/integrations/nrmssql + extratesting: go get -u github.com/denisenkom/go-mssqldb@master steps: - name: Install Go From 571f05f7bf8805a78c905aa08028cfdb87721cec Mon Sep 17 00:00:00 2001 From: Imran Shahid Date: Mon, 6 Jun 2022 13:29:33 +0400 Subject: [PATCH 4/5] removed mssql dependency from go.mod --- v3/go.mod | 1 - v3/integrations/nrmssql/go.mod | 21 +++++++++++++++++++++ v3/integrations/nrmssql/nrmssql.go | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 v3/integrations/nrmssql/go.mod diff --git a/v3/go.mod b/v3/go.mod index 6c1741b32..2ada3801e 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -3,7 +3,6 @@ module github.com/newrelic/go-agent/v3 go 1.7 require ( - github.com/denisenkom/go-mssqldb v0.11.0 github.com/golang/protobuf v1.3.3 google.golang.org/grpc v1.27.0 ) diff --git a/v3/integrations/nrmssql/go.mod b/v3/integrations/nrmssql/go.mod new file mode 100644 index 000000000..1691dc2cf --- /dev/null +++ b/v3/integrations/nrmssql/go.mod @@ -0,0 +1,21 @@ +module github.com/newrelic/go-agent/v3/integrations/nrmssql + +go 1.17 + +require ( + github.com/denisenkom/go-mssqldb v0.12.2 + github.com/newrelic/go-agent/v3 v3.16.1 +) + +require ( + github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect + github.com/golang-sql/sqlexp v0.1.0 // indirect + github.com/golang/protobuf v1.4.3 // indirect + golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect + golang.org/x/net v0.0.0-20210610132358-84b48f89b13b // indirect + golang.org/x/sys v0.0.0-20210423082822-04245dca01da // indirect + golang.org/x/text v0.3.6 // indirect + google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect + google.golang.org/grpc v1.39.0 // indirect + google.golang.org/protobuf v1.25.0 // indirect +) diff --git a/v3/integrations/nrmssql/nrmssql.go b/v3/integrations/nrmssql/nrmssql.go index 75c6e9e7f..36825ebb5 100644 --- a/v3/integrations/nrmssql/nrmssql.go +++ b/v3/integrations/nrmssql/nrmssql.go @@ -49,9 +49,9 @@ import ( "database/sql" "fmt" "github.com/denisenkom/go-mssqldb/msdsn" + "github.com/newrelic/go-agent/v3/internal" "github.com/denisenkom/go-mssqldb" - "github.com/newrelic/go-agent/v3/internal" "github.com/newrelic/go-agent/v3/newrelic" "github.com/newrelic/go-agent/v3/newrelic/sqlparse" ) From 7eea2443b09549e881322bc36d5956189a9ed178 Mon Sep 17 00:00:00 2001 From: Imran Shahid Date: Tue, 7 Jun 2022 18:54:25 +0400 Subject: [PATCH 5/5] lint fix --- v3/integrations/nrmssql/nrmssql.go | 1 - 1 file changed, 1 deletion(-) diff --git a/v3/integrations/nrmssql/nrmssql.go b/v3/integrations/nrmssql/nrmssql.go index 36825ebb5..19be91698 100644 --- a/v3/integrations/nrmssql/nrmssql.go +++ b/v3/integrations/nrmssql/nrmssql.go @@ -42,7 +42,6 @@ // // ctx := newrelic.NewContext(context.Background(), txn) // row := db.QueryRowContext(ctx, "SELECT count(*) from tables") - package nrmssql import (