Skip to content

Commit

Permalink
[exporter/awsemfexporter] add tags feature for Cloudwatch Log Group (o…
Browse files Browse the repository at this point in the history
…pen-telemetry#19406)

* Add set tags to config

* Add config to cloudwatchlogsexporter too

* Add unit testing to aws emf

* Add unit testing for other code changes and update README

* Add chlog entry

* Fix issue number

* Change naming to accountID

* Add sts endpoint and fix validate func

* Fix import

* Add comments to client code

* Move functions to utils.go

* Remove line

* Change tags call

* Fix code after merge

* Fix spelling error

* gci the file

* gci the exporter files

* Add gci option prefix

* Add comment to cwlog_client

* Address comments on PR

* Improve testing

* Run gci command

* Fix license header

* Simplify return statement

* Run gci command on code
  • Loading branch information
humivo authored and varunraiko committed May 17, 2023
1 parent 8a1430e commit 639eb2d
Show file tree
Hide file tree
Showing 12 changed files with 421 additions and 115 deletions.
16 changes: 16 additions & 0 deletions .chloggen/add-tags-log-group.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: awsemfexporter

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Added a `tags` field to the config of the exporter to set tags for a Cloudwatch Log Group

# One or more tracking issues related to the change
issues: [19406]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:
2 changes: 2 additions & 0 deletions exporter/awscloudwatchlogsexporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ The following settings can be optionally configured:
- `region`: The AWS region where the log stream is in.
- `endpoint`: The CloudWatch Logs service endpoint which the requests are forwarded to. [See the CloudWatch Logs endpoints](https://docs.aws.amazon.com/general/latest/gr/cwl_region.html) for a list.
- `log_retention`: LogRetention is the option to set the log retention policy for only newly created CloudWatch Log Groups. Defaults to Never Expire if not specified or set to 0. Possible values for retention in days are 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 2192, 2557, 2922, 3288, or 3653.
- `tags`: Tags is the option to set tags for the CloudWatch Log Group. If specified, please add at most 50 tags. Input is a string to string map like so: { 'key': 'value' }. Keys must be between 1-128 characters and follow the regex pattern: `^([\p{L}\p{Z}\p{N}_.:/=+\-@]+)$`(alphanumerics, whitespace, and _.:/=+-!). Values must be between 1-256 characters and follow the regex pattern: `^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`(alphanumerics, whitespace, and _.:/=+-!). [Link to tagging restrictions](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html#:~:text=Required%3A%20Yes-,tags,-The%20key%2Dvalue)
- `role_arn`: The AWS IAM role to upload segments to a same/different account
- `raw_log`: Boolean default false. If you want to export only the log message to cw logs. This is required for emf logs.

Expand All @@ -49,6 +50,7 @@ exporters:
role_arn: "arn:aws:iam::123456789:role/monitoring-application-logs"
endpoint: "logs.us-east-1.amazonaws.com"
log_retention: 365
tags: { 'sampleKey': 'sampleValue'}
sending_queue:
queue_size: 50
retry_on_failure:
Expand Down
42 changes: 9 additions & 33 deletions exporter/awscloudwatchlogsexporter/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"go.uber.org/zap"

"github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/awsutil"
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/cwlogs"
)

// Config represent a configuration for the CloudWatch logs exporter.
Expand All @@ -46,6 +47,11 @@ type Config struct {
// Possible values are 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 2192, 2557, 2922, 3288, or 3653
LogRetention int64 `mapstructure:"log_retention"`

// Tags is the option to set tags for the CloudWatch Log Group. If specified, please add add at least 1 and at most 50 tags. Input is a string to string map like so: { 'key': 'value' }
// Keys must be between 1-128 characters and follow the regex pattern: ^([\p{L}\p{Z}\p{N}_.:/=+\-@]+)$
// Values must be between 1-256 characters and follow the regex pattern: ^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$
Tags map[string]*string `mapstructure:"tags"`

// QueueSettings is a subset of exporterhelper.QueueSettings,
// because only QueueSize is user-settable due to how AWS CloudWatch API works
QueueSettings QueueSettings `mapstructure:"sending_queue"`
Expand Down Expand Up @@ -77,41 +83,11 @@ func (config *Config) Validate() error {
if config.QueueSettings.QueueSize < 1 {
return errors.New("'sending_queue.queue_size' must be 1 or greater")
}
if !isValidRetentionValue(config.LogRetention) {
return errors.New("invalid value for retention policy. Please make sure to use the following values: 0 (Never Expire), 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 2192, 2557, 2922, 3288, or 3653")
if retErr := cwlogs.ValidateRetentionValue(config.LogRetention); retErr != nil {
return retErr
}
return nil
}
return cwlogs.ValidateTagsInput(config.Tags)

// Added function to check if value is an accepted number of log retention days
func isValidRetentionValue(input int64) bool {
switch input {
case
0,
1,
3,
5,
7,
14,
30,
60,
90,
120,
150,
180,
365,
400,
545,
731,
1827,
2192,
2557,
2922,
3288,
3653:
return true
}
return false
}

func (config *Config) enforcedQueueSettings() exporterhelper.QueueSettings {
Expand Down
92 changes: 91 additions & 1 deletion exporter/awscloudwatchlogsexporter/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ package awscloudwatchlogsexporter

import (
"path/filepath"
"strconv"
"strings"
"testing"

"github.com/cenkalti/backoff/v4"
Expand Down Expand Up @@ -142,6 +144,94 @@ func TestRetentionValidateWrong(t *testing.T) {
QueueSize: exporterhelper.NewDefaultQueueSettings().QueueSize,
},
}
assert.Error(t, wrongcfg.Validate())
assert.Error(t, component.ValidateConfig(wrongcfg))

}

func TestValidateTags(t *testing.T) {
defaultRetrySettings := exporterhelper.NewDefaultRetrySettings()

// Create *string values for tags inputs
basicValue := "avalue"
wrongRegexValue := "***"
emptyValue := ""
tooLongValue := strings.Repeat("a", 257)

// Create a map with no items and then one with too many items for testing
emptyMap := make(map[string]*string)
bigMap := make(map[string]*string)
for i := 0; i < 51; i++ {
bigMap[strconv.Itoa(i)] = &basicValue
}

tests := []struct {
id component.ID
tags map[string]*string
errorMessage string
}{
{
id: component.NewIDWithName(typeStr, "validate-correct"),
tags: map[string]*string{"basicKey": &basicValue},
},
{
id: component.NewIDWithName(typeStr, "too-little-tags"),
tags: emptyMap,
errorMessage: "invalid amount of items. Please input at least 1 tag or remove the tag field",
},
{
id: component.NewIDWithName(typeStr, "too-many-tags"),
tags: bigMap,
errorMessage: "invalid amount of items. Please input at most 50 tags",
},
{
id: component.NewIDWithName(typeStr, "wrong-key-regex"),
tags: map[string]*string{"***": &basicValue},
errorMessage: "key - *** does not follow the regex pattern" + `^([\p{L}\p{Z}\p{N}_.:/=+\-@]+)$`,
},
{
id: component.NewIDWithName(typeStr, "wrong-value-regex"),
tags: map[string]*string{"basicKey": &wrongRegexValue},
errorMessage: "value - " + wrongRegexValue + " does not follow the regex pattern" + `^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`,
},
{
id: component.NewIDWithName(typeStr, "key-too-short"),
tags: map[string]*string{"": &basicValue},
errorMessage: "key - has an invalid length. Please use keys with a length of 1 to 128 characters",
},
{
id: component.NewIDWithName(typeStr, "key-too-long"),
tags: map[string]*string{strings.Repeat("a", 129): &basicValue},
errorMessage: "key - " + strings.Repeat("a", 129) + " has an invalid length. Please use keys with a length of 1 to 128 characters",
},
{
id: component.NewIDWithName(typeStr, "value-too-short"),
tags: map[string]*string{"basicKey": &emptyValue},
errorMessage: "value - " + emptyValue + " has an invalid length. Please use values with a length of 1 to 256 characters",
},
{
id: component.NewIDWithName(typeStr, "value-too-long"),
tags: map[string]*string{"basicKey": &tooLongValue},
errorMessage: "value - " + tooLongValue + " has an invalid length. Please use values with a length of 1 to 256 characters",
},
}
for _, tt := range tests {
t.Run(tt.id.String(), func(t *testing.T) {
cfg := &Config{
RetrySettings: defaultRetrySettings,
LogGroupName: "test-1",
LogStreamName: "testing",
Endpoint: "",
Tags: tt.tags,
AWSSessionSettings: awsutil.CreateDefaultSessionConfig(),
QueueSettings: QueueSettings{
QueueSize: exporterhelper.NewDefaultQueueSettings().QueueSize,
},
}
if tt.errorMessage != "" {
assert.EqualError(t, component.ValidateConfig(cfg), tt.errorMessage)
return
}
assert.NoError(t, component.ValidateConfig(cfg))
})
}
}
2 changes: 1 addition & 1 deletion exporter/awscloudwatchlogsexporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func newCwLogsPusher(expConfig *Config, params exp.CreateSettings) (*exporter, e
}

// create CWLogs client with aws session config
svcStructuredLog := cwlogs.NewClient(params.Logger, awsConfig, params.BuildInfo, expConfig.LogGroupName, expConfig.LogRetention, session)
svcStructuredLog := cwlogs.NewClient(params.Logger, awsConfig, params.BuildInfo, expConfig.LogGroupName, expConfig.LogRetention, expConfig.Tags, session)
collectorIdentifier, err := uuid.NewRandom()

if err != nil {
Expand Down
Loading

0 comments on commit 639eb2d

Please sign in to comment.