Skip to content

Commit 6ee8808

Browse files
committed
feat: Add fields to Datastore segment
1 parent 79b91c1 commit 6ee8808

File tree

1 file changed

+63
-9
lines changed

1 file changed

+63
-9
lines changed

v3/integrations/nroci/nroci_nosql.go

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ package nroci
55
import (
66
"context"
77
"fmt"
8+
"net/url"
9+
"strings"
810
"time"
911

1012
"github.com/newrelic/go-agent/v3/newrelic"
@@ -58,6 +60,7 @@ type ConfigWrapper struct {
5860

5961
type ClientWrapper struct {
6062
Client OCIClient
63+
Config *nosqldb.Config
6164
}
6265

6366
type ClientResponseWrapper[T any] struct {
@@ -78,14 +81,59 @@ func NRCreateClient(cfg *ConfigWrapper) (*ClientWrapper, error) {
7881
}
7982
return &ClientWrapper{
8083
Client: client,
84+
Config: cfg.Config,
8185
}, nil
8286
}
8387

88+
// extractOperation extracts the operation type from a statement
89+
// if the the statement is empty, or no word is found, then return "UNKNOWN"
90+
func extractOperation(statement string) string {
91+
if statement == "" {
92+
return "UNKNOWN"
93+
}
94+
95+
words := strings.Fields(strings.ToUpper(statement))
96+
if len(words) == 0 {
97+
return "UNKNOWN"
98+
}
99+
100+
return words[0]
101+
}
102+
103+
// extractHostPort extracts host and port from an endpoint URL
104+
func extractHostPort(endpoint string) (host, port string) {
105+
if endpoint == "" {
106+
return "", ""
107+
}
108+
109+
// Parse the endpoint URL
110+
parsedURL, err := url.Parse(endpoint)
111+
if err != nil {
112+
return "", ""
113+
}
114+
115+
host = parsedURL.Hostname()
116+
port = parsedURL.Port()
117+
118+
// Set default ports if not specified
119+
if port == "" {
120+
switch parsedURL.Scheme {
121+
case "https":
122+
port = "443"
123+
case "http":
124+
port = "80"
125+
}
126+
}
127+
128+
return host, port
129+
}
130+
84131
// executeWithDatastoreSegment is a generic helper function that executes a query with a given function from the
85132
// OCI Client. It takes a type parameter T as any because of the different response types that are used within the
86133
// OCI Client. This function will take the transaction from the context (if it exists) and create a Datastore Segment.
87134
// It will then call whatever client function has been passed in.
88135
func executeWithDatastoreSegment[T any](
136+
cw *ClientWrapper,
89137
ctx context.Context,
90138
req *nosqldb.TableRequest,
91139
fn func() (T, error),
@@ -96,12 +144,18 @@ func executeWithDatastoreSegment[T any](
96144
return nil, fmt.Errorf("error executing DoTableRequest, no transaction")
97145
}
98146

147+
// Extract host and port from config endpoint
148+
host, port := extractHostPort(cw.Config.Endpoint)
149+
99150
sgmt := newrelic.DatastoreSegment{
100-
StartTime: txn.StartSegmentNow(),
101-
Product: newrelic.DatastoreOracle,
102-
Collection: req.TableName,
103-
Operation: req.Namespace,
104-
DatabaseName: req.Namespace,
151+
StartTime: txn.StartSegmentNow(),
152+
Product: newrelic.DatastoreOracle,
153+
Collection: req.TableName,
154+
Operation: extractOperation(req.Statement),
155+
DatabaseName: req.Namespace,
156+
ParameterizedQuery: req.Statement,
157+
Host: host,
158+
PortPathOrID: port,
105159
}
106160

107161
responseWrapper := ClientResponseWrapper[T]{}
@@ -110,24 +164,24 @@ func executeWithDatastoreSegment[T any](
110164
if err != nil {
111165
return &responseWrapper, fmt.Errorf("error making request: %s", err.Error())
112166
}
113-
// 4. End segment
167+
114168
sgmt.End()
115-
// 5. Return result
169+
116170
return &responseWrapper, nil
117171
}
118172

119173
// Wrapper for nosqldb.Client.DoTableRequest. Provide the ClientWrapper and Context as parameters in addition to the nosqldbTableRequest.
120174
// Returns a ClientResponseWrapper[*nosqldbTableResult] and error.
121175
func NRDoTableRequest(cw *ClientWrapper, ctx context.Context, req *nosqldb.TableRequest) (*ClientResponseWrapper[*nosqldb.TableResult], error) {
122-
return executeWithDatastoreSegment(ctx, req, func() (*nosqldb.TableResult, error) {
176+
return executeWithDatastoreSegment(cw, ctx, req, func() (*nosqldb.TableResult, error) {
123177
return cw.Client.DoTableRequest(req)
124178
})
125179
}
126180

127181
// Wrapper for nosqldb.Client.DoTableRequestWait. Provide the ClientWrapper and Context as parameters in addition to the nosqldbTableRequest,
128182
// timeout, and pollInterval. Returns a ClientResponseWrapper[*nosqldbTableResult] and error.
129183
func NRDoTableRequestAndWait(cw *ClientWrapper, ctx context.Context, req *nosqldb.TableRequest, timeout time.Duration, pollInterval time.Duration) (*ClientResponseWrapper[*nosqldb.TableResult], error) {
130-
return executeWithDatastoreSegment(ctx, req, func() (*nosqldb.TableResult, error) {
184+
return executeWithDatastoreSegment(cw, ctx, req, func() (*nosqldb.TableResult, error) {
131185
return cw.Client.DoTableRequestAndWait(req, timeout, pollInterval)
132186
})
133187
}

0 commit comments

Comments
 (0)