Skip to content

Commit

Permalink
fix: Parsing NewRelic API Key (#428)
Browse files Browse the repository at this point in the history
<!--  Thanks for sending a pull request!  Here are some tips for you:

1. Run unit tests and ensure that they are passing
2. If your change introduces any API changes, make sure to update the
e2e tests
3. Make sure documentation is updated for your PR!

-->

**What this PR does / why we need it**:
<!-- Explain here the context and why you're making the change. What is
the problem you're trying to solve. --->

Inference Logger failed to get the correct NewRelic API Key value. For
example, if we have this url:
`https://log-api.newrelic.com/log/v1?Api-Key=LICENSEKEY`, the API Key
supplied when sinking the log is actually `Api-Key=LICENSEKEY`, instead
of just `LICENSEKEY`.

**Which issue(s) this PR fixes**:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->

Fixes getting NewRelic API Key from the logUrl.

**Does this PR introduce a user-facing change?**:
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required. Enter your extended release note in
the block below.
If the PR requires additional action from users switching to the new
release, include the string "action required".

For more information about release notes, see kubernetes' guide here:
http://git.k8s.io/community/contributors/guide/release-notes.md
-->

```release-note
NONE
```

**Checklist**

- [x] Added unit test, integration, and/or e2e tests
- [x] Tested locally
- [ ] Updated documentation
- [ ] Update Swagger spec if the PR introduce API changes
- [ ] Regenerated Golang and Python client if the PR introduce API
changes
  • Loading branch information
ariefrahmansyah authored Jul 13, 2023
1 parent c81e871 commit 76bd6c4
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 12 deletions.
32 changes: 21 additions & 11 deletions api/cmd/inference-logger/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,18 +279,26 @@ func getTopicName(serviceName string) string {
return fmt.Sprintf("merlin-%s-inference-log", serviceName)
}

func getNewRelicAPIKey(newRelicUrl string) (string, error) {
apiKey := ""
url, err := url.Parse(newRelicUrl)
if err != nil {
return "", fmt.Errorf("invalid NewRelic URL (%s): %w", newRelicUrl, err)
}

apiKey = url.Query().Get("Api-Key")
if apiKey == "" {
return "", fmt.Errorf("Api-Key query param not found")
}

return apiKey, nil
}

func getLogSink(
logUrl string,
log *zap.SugaredLogger,
) (merlinlogger.LogSink, error) {
var sinkKind merlinlogger.LoggerSinkKind
host := logUrl
for _, loggerSinkKind := range merlinlogger.LoggerSinkKinds {
if strings.HasPrefix(logUrl, loggerSinkKind) {
sinkKind = loggerSinkKind
host = strings.TrimPrefix(logUrl, loggerSinkKind+":")
}
}
sinkKind, url := merlinlogger.ParseSinkKindAndUrl(logUrl)

// Map inputs to respective variables for logging
projectName := *namespace
Expand All @@ -300,8 +308,10 @@ func getLogSink(

switch sinkKind {
case merlinlogger.NewRelic:
apiKeySplits := strings.Split(logUrl, "?")
apiKey := apiKeySplits[len(apiKeySplits)-1]
apiKey, err := getNewRelicAPIKey(url)
if err != nil {
return nil, fmt.Errorf("invalid NewRelic Api-Key: %w", err)
}

// https://github.com/newrelic/newrelic-client-go/blob/main/pkg/logs/logs.go
// Initialize the client configuration
Expand All @@ -321,7 +331,7 @@ func getLogSink(
// Create Kafka Producer
kafkaProducer, err := kafka.NewProducer(
&kafka.ConfigMap{
"bootstrap.servers": host,
"bootstrap.servers": url,
"message.max.bytes": merlinlogger.MaxMessageBytes,
"compression.type": merlinlogger.CompressionType,
},
Expand Down
41 changes: 41 additions & 0 deletions api/cmd/inference-logger/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,44 @@ func TestGetModelVersion(t *testing.T) {
func TestGetTopicName(t *testing.T) {
assert.Equal(t, "merlin-my-project-my-model-inference-log", getTopicName(getServiceName("my-project", "my-model")))
}

func Test_getNewRelicAPIKey(t *testing.T) {
type args struct {
newRelicUrl string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "valid",
args: args{
newRelicUrl: "https://log-api.newrelic.com/log/v1?Api-Key=LICENSEKEY",
},
want: "LICENSEKEY",
wantErr: false,
},
{
name: "not found",
args: args{
newRelicUrl: "https://log-api.newrelic.com/log/v1?foo=bar",
},
want: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := getNewRelicAPIKey(tt.args.newRelicUrl)
if (err != nil) != tt.wantErr {
t.Errorf("getNewRelicAPIKey() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("getNewRelicAPIKey() = %v, want %v", got, tt.want)
}
})
}
}
20 changes: 19 additions & 1 deletion api/pkg/inference-logger/logger/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package logger

import "github.com/golang/protobuf/ptypes/timestamp"
import (
"strings"

"github.com/golang/protobuf/ptypes/timestamp"
)

type LogEntry struct {
RequestId string
Expand Down Expand Up @@ -37,3 +41,17 @@ const (
)

var LoggerSinkKinds = []LoggerSinkKind{Kafka, NewRelic, Console}

func ParseSinkKindAndUrl(logUrl string) (LoggerSinkKind, string) {
sinkKind := Console
url := logUrl

for _, loggerSinkKind := range LoggerSinkKinds {
if strings.HasPrefix(logUrl, loggerSinkKind) {
sinkKind = loggerSinkKind
url = strings.TrimPrefix(logUrl, loggerSinkKind+":")
}
}

return sinkKind, url
}
62 changes: 62 additions & 0 deletions api/pkg/inference-logger/logger/types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package logger

import (
"reflect"
"testing"
)

func TestParseSinkKindAndUrl(t *testing.T) {
type args struct {
logUrl string
}
tests := []struct {
name string
args args
want LoggerSinkKind
want1 string
}{
{
"kafka",
args{
logUrl: "kafka:localhost:9092",
},
Kafka,
"localhost:9092",
},
{
"newrelic",
args{
logUrl: "newrelic:https://log-api.newrelic.com/log/v1?Api-Key=LICENSEKEY",
},
NewRelic,
"https://log-api.newrelic.com/log/v1?Api-Key=LICENSEKEY",
},
{
"console",
args{
logUrl: "console:localhost:8080",
},
Console,
"localhost:8080",
},
{
"invalid, fallback to console",
args{
logUrl: "invalid:localhost:8080",
},
Console,
"invalid:localhost:8080",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1 := ParseSinkKindAndUrl(tt.args.logUrl)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("ParseSinkKindAndUrl() got = %v, want %v", got, tt.want)
}
if got1 != tt.want1 {
t.Errorf("ParseSinkKindAndUrl() got1 = %v, want %v", got1, tt.want1)
}
})
}
}

0 comments on commit 76bd6c4

Please sign in to comment.