Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parsing requestId from message and stamping it as attribute #12

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/cloudwatch/cloudwatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cloudwatch

import (
"os"
"regexp"
"strconv"

"github.com/aws/aws-lambda-go/events"
Expand Down Expand Up @@ -52,14 +53,25 @@ func batchLogEntries(cloudwatchLogsData events.CloudwatchLogsData, channel chan

var currentBatch common.LogData

// Regular expression to match the pattern "RequestId: <UUID> <message>"
regularExpression := regexp.MustCompile(common.RequestIDRegex)

// Variable to keep track of the last requestId found
var lastRequestID string

for _, record := range cloudwatchLogsData.LogEvents {
messages := util.SplitLargeMessages(record.Message)

for _, message := range messages {

// logAttribute is a map of attributes for each individual log message.
logAttribute := common.LogAttributes{}

entry := common.Log{
Timestamp: strconv.FormatInt(record.Timestamp, 10),
Log: message,
Timestamp: strconv.FormatInt(record.Timestamp, 10),
Log: message,
Attributes: logAttribute,
}
lastRequestID = util.AddRequestID(cloudwatchLogsData.LogGroup, message, logAttribute, lastRequestID, regularExpression)

if batchSize+len(message) > common.MaxPayloadSize || messageCount >= common.MaxPayloadMessages {
util.ProduceMessageToChannel(channel, currentBatch, attributes)
Expand Down
6 changes: 6 additions & 0 deletions src/common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,9 @@ const CloudTrailDigestRegex = ".*_CloudTrail-Digest_.*\\.json\\.gz$"

// CloudTrailRegex is the regex pattern for CloudTrail files.
const CloudTrailRegex = ".*_CloudTrail_.*\\.json\\.gz$"

// RequestIDRegex is the regex pattern for RequestId.
const RequestIDRegex = "RequestId:\\s([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})"

// LambdaLogGroup is prefix for identifing log group belonging to lambda
const LambdaLogGroup = "/aws/lambda"
21 changes: 20 additions & 1 deletion src/util/message_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package util

import (
"encoding/json"
"github.com/newrelic/aws-unified-lambda-logging/common"
"regexp"
"strings"
"time"

"github.com/newrelic/aws-unified-lambda-logging/common"
)

// SplitLargeMessages splits a large message into smaller messages if its length exceeds the maximum message size.
Expand Down Expand Up @@ -93,3 +96,19 @@ func ParseCloudTrailEvents(message string) ([]string, error) {
}
return records, nil
}

// AddRequestID extracts the requestId from the message and updates the attributes map.
// It returns the last requestId found to keep track of the requestId across log messages.
func AddRequestID(logGroup, message string, logAttribute common.LogAttributes, lastRequestID string, regularExpression *regexp.Regexp) string {

if strings.HasPrefix(logGroup, common.LambdaLogGroup) {
matches := regularExpression.FindStringSubmatch(message)
if len(matches) == 2 {
lastRequestID = matches[1]
logAttribute["requestId"] = lastRequestID
} else if lastRequestID != "" {
logAttribute["requestId"] = lastRequestID
}
}
return lastRequestID
}
71 changes: 69 additions & 2 deletions src/util/message_util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package util

import (
"encoding/json"
"github.com/newrelic/aws-unified-lambda-logging/common"
"github.com/stretchr/testify/assert"
"reflect"
"regexp"
"testing"

"github.com/newrelic/aws-unified-lambda-logging/common"
"github.com/stretchr/testify/assert"
)

// TestAddCustomMetaData tests adding custom meta data utility function.
Expand Down Expand Up @@ -209,3 +211,68 @@ func TestParseCTEvents(t *testing.T) {
})
}
}

// TestAddRequestId tests the AddRequestId function.
func TestAddRequestId(t *testing.T) {
tests := []struct {
name string
logGroup string
message string
logAttribute common.LogAttributes
lastRequestID string
expectedReqID string
expectedAttrib common.LogAttributes
}{
{
name: "Valid RequestId",
logGroup: "/aws/lambda/test",
message: "RequestId: d653fb2c-0234-46ff-ae6b-9a418b888420 hello world",
logAttribute: common.LogAttributes{},
lastRequestID: "",
expectedReqID: "d653fb2c-0234-46ff-ae6b-9a418b888420",
expectedAttrib: common.LogAttributes{
"requestId": "d653fb2c-0234-46ff-ae6b-9a418b888420",
},
},
{
name: "No RequestId in message",
logGroup: "/aws/lambda/test",
message: "hello world",
logAttribute: common.LogAttributes{},
lastRequestID: "d653fb2c-0234-46ff-ae6b-9a418b888420",
expectedReqID: "d653fb2c-0234-46ff-ae6b-9a418b888420",
expectedAttrib: common.LogAttributes{
"requestId": "d653fb2c-0234-46ff-ae6b-9a418b888420",
},
},
{
name: "No RequestId and no previous RequestId",
logGroup: "/aws/lambda/test",
message: "hello world",
logAttribute: common.LogAttributes{},
lastRequestID: "",
expectedReqID: "",
expectedAttrib: common.LogAttributes{},
},
{
name: "Non-matching log group",
logGroup: "/aws/other/test",
message: "RequestId: d653fb2c-0234-46ff-ae6b-9a418b888420 hello world",
logAttribute: common.LogAttributes{},
lastRequestID: "",
expectedReqID: "",
expectedAttrib: common.LogAttributes{},
},
}

// Regular expression to match the pattern "RequestId: <UUID>"
re := regexp.MustCompile(`RequestId:\s([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})`)

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotReqID := AddRequestID(tt.logGroup, tt.message, tt.logAttribute, tt.lastRequestID, re)
assert.Equal(t, tt.expectedReqID, gotReqID)
assert.Equal(t, tt.expectedAttrib, tt.logAttribute)
})
}
}
Loading