Skip to content

Commit c6ab0c1

Browse files
authored
Add log_group_name_prefix config option for aws-cloudwatch input (#26187) (#26527)
(cherry picked from commit 1c9a488)
1 parent bedc535 commit c6ab0c1

File tree

6 files changed

+187
-16
lines changed

6 files changed

+187
-16
lines changed

CHANGELOG.next.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
581581
- Update PanOS module to parse HIP Match logs. {issue}24350[24350] {pull}25686[25686]
582582
- Support MongoDB 4.4 in filebeat's MongoDB module. {issue}20501[20501] {pull}24774[24774]
583583
- Enhance GCP module to populate orchestrator.* fields for GKE / K8S logs {pull}25368[25368]
584+
- Add log_group_name_prefix config into aws-cloudwatch input. {pull}26187[26187]
584585
- Move Filebeat azure module to GA. {pull}26114[26114] {pull}26168[26168]
585586
- Make `filestream` input GA. {pull}26127[26127]
586587
- http_endpoint: Support multiple documents in a single request by POSTing an array or NDJSON format. {pull}25764[25764]

x-pack/filebeat/_meta/config/filebeat.inputs.reference.xpack.yml.tmpl

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,60 @@
7676

7777
# List of S3 object metadata keys to include in events.
7878
#include_s3_metadata: []
79+
80+
#------------------------------ AWS CloudWatch input --------------------------------
81+
# Beta: Config options for AWS CloudWatch input
82+
#- type: aws-cloudwatch
83+
#enabled: false
84+
85+
# AWS Credentials
86+
# If access_key_id and secret_access_key are configured, then use them to make api calls.
87+
# If not, aws-cloudwatch input will load default AWS config or load with given profile name.
88+
#access_key_id: '${AWS_ACCESS_KEY_ID:""}'
89+
#secret_access_key: '${AWS_SECRET_ACCESS_KEY:""}'
90+
#session_token: '${AWS_SESSION_TOKEN:"”}'
91+
#credential_profile_name: test-aws-s3-input
92+
93+
# ARN of the log group to collect logs from
94+
#log_group_arn: "arn:aws:logs:us-east-1:428152502467:log-group:test:*"
95+
96+
# Name of the log group to collect logs from.
97+
# Note: region_name is required when log_group_name is given.
98+
#log_group_name: test
99+
100+
# The prefix for a group of log group names.
101+
# Note: `region_name` is required when `log_group_name_prefix` is given.
102+
# `log_group_name` and `log_group_name_prefix` cannot be given at the same time.
103+
#log_group_name_prefix: /aws/
104+
105+
# Region that the specified log group or log group prefix belongs to.
106+
#region_name: us-east-1
107+
108+
# A list of strings of log streams names that Filebeat collect log events from.
109+
#log_streams:
110+
# - log_stream_name
111+
112+
# A string to filter the results to include only log events from log streams
113+
# that have names starting with this prefix.
114+
#log_stream_prefix: test
115+
116+
# `start_position` allows user to specify if this input should read log files
117+
# from the `beginning` or from the `end`.
118+
# `beginning`: reads from the beginning of the log group (default).
119+
# `end`: read only new messages from current time minus `scan_frequency` going forward.
120+
#start_position: beginning
121+
122+
# This config parameter sets how often Filebeat checks for new log events from the
123+
# specified log group. Default `scan_frequency` is 1 minute, which means Filebeat
124+
# will sleep for 1 minute before querying for new logs again.
125+
#scan_frequency: 1m
126+
127+
# The maximum duration of AWS API can take. If it exceeds the timeout, AWS API
128+
# will be interrupted.
129+
# The default AWS API timeout for a message is 120 seconds.
130+
# The minimum is 0 seconds.
131+
#api_timeout: 120s
132+
133+
# This is used to sleep between AWS `FilterLogEvents` API calls inside the same
134+
# collection period.
135+
#api_sleep: 200ms

x-pack/filebeat/docs/inputs/input-aws-cloudwatch.asciidoc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,18 @@ ARN of the log group to collect logs from.
4545

4646
[float]
4747
==== `log_group_name`
48-
Name of the log group to collect logs from. Note: region_name is required when
48+
Name of the log group to collect logs from. Note: `region_name` is required when
4949
log_group_name is given.
5050

51+
[float]
52+
==== `log_group_name_prefix`
53+
The prefix for a group of log group names. Note: `region_name` is required when
54+
log_group_name_prefix is given. `log_group_name` and `log_group_name_prefix`
55+
cannot be given at the same time.
56+
5157
[float]
5258
==== `region_name`
53-
Region that the specified log group belongs to.
59+
Region that the specified log group or log group prefix belongs to.
5460

5561
[float]
5662
==== `log_streams`
@@ -109,6 +115,7 @@ Please see <<aws-credentials-config,AWS credentials options>> for more details.
109115
=== AWS Permissions
110116
Specific AWS permissions are required for IAM user to access aws-cloudwatch:
111117
----
118+
cloudwatchlogs:DescribeLogGroups
112119
logs:FilterLogEvents
113120
----
114121

x-pack/filebeat/filebeat.reference.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3094,6 +3094,63 @@ filebeat.inputs:
30943094
# List of S3 object metadata keys to include in events.
30953095
#include_s3_metadata: []
30963096

3097+
#------------------------------ AWS CloudWatch input --------------------------------
3098+
# Beta: Config options for AWS CloudWatch input
3099+
#- type: aws-cloudwatch
3100+
#enabled: false
3101+
3102+
# AWS Credentials
3103+
# If access_key_id and secret_access_key are configured, then use them to make api calls.
3104+
# If not, aws-cloudwatch input will load default AWS config or load with given profile name.
3105+
#access_key_id: '${AWS_ACCESS_KEY_ID:""}'
3106+
#secret_access_key: '${AWS_SECRET_ACCESS_KEY:""}'
3107+
#session_token: '${AWS_SESSION_TOKEN:"”}'
3108+
#credential_profile_name: test-aws-s3-input
3109+
3110+
# ARN of the log group to collect logs from
3111+
#log_group_arn: "arn:aws:logs:us-east-1:428152502467:log-group:test:*"
3112+
3113+
# Name of the log group to collect logs from.
3114+
# Note: region_name is required when log_group_name is given.
3115+
#log_group_name: test
3116+
3117+
# The prefix for a group of log group names.
3118+
# Note: `region_name` is required when `log_group_name_prefix` is given.
3119+
# `log_group_name` and `log_group_name_prefix` cannot be given at the same time.
3120+
#log_group_name_prefix: /aws/
3121+
3122+
# Region that the specified log group or log group prefix belongs to.
3123+
#region_name: us-east-1
3124+
3125+
# A list of strings of log streams names that Filebeat collect log events from.
3126+
#log_streams:
3127+
# - log_stream_name
3128+
3129+
# A string to filter the results to include only log events from log streams
3130+
# that have names starting with this prefix.
3131+
#log_stream_prefix: test
3132+
3133+
# `start_position` allows user to specify if this input should read log files
3134+
# from the `beginning` or from the `end`.
3135+
# `beginning`: reads from the beginning of the log group (default).
3136+
# `end`: read only new messages from current time minus `scan_frequency` going forward.
3137+
#start_position: beginning
3138+
3139+
# This config parameter sets how often Filebeat checks for new log events from the
3140+
# specified log group. Default `scan_frequency` is 1 minute, which means Filebeat
3141+
# will sleep for 1 minute before querying for new logs again.
3142+
#scan_frequency: 1m
3143+
3144+
# The maximum duration of AWS API can take. If it exceeds the timeout, AWS API
3145+
# will be interrupted.
3146+
# The default AWS API timeout for a message is 120 seconds.
3147+
# The minimum is 0 seconds.
3148+
#api_timeout: 120s
3149+
3150+
# This is used to sleep between AWS `FilterLogEvents` API calls inside the same
3151+
# collection period.
3152+
#api_sleep: 200ms
3153+
30973154
# =========================== Filebeat autodiscover ============================
30983155

30993156
# Autodiscover allows you to detect changes in the system and spawn new modules

x-pack/filebeat/input/awscloudwatch/config.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type config struct {
1616
harvester.ForwarderConfig `config:",inline"`
1717
LogGroupARN string `config:"log_group_arn"`
1818
LogGroupName string `config:"log_group_name"`
19+
LogGroupNamePrefix string `config:"log_group_name_prefix"`
1920
RegionName string `config:"region_name"`
2021
LogStreams []string `config:"log_streams"`
2122
LogStreamPrefix string `config:"log_stream_prefix"`
@@ -44,13 +45,17 @@ func (c *config) Validate() error {
4445
"either 'beginning' or 'end'")
4546
}
4647

47-
if c.LogGroupARN == "" && c.LogGroupName == "" {
48-
return errors.New("log_group_arn and log_group_name config parameter" +
49-
"cannot be both empty")
48+
if c.LogGroupARN == "" && c.LogGroupName == "" && c.LogGroupNamePrefix == "" {
49+
return errors.New("log_group_arn, log_group_name and log_group_name_prefix config parameter" +
50+
"cannot all be empty")
5051
}
5152

52-
if c.LogGroupName != "" && c.RegionName == "" {
53-
return errors.New("region_name is required when log_group_name " +
53+
if c.LogGroupName != "" && c.LogGroupNamePrefix != "" {
54+
return errors.New("log_group_name and log_group_name_prefix cannot be given at the same time")
55+
}
56+
57+
if (c.LogGroupName != "" || c.LogGroupNamePrefix != "") && c.RegionName == "" {
58+
return errors.New("region_name is required when log_group_name or log_group_name_prefix " +
5459
"config parameter is given")
5560
}
5661
return nil

x-pack/filebeat/input/awscloudwatch/input.go

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,33 @@ func NewInput(cfg *common.Config, connector channel.Connector, context input.Con
131131

132132
// Run runs the input
133133
func (in *awsCloudWatchInput) Run() {
134-
in.workerOnce.Do(func() {
135-
in.workerWg.Add(1)
136-
go func() {
137-
in.logger.Infof("aws-cloudwatch input worker for log group: '%v' has started", in.config.LogGroupName)
138-
defer in.logger.Infof("aws-cloudwatch input worker for log group '%v' has stopped.", in.config.LogGroupName)
139-
defer in.workerWg.Done()
140-
in.run()
141-
}()
142-
})
134+
cwConfig := awscommon.EnrichAWSConfigWithEndpoint(in.config.AwsConfig.Endpoint, "cloudwatchlogs", in.config.RegionName, in.awsConfig)
135+
svc := cloudwatchlogs.New(cwConfig)
136+
137+
var logGroupNames []string
138+
var err error
139+
if in.config.LogGroupNamePrefix != "" {
140+
logGroupNames, err = in.getLogGroupNames(svc)
141+
if err != nil {
142+
in.logger.Error("getLogGroupNames failed: ", err)
143+
return
144+
}
145+
} else {
146+
logGroupNames = []string{in.config.LogGroupName}
147+
}
148+
149+
for _, logGroup := range logGroupNames {
150+
in.config.LogGroupName = logGroup
151+
in.workerOnce.Do(func() {
152+
in.workerWg.Add(1)
153+
go func() {
154+
in.logger.Infof("aws-cloudwatch input worker for log group: '%v' has started", in.config.LogGroupName)
155+
defer in.logger.Infof("aws-cloudwatch input worker for log group '%v' has stopped.", in.config.LogGroupName)
156+
defer in.workerWg.Done()
157+
in.run()
158+
}()
159+
})
160+
}
143161
}
144162

145163
func (in *awsCloudWatchInput) run() {
@@ -176,6 +194,32 @@ func parseARN(logGroupARN string) (string, string, error) {
176194
return "", "", errors.Errorf("cannot get log group name from log group ARN: %s", logGroupARN)
177195
}
178196

197+
// getLogGroupNames uses DescribeLogGroups API to retrieve all log group names
198+
func (in *awsCloudWatchInput) getLogGroupNames(svc cloudwatchlogsiface.ClientAPI) ([]string, error) {
199+
// construct DescribeLogGroupsInput
200+
filterLogEventsInput := &cloudwatchlogs.DescribeLogGroupsInput{
201+
LogGroupNamePrefix: awssdk.String(in.config.LogGroupNamePrefix),
202+
}
203+
204+
// make API request
205+
req := svc.DescribeLogGroupsRequest(filterLogEventsInput)
206+
p := cloudwatchlogs.NewDescribeLogGroupsPaginator(req)
207+
var logGroupNames []string
208+
for p.Next(context.TODO()) {
209+
page := p.CurrentPage()
210+
in.logger.Debugf("Collecting #%v log group names", len(page.LogGroups))
211+
for _, lg := range page.LogGroups {
212+
logGroupNames = append(logGroupNames, *lg.LogGroupName)
213+
}
214+
}
215+
216+
if err := p.Err(); err != nil {
217+
in.logger.Error("failed DescribeLogGroupsRequest: ", err)
218+
return logGroupNames, err
219+
}
220+
return logGroupNames, nil
221+
}
222+
179223
// getLogEventsFromCloudWatch uses FilterLogEvents API to collect logs from CloudWatch
180224
func (in *awsCloudWatchInput) getLogEventsFromCloudWatch(svc cloudwatchlogsiface.ClientAPI) error {
181225
ctx, cancelFn := context.WithTimeout(in.inputCtx, in.config.APITimeout)

0 commit comments

Comments
 (0)