From 4c62bbad18a83c493d2cf5684095e094a17d0445 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Mon, 16 May 2022 18:09:18 +0930 Subject: [PATCH 01/38] x-pack/filebeat/module/cisco: remove invalid values from ECS fields (#31628) This prevents "monitored" from being written into event.outcome which does not allow this value according to ECS. --- CHANGELOG.next.asciidoc | 1 + .../filebeat/module/cisco/asa/test/sample.log-expected.json | 3 ++- .../filebeat/module/cisco/ftd/test/sample.log-expected.json | 3 ++- .../filebeat/module/cisco/shared/ingest/asa-ftd-pipeline.yml | 4 ++++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 348d8ee539ea..f9fb21734280 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -56,6 +56,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...main[Check the HEAD dif - aws-s3 input: Stop SQS keep-alive routine on InvalidParameterValue error. {issue}30675[30675] {pull}31499[31499] - Supporting the double digit date parsing in ingest pipeline for oracle logs. {pull}31514[31514] - Fix handling of code_sign data in ThreatIntel Malwarebazaar. {issue}29972[29972] {pull}31552[31552] +- Remove invalid term from event.outcome in the cisco asa and ftd modules. {pull}31628[31628] *Heartbeat* - Fix unintentional use of no-op logger. {pull}31543[31543] diff --git a/x-pack/filebeat/module/cisco/asa/test/sample.log-expected.json b/x-pack/filebeat/module/cisco/asa/test/sample.log-expected.json index 644e740b273a..82d1ee5dedac 100644 --- a/x-pack/filebeat/module/cisco/asa/test/sample.log-expected.json +++ b/x-pack/filebeat/module/cisco/asa/test/sample.log-expected.json @@ -3440,6 +3440,7 @@ "destination.port": 80, "event.action": "firewall-rule", "event.category": [ + "intrusion_detection", "network" ], "event.code": 338004, @@ -3447,7 +3448,7 @@ "event.kind": "event", "event.module": "cisco", "event.original": "%ASA-4-338004: Dynamic Filter monitored blacklisted TCP traffic from inside:10.1.1.1/33340 (10.2.1.1/33340) to outsidet:192.0.2.223/80 (192.0.2.223/80), destination 192.0.2.223 resolved from dynamic list: 192.0.2.223/255.255.255.255, threat-level: very-high, category: Malware", - "event.outcome": "monitored", + "event.outcome": "success", "event.severity": 4, "event.timezone": "-02:00", "event.type": [ diff --git a/x-pack/filebeat/module/cisco/ftd/test/sample.log-expected.json b/x-pack/filebeat/module/cisco/ftd/test/sample.log-expected.json index 84c749c8d755..86a55b6ef17a 100644 --- a/x-pack/filebeat/module/cisco/ftd/test/sample.log-expected.json +++ b/x-pack/filebeat/module/cisco/ftd/test/sample.log-expected.json @@ -3427,6 +3427,7 @@ "destination.port": 80, "event.action": "firewall-rule", "event.category": [ + "intrusion_detection", "network" ], "event.code": 338004, @@ -3434,7 +3435,7 @@ "event.kind": "event", "event.module": "cisco", "event.original": "%FTD-4-338004: Dynamic Filter monitored blacklisted TCP traffic from inside:10.1.1.1/33340 (10.2.1.1/33340) to outsidet:192.0.2.223/80 (192.0.2.225/80), destination 192.0.2.223 resolved from dynamic list: 192.0.2.223/255.255.255.255, threat-level: very-high, category: Malware", - "event.outcome": "monitored", + "event.outcome": "success", "event.severity": 4, "event.timezone": "-02:00", "event.type": [ diff --git a/x-pack/filebeat/module/cisco/shared/ingest/asa-ftd-pipeline.yml b/x-pack/filebeat/module/cisco/shared/ingest/asa-ftd-pipeline.yml index 190041591f9a..f171ee65ea3d 100644 --- a/x-pack/filebeat/module/cisco/shared/ingest/asa-ftd-pipeline.yml +++ b/x-pack/filebeat/module/cisco/shared/ingest/asa-ftd-pipeline.yml @@ -1879,6 +1879,10 @@ processors: } else if (ctx?.event?.action.startsWith('connection-')) { ctx.event.type.add('connection'); } + if (ctx.event.outcome == 'monitored') { + ctx.event.category.add('intrusion_detection'); + ctx.event.outcome = 'success'; + } - set: description: copy destination.user.name to user.name if it is not set From a4768ad9c4564f08596951f63a82a21dc45cee90 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Mon, 18 Mar 2024 13:39:29 +0000 Subject: [PATCH 02/38] AWS Health Initial Commit --- go.mod | 1 + go.sum | 2 + x-pack/metricbeat/include/list.go | 1 + .../module/aws/awshealth/_meta/data.json | 43 ++ .../module/aws/awshealth/_meta/docs.asciidoc | 1 + .../module/aws/awshealth/_meta/fields.yml | 75 +++ .../module/aws/awshealth/awshealth.go | 438 ++++++++++++++++++ .../awshealth/awshealth_integration_test.go | 37 ++ 8 files changed, 598 insertions(+) create mode 100644 x-pack/metricbeat/module/aws/awshealth/_meta/data.json create mode 100644 x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/aws/awshealth/awshealth.go create mode 100644 x-pack/metricbeat/module/aws/awshealth/awshealth_integration_test.go diff --git a/go.mod b/go.mod index fc7c97929b23..923016f8ae69 100644 --- a/go.mod +++ b/go.mod @@ -263,6 +263,7 @@ require ( github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.14 // indirect + github.com/aws/aws-sdk-go-v2/service/health v1.17.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.18 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect diff --git a/go.sum b/go.sum index f95a7973ed8a..7ba2d41fc6e2 100644 --- a/go.sum +++ b/go.sum @@ -344,6 +344,8 @@ github.com/aws/aws-sdk-go-v2/service/ec2 v1.36.1 h1:FS8Ja6LuLDVHcX+rmoNpOXqYb52N github.com/aws/aws-sdk-go-v2/service/ec2 v1.36.1/go.mod h1:KOy1O7Fc2+GRgsbn/Kjr15vYDVXMEQALBaPRia3twSY= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.18.4 h1:ZBYifRGfN3dOKzvk0+XJiUKOFzqoJddYqCVsN5quCh4= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.18.4/go.mod h1:9wKR88sRRyxrUAw5iVSDTfcCz90BLEFcAiyzP4v39uY= +github.com/aws/aws-sdk-go-v2/service/health v1.17.0 h1:DlG9888p6n8Fizx8Vuw1qalBOBtjoDk70UzqyilQ7+s= +github.com/aws/aws-sdk-go-v2/service/health v1.17.0/go.mod h1:z7JTQWRaBIdYYxK8TqDi4MKYYl04uI+jvTJuMEKIsL0= github.com/aws/aws-sdk-go-v2/service/iam v1.18.4 h1:E41guA79mjEbwJdh0zXz1d8+Zt4zxRr+b1ipiVbKXzs= github.com/aws/aws-sdk-go-v2/service/iam v1.18.4/go.mod h1:FpNvAfCZyIQ3qeNJUOw4CShKvdizHblXqAvSk0qmyL4= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9 h1:Lh1AShsuIJTwMkoxVCAYPJgNG5H+eN6SmoUn8nOZ5wE= diff --git a/x-pack/metricbeat/include/list.go b/x-pack/metricbeat/include/list.go index 0cbedc06dd4a..8e0d4be41afe 100644 --- a/x-pack/metricbeat/include/list.go +++ b/x-pack/metricbeat/include/list.go @@ -11,6 +11,7 @@ import ( _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/activemq" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/airflow" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/aws" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/aws/awshealth" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/aws/billing" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/aws/cloudwatch" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/awsfargate" diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/data.json b/x-pack/metricbeat/module/aws/awshealth/_meta/data.json new file mode 100644 index 000000000000..86a5ed50c4f8 --- /dev/null +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/data.json @@ -0,0 +1,43 @@ +{ + "@timestamp": "2017-10-12T08:05:34.853Z", + "aws": { + "awshealth": { + "affected_entities": [ + { + "aws_account_id": "627286350134", + "entity_url": "", + "entity_value": "arn:aws:eks:us-east-2:627286350134:cluster/michaliskatsoulisfargate", + "last_updated_time": "2024-02-26T21:44:05.825Z", + "status_code": "", + "entity_arn": "arn:aws:health:us-east-2:627286350134:entity/g1vUSeoFZcvk3ucsO-BHDR55XHsSYYfs6wqo1QhqQeEto=1g" + } + ], + "affected_entities_others": 0, + "affected_entities_pending": 0, + "affected_entities_resolved": 0, + "end_time": "0001-01-01T00:00:00Z", + "event_arn": "arn:aws:health:us-east-2::event/EKS/AWS_EKS_OPERATIONAL_NOTIFICATION/AWS_EKS_OPERATIONAL_NOTIFICATION_5edf7d286ca1fbcdd70306479c60f8fd560afa53f174d79ae319faaedfc94646", + "event_scope_code": "ACCOUNT_SPECIFIC", + "event_type_category": "accountNotification", + "event_type_code": "AWS_EKS_OPERATIONAL_NOTIFICATION", + "last_updated_time": "2024-02-26T22:00:11.574Z", + "region": "us-east-2", + "service": "EKS", + "start_time": "2024-02-26T21:35:00Z", + "status_code": "open" + } + }, + "cloud.provider": "aws", + "event": { + "dataset": "aws.awshealth", + "duration": 115000, + "module": "aws" + }, + "metricset": { + "name": "awshealth", + "period": 10000 + }, + "service": { + "type": "aws" + } +} \ No newline at end of file diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc b/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc new file mode 100644 index 000000000000..84b211ca52a4 --- /dev/null +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the awshealth metricset of the module aws. diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml new file mode 100644 index 000000000000..fa92abb380ec --- /dev/null +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml @@ -0,0 +1,75 @@ +- name: awshealth + type: group + release: beta + description: > + AWS Health metrics + fields: + - name: affected_entities_others + type: float + description: > + Number of affected resources, not able to verify status, related to the event. + - name: affected_entities_pending + type: float + description: > + Number of affected resources that may require action. + - name: affected_entities_resolved + type: float + description: > + Number of affected resources having no actions required. + - name: end_time + type: date + description: > + The date and time that the event ended. Certain events may not have an End date. + - name: event_arn + type: keyword + description: > + The unique identifier for the event. The event ARN has the arn:aws:health:event-region::event/SERVICE/EVENT_TYPE_CODE/EVENT_TYPE_PLUS_ID format. + - name: event_scope_code + type: keyword + description: > + This parameter specifies if the Health event is a public Amazon Web Service event or an account-specific event. Allowed values are PUBLIC/ ACCOUNT_SPECIFIC/ NONE. + - name: event_type_category + type: keyword + description: > + Event type category code. Possible values are issue accountNotification, or scheduledChange. + - name: event_type_code + type: keyword + description: > + The unique identifier for the event type. The format is AWS_SERVICE_DESCRIPTION + - name: last_updated_time + type: date + description: > + The most recent date and time that the event was updated. + - name: region + type: keyword + description: > + The Amazon Web Services Region name of the event. + - name: service + type: keyword + description: > + The Amazon Web Service that is affected by the event. For example, EC2 , RDS . + - name: start_time + type: date + description: > + The date and time that the event began. + - name: status_code + type: keyword + description: > + The most recent status of the event. Possible values are open , closed , and upcoming. + - name: affected_entities + type: nested + description: > + Information about an entity that is affected by a Health event. + fields: + - name: aws_account_id + type: keyword + - name: entity_url + type: keyword + - name: entity_value + type: keyword + - name: last_updated_time + type: date + - name: status_code + type: keyword + - name: entity_arn + type: keyword diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go new file mode 100644 index 000000000000..322a5d193176 --- /dev/null +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -0,0 +1,438 @@ +package awshealth + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "fmt" + "time" + + awssdk "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/health" + "github.com/aws/aws-sdk-go-v2/service/health/types" + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/aws" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +const metricsetName = "awshealth" + +var Locale string = "en" + +var maxResults int32 = 10 + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(aws.ModuleName, metricsetName, New, + mb.DefaultMetricSet(), + ) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + *aws.MetricSet + logger *logp.Logger + Config Config `config:"aws_health_config"` +} + +// Config holds the configuration specific for aws health metricset +type Config struct { + EventARNPattern []string `config:"event_arns_pattern"` +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + + logger := logp.NewLogger(metricsetName) + metricSet, err := aws.NewMetricSet(base) + if err != nil { + return nil, fmt.Errorf("error creating aws metricset: %w", err) + } + + cfgwarn.Beta("The aws awshealth metricset is beta.") + + config := struct { + Config Config `config:"aws_health_config"` + }{} + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + + return &MetricSet{ + MetricSet: metricSet, + logger: logger, + Config: config.Config, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(ctx context.Context, report mb.ReporterV2) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + var config aws.Config + err := m.Module().UnpackConfig(&config) + if err != nil { + return err + } + + // Get startDate and endDate + // startDate, endDate := getStartDateEndDate(m.Period) + + awsConfig := m.MetricSet.AwsConfig.Copy() + + // Get startTime and endTime + startTime, endTime := aws.GetStartTimeEndTime(time.Now(), m.Period, m.Latency) + m.Logger().Debugf("[AWS Health] startTime = %s, endTime = %s", startTime, endTime) + health_client := health.NewFromConfig(awsConfig, func(o *health.Options) { + if config.AWSConfig.FIPSEnabled { + o.EndpointOptions.UseFIPSEndpoint = awssdk.FIPSEndpointStateEnabled + } + }) + + events := m.getEventsSummary(ctx, health_client, startTime, endTime) + for _, event := range events { + report.Event(event) + } + + return nil +} + +// Make call to DescribeEvents() +// Returns information about events that meet the specified filter criteria. Events are returned in a summary form and do not include the detailed description, any additional metadata that depends on the event type, or any affected resources. +func (m *MetricSet) getEventsSummary( + ctx context.Context, + awsHealth *health.Client, + startTime time.Time, + endTime time.Time, +) []mb.Event { + var events []mb.Event + eventFilter := types.EventFilter{ + // LastUpdatedTimes: []types.DateTimeRange{ + // { + // From: &startTime, + // To: &endTime, + // }, + // }, + //Regions: []string{"ap-south"}, + EventStatusCodes: []types.EventStatusCode{ + types.EventStatusCodeUpcoming, + types.EventStatusCodeOpen, + // types.EventStatusCodeClosed, + }, + } + + var nextTokenString string = "" + var eventOutput *health.DescribeEventsOutput + var err error + + for { + if nextTokenString == "" { + eventOutput, err = awsHealth.DescribeEvents(ctx, + &health.DescribeEventsInput{ + Filter: &eventFilter, + MaxResults: &maxResults, + }, + ) + } else { + eventOutput, err = awsHealth.DescribeEvents(ctx, + &health.DescribeEventsInput{ + Filter: &eventFilter, + MaxResults: &maxResults, + NextToken: &nextTokenString, + }, + ) + } + if err != nil { + err = fmt.Errorf("AWS Health DescribeEvents failed with %w", err) + m.Logger().Error(err.Error()) + return nil + + } + ets := eventOutput.Events + c := make(chan HealthDetails) + select { + case <-ctx.Done(): + // Context cancelled, handle graceful termination + m.Logger().Info("Context cancelled. Exiting gracefully.") + close(c) + return nil + default: + // Context not cancelled, proceed with the function + } + + for _, et := range ets { + fmt.Printf("ARN : %s\n", *(et.Arn)) + if az := et.AvailabilityZone; az != nil { + fmt.Println("AZ", *(et.AvailabilityZone)) + } + fmt.Println("End Time:", et.EndTime) + fmt.Println("Event Scope Code:", et.EventScopeCode) + fmt.Println("Event Type Category:", et.EventTypeCategory) + fmt.Println("Event Type Code:", *(et.EventTypeCode)) + fmt.Println("Last updated Time:", et.LastUpdatedTime) + fmt.Println("Region:", *(et.Region)) + fmt.Println("Service:", *(et.Service)) + fmt.Println("Start Time:", et.StartTime) + fmt.Println("Event Status Code:", et.StatusCode) + fmt.Println("--------------------------") + go m.getDescribeEventDetails(ctx, awsHealth, et, c) + } + + for i := 0; i < len(ets); i++ { + select { + case <-ctx.Done(): + // Context cancelled, handle graceful termination + m.Logger().Debug("Context cancelled. Exiting gracefully.") + + close(c) + return nil + case healthDetails, ok := <-c: + if !ok { + return nil + } + fmt.Println("Heatlh Details ARN", *healthDetails.event.Arn) + fmt.Println("Health Details Event Description", healthDetails.eventDescription) + fmt.Println("Health Details Pending", healthDetails.affectedEntityPending) + fmt.Println("Health Details Pending", healthDetails.affectedEntityResolved) + fmt.Println("") + fmt.Println("-------------------------------------------") + events = append(events, createEvents(healthDetails)) + fmt.Println("Event size ", len(events)) + } + } + if eventOutput.NextToken == nil { + break + } else { + nextTokenString = *eventOutput.NextToken + } + time.Sleep(10 * time.Millisecond) + close(c) + } + return events +} + +func createEvents(hd HealthDetails) mb.Event { + event := mb.Event{} + event.MetricSetFields = mapstr.M{ + "event_arn": getStringValueOrDefault(hd.event.Arn), + "end_time": getTimeValueOrDefault(hd.event.EndTime), + "event_scope_code": getStringValueOrDefault((*string)(&hd.event.EventScopeCode)), + "event_type_category": getStringValueOrDefault((*string)(&hd.event.EventTypeCategory)), + "event_type_code": getStringValueOrDefault(hd.event.EventTypeCode), + "last_updated_time": getTimeValueOrDefault(hd.event.LastUpdatedTime), + "region": getStringValueOrDefault(hd.event.Region), + "service": getStringValueOrDefault(hd.event.Service), + "start_time": getTimeValueOrDefault(hd.event.StartTime), + "status_code": getStringValueOrDefault((*string)(&hd.event.StatusCode)), + "affected_entities_pending": hd.affectedEntityPending, + "affected_entities_resolved": hd.affectedEntityResolved, + "affected_entities_others": hd.affectedEntityOthers, + "affected_entities": createAffectedEntityDetails(hd.affectedEntities), + } + event.RootFields = mapstr.M{ + "cloud.provider": "aws", + } + currentDate := getCurrentDateTime() + eventID := currentDate + getStringValueOrDefault(hd.event.Arn) + getStringValueOrDefault((*string)(&hd.event.StatusCode)) + event.ID = generateEventID(eventID) + return event +} + +type HealthDetails struct { + event types.Event + eventDescription string + affectedEntities []types.AffectedEntity + affectedEntityPending int32 + affectedEntityResolved int32 + affectedEntityOthers int32 +} + +type AffectedEntityDetails struct { + AwsAccountId string `json:"aws_account_id"` + EntityUrl string `json:"entity_url"` + EntityValue string `json:"entity_value"` + LastUpdatedTime time.Time `json:"last_updated_time"` + StatusCode string `json:"status_code"` + EntityArn string `json:"entity_arn"` +} + +// getStringValueOrDefault returns the string value or an empty string if the pointer is nil. +func getStringValueOrDefault(s *string) string { + if s != nil { + return *s + } + return "" +} + +func getTimeValueOrDefault(t *time.Time) time.Time { + if t != nil { + return *t + } + return time.Time{} +} + +// createAffectedEntityDetails populates and returns a slice of AffectedEntityDetails +// based on the given list of AffectedEntity instances. +// Each AffectedEntity is converted into an AffectedEntityDetails struct, +func createAffectedEntityDetails(affectedEntities []types.AffectedEntity) []AffectedEntityDetails { + var aed []AffectedEntityDetails + // Populate a slice of AffectedEntityDetails + for _, entity := range affectedEntities { + aed = append(aed, AffectedEntityDetails{ + AwsAccountId: getStringValueOrDefault(entity.AwsAccountId), + EntityUrl: getStringValueOrDefault(entity.EntityUrl), + EntityValue: getStringValueOrDefault(entity.EntityValue), + LastUpdatedTime: getTimeValueOrDefault(entity.LastUpdatedTime), + StatusCode: string(entity.StatusCode), + EntityArn: getStringValueOrDefault(entity.EntityArn), + }) + } + return aed + +} + +func generateEventID(eventID string) string { + h := sha256.New() + h.Write([]byte(eventID)) + prefix := hex.EncodeToString(h.Sum(nil)) + return prefix[:20] +} + +func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *health.Client, event types.Event, ch chan<- HealthDetails) { + var hd HealthDetails + hd.event = event + eventDetails, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ + EventArns: []string{*event.Arn}, + Locale: &Locale, + }) + if err != nil { + if ctx.Err() == context.Canceled { + m.Logger().Debug("Context cancelled. Exiting gracefully.") + return + } + err = fmt.Errorf("AWS Health DescribeEventDetails failed with %w", err) + m.Logger().Error(err.Error()) + return + } else { + hd.eventDescription = *(eventDetails.SuccessfulSet[0].EventDescription.LatestDescription) + } + + var affEntityTokString string = "" + var nextToken *string + var pending int32 = 0 + var resolved int32 = 0 + var others int32 = 0 + for { + if affEntityTokString == "" { + affectedEntities, err := awsHealth.DescribeAffectedEntities(ctx, &health.DescribeAffectedEntitiesInput{ + Filter: &types.EntityFilter{ + EventArns: []string{*event.Arn}, + }, + Locale: &Locale, + MaxResults: &maxResults, + }) + if err != nil { + err = fmt.Errorf("AWS Health DescribeAffectedEntities failed with %w", err) + + // Check if the error is due to context cancellation + if ctx.Err() == context.Canceled { + m.Logger().Info("Context cancelled. Exiting gracefully.") + return + } + // Handle other errors + m.Logger().Error(err.Error()) + return + } + if affectedEntities != nil { + nextToken = affectedEntities.NextToken + + hd.affectedEntities = append(hd.affectedEntities, affectedEntities.Entities...) + for _, affEntity := range affectedEntities.Entities { + if affEntity.StatusCode != "" { + if affEntity.StatusCode == "PENDING" { + pending++ + } else if affEntity.StatusCode == "RESOLVED" { + resolved++ + } else { + others++ + } + } + } + } + + } else { + affectedEntities, err := awsHealth.DescribeAffectedEntities(ctx, &health.DescribeAffectedEntitiesInput{ + Filter: &types.EntityFilter{ + EventArns: []string{*event.Arn}, + }, + Locale: &Locale, + MaxResults: &maxResults, + NextToken: &affEntityTokString, + }) + if err != nil { + err = fmt.Errorf("AWS Health DescribeAffectedEntities failed with %w", err) + + // Check if the error is due to context cancellation + if ctx.Err() == context.Canceled { + m.Logger().Info("Context cancelled. Exiting gracefully.") + return + } + // Handle other errors + m.Logger().Error(err.Error()) + return + } + if affectedEntities != nil { + nextToken = affectedEntities.NextToken + + // nextToken = affectedEntities.NextToken + hd.affectedEntities = append(hd.affectedEntities, affectedEntities.Entities...) + + for _, affEntity := range affectedEntities.Entities { + if affEntity.StatusCode != "" { + if affEntity.StatusCode == "PENDING" { + pending++ + } else if affEntity.StatusCode == "RESOLVED" { + resolved++ + } else { + others++ + } + } + } + } + } + if nextToken == nil { + break + } else { + affEntityTokString = *nextToken + } + } + hd.affectedEntityResolved = resolved + hd.affectedEntityPending = pending + hd.affectedEntityOthers = others + select { + case ch <- hd: + // Writing to the channel + default: + // Channel is closed, + return + } + time.Sleep(10 * time.Millisecond) +} + +func getCurrentDateTime() string { + currentTime := time.Now() + return fmt.Sprintf("%04d%02d%02d%02d%02d%02d", currentTime.Year(), int(currentTime.Month()), currentTime.Day(), currentTime.Hour(), currentTime.Minute(), currentTime.Second()) +} diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth_integration_test.go b/x-pack/metricbeat/module/aws/awshealth/awshealth_integration_test.go new file mode 100644 index 000000000000..7edc1e7ec11c --- /dev/null +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth_integration_test.go @@ -0,0 +1,37 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package awshealth + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/aws/mtest" +) + +// TODO +// There seems to be problem with Flatten() function of type M map[string]interface{} +// The Flatten function returns aws.awshealth.affected_entities instead of aws.awshealth.affected_entities.aws_account_id, needed for nested type. + +func TestFetch(t *testing.T) { + config := mtest.GetConfigForTest(t, "awshealth", "24h") + metricSet := mbtest.NewReportingMetricSetV2WithContext(t, config) + events, errs := mbtest.ReportingFetchV2WithContext(metricSet) + if len(errs) > 0 { + t.Fatalf("Expected 0 error, had %d. %v\n", len(errs), errs) + } + assert.NotEmpty(t, events) + mbtest.TestMetricsetFieldsDocumented(t, metricSet, events) +} + +func TestData(t *testing.T) { + config := mtest.GetConfigForTest(t, "awshealth", "1h") + config["dataset_id"] = "master_aws_awshealth" + + metricSet := mbtest.NewFetcher(t, config) + metricSet.WriteEvents(t, "/") +} From ac9a664702c2cea6de111ac8b5671ff1fc5fdc45 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Mon, 18 Mar 2024 13:58:41 +0000 Subject: [PATCH 03/38] Updated doc files --- metricbeat/docs/fields.asciidoc | 147 ++++++++++++++++++ metricbeat/docs/modules/aws.asciidoc | 4 + metricbeat/docs/modules_list.asciidoc | 3 +- .../module/aws/awshealth/awshealth.go | 4 + x-pack/metricbeat/module/aws/fields.go | 2 +- 5 files changed, 158 insertions(+), 2 deletions(-) diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 435760b7406e..b302fb7ccf23 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -1545,6 +1545,153 @@ type: keyword -- +[float] +=== awshealth + +AWS Health metrics + + + +*`aws.awshealth.affected_entities_others`*:: ++ +-- +Number of affected resources, not able to verify status, related to the event. + + +type: float + +-- + +*`aws.awshealth.affected_entities_pending`*:: ++ +-- +Number of affected resources that may require action. + + +type: float + +-- + +*`aws.awshealth.affected_entities_resolved`*:: ++ +-- +Number of affected resources having no actions required. + + +type: float + +-- + +*`aws.awshealth.end_time`*:: ++ +-- +The date and time that the event ended. Certain events may not have an End date. + + +type: date + +-- + +*`aws.awshealth.event_arn`*:: ++ +-- +The unique identifier for the event. The event ARN has the arn:aws:health:event-region::event/SERVICE/EVENT_TYPE_CODE/EVENT_TYPE_PLUS_ID format. + + +type: keyword + +-- + +*`aws.awshealth.event_scope_code`*:: ++ +-- +This parameter specifies if the Health event is a public Amazon Web Service event or an account-specific event. Allowed values are PUBLIC/ ACCOUNT_SPECIFIC/ NONE. + + +type: keyword + +-- + +*`aws.awshealth.event_type_category`*:: ++ +-- +Event type category code. Possible values are issue accountNotification, or scheduledChange. + + +type: keyword + +-- + +*`aws.awshealth.event_type_code`*:: ++ +-- +The unique identifier for the event type. The format is AWS_SERVICE_DESCRIPTION + + +type: keyword + +-- + +*`aws.awshealth.last_updated_time`*:: ++ +-- +The most recent date and time that the event was updated. + + +type: date + +-- + +*`aws.awshealth.region`*:: ++ +-- +The Amazon Web Services Region name of the event. + + +type: keyword + +-- + +*`aws.awshealth.service`*:: ++ +-- +The Amazon Web Service that is affected by the event. For example, EC2 , RDS . + + +type: keyword + +-- + +*`aws.awshealth.start_time`*:: ++ +-- +The date and time that the event began. + + +type: date + +-- + +*`aws.awshealth.status_code`*:: ++ +-- +The most recent status of the event. Possible values are open , closed , and upcoming. + + +type: keyword + +-- + +*`aws.awshealth.affected_entities`*:: ++ +-- +Information about an entity that is affected by a Health event. + + +type: nested + +-- + [float] === billing diff --git a/metricbeat/docs/modules/aws.asciidoc b/metricbeat/docs/modules/aws.asciidoc index ee2a73e17dc6..47edfa1888fa 100644 --- a/metricbeat/docs/modules/aws.asciidoc +++ b/metricbeat/docs/modules/aws.asciidoc @@ -439,6 +439,8 @@ metricbeat.modules: The following metricsets are available: +* <> + * <> * <> @@ -473,6 +475,8 @@ The following metricsets are available: * <> +include::aws/awshealth.asciidoc[] + include::aws/billing.asciidoc[] include::aws/cloudwatch.asciidoc[] diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc index 2a77f4d38cd3..da0f7525e0fe 100644 --- a/metricbeat/docs/modules_list.asciidoc +++ b/metricbeat/docs/modules_list.asciidoc @@ -16,7 +16,8 @@ This file is generated! See scripts/mage/docs_collector.go |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | .1+| .1+| |<> |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | -.17+| .17+| |<> beta[] +.18+| .18+| |<> beta[] +|<> beta[] |<> |<> beta[] |<> diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 322a5d193176..72c9a72d2c0a 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package awshealth import ( diff --git a/x-pack/metricbeat/module/aws/fields.go b/x-pack/metricbeat/module/aws/fields.go index 713690883f30..6c1762a1d990 100644 --- a/x-pack/metricbeat/module/aws/fields.go +++ b/x-pack/metricbeat/module/aws/fields.go @@ -19,5 +19,5 @@ func init() { // AssetAws returns asset data. // This is the base64 encoded zlib format compressed contents of module/aws. func AssetAws() string { - return "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" + return "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" } From 7c09b9d2d6791ad61a73fc0e6b5ac7a2634aadae Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Mon, 18 Mar 2024 14:07:38 +0000 Subject: [PATCH 04/38] Applying Tidy --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 923016f8ae69..a84a630d6b4d 100644 --- a/go.mod +++ b/go.mod @@ -197,6 +197,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.33 github.com/aws/aws-sdk-go-v2/service/cloudformation v1.20.4 + github.com/aws/aws-sdk-go-v2/service/health v1.17.0 github.com/aws/aws-sdk-go-v2/service/kinesis v1.15.8 github.com/aws/smithy-go v1.13.5 github.com/awslabs/kinesis-aggregation/go/v2 v2.0.0-20220623125934-28468a6701b5 @@ -263,7 +264,6 @@ require ( github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.14 // indirect - github.com/aws/aws-sdk-go-v2/service/health v1.17.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.18 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect From 3c1d98cc24f9785518c500756fc3575ca79bc4e6 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Mon, 18 Mar 2024 14:10:42 +0000 Subject: [PATCH 05/38] Adding missing doc, go mod tidy changes --- .../docs/modules/aws/awshealth.asciidoc | 30 +++++++++++++++++++ .../module/aws/awshealth/awshealth.go | 1 + 2 files changed, 31 insertions(+) create mode 100644 metricbeat/docs/modules/aws/awshealth.asciidoc diff --git a/metricbeat/docs/modules/aws/awshealth.asciidoc b/metricbeat/docs/modules/aws/awshealth.asciidoc new file mode 100644 index 000000000000..35a8cecde3c8 --- /dev/null +++ b/metricbeat/docs/modules/aws/awshealth.asciidoc @@ -0,0 +1,30 @@ +//// +This file is generated! See scripts/mage/docs_collector.go +//// +:edit_url: https://github.com/elastic/beats/edit/main/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc + + +[[metricbeat-metricset-aws-awshealth]] +[role="xpack"] +=== AWS awshealth metricset + +beta[] + +include::../../../../x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc[] + +This is a default metricset. If the host module is unconfigured, this metricset is enabled by default. + +:edit_url: + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../../x-pack/metricbeat/module/aws/awshealth/_meta/data.json[] +---- +:edit_url!: \ No newline at end of file diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 72c9a72d2c0a..0978c1ab1db9 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -14,6 +14,7 @@ import ( awssdk "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/health" "github.com/aws/aws-sdk-go-v2/service/health/types" + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/x-pack/metricbeat/module/aws" From c69550e6c32114a1b0f54639f9753e77dc36281d Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Mon, 18 Mar 2024 16:43:18 +0000 Subject: [PATCH 06/38] Updated NOTICE.TXT --- NOTICE.txt | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) diff --git a/NOTICE.txt b/NOTICE.txt index 2f66d290a432..707bae4e639e 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -7374,6 +7374,218 @@ Contents of probable licence file $GOMODCACHE/github.com/aws/aws-sdk-go-v2/servi limitations under the License. +-------------------------------------------------------------------------------- +Dependency : github.com/aws/aws-sdk-go-v2/service/health +Version: v1.17.0 +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/aws/aws-sdk-go-v2/service/health@v1.17.0/LICENSE.txt: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + -------------------------------------------------------------------------------- Dependency : github.com/aws/aws-sdk-go-v2/service/iam Version: v1.18.4 From a95f186cad372080b68a698547fbb20224e4a56d Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Tue, 19 Mar 2024 08:08:47 +0000 Subject: [PATCH 07/38] Addressed lint suggestions from golangci-lint --- .../module/aws/awshealth/awshealth.go | 31 +++---------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 0978c1ab1db9..79d4869f0567 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -139,7 +139,7 @@ func (m *MetricSet) getEventsSummary( }, } - var nextTokenString string = "" + var nextTokenString = "" var eventOutput *health.DescribeEventsOutput var err error @@ -164,7 +164,6 @@ func (m *MetricSet) getEventsSummary( err = fmt.Errorf("AWS Health DescribeEvents failed with %w", err) m.Logger().Error(err.Error()) return nil - } ets := eventOutput.Events c := make(chan HealthDetails) @@ -179,20 +178,7 @@ func (m *MetricSet) getEventsSummary( } for _, et := range ets { - fmt.Printf("ARN : %s\n", *(et.Arn)) - if az := et.AvailabilityZone; az != nil { - fmt.Println("AZ", *(et.AvailabilityZone)) - } - fmt.Println("End Time:", et.EndTime) - fmt.Println("Event Scope Code:", et.EventScopeCode) - fmt.Println("Event Type Category:", et.EventTypeCategory) - fmt.Println("Event Type Code:", *(et.EventTypeCode)) - fmt.Println("Last updated Time:", et.LastUpdatedTime) - fmt.Println("Region:", *(et.Region)) - fmt.Println("Service:", *(et.Service)) - fmt.Println("Start Time:", et.StartTime) - fmt.Println("Event Status Code:", et.StatusCode) - fmt.Println("--------------------------") + m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getStringValueOrDefault(et.Arn)) go m.getDescribeEventDetails(ctx, awsHealth, et, c) } @@ -201,21 +187,14 @@ func (m *MetricSet) getEventsSummary( case <-ctx.Done(): // Context cancelled, handle graceful termination m.Logger().Debug("Context cancelled. Exiting gracefully.") - close(c) return nil case healthDetails, ok := <-c: if !ok { return nil } - fmt.Println("Heatlh Details ARN", *healthDetails.event.Arn) - fmt.Println("Health Details Event Description", healthDetails.eventDescription) - fmt.Println("Health Details Pending", healthDetails.affectedEntityPending) - fmt.Println("Health Details Pending", healthDetails.affectedEntityResolved) - fmt.Println("") - fmt.Println("-------------------------------------------") + m.Logger().Debugf("[AWS Health] [DescribeEventDetails] Event ARN : %s, Affected Entities (Pending) : %d, Affected Entities (Resolved): %d, Affected Entities (Others) : %d", *healthDetails.event.Arn, healthDetails.affectedEntityPending, healthDetails.affectedEntityResolved, healthDetails.affectedEntityOthers) events = append(events, createEvents(healthDetails)) - fmt.Println("Event size ", len(events)) } } if eventOutput.NextToken == nil { @@ -293,7 +272,7 @@ func getTimeValueOrDefault(t *time.Time) time.Time { // based on the given list of AffectedEntity instances. // Each AffectedEntity is converted into an AffectedEntityDetails struct, func createAffectedEntityDetails(affectedEntities []types.AffectedEntity) []AffectedEntityDetails { - var aed []AffectedEntityDetails + aed := []AffectedEntityDetails{} // Populate a slice of AffectedEntityDetails for _, entity := range affectedEntities { aed = append(aed, AffectedEntityDetails{ @@ -335,7 +314,7 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal hd.eventDescription = *(eventDetails.SuccessfulSet[0].EventDescription.LatestDescription) } - var affEntityTokString string = "" + var affEntityTokString = "" var nextToken *string var pending int32 = 0 var resolved int32 = 0 From 46d90e688f56af76d4d06ca09c862b90f04d9313 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Wed, 20 Mar 2024 06:17:25 +0000 Subject: [PATCH 08/38] Applying concurrancy and sync fix --- .../module/aws/awshealth/awshealth.go | 74 +++++++++++-------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 79d4869f0567..a8f1a4eab7ba 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -8,7 +8,9 @@ import ( "context" "crypto/sha256" "encoding/hex" + "errors" "fmt" + "sync" "time" awssdk "github.com/aws/aws-sdk-go-v2/aws" @@ -107,7 +109,7 @@ func (m *MetricSet) Fetch(ctx context.Context, report mb.ReporterV2) error { } }) - events := m.getEventsSummary(ctx, health_client, startTime, endTime) + events := m.getEventsSummary(ctx, health_client) for _, event := range events { report.Event(event) } @@ -120,29 +122,23 @@ func (m *MetricSet) Fetch(ctx context.Context, report mb.ReporterV2) error { func (m *MetricSet) getEventsSummary( ctx context.Context, awsHealth *health.Client, - startTime time.Time, - endTime time.Time, ) []mb.Event { var events []mb.Event eventFilter := types.EventFilter{ - // LastUpdatedTimes: []types.DateTimeRange{ - // { - // From: &startTime, - // To: &endTime, - // }, - // }, - //Regions: []string{"ap-south"}, EventStatusCodes: []types.EventStatusCode{ types.EventStatusCodeUpcoming, types.EventStatusCodeOpen, - // types.EventStatusCodeClosed, }, } var nextTokenString = "" var eventOutput *health.DescribeEventsOutput var err error + var wg sync.WaitGroup // WaitGroup for goroutine synchronization + errCh := make(chan error, maxResults) + + c := make(chan HealthDetails, maxResults) for { if nextTokenString == "" { eventOutput, err = awsHealth.DescribeEvents(ctx, @@ -166,11 +162,9 @@ func (m *MetricSet) getEventsSummary( return nil } ets := eventOutput.Events - c := make(chan HealthDetails) select { case <-ctx.Done(): // Context cancelled, handle graceful termination - m.Logger().Info("Context cancelled. Exiting gracefully.") close(c) return nil default: @@ -178,9 +172,23 @@ func (m *MetricSet) getEventsSummary( } for _, et := range ets { - m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getStringValueOrDefault(et.Arn)) - go m.getDescribeEventDetails(ctx, awsHealth, et, c) + m.Logger().Infof("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getStringValueOrDefault(et.Arn)) + // Increment the WaitGroup counter + wg.Add(1) + go func(et types.Event) { + defer wg.Done() // Decrement the WaitGroup counter when goroutine exits + err := m.getDescribeEventDetails(ctx, awsHealth, et, c) + if err != nil { + errCh <- err + } + }(et) } + // Wait for all goroutines to finish + // wg.Wait() + // for healthDetails := range c { + // m.Logger().Infof("[AWS Health] [DescribeEventDetails] Event ARN : %s, Affected Entities (Pending) : %d, Affected Entities (Resolved): %d, Affected Entities (Others) : %d", *healthDetails.event.Arn, healthDetails.affectedEntityPending, healthDetails.affectedEntityResolved, healthDetails.affectedEntityOthers) + // events = append(events, createEvents(healthDetails)) + // } for i := 0; i < len(ets); i++ { select { @@ -189,22 +197,25 @@ func (m *MetricSet) getEventsSummary( m.Logger().Debug("Context cancelled. Exiting gracefully.") close(c) return nil + case err := <-errCh: + // Handle errors received from goroutines + m.Logger().Error(err.Error()) case healthDetails, ok := <-c: if !ok { return nil } - m.Logger().Debugf("[AWS Health] [DescribeEventDetails] Event ARN : %s, Affected Entities (Pending) : %d, Affected Entities (Resolved): %d, Affected Entities (Others) : %d", *healthDetails.event.Arn, healthDetails.affectedEntityPending, healthDetails.affectedEntityResolved, healthDetails.affectedEntityOthers) + m.Logger().Infof("[AWS Health] [DescribeEventDetails] Event ARN : %s, Affected Entities (Pending) : %d, Affected Entities (Resolved): %d, Affected Entities (Others) : %d", *healthDetails.event.Arn, healthDetails.affectedEntityPending, healthDetails.affectedEntityResolved, healthDetails.affectedEntityOthers) events = append(events, createEvents(healthDetails)) } } + wg.Wait() if eventOutput.NextToken == nil { break } else { nextTokenString = *eventOutput.NextToken } - time.Sleep(10 * time.Millisecond) - close(c) } + close(c) return events } @@ -295,7 +306,7 @@ func generateEventID(eventID string) string { return prefix[:20] } -func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *health.Client, event types.Event, ch chan<- HealthDetails) { +func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *health.Client, event types.Event, ch chan<- HealthDetails) error { var hd HealthDetails hd.event = event eventDetails, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ @@ -303,13 +314,13 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal Locale: &Locale, }) if err != nil { - if ctx.Err() == context.Canceled { + if errors.Is(err, context.Canceled) { m.Logger().Debug("Context cancelled. Exiting gracefully.") - return + return nil } err = fmt.Errorf("AWS Health DescribeEventDetails failed with %w", err) m.Logger().Error(err.Error()) - return + return err } else { hd.eventDescription = *(eventDetails.SuccessfulSet[0].EventDescription.LatestDescription) } @@ -332,13 +343,13 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal err = fmt.Errorf("AWS Health DescribeAffectedEntities failed with %w", err) // Check if the error is due to context cancellation - if ctx.Err() == context.Canceled { + if errors.Is(err, context.Canceled) { m.Logger().Info("Context cancelled. Exiting gracefully.") - return + return nil } // Handle other errors m.Logger().Error(err.Error()) - return + return err } if affectedEntities != nil { nextToken = affectedEntities.NextToken @@ -370,18 +381,16 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal err = fmt.Errorf("AWS Health DescribeAffectedEntities failed with %w", err) // Check if the error is due to context cancellation - if ctx.Err() == context.Canceled { + if errors.Is(err, context.Canceled) { m.Logger().Info("Context cancelled. Exiting gracefully.") - return + return nil } // Handle other errors m.Logger().Error(err.Error()) - return + return err } if affectedEntities != nil { nextToken = affectedEntities.NextToken - - // nextToken = affectedEntities.NextToken hd.affectedEntities = append(hd.affectedEntities, affectedEntities.Entities...) for _, affEntity := range affectedEntities.Entities { @@ -406,14 +415,15 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal hd.affectedEntityResolved = resolved hd.affectedEntityPending = pending hd.affectedEntityOthers = others + select { case ch <- hd: // Writing to the channel default: // Channel is closed, - return + return nil } - time.Sleep(10 * time.Millisecond) + return nil } func getCurrentDateTime() string { From 66cf47c07e7c83960bcd24db6e52dfee763b2548 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Wed, 20 Mar 2024 10:11:37 +0000 Subject: [PATCH 09/38] Converted Info log to debug log. Added unit test script. Added build tags for integration tests --- .../module/aws/awshealth/awshealth.go | 6 +-- .../awshealth/awshealth_integration_test.go | 2 + .../module/aws/awshealth/awshealth_test.go | 50 +++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 x-pack/metricbeat/module/aws/awshealth/awshealth_test.go diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index a8f1a4eab7ba..0008d8f0f215 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -172,7 +172,7 @@ func (m *MetricSet) getEventsSummary( } for _, et := range ets { - m.Logger().Infof("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getStringValueOrDefault(et.Arn)) + m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getStringValueOrDefault(et.Arn)) // Increment the WaitGroup counter wg.Add(1) go func(et types.Event) { @@ -204,7 +204,7 @@ func (m *MetricSet) getEventsSummary( if !ok { return nil } - m.Logger().Infof("[AWS Health] [DescribeEventDetails] Event ARN : %s, Affected Entities (Pending) : %d, Affected Entities (Resolved): %d, Affected Entities (Others) : %d", *healthDetails.event.Arn, healthDetails.affectedEntityPending, healthDetails.affectedEntityResolved, healthDetails.affectedEntityOthers) + m.Logger().Debugf("[AWS Health] [DescribeEventDetails] Event ARN : %s, Affected Entities (Pending) : %d, Affected Entities (Resolved): %d, Affected Entities (Others) : %d", *healthDetails.event.Arn, healthDetails.affectedEntityPending, healthDetails.affectedEntityResolved, healthDetails.affectedEntityOthers) events = append(events, createEvents(healthDetails)) } } @@ -344,7 +344,7 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal // Check if the error is due to context cancellation if errors.Is(err, context.Canceled) { - m.Logger().Info("Context cancelled. Exiting gracefully.") + m.Logger().Debug("Context cancelled. Exiting gracefully.") return nil } // Handle other errors diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth_integration_test.go b/x-pack/metricbeat/module/aws/awshealth/awshealth_integration_test.go index 7edc1e7ec11c..3a9f99de077c 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth_integration_test.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth_integration_test.go @@ -2,6 +2,8 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. +//go:build aws && integration && awshealth + package awshealth import ( diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go new file mode 100644 index 000000000000..a05b409fe7b7 --- /dev/null +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go @@ -0,0 +1,50 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package awshealth + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestGetCurrentDateTime(t *testing.T) { + cdt := getCurrentDateTime() + assert.NotEmpty(t, cdt) +} + +func TestGenerateEventID(t *testing.T) { + cdt := getCurrentDateTime() + e_arn := "arn:aws:health:us-east-1::event/LAMBDA/AWS_LAMBDA_OPERATIONAL_NOTIFICATION/AWS_LAMBDA_OPERATIONAL_NOTIFICATION_e76969649ab96dd" + sc := "" + eventID := cdt + e_arn + sc + eid := generateEventID(eventID) + assert.NotEmpty(t, eid) +} + +func TestGetStringValueOrDefault(t *testing.T) { + // Test case 1: Test with non-nil string pointer + input := "hello" + result := getStringValueOrDefault(&input) + assert.Equal(t, "hello", result, "Result should match input string") + + // Test case 2: Test with nil string pointer + var nilString *string + result = getStringValueOrDefault(nilString) + assert.Equal(t, "", result, "Result should be an empty string") +} + +func TestGetTimeValueOrDefault(t *testing.T) { + // Test case 1: Test with non-nil time pointer + now := time.Now() + result := getTimeValueOrDefault(&now) + assert.Equal(t, now, result, "Result should match current time") + + // Test case 2: Test with nil time pointer + var nilTime *time.Time + result = getTimeValueOrDefault(nilTime) + assert.Equal(t, time.Time{}, result, "Result should be zero time") +} From 51a0c3adc2e65af79a479dd780552a456ad8b840 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Thu, 21 Mar 2024 06:11:42 +0000 Subject: [PATCH 10/38] Added awshealth to aws.yml.disabled --- x-pack/metricbeat/modules.d/aws.yml.disabled | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/metricbeat/modules.d/aws.yml.disabled b/x-pack/metricbeat/modules.d/aws.yml.disabled index ddd36a4c3269..28b6a2bd60ab 100644 --- a/x-pack/metricbeat/modules.d/aws.yml.disabled +++ b/x-pack/metricbeat/modules.d/aws.yml.disabled @@ -49,6 +49,7 @@ period: 24h metricsets: - s3_daily_storage + - awshealth - module: aws period: 1m latency: 5m From 8729967ca6c725954a8350ce27abdce3dd7c99d3 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Thu, 21 Mar 2024 06:56:04 +0000 Subject: [PATCH 11/38] Updating AWS meta config --- x-pack/metricbeat/module/aws/_meta/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/metricbeat/module/aws/_meta/config.yml b/x-pack/metricbeat/module/aws/_meta/config.yml index 6adf3af2fcd5..dacfadb9f312 100644 --- a/x-pack/metricbeat/module/aws/_meta/config.yml +++ b/x-pack/metricbeat/module/aws/_meta/config.yml @@ -46,6 +46,7 @@ period: 24h metricsets: - s3_daily_storage + - awshealth - module: aws period: 1m latency: 5m From 29b5c444bd987191c03959dc6b21e3ebdd552194 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Thu, 21 Mar 2024 08:20:47 +0000 Subject: [PATCH 12/38] Cleanup of Error Channel included --- x-pack/metricbeat/module/aws/awshealth/awshealth.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 0008d8f0f215..1bcc6dab69d6 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -216,6 +216,7 @@ func (m *MetricSet) getEventsSummary( } } close(c) + close(errCh) return events } From 2dfbb42995352cf835d50b60b66da3634453cdf0 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Fri, 22 Mar 2024 10:17:18 +0000 Subject: [PATCH 13/38] Code lint applied with minor optimisations --- .../module/aws/awshealth/awshealth.go | 146 +++++++++--------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 1bcc6dab69d6..4877f4787402 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -26,9 +26,10 @@ import ( const metricsetName = "awshealth" -var Locale string = "en" - -var maxResults int32 = 10 +var ( + locale = "en" + maxResults = int32(10) +) // init registers the MetricSet with the central registry as soon as the program // starts. The New function will be called later to instantiate an instance of @@ -50,7 +51,7 @@ type MetricSet struct { Config Config `config:"aws_health_config"` } -// Config holds the configuration specific for aws health metricset +// Config holds the configuration specific for aws-awshealth metricset type Config struct { EventARNPattern []string `config:"event_arns_pattern"` } @@ -65,7 +66,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { return nil, fmt.Errorf("error creating aws metricset: %w", err) } - cfgwarn.Beta("The aws awshealth metricset is beta.") + cfgwarn.Beta("The aws:awshealth metricset is beta.") config := struct { Config Config `config:"aws_health_config"` @@ -100,9 +101,6 @@ func (m *MetricSet) Fetch(ctx context.Context, report mb.ReporterV2) error { awsConfig := m.MetricSet.AwsConfig.Copy() - // Get startTime and endTime - startTime, endTime := aws.GetStartTimeEndTime(time.Now(), m.Period, m.Latency) - m.Logger().Debugf("[AWS Health] startTime = %s, endTime = %s", startTime, endTime) health_client := health.NewFromConfig(awsConfig, func(o *health.Options) { if config.AWSConfig.FIPSEnabled { o.EndpointOptions.UseFIPSEndpoint = awssdk.FIPSEndpointStateEnabled @@ -131,15 +129,19 @@ func (m *MetricSet) getEventsSummary( }, } - var nextTokenString = "" - var eventOutput *health.DescribeEventsOutput - var err error - var wg sync.WaitGroup // WaitGroup for goroutine synchronization - + var ( + nextTokenString string + eventOutput *health.DescribeEventsOutput + err error + wg sync.WaitGroup + ) errCh := make(chan error, maxResults) - c := make(chan HealthDetails, maxResults) + for { + // When invoking the DescribeEvents for the first time, there must not exist any NextToken. + // DescribeEvents API call will return the next token if there are more records left for querying + // If there exist no futher records to fetch, next toke will be empty. if nextTokenString == "" { eventOutput, err = awsHealth.DescribeEvents(ctx, &health.DescribeEventsInput{ @@ -157,7 +159,7 @@ func (m *MetricSet) getEventsSummary( ) } if err != nil { - err = fmt.Errorf("AWS Health DescribeEvents failed with %w", err) + err = fmt.Errorf("[AWS Health] DescribeEvents failed with : %w", err) m.Logger().Error(err.Error()) return nil } @@ -183,12 +185,6 @@ func (m *MetricSet) getEventsSummary( } }(et) } - // Wait for all goroutines to finish - // wg.Wait() - // for healthDetails := range c { - // m.Logger().Infof("[AWS Health] [DescribeEventDetails] Event ARN : %s, Affected Entities (Pending) : %d, Affected Entities (Resolved): %d, Affected Entities (Others) : %d", *healthDetails.event.Arn, healthDetails.affectedEntityPending, healthDetails.affectedEntityResolved, healthDetails.affectedEntityOthers) - // events = append(events, createEvents(healthDetails)) - // } for i := 0; i < len(ets); i++ { select { @@ -221,29 +217,30 @@ func (m *MetricSet) getEventsSummary( } func createEvents(hd HealthDetails) mb.Event { - event := mb.Event{} - event.MetricSetFields = mapstr.M{ - "event_arn": getStringValueOrDefault(hd.event.Arn), - "end_time": getTimeValueOrDefault(hd.event.EndTime), - "event_scope_code": getStringValueOrDefault((*string)(&hd.event.EventScopeCode)), - "event_type_category": getStringValueOrDefault((*string)(&hd.event.EventTypeCategory)), - "event_type_code": getStringValueOrDefault(hd.event.EventTypeCode), - "last_updated_time": getTimeValueOrDefault(hd.event.LastUpdatedTime), - "region": getStringValueOrDefault(hd.event.Region), - "service": getStringValueOrDefault(hd.event.Service), - "start_time": getTimeValueOrDefault(hd.event.StartTime), - "status_code": getStringValueOrDefault((*string)(&hd.event.StatusCode)), - "affected_entities_pending": hd.affectedEntityPending, - "affected_entities_resolved": hd.affectedEntityResolved, - "affected_entities_others": hd.affectedEntityOthers, - "affected_entities": createAffectedEntityDetails(hd.affectedEntities), - } - event.RootFields = mapstr.M{ - "cloud.provider": "aws", - } currentDate := getCurrentDateTime() eventID := currentDate + getStringValueOrDefault(hd.event.Arn) + getStringValueOrDefault((*string)(&hd.event.StatusCode)) - event.ID = generateEventID(eventID) + event := mb.Event{ + MetricSetFields: mapstr.M{ + "event_arn": getStringValueOrDefault(hd.event.Arn), + "end_time": getTimeValueOrDefault(hd.event.EndTime), + "event_scope_code": getStringValueOrDefault((*string)(&hd.event.EventScopeCode)), + "event_type_category": getStringValueOrDefault((*string)(&hd.event.EventTypeCategory)), + "event_type_code": getStringValueOrDefault(hd.event.EventTypeCode), + "last_updated_time": getTimeValueOrDefault(hd.event.LastUpdatedTime), + "region": getStringValueOrDefault(hd.event.Region), + "service": getStringValueOrDefault(hd.event.Service), + "start_time": getTimeValueOrDefault(hd.event.StartTime), + "status_code": getStringValueOrDefault((*string)(&hd.event.StatusCode)), + "affected_entities_pending": hd.affectedEntityPending, + "affected_entities_resolved": hd.affectedEntityResolved, + "affected_entities_others": hd.affectedEntityOthers, + "affected_entities": createAffectedEntityDetails(hd.affectedEntities), + }, + RootFields: mapstr.M{ + "cloud.provider": "aws", + }, + ID: generateEventID(eventID), + } return event } @@ -308,40 +305,41 @@ func generateEventID(eventID string) string { } func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *health.Client, event types.Event, ch chan<- HealthDetails) error { - var hd HealthDetails - hd.event = event + hd := HealthDetails{event: event} eventDetails, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ EventArns: []string{*event.Arn}, - Locale: &Locale, + Locale: &locale, }) if err != nil { if errors.Is(err, context.Canceled) { m.Logger().Debug("Context cancelled. Exiting gracefully.") return nil } - err = fmt.Errorf("AWS Health DescribeEventDetails failed with %w", err) + err = fmt.Errorf("[AWS Health] DescribeEventDetails failed with : %w", err) m.Logger().Error(err.Error()) return err } else { hd.eventDescription = *(eventDetails.SuccessfulSet[0].EventDescription.LatestDescription) } - var affEntityTokString = "" - var nextToken *string - var pending int32 = 0 - var resolved int32 = 0 - var others int32 = 0 + var ( + affEntityTokString string + nextToken *string + pending int32 + resolved int32 + others int32 + ) for { if affEntityTokString == "" { affectedEntities, err := awsHealth.DescribeAffectedEntities(ctx, &health.DescribeAffectedEntitiesInput{ Filter: &types.EntityFilter{ EventArns: []string{*event.Arn}, }, - Locale: &Locale, + Locale: &locale, MaxResults: &maxResults, }) if err != nil { - err = fmt.Errorf("AWS Health DescribeAffectedEntities failed with %w", err) + err = fmt.Errorf("AWS Health DescribeAffectedEntities failed with : %w", err) // Check if the error is due to context cancellation if errors.Is(err, context.Canceled) { @@ -357,14 +355,15 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal hd.affectedEntities = append(hd.affectedEntities, affectedEntities.Entities...) for _, affEntity := range affectedEntities.Entities { - if affEntity.StatusCode != "" { - if affEntity.StatusCode == "PENDING" { - pending++ - } else if affEntity.StatusCode == "RESOLVED" { - resolved++ - } else { - others++ - } + switch affEntity.StatusCode { + case "PENDING": + pending++ + case "RESOLVED": + resolved++ + case "": + // Do nothing + default: + others++ } } } @@ -374,12 +373,12 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal Filter: &types.EntityFilter{ EventArns: []string{*event.Arn}, }, - Locale: &Locale, + Locale: &locale, MaxResults: &maxResults, NextToken: &affEntityTokString, }) if err != nil { - err = fmt.Errorf("AWS Health DescribeAffectedEntities failed with %w", err) + err = fmt.Errorf("AWS Health DescribeAffectedEntities failed with : %w", err) // Check if the error is due to context cancellation if errors.Is(err, context.Canceled) { @@ -395,14 +394,15 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal hd.affectedEntities = append(hd.affectedEntities, affectedEntities.Entities...) for _, affEntity := range affectedEntities.Entities { - if affEntity.StatusCode != "" { - if affEntity.StatusCode == "PENDING" { - pending++ - } else if affEntity.StatusCode == "RESOLVED" { - resolved++ - } else { - others++ - } + switch affEntity.StatusCode { + case "PENDING": + pending++ + case "RESOLVED": + resolved++ + case "": + // Do nothing + default: + others++ } } } @@ -428,6 +428,6 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal } func getCurrentDateTime() string { - currentTime := time.Now() - return fmt.Sprintf("%04d%02d%02d%02d%02d%02d", currentTime.Year(), int(currentTime.Month()), currentTime.Day(), currentTime.Hour(), currentTime.Minute(), currentTime.Second()) + // Reference: https://golang.org/pkg/time/#Time.Format + return time.Now().Format("20060102150405") } From 62417b4de59fe6ac35b84c5ca555c23ceeaba79d Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Fri, 22 Mar 2024 10:34:54 +0000 Subject: [PATCH 14/38] Fixed typo --- x-pack/metricbeat/module/aws/awshealth/awshealth.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 4877f4787402..cdd9e2b54796 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -141,7 +141,7 @@ func (m *MetricSet) getEventsSummary( for { // When invoking the DescribeEvents for the first time, there must not exist any NextToken. // DescribeEvents API call will return the next token if there are more records left for querying - // If there exist no futher records to fetch, next toke will be empty. + // If there exist no further records to fetch, next toke will be empty. if nextTokenString == "" { eventOutput, err = awsHealth.DescribeEvents(ctx, &health.DescribeEventsInput{ @@ -330,6 +330,9 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal others int32 ) for { + // When invoking the DescribeAffectedEntities for the first time, there must not exist any NextToken. + // DescribeAffectedEntities API call will return the next token if there are more records left for querying + // If there exist no further records to fetch, next toke will be empty. if affEntityTokString == "" { affectedEntities, err := awsHealth.DescribeAffectedEntities(ctx, &health.DescribeAffectedEntitiesInput{ Filter: &types.EntityFilter{ From 970855d12a1a47882c2d49ea8845031c62b99100 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Sun, 24 Mar 2024 10:05:19 +0000 Subject: [PATCH 15/38] Add kibana dashboard --- .../fce44690-e9c2-11ee-9f73-dfef113e2924.json | 966 ++++++++++++++++++ 1 file changed, 966 insertions(+) create mode 100644 x-pack/metricbeat/module/aws/awshealth/_meta/kibana/8/dashboard/fce44690-e9c2-11ee-9f73-dfef113e2924.json diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/kibana/8/dashboard/fce44690-e9c2-11ee-9f73-dfef113e2924.json b/x-pack/metricbeat/module/aws/awshealth/_meta/kibana/8/dashboard/fce44690-e9c2-11ee-9f73-dfef113e2924.json new file mode 100644 index 000000000000..d42cc2b24398 --- /dev/null +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/kibana/8/dashboard/fce44690-e9c2-11ee-9f73-dfef113e2924.json @@ -0,0 +1,966 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "optionsJSON": { + "hidePanelTitles": false, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "useMargins": true + }, + "panelsJSON": [ + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "layers": { + "5b2a4b04-92d5-4ac9-96de-ac4d4687217c": { + "columnOrder": [ + "37fde872-7524-4cf2-a120-05568c2aef7f" + ], + "columns": { + "37fde872-7524-4cf2-a120-05568c2aef7f": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Event Count", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "aws.awshealth.event_arn" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "color": "#6092C0", + "layerId": "5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "layerType": "data", + "metricAccessor": "37fde872-7524-4cf2-a120-05568c2aef7f" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsMetric" + }, + "enhancements": {}, + "hidePanelTitles": false + }, + "gridData": { + "h": 8, + "i": "7237f280-dd55-41d0-8d24-9e42ee51baa6", + "w": 12, + "x": 0, + "y": 0 + }, + "panelIndex": "7237f280-dd55-41d0-8d24-9e42ee51baa6", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "layers": { + "5b2a4b04-92d5-4ac9-96de-ac4d4687217c": { + "columnOrder": [ + "37fde872-7524-4cf2-a120-05568c2aef7f" + ], + "columns": { + "37fde872-7524-4cf2-a120-05568c2aef7f": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Affected Entities (Pending)", + "operationType": "sum", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "aws.awshealth.affected_entities_pending" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "color": "#E7664C", + "layerId": "5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "layerType": "data", + "metricAccessor": "37fde872-7524-4cf2-a120-05568c2aef7f" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsMetric" + }, + "enhancements": {} + }, + "gridData": { + "h": 8, + "i": "cc683ea6-423c-44bb-969b-9400d0a10fb8", + "w": 11, + "x": 12, + "y": 0 + }, + "panelIndex": "cc683ea6-423c-44bb-969b-9400d0a10fb8", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "layers": { + "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44": { + "columnOrder": [ + "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5", + "c4667d35-2756-4eb1-9321-869092c30d4b" + ], + "columns": { + "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5": { + "dataType": "string", + "isBucketed": true, + "label": "Top 5 values of aws.awshealth.service", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "c4667d35-2756-4eb1-9321-869092c30d4b", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "aws.awshealth.service" + }, + "c4667d35-2756-4eb1-9321-869092c30d4b": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Event Count", + "operationType": "count", + "params": { + "emptyAsNull": true, + "format": { + "id": "number", + "params": { + "decimals": 0 + } + } + }, + "scale": "ratio", + "sourceField": "aws.awshealth.event_arn" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "breakdownByAccessor": "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5", + "layerId": "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "layerType": "data", + "maxCols": 3, + "metricAccessor": "c4667d35-2756-4eb1-9321-869092c30d4b" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsMetric" + }, + "enhancements": {}, + "hidePanelTitles": false + }, + "gridData": { + "h": 16, + "i": "d9bee328-436d-4936-9942-17ba670c8538", + "w": 25, + "x": 23, + "y": 0 + }, + "panelIndex": "d9bee328-436d-4936-9942-17ba670c8538", + "title": "Event Count per Service", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "layers": { + "5b2a4b04-92d5-4ac9-96de-ac4d4687217c": { + "columnOrder": [ + "37fde872-7524-4cf2-a120-05568c2aef7f" + ], + "columns": { + "37fde872-7524-4cf2-a120-05568c2aef7f": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Affected Entities (Resolved)", + "operationType": "sum", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "aws.awshealth.affected_entities_resolved" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "color": "#54B399", + "layerId": "5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "layerType": "data", + "metricAccessor": "37fde872-7524-4cf2-a120-05568c2aef7f" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsMetric" + }, + "enhancements": {} + }, + "gridData": { + "h": 8, + "i": "34211b75-8a7d-40d5-ac6f-af9ce7ecfe34", + "w": 12, + "x": 0, + "y": 8 + }, + "panelIndex": "34211b75-8a7d-40d5-ac6f-af9ce7ecfe34", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "layers": { + "5b2a4b04-92d5-4ac9-96de-ac4d4687217c": { + "columnOrder": [ + "37fde872-7524-4cf2-a120-05568c2aef7f" + ], + "columns": { + "37fde872-7524-4cf2-a120-05568c2aef7f": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Affected Entities (Others)", + "operationType": "sum", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "aws.awshealth.affected_entities_others" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "color": "#D6BF57", + "layerId": "5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "layerType": "data", + "metricAccessor": "37fde872-7524-4cf2-a120-05568c2aef7f" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsMetric" + }, + "enhancements": {} + }, + "gridData": { + "h": 8, + "i": "d3a13b2f-738b-4b93-b8d7-2852e2b46d52", + "w": 11, + "x": 12, + "y": 8 + }, + "panelIndex": "d3a13b2f-738b-4b93-b8d7-2852e2b46d52", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44": { + "columnOrder": [ + "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5", + "c4667d35-2756-4eb1-9321-869092c30d4b" + ], + "columns": { + "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5": { + "dataType": "string", + "isBucketed": true, + "label": "Top 5 values of aws.awshealth.service", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "c4667d35-2756-4eb1-9321-869092c30d4b", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "aws.awshealth.service" + }, + "c4667d35-2756-4eb1-9321-869092c30d4b": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Pending", + "operationType": "sum", + "params": { + "emptyAsNull": true, + "format": { + "id": "number", + "params": { + "decimals": 0 + } + } + }, + "scale": "ratio", + "sourceField": "aws.awshealth.affected_entities_pending" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "gridConfig": { + "isCellLabelVisible": false, + "isXAxisLabelVisible": true, + "isXAxisTitleVisible": false, + "isYAxisLabelVisible": true, + "isYAxisTitleVisible": false, + "type": "heatmap_grid" + }, + "layerId": "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "layerType": "data", + "legend": { + "isVisible": true, + "position": "right", + "type": "heatmap_legend" + }, + "palette": { + "accessor": "c4667d35-2756-4eb1-9321-869092c30d4b", + "name": "negative", + "params": { + "continuity": "above", + "name": "negative", + "rangeMax": null, + "rangeMin": 0, + "reverse": false, + "stops": [ + { + "color": "#fbddd6", + "stop": 0 + }, + { + "color": "#f3bbaf", + "stop": 20 + }, + { + "color": "#e99a89", + "stop": 40 + }, + { + "color": "#db7965", + "stop": 60 + }, + { + "color": "#cc5642", + "stop": 80 + } + ] + }, + "type": "palette" + }, + "shape": "heatmap", + "valueAccessor": "c4667d35-2756-4eb1-9321-869092c30d4b", + "xAccessor": "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsHeatmap" + }, + "enhancements": {}, + "hidePanelTitles": false + }, + "gridData": { + "h": 14, + "i": "fd710b8a-c2a7-45a7-8c55-13430ab25039", + "w": 23, + "x": 0, + "y": 16 + }, + "panelIndex": "fd710b8a-c2a7-45a7-8c55-13430ab25039", + "title": "Affected Entities (Pending)", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44": { + "columnOrder": [ + "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5", + "edd0b2f0-5ba3-4111-946b-6d9dedccd256" + ], + "columns": { + "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5": { + "dataType": "string", + "isBucketed": true, + "label": "Top 5 values of aws.awshealth.service", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "aws.awshealth.service" + }, + "edd0b2f0-5ba3-4111-946b-6d9dedccd256": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Resolved", + "operationType": "sum", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "aws.awshealth.affected_entities_resolved" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "gridConfig": { + "isCellLabelVisible": false, + "isXAxisLabelVisible": true, + "isXAxisTitleVisible": false, + "isYAxisLabelVisible": true, + "isYAxisTitleVisible": false, + "type": "heatmap_grid" + }, + "layerId": "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "layerType": "data", + "legend": { + "isVisible": true, + "position": "right", + "type": "heatmap_legend" + }, + "palette": { + "accessor": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", + "name": "positive", + "params": { + "continuity": "above", + "name": "positive", + "rangeMax": null, + "rangeMin": 0, + "reverse": false, + "stops": [ + { + "color": "#d6e9e4", + "stop": 0 + }, + { + "color": "#aed3ca", + "stop": 20 + }, + { + "color": "#85bdb1", + "stop": 40 + }, + { + "color": "#5aa898", + "stop": 60 + }, + { + "color": "#209280", + "stop": 80 + } + ] + }, + "type": "palette" + }, + "shape": "heatmap", + "valueAccessor": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", + "xAccessor": "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsHeatmap" + }, + "enhancements": {}, + "hidePanelTitles": false + }, + "gridData": { + "h": 14, + "i": "404e1f7a-ea8c-415e-90f0-8a1cc8f9fdad", + "w": 25, + "x": 23, + "y": 16 + }, + "panelIndex": "404e1f7a-ea8c-415e-90f0-8a1cc8f9fdad", + "title": "Affected Entities (Resolved)", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "layers": { + "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44": { + "columnOrder": [ + "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5", + "edd0b2f0-5ba3-4111-946b-6d9dedccd256" + ], + "columns": { + "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5": { + "dataType": "string", + "isBucketed": true, + "label": "Top 5 values of aws.awshealth.service", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "aws.awshealth.service" + }, + "edd0b2f0-5ba3-4111-946b-6d9dedccd256": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Affected Entities (Others)", + "operationType": "sum", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "aws.awshealth.affected_entities_others" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "gridConfig": { + "isCellLabelVisible": false, + "isXAxisLabelVisible": true, + "isXAxisTitleVisible": false, + "isYAxisLabelVisible": true, + "isYAxisTitleVisible": false, + "type": "heatmap_grid" + }, + "layerId": "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "layerType": "data", + "legend": { + "isVisible": true, + "position": "right", + "type": "heatmap_legend" + }, + "palette": { + "accessor": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", + "name": "warm", + "params": { + "continuity": "above", + "name": "warm", + "rangeMax": null, + "rangeMin": 0, + "reverse": false, + "stops": [ + { + "color": "#f7e0b8", + "stop": 0 + }, + { + "color": "#f2c596", + "stop": 20 + }, + { + "color": "#eca976", + "stop": 40 + }, + { + "color": "#e78c5b", + "stop": 60 + }, + { + "color": "#e7664c", + "stop": 80 + } + ] + }, + "type": "palette" + }, + "shape": "heatmap", + "valueAccessor": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", + "xAccessor": "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsHeatmap" + }, + "enhancements": {}, + "hidePanelTitles": false + }, + "gridData": { + "h": 13, + "i": "6da4d7e2-1f3a-44b7-8848-2d172228af18", + "w": 23, + "x": 0, + "y": 30 + }, + "panelIndex": "6da4d7e2-1f3a-44b7-8848-2d172228af18", + "title": "Affected Entities (Others)", + "type": "lens" + } + ], + "timeRestore": false, + "title": "[AWS Health] Overview", + "version": 1 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2024-03-24T09:43:37.083Z", + "id": "fce44690-e9c2-11ee-9f73-dfef113e2924", + "managed": false, + "references": [ + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "7237f280-dd55-41d0-8d24-9e42ee51baa6:indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "type": "index-pattern" + }, + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "cc683ea6-423c-44bb-969b-9400d0a10fb8:indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "type": "index-pattern" + }, + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "d9bee328-436d-4936-9942-17ba670c8538:indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "type": "index-pattern" + }, + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "34211b75-8a7d-40d5-ac6f-af9ce7ecfe34:indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "type": "index-pattern" + }, + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "d3a13b2f-738b-4b93-b8d7-2852e2b46d52:indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", + "type": "index-pattern" + }, + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "fd710b8a-c2a7-45a7-8c55-13430ab25039:indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "type": "index-pattern" + }, + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "404e1f7a-ea8c-415e-90f0-8a1cc8f9fdad:indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "type": "index-pattern" + }, + { + "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", + "name": "6da4d7e2-1f3a-44b7-8848-2d172228af18:indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", + "type": "index-pattern" + } + ], + "type": "dashboard", + "typeMigrationVersion": "8.9.0", + "updated_at": "2024-03-24T09:43:37.083Z", + "version": "Wzc2MywxXQ==" +} \ No newline at end of file From 7b74fc0332d720baa40f6e92a3ecd512d13e7249 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Sun, 24 Mar 2024 13:26:08 +0000 Subject: [PATCH 16/38] Removing dashboard files due to formatting error --- .../fce44690-e9c2-11ee-9f73-dfef113e2924.json | 966 ------------------ 1 file changed, 966 deletions(-) delete mode 100644 x-pack/metricbeat/module/aws/awshealth/_meta/kibana/8/dashboard/fce44690-e9c2-11ee-9f73-dfef113e2924.json diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/kibana/8/dashboard/fce44690-e9c2-11ee-9f73-dfef113e2924.json b/x-pack/metricbeat/module/aws/awshealth/_meta/kibana/8/dashboard/fce44690-e9c2-11ee-9f73-dfef113e2924.json deleted file mode 100644 index d42cc2b24398..000000000000 --- a/x-pack/metricbeat/module/aws/awshealth/_meta/kibana/8/dashboard/fce44690-e9c2-11ee-9f73-dfef113e2924.json +++ /dev/null @@ -1,966 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": { - "filter": [], - "query": { - "language": "kuery", - "query": "" - } - } - }, - "optionsJSON": { - "hidePanelTitles": false, - "syncColors": false, - "syncCursor": true, - "syncTooltips": false, - "useMargins": true - }, - "panelsJSON": [ - { - "embeddableConfig": { - "attributes": { - "description": "", - "references": [ - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "type": "index-pattern" - } - ], - "state": { - "adHocDataViews": {}, - "datasourceStates": { - "formBased": { - "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "layers": { - "5b2a4b04-92d5-4ac9-96de-ac4d4687217c": { - "columnOrder": [ - "37fde872-7524-4cf2-a120-05568c2aef7f" - ], - "columns": { - "37fde872-7524-4cf2-a120-05568c2aef7f": { - "customLabel": true, - "dataType": "number", - "isBucketed": false, - "label": "Event Count", - "operationType": "count", - "params": { - "emptyAsNull": true - }, - "scale": "ratio", - "sourceField": "aws.awshealth.event_arn" - } - }, - "ignoreGlobalFilters": false, - "incompleteColumns": {}, - "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "sampling": 1 - } - } - }, - "indexpattern": { - "layers": {} - }, - "textBased": { - "layers": {} - } - }, - "filters": [], - "internalReferences": [], - "query": { - "language": "kuery", - "query": "" - }, - "visualization": { - "color": "#6092C0", - "layerId": "5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "layerType": "data", - "metricAccessor": "37fde872-7524-4cf2-a120-05568c2aef7f" - } - }, - "title": "", - "type": "lens", - "visualizationType": "lnsMetric" - }, - "enhancements": {}, - "hidePanelTitles": false - }, - "gridData": { - "h": 8, - "i": "7237f280-dd55-41d0-8d24-9e42ee51baa6", - "w": 12, - "x": 0, - "y": 0 - }, - "panelIndex": "7237f280-dd55-41d0-8d24-9e42ee51baa6", - "type": "lens" - }, - { - "embeddableConfig": { - "attributes": { - "description": "", - "references": [ - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "type": "index-pattern" - } - ], - "state": { - "adHocDataViews": {}, - "datasourceStates": { - "formBased": { - "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "layers": { - "5b2a4b04-92d5-4ac9-96de-ac4d4687217c": { - "columnOrder": [ - "37fde872-7524-4cf2-a120-05568c2aef7f" - ], - "columns": { - "37fde872-7524-4cf2-a120-05568c2aef7f": { - "customLabel": true, - "dataType": "number", - "isBucketed": false, - "label": "Affected Entities (Pending)", - "operationType": "sum", - "params": { - "emptyAsNull": true - }, - "scale": "ratio", - "sourceField": "aws.awshealth.affected_entities_pending" - } - }, - "ignoreGlobalFilters": false, - "incompleteColumns": {}, - "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "sampling": 1 - } - } - }, - "indexpattern": { - "layers": {} - }, - "textBased": { - "layers": {} - } - }, - "filters": [], - "internalReferences": [], - "query": { - "language": "kuery", - "query": "" - }, - "visualization": { - "color": "#E7664C", - "layerId": "5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "layerType": "data", - "metricAccessor": "37fde872-7524-4cf2-a120-05568c2aef7f" - } - }, - "title": "", - "type": "lens", - "visualizationType": "lnsMetric" - }, - "enhancements": {} - }, - "gridData": { - "h": 8, - "i": "cc683ea6-423c-44bb-969b-9400d0a10fb8", - "w": 11, - "x": 12, - "y": 0 - }, - "panelIndex": "cc683ea6-423c-44bb-969b-9400d0a10fb8", - "type": "lens" - }, - { - "embeddableConfig": { - "attributes": { - "description": "", - "references": [ - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "type": "index-pattern" - } - ], - "state": { - "adHocDataViews": {}, - "datasourceStates": { - "formBased": { - "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "layers": { - "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44": { - "columnOrder": [ - "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5", - "c4667d35-2756-4eb1-9321-869092c30d4b" - ], - "columns": { - "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5": { - "dataType": "string", - "isBucketed": true, - "label": "Top 5 values of aws.awshealth.service", - "operationType": "terms", - "params": { - "exclude": [], - "excludeIsRegex": false, - "include": [], - "includeIsRegex": false, - "missingBucket": false, - "orderBy": { - "columnId": "c4667d35-2756-4eb1-9321-869092c30d4b", - "type": "column" - }, - "orderDirection": "desc", - "otherBucket": true, - "parentFormat": { - "id": "terms" - }, - "size": 5 - }, - "scale": "ordinal", - "sourceField": "aws.awshealth.service" - }, - "c4667d35-2756-4eb1-9321-869092c30d4b": { - "customLabel": true, - "dataType": "number", - "isBucketed": false, - "label": "Event Count", - "operationType": "count", - "params": { - "emptyAsNull": true, - "format": { - "id": "number", - "params": { - "decimals": 0 - } - } - }, - "scale": "ratio", - "sourceField": "aws.awshealth.event_arn" - } - }, - "ignoreGlobalFilters": false, - "incompleteColumns": {}, - "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "sampling": 1 - } - } - }, - "indexpattern": { - "layers": {} - }, - "textBased": { - "layers": {} - } - }, - "filters": [], - "internalReferences": [], - "query": { - "language": "kuery", - "query": "" - }, - "visualization": { - "breakdownByAccessor": "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5", - "layerId": "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "layerType": "data", - "maxCols": 3, - "metricAccessor": "c4667d35-2756-4eb1-9321-869092c30d4b" - } - }, - "title": "", - "type": "lens", - "visualizationType": "lnsMetric" - }, - "enhancements": {}, - "hidePanelTitles": false - }, - "gridData": { - "h": 16, - "i": "d9bee328-436d-4936-9942-17ba670c8538", - "w": 25, - "x": 23, - "y": 0 - }, - "panelIndex": "d9bee328-436d-4936-9942-17ba670c8538", - "title": "Event Count per Service", - "type": "lens" - }, - { - "embeddableConfig": { - "attributes": { - "description": "", - "references": [ - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "type": "index-pattern" - } - ], - "state": { - "adHocDataViews": {}, - "datasourceStates": { - "formBased": { - "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "layers": { - "5b2a4b04-92d5-4ac9-96de-ac4d4687217c": { - "columnOrder": [ - "37fde872-7524-4cf2-a120-05568c2aef7f" - ], - "columns": { - "37fde872-7524-4cf2-a120-05568c2aef7f": { - "customLabel": true, - "dataType": "number", - "isBucketed": false, - "label": "Affected Entities (Resolved)", - "operationType": "sum", - "params": { - "emptyAsNull": true - }, - "scale": "ratio", - "sourceField": "aws.awshealth.affected_entities_resolved" - } - }, - "ignoreGlobalFilters": false, - "incompleteColumns": {}, - "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "sampling": 1 - } - } - }, - "indexpattern": { - "layers": {} - }, - "textBased": { - "layers": {} - } - }, - "filters": [], - "internalReferences": [], - "query": { - "language": "kuery", - "query": "" - }, - "visualization": { - "color": "#54B399", - "layerId": "5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "layerType": "data", - "metricAccessor": "37fde872-7524-4cf2-a120-05568c2aef7f" - } - }, - "title": "", - "type": "lens", - "visualizationType": "lnsMetric" - }, - "enhancements": {} - }, - "gridData": { - "h": 8, - "i": "34211b75-8a7d-40d5-ac6f-af9ce7ecfe34", - "w": 12, - "x": 0, - "y": 8 - }, - "panelIndex": "34211b75-8a7d-40d5-ac6f-af9ce7ecfe34", - "type": "lens" - }, - { - "embeddableConfig": { - "attributes": { - "description": "", - "references": [ - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "type": "index-pattern" - } - ], - "state": { - "adHocDataViews": {}, - "datasourceStates": { - "formBased": { - "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "layers": { - "5b2a4b04-92d5-4ac9-96de-ac4d4687217c": { - "columnOrder": [ - "37fde872-7524-4cf2-a120-05568c2aef7f" - ], - "columns": { - "37fde872-7524-4cf2-a120-05568c2aef7f": { - "customLabel": true, - "dataType": "number", - "isBucketed": false, - "label": "Affected Entities (Others)", - "operationType": "sum", - "params": { - "emptyAsNull": true - }, - "scale": "ratio", - "sourceField": "aws.awshealth.affected_entities_others" - } - }, - "ignoreGlobalFilters": false, - "incompleteColumns": {}, - "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "sampling": 1 - } - } - }, - "indexpattern": { - "layers": {} - }, - "textBased": { - "layers": {} - } - }, - "filters": [], - "internalReferences": [], - "query": { - "language": "kuery", - "query": "" - }, - "visualization": { - "color": "#D6BF57", - "layerId": "5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "layerType": "data", - "metricAccessor": "37fde872-7524-4cf2-a120-05568c2aef7f" - } - }, - "title": "", - "type": "lens", - "visualizationType": "lnsMetric" - }, - "enhancements": {} - }, - "gridData": { - "h": 8, - "i": "d3a13b2f-738b-4b93-b8d7-2852e2b46d52", - "w": 11, - "x": 12, - "y": 8 - }, - "panelIndex": "d3a13b2f-738b-4b93-b8d7-2852e2b46d52", - "type": "lens" - }, - { - "embeddableConfig": { - "attributes": { - "description": "", - "references": [ - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "type": "index-pattern" - } - ], - "state": { - "adHocDataViews": {}, - "datasourceStates": { - "formBased": { - "layers": { - "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44": { - "columnOrder": [ - "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5", - "c4667d35-2756-4eb1-9321-869092c30d4b" - ], - "columns": { - "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5": { - "dataType": "string", - "isBucketed": true, - "label": "Top 5 values of aws.awshealth.service", - "operationType": "terms", - "params": { - "exclude": [], - "excludeIsRegex": false, - "include": [], - "includeIsRegex": false, - "missingBucket": false, - "orderBy": { - "columnId": "c4667d35-2756-4eb1-9321-869092c30d4b", - "type": "column" - }, - "orderDirection": "desc", - "otherBucket": true, - "parentFormat": { - "id": "terms" - }, - "size": 5 - }, - "scale": "ordinal", - "sourceField": "aws.awshealth.service" - }, - "c4667d35-2756-4eb1-9321-869092c30d4b": { - "customLabel": true, - "dataType": "number", - "isBucketed": false, - "label": "Pending", - "operationType": "sum", - "params": { - "emptyAsNull": true, - "format": { - "id": "number", - "params": { - "decimals": 0 - } - } - }, - "scale": "ratio", - "sourceField": "aws.awshealth.affected_entities_pending" - } - }, - "ignoreGlobalFilters": false, - "incompleteColumns": {}, - "sampling": 1 - } - } - }, - "indexpattern": { - "layers": {} - }, - "textBased": { - "layers": {} - } - }, - "filters": [], - "internalReferences": [], - "query": { - "language": "kuery", - "query": "" - }, - "visualization": { - "gridConfig": { - "isCellLabelVisible": false, - "isXAxisLabelVisible": true, - "isXAxisTitleVisible": false, - "isYAxisLabelVisible": true, - "isYAxisTitleVisible": false, - "type": "heatmap_grid" - }, - "layerId": "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "layerType": "data", - "legend": { - "isVisible": true, - "position": "right", - "type": "heatmap_legend" - }, - "palette": { - "accessor": "c4667d35-2756-4eb1-9321-869092c30d4b", - "name": "negative", - "params": { - "continuity": "above", - "name": "negative", - "rangeMax": null, - "rangeMin": 0, - "reverse": false, - "stops": [ - { - "color": "#fbddd6", - "stop": 0 - }, - { - "color": "#f3bbaf", - "stop": 20 - }, - { - "color": "#e99a89", - "stop": 40 - }, - { - "color": "#db7965", - "stop": 60 - }, - { - "color": "#cc5642", - "stop": 80 - } - ] - }, - "type": "palette" - }, - "shape": "heatmap", - "valueAccessor": "c4667d35-2756-4eb1-9321-869092c30d4b", - "xAccessor": "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5" - } - }, - "title": "", - "type": "lens", - "visualizationType": "lnsHeatmap" - }, - "enhancements": {}, - "hidePanelTitles": false - }, - "gridData": { - "h": 14, - "i": "fd710b8a-c2a7-45a7-8c55-13430ab25039", - "w": 23, - "x": 0, - "y": 16 - }, - "panelIndex": "fd710b8a-c2a7-45a7-8c55-13430ab25039", - "title": "Affected Entities (Pending)", - "type": "lens" - }, - { - "embeddableConfig": { - "attributes": { - "description": "", - "references": [ - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "type": "index-pattern" - } - ], - "state": { - "adHocDataViews": {}, - "datasourceStates": { - "formBased": { - "layers": { - "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44": { - "columnOrder": [ - "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5", - "edd0b2f0-5ba3-4111-946b-6d9dedccd256" - ], - "columns": { - "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5": { - "dataType": "string", - "isBucketed": true, - "label": "Top 5 values of aws.awshealth.service", - "operationType": "terms", - "params": { - "exclude": [], - "excludeIsRegex": false, - "include": [], - "includeIsRegex": false, - "missingBucket": false, - "orderBy": { - "columnId": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", - "type": "column" - }, - "orderDirection": "desc", - "otherBucket": true, - "parentFormat": { - "id": "terms" - }, - "size": 5 - }, - "scale": "ordinal", - "sourceField": "aws.awshealth.service" - }, - "edd0b2f0-5ba3-4111-946b-6d9dedccd256": { - "customLabel": true, - "dataType": "number", - "isBucketed": false, - "label": "Resolved", - "operationType": "sum", - "params": { - "emptyAsNull": true - }, - "scale": "ratio", - "sourceField": "aws.awshealth.affected_entities_resolved" - } - }, - "ignoreGlobalFilters": false, - "incompleteColumns": {}, - "sampling": 1 - } - } - }, - "indexpattern": { - "layers": {} - }, - "textBased": { - "layers": {} - } - }, - "filters": [], - "internalReferences": [], - "query": { - "language": "kuery", - "query": "" - }, - "visualization": { - "gridConfig": { - "isCellLabelVisible": false, - "isXAxisLabelVisible": true, - "isXAxisTitleVisible": false, - "isYAxisLabelVisible": true, - "isYAxisTitleVisible": false, - "type": "heatmap_grid" - }, - "layerId": "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "layerType": "data", - "legend": { - "isVisible": true, - "position": "right", - "type": "heatmap_legend" - }, - "palette": { - "accessor": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", - "name": "positive", - "params": { - "continuity": "above", - "name": "positive", - "rangeMax": null, - "rangeMin": 0, - "reverse": false, - "stops": [ - { - "color": "#d6e9e4", - "stop": 0 - }, - { - "color": "#aed3ca", - "stop": 20 - }, - { - "color": "#85bdb1", - "stop": 40 - }, - { - "color": "#5aa898", - "stop": 60 - }, - { - "color": "#209280", - "stop": 80 - } - ] - }, - "type": "palette" - }, - "shape": "heatmap", - "valueAccessor": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", - "xAccessor": "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5" - } - }, - "title": "", - "type": "lens", - "visualizationType": "lnsHeatmap" - }, - "enhancements": {}, - "hidePanelTitles": false - }, - "gridData": { - "h": 14, - "i": "404e1f7a-ea8c-415e-90f0-8a1cc8f9fdad", - "w": 25, - "x": 23, - "y": 16 - }, - "panelIndex": "404e1f7a-ea8c-415e-90f0-8a1cc8f9fdad", - "title": "Affected Entities (Resolved)", - "type": "lens" - }, - { - "embeddableConfig": { - "attributes": { - "description": "", - "references": [ - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "type": "index-pattern" - } - ], - "state": { - "adHocDataViews": {}, - "datasourceStates": { - "formBased": { - "currentIndexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "layers": { - "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44": { - "columnOrder": [ - "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5", - "edd0b2f0-5ba3-4111-946b-6d9dedccd256" - ], - "columns": { - "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5": { - "dataType": "string", - "isBucketed": true, - "label": "Top 5 values of aws.awshealth.service", - "operationType": "terms", - "params": { - "exclude": [], - "excludeIsRegex": false, - "include": [], - "includeIsRegex": false, - "missingBucket": false, - "orderBy": { - "columnId": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", - "type": "column" - }, - "orderDirection": "desc", - "otherBucket": true, - "parentFormat": { - "id": "terms" - }, - "size": 5 - }, - "scale": "ordinal", - "sourceField": "aws.awshealth.service" - }, - "edd0b2f0-5ba3-4111-946b-6d9dedccd256": { - "customLabel": true, - "dataType": "number", - "isBucketed": false, - "label": "Affected Entities (Others)", - "operationType": "sum", - "params": { - "emptyAsNull": true - }, - "scale": "ratio", - "sourceField": "aws.awshealth.affected_entities_others" - } - }, - "ignoreGlobalFilters": false, - "incompleteColumns": {}, - "indexPatternId": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "sampling": 1 - } - } - }, - "indexpattern": { - "layers": {} - }, - "textBased": { - "layers": {} - } - }, - "filters": [], - "internalReferences": [], - "query": { - "language": "kuery", - "query": "" - }, - "visualization": { - "gridConfig": { - "isCellLabelVisible": false, - "isXAxisLabelVisible": true, - "isXAxisTitleVisible": false, - "isYAxisLabelVisible": true, - "isYAxisTitleVisible": false, - "type": "heatmap_grid" - }, - "layerId": "f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "layerType": "data", - "legend": { - "isVisible": true, - "position": "right", - "type": "heatmap_legend" - }, - "palette": { - "accessor": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", - "name": "warm", - "params": { - "continuity": "above", - "name": "warm", - "rangeMax": null, - "rangeMin": 0, - "reverse": false, - "stops": [ - { - "color": "#f7e0b8", - "stop": 0 - }, - { - "color": "#f2c596", - "stop": 20 - }, - { - "color": "#eca976", - "stop": 40 - }, - { - "color": "#e78c5b", - "stop": 60 - }, - { - "color": "#e7664c", - "stop": 80 - } - ] - }, - "type": "palette" - }, - "shape": "heatmap", - "valueAccessor": "edd0b2f0-5ba3-4111-946b-6d9dedccd256", - "xAccessor": "26f17aa9-d2df-481f-8b3f-a7bf3cf553b5" - } - }, - "title": "", - "type": "lens", - "visualizationType": "lnsHeatmap" - }, - "enhancements": {}, - "hidePanelTitles": false - }, - "gridData": { - "h": 13, - "i": "6da4d7e2-1f3a-44b7-8848-2d172228af18", - "w": 23, - "x": 0, - "y": 30 - }, - "panelIndex": "6da4d7e2-1f3a-44b7-8848-2d172228af18", - "title": "Affected Entities (Others)", - "type": "lens" - } - ], - "timeRestore": false, - "title": "[AWS Health] Overview", - "version": 1 - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2024-03-24T09:43:37.083Z", - "id": "fce44690-e9c2-11ee-9f73-dfef113e2924", - "managed": false, - "references": [ - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "7237f280-dd55-41d0-8d24-9e42ee51baa6:indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "type": "index-pattern" - }, - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "cc683ea6-423c-44bb-969b-9400d0a10fb8:indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "type": "index-pattern" - }, - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "d9bee328-436d-4936-9942-17ba670c8538:indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "type": "index-pattern" - }, - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "34211b75-8a7d-40d5-ac6f-af9ce7ecfe34:indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "type": "index-pattern" - }, - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "d3a13b2f-738b-4b93-b8d7-2852e2b46d52:indexpattern-datasource-layer-5b2a4b04-92d5-4ac9-96de-ac4d4687217c", - "type": "index-pattern" - }, - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "fd710b8a-c2a7-45a7-8c55-13430ab25039:indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "type": "index-pattern" - }, - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "404e1f7a-ea8c-415e-90f0-8a1cc8f9fdad:indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "type": "index-pattern" - }, - { - "id": "009ebc57-9a9b-4731-bc39-46c1aef9849b", - "name": "6da4d7e2-1f3a-44b7-8848-2d172228af18:indexpattern-datasource-layer-f6094941-e5a7-4a44-b55e-a8e4e8ecdf44", - "type": "index-pattern" - } - ], - "type": "dashboard", - "typeMigrationVersion": "8.9.0", - "updated_at": "2024-03-24T09:43:37.083Z", - "version": "Wzc2MywxXQ==" -} \ No newline at end of file From 15c9b4c90b5481de6e83fb9cb5e3c33c7d0c3815 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Tue, 26 Mar 2024 04:16:29 +0000 Subject: [PATCH 17/38] Added changelog entry --- CHANGELOG.next.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index e0653d6139f8..24a6cd4c68d6 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -216,6 +216,7 @@ Setting environmental variable ELASTIC_NETINFO:false in Elastic Agent pod will d - Parse more fields from Elasticsearch slowlogs {pull}38295[38295] - Update CEL mito extensions to v1.10.0 to add keys/values helper. {pull}38504[38504] - Add support for Active Directory an entity analytics provider. {pull}37919[37919] +- Add AWS AWSHealth metricset. {pull}38370[38370] *Auditbeat* From f25723b35d63b0b1567eb203d94663a24418a266 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Tue, 26 Mar 2024 10:11:00 +0000 Subject: [PATCH 18/38] Optimised function defs. Modified system test script using new function def. Added inline comments --- .../module/aws/awshealth/awshealth.go | 80 +++++++++++-------- .../module/aws/awshealth/awshealth_test.go | 77 ++++++++++++++---- 2 files changed, 109 insertions(+), 48 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index cdd9e2b54796..412b40ad9aa8 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -115,8 +115,10 @@ func (m *MetricSet) Fetch(ctx context.Context, report mb.ReporterV2) error { return nil } -// Make call to DescribeEvents() -// Returns information about events that meet the specified filter criteria. Events are returned in a summary form and do not include the detailed description, any additional metadata that depends on the event type, or any affected resources. +// getEventsSummary retrieves a summary of AWS Health events which are upcoming +// or open. It uses the DescribeEvents API to get a list of events. Each event is +// identified by a Event ARN. The function returns a slice of mb.Event structs +// containing the summarized event info. func (m *MetricSet) getEventsSummary( ctx context.Context, awsHealth *health.Client, @@ -174,11 +176,12 @@ func (m *MetricSet) getEventsSummary( } for _, et := range ets { - m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getStringValueOrDefault(et.Arn)) + // m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getStringValueOrDefault(et.Arn)) + m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getValueOrDefault(et.Arn, "")) // Increment the WaitGroup counter wg.Add(1) go func(et types.Event) { - defer wg.Done() // Decrement the WaitGroup counter when goroutine exits + defer wg.Done() err := m.getDescribeEventDetails(ctx, awsHealth, et, c) if err != nil { errCh <- err @@ -216,21 +219,27 @@ func (m *MetricSet) getEventsSummary( return events } +// createEvents takes in a HealthDetails struct and returns an mb.Event struct +// populated with the data from the HealthDetails. It sets the MetricSetFields, +// RootFields and ID fields of the mb.Event struct. The MetricSetFields contain +// the details of the health event. The RootFields specify that it is an AWS +// event. The ID is generated from the event ARN, status code and current date. func createEvents(hd HealthDetails) mb.Event { currentDate := getCurrentDateTime() - eventID := currentDate + getStringValueOrDefault(hd.event.Arn) + getStringValueOrDefault((*string)(&hd.event.StatusCode)) + //eventID := currentDate + getStringValueOrDefault(hd.event.Arn) + getStringValueOrDefault((*string)(&hd.event.StatusCode)) + eventID := currentDate + getValueOrDefault(hd.event.Arn, "") + getValueOrDefault((*string)(&hd.event.StatusCode), "") event := mb.Event{ MetricSetFields: mapstr.M{ - "event_arn": getStringValueOrDefault(hd.event.Arn), - "end_time": getTimeValueOrDefault(hd.event.EndTime), - "event_scope_code": getStringValueOrDefault((*string)(&hd.event.EventScopeCode)), - "event_type_category": getStringValueOrDefault((*string)(&hd.event.EventTypeCategory)), - "event_type_code": getStringValueOrDefault(hd.event.EventTypeCode), - "last_updated_time": getTimeValueOrDefault(hd.event.LastUpdatedTime), - "region": getStringValueOrDefault(hd.event.Region), - "service": getStringValueOrDefault(hd.event.Service), - "start_time": getTimeValueOrDefault(hd.event.StartTime), - "status_code": getStringValueOrDefault((*string)(&hd.event.StatusCode)), + "event_arn": getValueOrDefault(hd.event.Arn, ""), + "end_time": getValueOrDefault(hd.event.EndTime, time.Time{}), + "event_scope_code": getValueOrDefault((*string)(&hd.event.EventScopeCode), ""), + "event_type_category": getValueOrDefault((*string)(&hd.event.EventTypeCategory), ""), + "event_type_code": getValueOrDefault(hd.event.EventTypeCode, ""), + "last_updated_time": getValueOrDefault(hd.event.LastUpdatedTime, time.Time{}), + "region": getValueOrDefault(hd.event.Region, ""), + "service": getValueOrDefault(hd.event.Service, ""), + "start_time": getValueOrDefault(hd.event.StartTime, time.Time{}), + "status_code": getValueOrDefault((*string)(&hd.event.StatusCode), ""), "affected_entities_pending": hd.affectedEntityPending, "affected_entities_resolved": hd.affectedEntityResolved, "affected_entities_others": hd.affectedEntityOthers, @@ -262,41 +271,37 @@ type AffectedEntityDetails struct { EntityArn string `json:"entity_arn"` } -// getStringValueOrDefault returns the string value or an empty string if the pointer is nil. -func getStringValueOrDefault(s *string) string { - if s != nil { - return *s +// getValueOrDefault returns the dereferenced value of a pointer v of any type T. +// If the pointer is nil, it returns the specified defaultValue of type T. +func getValueOrDefault[T any](v *T, defaultValue T) T { + if v != nil { + return *v } - return "" -} - -func getTimeValueOrDefault(t *time.Time) time.Time { - if t != nil { - return *t - } - return time.Time{} + return defaultValue } // createAffectedEntityDetails populates and returns a slice of AffectedEntityDetails // based on the given list of AffectedEntity instances. -// Each AffectedEntity is converted into an AffectedEntityDetails struct, +// Each AffectedEntity is converted into an AffectedEntityDetails struct. func createAffectedEntityDetails(affectedEntities []types.AffectedEntity) []AffectedEntityDetails { aed := []AffectedEntityDetails{} // Populate a slice of AffectedEntityDetails for _, entity := range affectedEntities { aed = append(aed, AffectedEntityDetails{ - AwsAccountId: getStringValueOrDefault(entity.AwsAccountId), - EntityUrl: getStringValueOrDefault(entity.EntityUrl), - EntityValue: getStringValueOrDefault(entity.EntityValue), - LastUpdatedTime: getTimeValueOrDefault(entity.LastUpdatedTime), - StatusCode: string(entity.StatusCode), - EntityArn: getStringValueOrDefault(entity.EntityArn), + AwsAccountId: getValueOrDefault(entity.AwsAccountId, ""), + EntityUrl: getValueOrDefault(entity.EntityUrl, ""), + EntityValue: getValueOrDefault(entity.EntityValue, ""), + LastUpdatedTime: getValueOrDefault(entity.LastUpdatedTime, time.Time{}), + StatusCode: getValueOrDefault((*string)(&entity.StatusCode), ""), + EntityArn: getValueOrDefault(entity.EntityArn, ""), }) } return aed } +// generateEventID hashes the provided eventID and returns the first 20 characters. +// This is used to generate a unique but consistent event ID prefix. func generateEventID(eventID string) string { h := sha256.New() h.Write([]byte(eventID)) @@ -304,6 +309,12 @@ func generateEventID(eventID string) string { return prefix[:20] } +// getEventsSummary retrieves a summary of AWS Health events that meet the specified +// filter criteria. It uses the DescribeEvents API to get a list of events. For each +// event, it calls getDescribeEventDetails with the EventARN to get details like details +// of affected entities by calling DescribeAffectedEntities API. The DescribeAffectedEntities +// is called to fetch the description of the event. +// The function returns a slice of mb.Event structs containing the summarized event info. func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *health.Client, event types.Event, ch chan<- HealthDetails) error { hd := HealthDetails{event: event} eventDetails, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ @@ -329,6 +340,7 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal resolved int32 others int32 ) + for { // When invoking the DescribeAffectedEntities for the first time, there must not exist any NextToken. // DescribeAffectedEntities API call will return the next token if there are more records left for querying diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go index a05b409fe7b7..83121e4bfa50 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go @@ -1,3 +1,54 @@ +// // Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// // or more contributor license agreements. Licensed under the Elastic License; +// // you may not use this file except in compliance with the Elastic License. + +// package awshealth + +// import ( +// "testing" +// "time" + +// "github.com/stretchr/testify/assert" +// ) + +// func TestGetCurrentDateTime(t *testing.T) { +// cdt := getCurrentDateTime() +// assert.NotEmpty(t, cdt) +// } + +// func TestGenerateEventID(t *testing.T) { +// cdt := getCurrentDateTime() +// e_arn := "arn:aws:health:us-east-1::event/LAMBDA/AWS_LAMBDA_OPERATIONAL_NOTIFICATION/AWS_LAMBDA_OPERATIONAL_NOTIFICATION_e76969649ab96dd" +// sc := "" +// eventID := cdt + e_arn + sc +// eid := generateEventID(eventID) +// assert.NotEmpty(t, eid) +// } + +// func TestGetStringValueOrDefault(t *testing.T) { +// // Test case 1: Test with non-nil string pointer +// input := "hello" +// result := getStringValueOrDefault(&input) +// assert.Equal(t, "hello", result, "Result should match input string") + +// // Test case 2: Test with nil string pointer +// var nilString *string +// result = getStringValueOrDefault(nilString) +// assert.Equal(t, "", result, "Result should be an empty string") +// } + +// func TestGetTimeValueOrDefault(t *testing.T) { +// // Test case 1: Test with non-nil time pointer +// now := time.Now() +// result := getTimeValueOrDefault(&now) +// assert.Equal(t, now, result, "Result should match current time") + +// // Test case 2: Test with nil time pointer +// var nilTime *time.Time +// result = getTimeValueOrDefault(nilTime) +// assert.Equal(t, time.Time{}, result, "Result should be zero time") +// } + // Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. @@ -25,26 +76,24 @@ func TestGenerateEventID(t *testing.T) { assert.NotEmpty(t, eid) } -func TestGetStringValueOrDefault(t *testing.T) { +func TestGetValueOrDefault(t *testing.T) { // Test case 1: Test with non-nil string pointer - input := "hello" - result := getStringValueOrDefault(&input) - assert.Equal(t, "hello", result, "Result should match input string") + inputString := "hello" + resultString := getValueOrDefault(&inputString, "") + assert.Equal(t, "hello", resultString, "Result should match input string") // Test case 2: Test with nil string pointer var nilString *string - result = getStringValueOrDefault(nilString) - assert.Equal(t, "", result, "Result should be an empty string") -} + resultString = getValueOrDefault(nilString, "") + assert.Equal(t, "", resultString, "Result should be an empty string") -func TestGetTimeValueOrDefault(t *testing.T) { - // Test case 1: Test with non-nil time pointer + // Test case 3: Test with non-nil time pointer now := time.Now() - result := getTimeValueOrDefault(&now) - assert.Equal(t, now, result, "Result should match current time") + resultTime := getValueOrDefault(&now, time.Time{}) + assert.Equal(t, now, resultTime, "Result should match current time") - // Test case 2: Test with nil time pointer + // Test case 4: Test with nil time pointer var nilTime *time.Time - result = getTimeValueOrDefault(nilTime) - assert.Equal(t, time.Time{}, result, "Result should be zero time") + resultTime = getValueOrDefault(nilTime, time.Time{}) + assert.Equal(t, time.Time{}, resultTime, "Result should be zero time") } From e0f78573317abfb804206ac8763fb1c3b1c10d86 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Tue, 26 Mar 2024 10:19:56 +0000 Subject: [PATCH 19/38] Removed commented out code --- .../module/aws/awshealth/awshealth_test.go | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go index 83121e4bfa50..eecaeaae5cd3 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go @@ -1,54 +1,3 @@ -// // Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// // or more contributor license agreements. Licensed under the Elastic License; -// // you may not use this file except in compliance with the Elastic License. - -// package awshealth - -// import ( -// "testing" -// "time" - -// "github.com/stretchr/testify/assert" -// ) - -// func TestGetCurrentDateTime(t *testing.T) { -// cdt := getCurrentDateTime() -// assert.NotEmpty(t, cdt) -// } - -// func TestGenerateEventID(t *testing.T) { -// cdt := getCurrentDateTime() -// e_arn := "arn:aws:health:us-east-1::event/LAMBDA/AWS_LAMBDA_OPERATIONAL_NOTIFICATION/AWS_LAMBDA_OPERATIONAL_NOTIFICATION_e76969649ab96dd" -// sc := "" -// eventID := cdt + e_arn + sc -// eid := generateEventID(eventID) -// assert.NotEmpty(t, eid) -// } - -// func TestGetStringValueOrDefault(t *testing.T) { -// // Test case 1: Test with non-nil string pointer -// input := "hello" -// result := getStringValueOrDefault(&input) -// assert.Equal(t, "hello", result, "Result should match input string") - -// // Test case 2: Test with nil string pointer -// var nilString *string -// result = getStringValueOrDefault(nilString) -// assert.Equal(t, "", result, "Result should be an empty string") -// } - -// func TestGetTimeValueOrDefault(t *testing.T) { -// // Test case 1: Test with non-nil time pointer -// now := time.Now() -// result := getTimeValueOrDefault(&now) -// assert.Equal(t, now, result, "Result should match current time") - -// // Test case 2: Test with nil time pointer -// var nilTime *time.Time -// result = getTimeValueOrDefault(nilTime) -// assert.Equal(t, time.Time{}, result, "Result should be zero time") -// } - // Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. From 540056583d752f53f1bce90c7588f24dbe34de2e Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Thu, 28 Mar 2024 06:36:56 +0000 Subject: [PATCH 20/38] Added inline comments --- .../module/aws/awshealth/awshealth.go | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 412b40ad9aa8..d644e936320f 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -96,9 +96,6 @@ func (m *MetricSet) Fetch(ctx context.Context, report mb.ReporterV2) error { return err } - // Get startDate and endDate - // startDate, endDate := getStartDateEndDate(m.Period) - awsConfig := m.MetricSet.AwsConfig.Copy() health_client := health.NewFromConfig(awsConfig, func(o *health.Options) { @@ -138,12 +135,14 @@ func (m *MetricSet) getEventsSummary( wg sync.WaitGroup ) errCh := make(chan error, maxResults) + + // Create buffered channel to receive event with event description and affected entity details c := make(chan HealthDetails, maxResults) for { // When invoking the DescribeEvents for the first time, there must not exist any NextToken. - // DescribeEvents API call will return the next token if there are more records left for querying - // If there exist no further records to fetch, next toke will be empty. + // Upon calling the DescribeEvents API, the next token will be returned if there are additional records available for querying. + // If there are no more records to fetch, the next token will be empty. if nextTokenString == "" { eventOutput, err = awsHealth.DescribeEvents(ctx, &health.DescribeEventsInput{ @@ -175,9 +174,8 @@ func (m *MetricSet) getEventsSummary( // Context not cancelled, proceed with the function } - for _, et := range ets { - // m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getStringValueOrDefault(et.Arn)) - m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getValueOrDefault(et.Arn, "")) + for i := range ets { + m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getValueOrDefault(ets[i].Arn, "")) // Increment the WaitGroup counter wg.Add(1) go func(et types.Event) { @@ -186,7 +184,7 @@ func (m *MetricSet) getEventsSummary( if err != nil { errCh <- err } - }(et) + }(ets[i]) } for i := 0; i < len(ets); i++ { @@ -280,24 +278,19 @@ func getValueOrDefault[T any](v *T, defaultValue T) T { return defaultValue } -// createAffectedEntityDetails populates and returns a slice of AffectedEntityDetails -// based on the given list of AffectedEntity instances. -// Each AffectedEntity is converted into an AffectedEntityDetails struct. func createAffectedEntityDetails(affectedEntities []types.AffectedEntity) []AffectedEntityDetails { - aed := []AffectedEntityDetails{} - // Populate a slice of AffectedEntityDetails - for _, entity := range affectedEntities { - aed = append(aed, AffectedEntityDetails{ - AwsAccountId: getValueOrDefault(entity.AwsAccountId, ""), - EntityUrl: getValueOrDefault(entity.EntityUrl, ""), - EntityValue: getValueOrDefault(entity.EntityValue, ""), - LastUpdatedTime: getValueOrDefault(entity.LastUpdatedTime, time.Time{}), - StatusCode: getValueOrDefault((*string)(&entity.StatusCode), ""), - EntityArn: getValueOrDefault(entity.EntityArn, ""), - }) + aed := make([]AffectedEntityDetails, len(affectedEntities)) + for i := range affectedEntities { + aed[i] = AffectedEntityDetails{ + AwsAccountId: getValueOrDefault(affectedEntities[i].AwsAccountId, ""), + EntityUrl: getValueOrDefault(affectedEntities[i].EntityUrl, ""), + EntityValue: getValueOrDefault(affectedEntities[i].EntityValue, ""), + LastUpdatedTime: getValueOrDefault(affectedEntities[i].LastUpdatedTime, time.Time{}), + StatusCode: getValueOrDefault((*string)(&affectedEntities[i].StatusCode), ""), + EntityArn: getValueOrDefault(affectedEntities[i].EntityArn, ""), + } } return aed - } // generateEventID hashes the provided eventID and returns the first 20 characters. From 77c38bf497dec053172fdf5016227e4951a1a593 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Mon, 1 Apr 2024 05:31:34 +0000 Subject: [PATCH 21/38] Added minor optimisations --- x-pack/metricbeat/module/aws/awshealth/awshealth.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index d644e936320f..9945687d8bb8 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -208,9 +208,8 @@ func (m *MetricSet) getEventsSummary( wg.Wait() if eventOutput.NextToken == nil { break - } else { - nextTokenString = *eventOutput.NextToken } + nextTokenString = *eventOutput.NextToken } close(c) close(errCh) @@ -417,9 +416,8 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal } if nextToken == nil { break - } else { - affEntityTokString = *nextToken } + affEntityTokString = *nextToken } hd.affectedEntityResolved = resolved hd.affectedEntityPending = pending @@ -429,7 +427,7 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal case ch <- hd: // Writing to the channel default: - // Channel is closed, + // Channel buffer is full or closed, dropping the event to avoid blocking. return nil } return nil From 901d666247059c0f96a341d163da083b7231ce05 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Wed, 3 Apr 2024 19:28:18 +0000 Subject: [PATCH 22/38] Added minor code optimisation --- x-pack/metricbeat/module/aws/awshealth/awshealth.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 9945687d8bb8..388af84e6861 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -10,7 +10,6 @@ import ( "encoding/hex" "errors" "fmt" - "sync" "time" awssdk "github.com/aws/aws-sdk-go-v2/aws" @@ -132,7 +131,6 @@ func (m *MetricSet) getEventsSummary( nextTokenString string eventOutput *health.DescribeEventsOutput err error - wg sync.WaitGroup ) errCh := make(chan error, maxResults) @@ -176,10 +174,7 @@ func (m *MetricSet) getEventsSummary( for i := range ets { m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getValueOrDefault(ets[i].Arn, "")) - // Increment the WaitGroup counter - wg.Add(1) go func(et types.Event) { - defer wg.Done() err := m.getDescribeEventDetails(ctx, awsHealth, et, c) if err != nil { errCh <- err @@ -205,7 +200,6 @@ func (m *MetricSet) getEventsSummary( events = append(events, createEvents(healthDetails)) } } - wg.Wait() if eventOutput.NextToken == nil { break } @@ -321,10 +315,10 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal err = fmt.Errorf("[AWS Health] DescribeEventDetails failed with : %w", err) m.Logger().Error(err.Error()) return err - } else { - hd.eventDescription = *(eventDetails.SuccessfulSet[0].EventDescription.LatestDescription) } + hd.eventDescription = *(eventDetails.SuccessfulSet[0].EventDescription.LatestDescription) + var ( affEntityTokString string nextToken *string From e9fbddd5ab16022370325d00aab09c228e8e1ee3 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Thu, 4 Apr 2024 13:03:18 +0000 Subject: [PATCH 23/38] Updated field description and mappings --- metricbeat/docs/fields.asciidoc | 36 ++++++++++++------- .../module/aws/awshealth/_meta/fields.yml | 30 +++++++++------- .../module/aws/awshealth/awshealth.go | 8 +++-- x-pack/metricbeat/module/aws/fields.go | 2 +- 4 files changed, 47 insertions(+), 29 deletions(-) diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index fc37f7dd78a8..af6b2b09f858 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -1555,7 +1555,7 @@ AWS Health metrics *`aws.awshealth.affected_entities_others`*:: + -- -Number of affected resources, not able to verify status, related to the event. +The number of affected resources related to the event whose status cannot be verified. type: float @@ -1565,7 +1565,7 @@ type: float *`aws.awshealth.affected_entities_pending`*:: + -- -Number of affected resources that may require action. +The number of affected resources that may require action. type: float @@ -1575,7 +1575,7 @@ type: float *`aws.awshealth.affected_entities_resolved`*:: + -- -Number of affected resources having no actions required. +The number of affected resources that do not require any action. type: float @@ -1585,7 +1585,7 @@ type: float *`aws.awshealth.end_time`*:: + -- -The date and time that the event ended. Certain events may not have an End date. +The date and time when the event ended. Some events may not have an end date. type: date @@ -1595,7 +1595,7 @@ type: date *`aws.awshealth.event_arn`*:: + -- -The unique identifier for the event. The event ARN has the arn:aws:health:event-region::event/SERVICE/EVENT_TYPE_CODE/EVENT_TYPE_PLUS_ID format. +The unique identifier for the event. The event ARN has the format arn:aws:health:event-region::event/SERVICE/EVENT_TYPE_CODE/EVENT_TYPE_PLUS_ID. type: keyword @@ -1605,7 +1605,7 @@ type: keyword *`aws.awshealth.event_scope_code`*:: + -- -This parameter specifies if the Health event is a public Amazon Web Service event or an account-specific event. Allowed values are PUBLIC/ ACCOUNT_SPECIFIC/ NONE. +This parameter specifies whether the Health event is a public Amazon Web Service event or an account-specific event. Allowed values are PUBLIC, ACCOUNT_SPECIFIC, or NONE. type: keyword @@ -1615,7 +1615,7 @@ type: keyword *`aws.awshealth.event_type_category`*:: + -- -Event type category code. Possible values are issue accountNotification, or scheduledChange. +The event type category code. Possible values are issue, accountNotification, or scheduledChange. type: keyword @@ -1625,7 +1625,7 @@ type: keyword *`aws.awshealth.event_type_code`*:: + -- -The unique identifier for the event type. The format is AWS_SERVICE_DESCRIPTION +The unique identifier for the event type. The format is AWS_SERVICE_DESCRIPTION. type: keyword @@ -1635,7 +1635,7 @@ type: keyword *`aws.awshealth.last_updated_time`*:: + -- -The most recent date and time that the event was updated. +The most recent date and time when the event was updated. type: date @@ -1655,7 +1655,7 @@ type: keyword *`aws.awshealth.service`*:: + -- -The Amazon Web Service that is affected by the event. For example, EC2 , RDS . +The Amazon Web Service affected by the event. For example, EC2 or RDS. type: keyword @@ -1665,7 +1665,7 @@ type: keyword *`aws.awshealth.start_time`*:: + -- -The date and time that the event began. +The date and time when the event began. type: date @@ -1675,17 +1675,27 @@ type: date *`aws.awshealth.status_code`*:: + -- -The most recent status of the event. Possible values are open , closed , and upcoming. +The most recent status of the event. Possible values are open, closed, and upcoming. type: keyword -- +*`aws.awshealth.event_description`*:: ++ +-- +The detailed description of the event. + + +type: text + +-- + *`aws.awshealth.affected_entities`*:: + -- -Information about an entity that is affected by a Health event. +Information about an entity affected by a Health event. type: nested diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml index fa92abb380ec..b329705713b1 100644 --- a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml @@ -7,39 +7,39 @@ - name: affected_entities_others type: float description: > - Number of affected resources, not able to verify status, related to the event. + The number of affected resources related to the event whose status cannot be verified. - name: affected_entities_pending type: float description: > - Number of affected resources that may require action. + The number of affected resources that may require action. - name: affected_entities_resolved type: float description: > - Number of affected resources having no actions required. + The number of affected resources that do not require any action. - name: end_time type: date description: > - The date and time that the event ended. Certain events may not have an End date. + The date and time when the event ended. Some events may not have an end date. - name: event_arn type: keyword description: > - The unique identifier for the event. The event ARN has the arn:aws:health:event-region::event/SERVICE/EVENT_TYPE_CODE/EVENT_TYPE_PLUS_ID format. + The unique identifier for the event. The event ARN has the format arn:aws:health:event-region::event/SERVICE/EVENT_TYPE_CODE/EVENT_TYPE_PLUS_ID. - name: event_scope_code type: keyword description: > - This parameter specifies if the Health event is a public Amazon Web Service event or an account-specific event. Allowed values are PUBLIC/ ACCOUNT_SPECIFIC/ NONE. + This parameter specifies whether the Health event is a public Amazon Web Service event or an account-specific event. Allowed values are PUBLIC, ACCOUNT_SPECIFIC, or NONE. - name: event_type_category type: keyword description: > - Event type category code. Possible values are issue accountNotification, or scheduledChange. + The event type category code. Possible values are issue, accountNotification, or scheduledChange. - name: event_type_code type: keyword description: > - The unique identifier for the event type. The format is AWS_SERVICE_DESCRIPTION + The unique identifier for the event type. The format is AWS_SERVICE_DESCRIPTION. - name: last_updated_time type: date description: > - The most recent date and time that the event was updated. + The most recent date and time when the event was updated. - name: region type: keyword description: > @@ -47,19 +47,23 @@ - name: service type: keyword description: > - The Amazon Web Service that is affected by the event. For example, EC2 , RDS . + The Amazon Web Service affected by the event. For example, EC2 or RDS. - name: start_time type: date description: > - The date and time that the event began. + The date and time when the event began. - name: status_code type: keyword description: > - The most recent status of the event. Possible values are open , closed , and upcoming. + The most recent status of the event. Possible values are open, closed, and upcoming. + - name: event_description + type: text + description: > + The detailed description of the event. - name: affected_entities type: nested description: > - Information about an entity that is affected by a Health event. + Information about an entity affected by a Health event. fields: - name: aws_account_id type: keyword diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 388af84e6861..2f8dda4a00d5 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -217,7 +217,6 @@ func (m *MetricSet) getEventsSummary( // event. The ID is generated from the event ARN, status code and current date. func createEvents(hd HealthDetails) mb.Event { currentDate := getCurrentDateTime() - //eventID := currentDate + getStringValueOrDefault(hd.event.Arn) + getStringValueOrDefault((*string)(&hd.event.StatusCode)) eventID := currentDate + getValueOrDefault(hd.event.Arn, "") + getValueOrDefault((*string)(&hd.event.StatusCode), "") event := mb.Event{ MetricSetFields: mapstr.M{ @@ -235,6 +234,7 @@ func createEvents(hd HealthDetails) mb.Event { "affected_entities_resolved": hd.affectedEntityResolved, "affected_entities_others": hd.affectedEntityOthers, "affected_entities": createAffectedEntityDetails(hd.affectedEntities), + "event_description": hd.eventDescription, }, RootFields: mapstr.M{ "cloud.provider": "aws", @@ -317,7 +317,11 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal return err } - hd.eventDescription = *(eventDetails.SuccessfulSet[0].EventDescription.LatestDescription) + if len(eventDetails.SuccessfulSet) > 0 { + hd.eventDescription = *(eventDetails.SuccessfulSet[0].EventDescription.LatestDescription) + } else { + hd.eventDescription = "Unable to find event description details." + } var ( affEntityTokString string diff --git a/x-pack/metricbeat/module/aws/fields.go b/x-pack/metricbeat/module/aws/fields.go index 6c1762a1d990..9fb15fd111b9 100644 --- a/x-pack/metricbeat/module/aws/fields.go +++ b/x-pack/metricbeat/module/aws/fields.go @@ -19,5 +19,5 @@ func init() { // AssetAws returns asset data. // This is the base64 encoded zlib format compressed contents of module/aws. func AssetAws() string { - return "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" + return "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" } From 1b7f83eced85f60676bab66f42477143a85da2dd Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Tue, 9 Apr 2024 12:11:11 +0000 Subject: [PATCH 24/38] Added minor code optimisations --- .../metricbeat/module/aws/awshealth/awshealth.go | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 2f8dda4a00d5..1d322f0fff3c 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -90,8 +90,7 @@ func (m *MetricSet) Fetch(ctx context.Context, report mb.ReporterV2) error { defer cancel() var config aws.Config - err := m.Module().UnpackConfig(&config) - if err != nil { + if err := m.Module().UnpackConfig(&config); err != nil { return err } @@ -157,9 +156,9 @@ func (m *MetricSet) getEventsSummary( }, ) } + if err != nil { - err = fmt.Errorf("[AWS Health] DescribeEvents failed with : %w", err) - m.Logger().Error(err.Error()) + m.Logger().Errorf("[AWS Health] DescribeEvents failed with : %w", err) return nil } ets := eventOutput.Events @@ -302,7 +301,7 @@ func generateEventID(eventID string) string { // is called to fetch the description of the event. // The function returns a slice of mb.Event structs containing the summarized event info. func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *health.Client, event types.Event, ch chan<- HealthDetails) error { - hd := HealthDetails{event: event} + hd := HealthDetails{event: event, affectedEntities: []types.AffectedEntity{}} eventDetails, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ EventArns: []string{*event.Arn}, Locale: &locale, @@ -313,7 +312,6 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal return nil } err = fmt.Errorf("[AWS Health] DescribeEventDetails failed with : %w", err) - m.Logger().Error(err.Error()) return err } @@ -351,8 +349,6 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal m.Logger().Debug("Context cancelled. Exiting gracefully.") return nil } - // Handle other errors - m.Logger().Error(err.Error()) return err } if affectedEntities != nil { @@ -390,8 +386,6 @@ func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *heal m.Logger().Info("Context cancelled. Exiting gracefully.") return nil } - // Handle other errors - m.Logger().Error(err.Error()) return err } if affectedEntities != nil { From f1203b595465b96f193357bd514f3d13da575018 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Thu, 11 Apr 2024 16:48:58 +0000 Subject: [PATCH 25/38] Major code refactoring by using AWS Paginator. Removed Channels. Introduced EvenARN batching. Nested to Object type conversion --- metricbeat/docs/fields.asciidoc | 62 ++- .../module/aws/awshealth/_meta/fields.yml | 40 +- .../module/aws/awshealth/awshealth.go | 451 +++++++----------- x-pack/metricbeat/module/aws/fields.go | 2 +- 4 files changed, 254 insertions(+), 301 deletions(-) diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index af6b2b09f858..f4337174b6bd 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -1698,7 +1698,67 @@ type: text Information about an entity affected by a Health event. -type: nested +type: array + +-- + +*`aws.awshealth.affected_entities.aws_account_id`*:: ++ +-- +The Amazon Web Services account number that contains the affected entity. + + +type: keyword + +-- + +*`aws.awshealth.affected_entities.entity_url`*:: ++ +-- +The URL of the affected entity. + + +type: keyword + +-- + +*`aws.awshealth.affected_entities.entity_value`*:: ++ +-- +The ID of the affected entity. + + +type: keyword + +-- + +*`aws.awshealth.affected_entities.last_updated_time`*:: ++ +-- +The most recent time that the entity was updated. + + +type: date + +-- + +*`aws.awshealth.affected_entities.status_code`*:: ++ +-- +The most recent status of the entity affected by the event. + + +type: keyword + +-- + +*`aws.awshealth.affected_entities.entity_arn`*:: ++ +-- +The unique identifier for the entity. The entity ARN has the format: arn:aws:health:entity-region:aws-account:entity/entity-id. + + +type: keyword -- diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml index b329705713b1..1ea0691210be 100644 --- a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml @@ -61,19 +61,31 @@ description: > The detailed description of the event. - name: affected_entities - type: nested + type: array description: > Information about an entity affected by a Health event. - fields: - - name: aws_account_id - type: keyword - - name: entity_url - type: keyword - - name: entity_value - type: keyword - - name: last_updated_time - type: date - - name: status_code - type: keyword - - name: entity_arn - type: keyword + + - name: affected_entities.aws_account_id + type: keyword + description: > + The Amazon Web Services account number that contains the affected entity. + - name: affected_entities.entity_url + type: keyword + description: > + The URL of the affected entity. + - name: affected_entities.entity_value + type: keyword + description: > + The ID of the affected entity. + - name: affected_entities.last_updated_time + type: date + description: > + The most recent time that the entity was updated. + - name: affected_entities.status_code + type: keyword + description: > + The most recent status of the entity affected by the event. + - name: affected_entities.entity_arn + type: keyword + description: > + The unique identifier for the entity. The entity ARN has the format: arn:aws:health:entity-region:aws-account:entity/entity-id. diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 1d322f0fff3c..4a9fc0c3c73e 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -6,9 +6,6 @@ package awshealth import ( "context" - "crypto/sha256" - "encoding/hex" - "errors" "fmt" "time" @@ -26,8 +23,7 @@ import ( const metricsetName = "awshealth" var ( - locale = "en" - maxResults = int32(10) + locale = "en" ) // init registers the MetricSet with the central registry as soon as the program @@ -40,6 +36,33 @@ func init() { ) } +type AffectedEntityDetails struct { + AwsAccountId string `json:"aws_account_id"` + EntityUrl string `json:"entity_url"` + EntityValue string `json:"entity_value"` + LastUpdatedTime time.Time `json:"last_updated_time"` + StatusCode string `json:"status_code"` + EntityArn string `json:"entity_arn"` +} + +type AWSHealthMetric struct { + EventArn string `json:"event_arn"` + EndTime time.Time `json:"end_time"` + EventScopeCode string `json:"event_scope_code"` + EventTypeCategory string `json:"event_type_category"` + EventTypeCode string `json:"event_type_code"` + LastUpdatedTime time.Time `json:"last_updated_time"` + Region string `json:"region"` + Service string `json:"service"` + StartTime time.Time `json:"start_time"` + StatusCode string `json:"status_code"` + AffectedEntitiesPending int32 `json:"affected_entities_pending"` + AffectedEntitiesResolved int32 `json:"affected_entities_resolved"` + AffectedEntitiesOthers int32 `json:"affected_entities_others"` + AffectedEntities []AffectedEntityDetails `json:"affected_entities"` + EventDescription string `json:"event_description"` +} + // MetricSet holds any configuration or state information. It must implement // the mb.MetricSet interface. And this is best achieved by embedding // mb.BaseMetricSet because it implements all of the required mb.MetricSet @@ -101,8 +124,7 @@ func (m *MetricSet) Fetch(ctx context.Context, report mb.ReporterV2) error { o.EndpointOptions.UseFIPSEndpoint = awssdk.FIPSEndpointStateEnabled } }) - - events := m.getEventsSummary(ctx, health_client) + events := m.getEventDetails(ctx, health_client) for _, event := range events { report.Event(event) } @@ -110,11 +132,11 @@ func (m *MetricSet) Fetch(ctx context.Context, report mb.ReporterV2) error { return nil } -// getEventsSummary retrieves a summary of AWS Health events which are upcoming +// getEventDetails retrieves a AWS Health events which are upcoming // or open. It uses the DescribeEvents API to get a list of events. Each event is // identified by a Event ARN. The function returns a slice of mb.Event structs // containing the summarized event info. -func (m *MetricSet) getEventsSummary( +func (m *MetricSet) getEventDetails( ctx context.Context, awsHealth *health.Client, ) []mb.Event { @@ -125,307 +147,166 @@ func (m *MetricSet) getEventsSummary( types.EventStatusCodeOpen, }, } - var ( - nextTokenString string - eventOutput *health.DescribeEventsOutput - err error + deEvents []types.Event + affPage health.DescribeAffectedEntitiesPaginator + healthDetails []AWSHealthMetric + healthDetailsTemp []AWSHealthMetric + affEntityTemp AffectedEntityDetails + affInputParams health.DescribeAffectedEntitiesInput ) - errCh := make(chan error, maxResults) - - // Create buffered channel to receive event with event description and affected entity details - c := make(chan HealthDetails, maxResults) - - for { - // When invoking the DescribeEvents for the first time, there must not exist any NextToken. - // Upon calling the DescribeEvents API, the next token will be returned if there are additional records available for querying. - // If there are no more records to fetch, the next token will be empty. - if nextTokenString == "" { - eventOutput, err = awsHealth.DescribeEvents(ctx, - &health.DescribeEventsInput{ - Filter: &eventFilter, - MaxResults: &maxResults, - }, - ) - } else { - eventOutput, err = awsHealth.DescribeEvents(ctx, - &health.DescribeEventsInput{ - Filter: &eventFilter, - MaxResults: &maxResults, - NextToken: &nextTokenString, - }, - ) - } - - if err != nil { - m.Logger().Errorf("[AWS Health] DescribeEvents failed with : %w", err) - return nil - } - ets := eventOutput.Events - select { - case <-ctx.Done(): - // Context cancelled, handle graceful termination - close(c) - return nil - default: - // Context not cancelled, proceed with the function - } - - for i := range ets { - m.Logger().Debugf("[AWS Health] [Fetch DescribeEventDetails] Event ARN : %s", getValueOrDefault(ets[i].Arn, "")) - go func(et types.Event) { - err := m.getDescribeEventDetails(ctx, awsHealth, et, c) - if err != nil { - errCh <- err - } - }(ets[i]) - } - for i := 0; i < len(ets); i++ { - select { - case <-ctx.Done(): - // Context cancelled, handle graceful termination - m.Logger().Debug("Context cancelled. Exiting gracefully.") - close(c) - return nil - case err := <-errCh: - // Handle errors received from goroutines - m.Logger().Error(err.Error()) - case healthDetails, ok := <-c: - if !ok { - return nil - } - m.Logger().Debugf("[AWS Health] [DescribeEventDetails] Event ARN : %s, Affected Entities (Pending) : %d, Affected Entities (Resolved): %d, Affected Entities (Others) : %d", *healthDetails.event.Arn, healthDetails.affectedEntityPending, healthDetails.affectedEntityResolved, healthDetails.affectedEntityOthers) - events = append(events, createEvents(healthDetails)) - } - } - if eventOutput.NextToken == nil { - break - } - nextTokenString = *eventOutput.NextToken + // Create an instance of DescribeEventsInput with desired parameters + deInputParams := health.DescribeEventsInput{ + Filter: &eventFilter, } - close(c) - close(errCh) - return events -} -// createEvents takes in a HealthDetails struct and returns an mb.Event struct -// populated with the data from the HealthDetails. It sets the MetricSetFields, -// RootFields and ID fields of the mb.Event struct. The MetricSetFields contain -// the details of the health event. The RootFields specify that it is an AWS -// event. The ID is generated from the event ARN, status code and current date. -func createEvents(hd HealthDetails) mb.Event { - currentDate := getCurrentDateTime() - eventID := currentDate + getValueOrDefault(hd.event.Arn, "") + getValueOrDefault((*string)(&hd.event.StatusCode), "") - event := mb.Event{ - MetricSetFields: mapstr.M{ - "event_arn": getValueOrDefault(hd.event.Arn, ""), - "end_time": getValueOrDefault(hd.event.EndTime, time.Time{}), - "event_scope_code": getValueOrDefault((*string)(&hd.event.EventScopeCode), ""), - "event_type_category": getValueOrDefault((*string)(&hd.event.EventTypeCategory), ""), - "event_type_code": getValueOrDefault(hd.event.EventTypeCode, ""), - "last_updated_time": getValueOrDefault(hd.event.LastUpdatedTime, time.Time{}), - "region": getValueOrDefault(hd.event.Region, ""), - "service": getValueOrDefault(hd.event.Service, ""), - "start_time": getValueOrDefault(hd.event.StartTime, time.Time{}), - "status_code": getValueOrDefault((*string)(&hd.event.StatusCode), ""), - "affected_entities_pending": hd.affectedEntityPending, - "affected_entities_resolved": hd.affectedEntityResolved, - "affected_entities_others": hd.affectedEntityOthers, - "affected_entities": createAffectedEntityDetails(hd.affectedEntities), - "event_description": hd.eventDescription, - }, - RootFields: mapstr.M{ - "cloud.provider": "aws", - }, - ID: generateEventID(eventID), + // Create an instance of DescribeEventsPaginatorOptions with desired options + deOptions := &health.DescribeEventAggregatesPaginatorOptions{ + Limit: 10, + StopOnDuplicateToken: true, } - return event -} - -type HealthDetails struct { - event types.Event - eventDescription string - affectedEntities []types.AffectedEntity - affectedEntityPending int32 - affectedEntityResolved int32 - affectedEntityOthers int32 -} - -type AffectedEntityDetails struct { - AwsAccountId string `json:"aws_account_id"` - EntityUrl string `json:"entity_url"` - EntityValue string `json:"entity_value"` - LastUpdatedTime time.Time `json:"last_updated_time"` - StatusCode string `json:"status_code"` - EntityArn string `json:"entity_arn"` -} -// getValueOrDefault returns the dereferenced value of a pointer v of any type T. -// If the pointer is nil, it returns the specified defaultValue of type T. -func getValueOrDefault[T any](v *T, defaultValue T) T { - if v != nil { - return *v + // Create a function option to apply the options to the paginator + deOptFn := func(options *health.DescribeEventsPaginatorOptions) { + // Apply the provided options + options.Limit = deOptions.Limit + options.StopOnDuplicateToken = deOptions.StopOnDuplicateToken } - return defaultValue -} -func createAffectedEntityDetails(affectedEntities []types.AffectedEntity) []AffectedEntityDetails { - aed := make([]AffectedEntityDetails, len(affectedEntities)) - for i := range affectedEntities { - aed[i] = AffectedEntityDetails{ - AwsAccountId: getValueOrDefault(affectedEntities[i].AwsAccountId, ""), - EntityUrl: getValueOrDefault(affectedEntities[i].EntityUrl, ""), - EntityValue: getValueOrDefault(affectedEntities[i].EntityValue, ""), - LastUpdatedTime: getValueOrDefault(affectedEntities[i].LastUpdatedTime, time.Time{}), - StatusCode: getValueOrDefault((*string)(&affectedEntities[i].StatusCode), ""), - EntityArn: getValueOrDefault(affectedEntities[i].EntityArn, ""), - } + affOptions := &health.DescribeAffectedEntitiesPaginatorOptions{ + Limit: 10, + StopOnDuplicateToken: true, } - return aed -} - -// generateEventID hashes the provided eventID and returns the first 20 characters. -// This is used to generate a unique but consistent event ID prefix. -func generateEventID(eventID string) string { - h := sha256.New() - h.Write([]byte(eventID)) - prefix := hex.EncodeToString(h.Sum(nil)) - return prefix[:20] -} - -// getEventsSummary retrieves a summary of AWS Health events that meet the specified -// filter criteria. It uses the DescribeEvents API to get a list of events. For each -// event, it calls getDescribeEventDetails with the EventARN to get details like details -// of affected entities by calling DescribeAffectedEntities API. The DescribeAffectedEntities -// is called to fetch the description of the event. -// The function returns a slice of mb.Event structs containing the summarized event info. -func (m *MetricSet) getDescribeEventDetails(ctx context.Context, awsHealth *health.Client, event types.Event, ch chan<- HealthDetails) error { - hd := HealthDetails{event: event, affectedEntities: []types.AffectedEntity{}} - eventDetails, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ - EventArns: []string{*event.Arn}, - Locale: &locale, - }) - if err != nil { - if errors.Is(err, context.Canceled) { - m.Logger().Debug("Context cancelled. Exiting gracefully.") - return nil - } - err = fmt.Errorf("[AWS Health] DescribeEventDetails failed with : %w", err) - return err + affOptFn := func(options *health.DescribeAffectedEntitiesPaginatorOptions) { + // Apply the provided options + options.Limit = affOptions.Limit + options.StopOnDuplicateToken = affOptions.StopOnDuplicateToken } - if len(eventDetails.SuccessfulSet) > 0 { - hd.eventDescription = *(eventDetails.SuccessfulSet[0].EventDescription.LatestDescription) - } else { - hd.eventDescription = "Unable to find event description details." - } + dePage := health.NewDescribeEventsPaginator(awsHealth, &deInputParams, deOptFn) - var ( - affEntityTokString string - nextToken *string - pending int32 - resolved int32 - others int32 - ) + for dePage.HasMorePages() { + healthDetailsTemp = []AWSHealthMetric{} - for { - // When invoking the DescribeAffectedEntities for the first time, there must not exist any NextToken. - // DescribeAffectedEntities API call will return the next token if there are more records left for querying - // If there exist no further records to fetch, next toke will be empty. - if affEntityTokString == "" { - affectedEntities, err := awsHealth.DescribeAffectedEntities(ctx, &health.DescribeAffectedEntitiesInput{ - Filter: &types.EntityFilter{ - EventArns: []string{*event.Arn}, - }, - Locale: &locale, - MaxResults: &maxResults, + // Perform actions for the current page + currentPage, err := dePage.NextPage(ctx) + if err != nil { + m.Logger().Errorf("[AWS Health] DescribeEvents failed with : %w", err) + break + } + deEvents = currentPage.Events + eventArns := make([]string, len(deEvents)) + for i := range deEvents { + healthDetailsTemp = append(healthDetailsTemp, AWSHealthMetric{ + EventArn: awssdk.ToString(deEvents[i].Arn), + EndTime: awssdk.ToTime(deEvents[i].EndTime), + EventScopeCode: awssdk.ToString((*string)(&deEvents[i].EventScopeCode)), + EventTypeCategory: awssdk.ToString((*string)(&deEvents[i].EventTypeCategory)), + EventTypeCode: awssdk.ToString(deEvents[i].EventTypeCode), + LastUpdatedTime: awssdk.ToTime(deEvents[i].LastUpdatedTime), + Region: awssdk.ToString(deEvents[i].Region), + Service: awssdk.ToString(deEvents[i].Service), + StartTime: awssdk.ToTime(deEvents[i].StartTime), + StatusCode: awssdk.ToString((*string)(&deEvents[i].StatusCode)), }) - if err != nil { - err = fmt.Errorf("AWS Health DescribeAffectedEntities failed with : %w", err) + eventArns[i] = awssdk.ToString(deEvents[i].Arn) + } - // Check if the error is due to context cancellation - if errors.Is(err, context.Canceled) { - m.Logger().Debug("Context cancelled. Exiting gracefully.") - return nil - } - return err - } - if affectedEntities != nil { - nextToken = affectedEntities.NextToken - - hd.affectedEntities = append(hd.affectedEntities, affectedEntities.Entities...) - for _, affEntity := range affectedEntities.Entities { - switch affEntity.StatusCode { - case "PENDING": - pending++ - case "RESOLVED": - resolved++ - case "": - // Do nothing - default: - others++ - } + eventDetails, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ + EventArns: eventArns, + Locale: &locale, + }) + if err != nil { + m.Logger().Errorf("[AWS Health] DescribeEventDetails failed with : %w", err) + break + } + + successSet := eventDetails.SuccessfulSet + for x := range successSet { + for y := range healthDetailsTemp { + if awssdk.ToString(successSet[x].Event.Arn) == healthDetailsTemp[y].EventArn { + healthDetailsTemp[y].EventDescription = awssdk.ToString(successSet[x].EventDescription.LatestDescription) } } + } + // Fetch the details of all the affected Entities related to the EvenARNs in the present page of DescribeEvents API call - } else { - affectedEntities, err := awsHealth.DescribeAffectedEntities(ctx, &health.DescribeAffectedEntitiesInput{ - Filter: &types.EntityFilter{ - EventArns: []string{*event.Arn}, - }, - Locale: &locale, - MaxResults: &maxResults, - NextToken: &affEntityTokString, - }) + affInputParams = health.DescribeAffectedEntitiesInput{ + Filter: &types.EntityFilter{ + EventArns: eventArns, + }, + } + affPage = *health.NewDescribeAffectedEntitiesPaginator( + awsHealth, + &affInputParams, + affOptFn, + ) + + for affPage.HasMorePages() { + affCurrentPage, err := affPage.NextPage(ctx) if err != nil { - err = fmt.Errorf("AWS Health DescribeAffectedEntities failed with : %w", err) - - // Check if the error is due to context cancellation - if errors.Is(err, context.Canceled) { - m.Logger().Info("Context cancelled. Exiting gracefully.") - return nil - } - return err + m.Logger().Errorf("[AWS Health] DescribeAffectedEntitie failed with : %w", err) + break } - if affectedEntities != nil { - nextToken = affectedEntities.NextToken - hd.affectedEntities = append(hd.affectedEntities, affectedEntities.Entities...) - - for _, affEntity := range affectedEntities.Entities { - switch affEntity.StatusCode { - case "PENDING": - pending++ - case "RESOLVED": - resolved++ - case "": - // Do nothing - default: - others++ + for k := range affCurrentPage.Entities { + affEntityTemp = AffectedEntityDetails{ + AwsAccountId: awssdk.ToString(affCurrentPage.Entities[k].AwsAccountId), + EntityUrl: awssdk.ToString(affCurrentPage.Entities[k].EntityUrl), + EntityValue: awssdk.ToString(affCurrentPage.Entities[k].EntityValue), + LastUpdatedTime: awssdk.ToTime(affCurrentPage.Entities[k].LastUpdatedTime), + StatusCode: awssdk.ToString((*string)(&affCurrentPage.Entities[k].StatusCode)), + EntityArn: awssdk.ToString(affCurrentPage.Entities[k].EntityArn), + } + for l := range healthDetailsTemp { + + if awssdk.ToString(affCurrentPage.Entities[k].EventArn) == healthDetailsTemp[l].EventArn { + healthDetailsTemp[l].AffectedEntities = append(healthDetailsTemp[l].AffectedEntities, affEntityTemp) + switch awssdk.ToString((*string)(&affCurrentPage.Entities[k].StatusCode)) { + case "PENDING": + healthDetailsTemp[l].AffectedEntitiesPending++ + case "RESOLVED": + healthDetailsTemp[l].AffectedEntitiesResolved++ + case "": + // Do Nothing + default: + healthDetailsTemp[l].AffectedEntitiesOthers++ + + } } } } + } - if nextToken == nil { - break - } - affEntityTokString = *nextToken + healthDetails = append(healthDetails, healthDetailsTemp...) } - hd.affectedEntityResolved = resolved - hd.affectedEntityPending = pending - hd.affectedEntityOthers = others - - select { - case ch <- hd: - // Writing to the channel - default: - // Channel buffer is full or closed, dropping the event to avoid blocking. - return nil - } - return nil -} -func getCurrentDateTime() string { - // Reference: https://golang.org/pkg/time/#Time.Format - return time.Now().Format("20060102150405") + for _, detail := range healthDetails { + event := mb.Event{ + MetricSetFields: mapstr.M{ + "event_arn": detail.EventArn, + "end_time": detail.EndTime, + "event_scope_code": detail.EventScopeCode, + "event_type_category": detail.EventTypeCategory, + "event_type_code": detail.EventTypeCode, + "last_updated_time": detail.LastUpdatedTime, + "region": detail.Region, + "service": detail.Service, + "start_time": detail.StartTime, + "status_code": detail.StatusCode, + "affected_entities": detail.AffectedEntities, + "event_description": detail.EventDescription, + "affected_entities_pending": detail.AffectedEntitiesPending, + "affected_entities_resolved": detail.AffectedEntitiesResolved, + "affected_entities_others": detail.AffectedEntitiesOthers, + }, + RootFields: mapstr.M{ + "cloud.provider": "aws", + }, + Service: "aws-health", + } + + events = append(events, event) + } + return events } diff --git a/x-pack/metricbeat/module/aws/fields.go b/x-pack/metricbeat/module/aws/fields.go index 9fb15fd111b9..26c1fc3e9a2e 100644 --- a/x-pack/metricbeat/module/aws/fields.go +++ b/x-pack/metricbeat/module/aws/fields.go @@ -19,5 +19,5 @@ func init() { // AssetAws returns asset data. // This is the base64 encoded zlib format compressed contents of module/aws. func AssetAws() string { - return "eJzsvV1z4zbyL3yfT4Ham8xsebTJJNl6KhdPlS07G5/1eBzLs5NzxYXIloQ1CXAA0B6l9sOfQgMgQfFFb6Ts/Os/N7uxJODXjUaju9HofkceYf0zoc/qG0I00yn8TP5y/nn2l28ISUDFkuWaCf4z+f+/IYSQf9Nn9W+SiaRIgcQiTSHWipx/npFMcKaFZHxJMtCSxYospMjws2kqiuSZ6ng1+YYQCSlQBT+TJf2GkAWDNFE/4+jvCKcZeDTmn17n5otSFLn7Swuo+iDhQJou1eSv5Z/9eGL+H4h18Gf7h8h++gjrZyGT9o+jjOY540v33b/89S/B91qx2X8PdGkGJk80LYDklEnHH/qsiAQlChmDmjQoUD9M5kX8CHpi/rtBSRNrD4ZbmgERC0LJ7AfiRm1MmLAMuGKCvxLGfUBhCmE1IH/714kTuclfJ3/9dk/UiSjmKYwBWhG9oppI0IXkkNj1rvYCOb+7Jl8KkOsmSSnjj5BENI5FwXWDonBDkBb5D4diSe3P3ZKzhSbz7/qSFAoSogVhCXDNFmsHlTiok1YMG7J7JAorx5LQlFG1O6BAu6yApnq1la2lppqDprutvFF3v+LoXg3uuEx0sYBYQxIZKjQDFQm9Aqla2bZIBdX7Me1hBYQX2RwkqgA3W6V6DLFUW1bqFRB4Aq7J80ooIEpTXSgSU86FJnMgTyDZgkHSvtpNUnLgCePLk9GC+y6jayLhS8EkEBqbsXaFawZKn6B944yGNxHEsLeEzNe9sIEnkWYd+yqhevODOkbSCtL8jFCeEDMweV4BD2QBeALJhMxE5v6ikMUG84o+md+Zr+AYHYjNjyIq+XCqwIAuOPtSgN//DCRZCFnhnuCXLAnn97dkRRV+uBAyo5pQyX+mz+pnqxJ+xu+9k7A0E9r/+tvs6v5f19Orv1396+r2IXr4v3dX0fTjZe2/724+zaLryz66VSxyiGKRDKgJH1ZMkZxKmoEGSVQOseGAMktntAcS6tSR5QBThJK8mKcsJucZ/UNw8hnmZAbyicWeTUa3cq9A37lRY8/O8zQVz5BYU0YRKoHcfbq4uZ6ekfPp9OOn24dodnc1vf7F/EVIcvvx9mpCejiDJ21MNSyFXA8rG5YeMwjxExCzBBNyJ5Ri8xRCMphSBZx5wm+FEaeYmvGREBWvwBi+yXRF+bJXyC1JA6/1VlHH4a28O+lmaJxHToKjy6vZ9P767uH64207+pQqHRW52cPHaJdW8JlQRrvFBmivonk2p7rF0I7Sbs9hWdvcDIrc4zw4qVHclUppRaXsz8aGVZ0f83Wo5X4RksBXmuUpnJGr6XsjsfeXsw6smko99AL3LuoclrTjJLPmxQjbJZQ4Z8PUlrFVCYgc+BmJU6EgOUNyijwWGePLvg0foGmlQcPXA4yGBDRlKSThd3eQxIZF0wqJg9ING2ebA8CtYjE46FwU2p76mul1TS5p7dSZbIzTZgeTuoXuXZ+o4b6QLXIRWkgGV1TI9NghUDwOHmSbUiV9+26XbbI3PU0brHsI/9M5S9O6Dd/uNPVI0L/dGP8mseCaMm4tMVCaZeh7xCsql6DwVFuLQqI75SSBML4RSPL/uty0Pnfrys85tVO27pBUNHyWGnUf6FeWFVkHAQ57j1s8LaQEHh9s81w15o3diMZS6JjUHSO3R7jk/iTCg9FbIFkXM9phnGdCavYHJFOhNjVju2B1LWk4Ks024iX1IRuxnlbySmgkNgdIx5h+SsPpvfdj/4yNIf1cFyk6Ya+PZQ7YyRhWm6+TXbfmrEoNXz8puoTzNlwvzLgKIikMxlMwr2PObj5+4vPXKngltJOJ3saM3UwzrP2toHjivjKm4ap/cdhOwrT6jJ1Ms35Jixm0+9lkRrCuiDmZJGjJ4InxJZ7HZslUZzjtmHmvXOhrv1lRBKIEFoyzTt/hEDl5hE2Z20ZNgyLjgCiNN3ruHiOXoDDuR/Euy1BKy6BT0oozuItb5/vbrbtDMiYIxnnEogVInd/zde1ui3TfFJHtd1xkjyujBkFND8uoWAJf81RIkBavcajKu0PVMMzj0ig+yjavhtkwz7PwMusZJBAVS5r7C63ygvczXmo9r1i8qgZouRZWGA5Yk4QtFiDNfxg6VE7juq1Yvyf2//qM+nKcYcMI5bCBrGN0Ay/vAv4TmrOWG9U1p5lI5ketjh/kRGtjfniJU15eHOtqNe/BulnQNVY43qyIY1BqUaT38KUApW+oNj7PhD5temtkz4Oxuf7EyQB9AmmOsNTOZbSMKnHgnQ0oo4VEyTZiXEAbvSv/NNMSaLbJCgekcHotFDOMpOUgmUg2gyg7MCSjX0djiHf3XiNDPvKUcbjmCXy9AxkD13QJd1IsJSg1qpjk5XSGIbHI8hQwWIb6ghIOz2SZijlNiYJY8ITKNWEGKGGKzMEQTJPEXsNSouk8hW4676R4YooJDslnyTRMaU5jptefONPj0lndZuYVBvJsQJDYoUArTzkrASnBi6UO+nei8h5o8tJESqDJ4DROBVdFdmoCvVKrCG0jLnbYiHhyN4qt2/GsdRolyFoUJKacaEnjR7ISzyQr4pWZDUN8IW/1SopiucoLvLkq1OYF0G4sU0XWybKWkN4eDFNF9ifl0on1Q1OyWnXDn49po8vWn4lP95Cn7oL8lDYYpDRXnvI56GcwZyv3d8aEacgIzXOgaEAwew1Z2hwKbQ6js1tnEhyMX2kIsxrdXgKihd0cmXJM0yp/4SZz+n/L+d3Cv1OYbP9j+PcgKVc2R2oq+CJlsR5NAM+d8En4j73lNLS8S+EJAms3KQDz5ypcNDWbF6Gpktex4Paipi2uRqrhhGWGohngdGo/Voykq4Sm6Wtlw7m9busyGTVL2R+4306iqOrewDYjskB0VV5Ha0ZtP7H1A+vVUNt6pu1N7mytNGRXUgo55jm8p+tqFdsSOMi2y3vzj3Ly68PDHfnpu+/KVFqRwBEO7lTwhNl9NV1B/PgLZok4739M5lT23MImplCtIcstt3KQCyEzs689Orv0PRv2zmYGByfhFKXgFCTgaWQPPbeMVAIi1sANQc2jrHXUeaHtzzENlgtN1qDJ3Ki4YLAjLQWaPKyk0DqFK8y9HYlD923Sj8TB1xjQPoRuTdY65EAusid/bDHfmwOBxZyyjOn2aJbghJYZ3+SNMvY3VTWWcMuCt908QP3+OuWgruPHFAR37H2gX82uUL0m83GqwhvM/fER5IrxruZgH6PM10H6dJMO4hO3UVpIIkCh0qB5nq6t2nmXQIZGs+GSMmxqZ1KfZq3Y9GBGuTEm2itmWCURltR2V3YjZioWIacxBbbBPF2xOqa5CnOVOsxOmngjwAHeQVyRnkL1qPC29fhsT8dTLkirLfa6V8RCHnVJXvVCvLwu+UC/Bl4Gym+XXzVmAOM4f2rFlito5C/Zf42xNmR/i5zvw7hOH+1lOLcphu1MC3/Ss0cP5FqZgzMPbaf9L8lhrk54P351MTsuXWHoi/F/ibTIcGNerI02O97p90Evxf5AwQEar+z+ELnxd5ngoRfrotBoIubamLxPCEkZN5HGK3+tecu0FO/m1Cg4xpWmPIYz8rwy66ODiMJGeo//c0sQfJvDbFmDW29U3tht8KdkjpGbj/kQnDEKR2OUcMMOLPmiMPTbgIhPW1jWc2IH6zge1o1FPBLsbwUUcAN8qVcD4d3gqjncN+WuDGI9U6ZRAoUxKVxCAkrWESQ9lB5vlV4xEG31g+r6bx/DdchBuiOFvLn+eDd7SxJI2RNISPyrKLuW5sPaKbew/rWL4V1dzNzmm5BPZp89M70K8wzsALPZZblHBU/X29gS3kiPIqIuT7tn4RV5w6vsbi3I+5/+/s8Nw+htdZ3YLwXD8OaikEpf0NTosQG4UWH6B8ZcU3JXyFwoQEhvlvn7t2ekElDyMdcsQ278enlJ3ij9/Vt7ITUVqf9b/P3bOjGW3gTM1t988KZbpTSWkBij842RNAOC4LOYEkbtc6W/Rwg4sYSMMh5ctM0Nwxr1WdpFDi9jMDhoFqwvFHS4OrQ7Thk5scYPTdOGPreOy0DqxQCwoa4TU9XYTUOSdZ2kpyCoF6PNQ+PCrZ9sUmyN5GKeMV17f13a6PH742z0+P0pbfTp++Ns9DgvJsjpSd5IDLfEq5imkEQHlgWpaxKapiLGO/ir6XuUu0JDGBqgEtwbP50ap4oUCvz9qDcW29/bGUKsEorw0U8rLdsePG4rbTK9+1RqunJjhdjwIDbfKgLHdxveuT08RkEMFEszhcAto3mFeUWV8VllAQlRzPyF2SIFKS04Gu6o06nsLFhgiFGFzNNCRScgyk1Vpwgvp/BSqlJ5nBQcI0eBr2FVhPnZ9O7TFEdwp7crXsYU+QOk2JVSFdl3oO3VdI4mFWlpJdjsFS40ySlLSCKeuSG5ud7WGrBqRa8Ko0DjwhZAScprTEtCR3Er0M9CPk4Yn+TUHNqHPSZup3RTy7sZsKoBezKix/HkciAI4xrkgsagGluPcV+xzxgzbU5hN0VRDjJSEI+gAZu0BWY+6nJjde1MZj9FotAnXKT90R+wSAFJ/1NWifHJfK13f5RvTfSfSduPDlg+HOZkOwxnO8nKWbqCddufxO2i+PILd7Jd94IrN9SOS5h6ZGJivIHTrRyumt9k1Jn5hopyPZQWEqr46BNlKd4suNqEB6xbg9CR1u2iIitYroMp7CUGfbcXWbYwrekk6xaQOurCecKCtTuQxu1iuFnatXfhdlqcKlCxGZ459RaztZv6Vmp/Gqed1A2x0/aJ7bQK55jL2YxLnXbjjbucDeqO332HrKZNzZ3EK4gfI5veOhCp95ALqetVOWvRhZwqTPYQelX/0KcLG0zuGQUQhYnQ9c9c7DilSpOM8aKrBmsLkZEd78S0jkGIn+cFSGlfsV2JKQ+NWMg+TWLMuyVsvrvZP0QnpKtRtv3EKj9lGV3CZMhq4gbY9aW/ucPxy2reNrS2D74qEjwxazBgDYhrnrAYk8S9JJR1GYPwM1MEuNFFHQq1BJpL9kQ1TBKuomELo2NA2Y5OLm9ntcKlDQ9hR5RsMwvFSeLmn/eAdn339COhSSJBKUKVEjHDmDfe6h2EFesZj8VQWyx5k587SqWDNiAXPeMcjiujXFhMru/KT94YBr8lc1Hwspz7vizFLTTpLMl6sCLCcTd5eGYz4b//+7s506Tgii05RqRxkp2QDr/urUjJG1fKnvyXyIJz+//UqtCa8eU7jDL/l2iQGeMo0/81FgsWBPL/F5K3WyjSK2PgWkfHqOqxjgI3D5pb/lhoufBLj6tcA+kpi9Zc3bTXq3mxpLwLGj8CT6aCc2t1D/SArb6UcTl8yFYudFCUJV0TUJrOU6ZWxth0rzDRQBE0Ie5GSpZ2poQlUxqza7xs9uQI//rwcDcVCUSO4uj9778PTCW+onv/++9EgsoFV2Df0fnHd5i0eiToH8YB/cOooH8cB/SPo4L+aRzQP40C+urmYkwuxynDDhtGNSBoVUfd2KM7Qh6RxwrkE8hBILu3ZsM8/NxMkHR5kFUsBeFW2jKjXS9x0VR6omnPi+Scpal4Ajkc9GberH+HV2r18un9HGJaKJsVrAqJBTbBXtAbdd8jI1ibff2r8Ew/9t1Lnem2lcq62mDhrkMjH6uO7CgdM0NZmEQ7BNhONr9BAU8NWg7y7aa0vHmYhp+WeQbeKpSi8Om2tMGHbho/8ZGXpODDLspw5V6q1cD8NFeb5Iww7jPazqxZiNm95itNgwUNQF293bfsb1H1pOCapY2AjXR9rxSUlo87QFZAE5A9J0RZgv385uI81uwJKkvPLuQwLKqqqteMPpcLRoxYhnJKEYplnD1clPcEm7Zeyd76R+b7VC5B70i+T3++mX4aKu25jeo6yI03X29upp/ehi/nzvOysAC5Mb+82CrbIU238Hy69eTw3FjI0GI/3WreSWGcBhjsIVEXye5i20+3+6KV9bCrrx7rqNaHOqHPGpD76tzXdp02hqXzCrTZFMd+uJndwlJoRkt3fQzT9OFmViMSK4CH1rNzCmxvQJagN1+qA0KJAqWwtKgPm9YJdkWYKE6EZnq/0xD9wr5CEt27oy8ag+aFmeJdebrSRsSiilZsAXsPCZMQ61FgSjf4IAA/yTS6YRnT0RVWzoDkhJhjUaQJ/1bXH3+FjsOn+xt/TVWuCyahG9Gy5o9xKFKzd6QZlJP/7587up8//P77KLQGIRVLtMFqfVCkWki2xPhrhzLY3eEfD36H2z8k/p/GxN8RAxgU/3ffjYj/u+9GBP5+TODvRwT+w5jAfxgR+I9jAv9xSODXd09/3zCwx7CnWkzrppGAr8UNoH64I0bozPBV+KXMSN4vgtjipo3B0hd30F6b2PyIBPXLz70LV46xQNsuwFpDpXVSVljtydZfYNjSerNQTzD0y8awq0XZi/9FCldPNC1sct3Q4Ip0u7gs2RPY8nc2PCexUawtWOGIoZysRNGzxUeILh0UU9onSjpyUNepi+BlqOCKJRjxdOHeFww596Erw9HNgI5LVDk2mFMNc8JAzq2d9JUGcX5JxfOQIcyeAM4iFc+KvKlfnrxtno/bzrsN4NHD9G588OaEH42Am9kJCLiZjUbAp8sTrMCny+FW4M94bpwgDrnJfSMzK8oTtaKP3sVxJZ7d5TivsFRNA3wIw5ghNtLoL0d7jfVKFY1lpneIT6+17g4sFw3bqRB3SAtu7tHcju49PTRNr8TJOCOMx2mB1+oP07u/Xd9tv42tQx9tQVrgh6Lf16YB1+NPsbNDitz+ttLUQ930LrK6K7oHBUMG55sJGwo0eXM/e3hbf25vH4CVlydiR9hXNxcvgvnQnCmD2QrTi7Pastey2rL9fz2iIT2iR8ZBseMqo7oxTuUL2TJ7/7STtvpCL9g/9B+g7yEWMlHRUOkN+zRC8w/fsUM0BOFAxy7XX+mMZEBVIbc2/eoW6IDQa220jJDnS/jA0pS51KpxSV+WzyfwAZxELPgyM00DcCSmaeoSMenSyJYmdDhumH/nS8yKNL/yXYdjqGXAe9cDh7IFgYA3sDtyNrBjLajgSby2XaqBZjutzSlap9nEOfronrYHBJTPbocVOPe/J+njIh0pLXtKrahMhqXMdds9CWVBR922JXMvpYfSF9c8Fhnjy/G1YqNkS/hIJS+030V1JbCNMFsJ3x4XznnAOihmBpSIu8LxEHd4+V8hR7dzx0v2afjjZXtMDjnlhs+Oh+BU+fUTnK8Np6yTNYXyKf4VcVXB5EP3TEXrC6jxFkIGUAMVSV7Vna5jdqDwbOcw61YMbhpVEv2CNuBesqqGFNbTGB2e7i6pHdb4CIjbRW6PO6I3feRWDemK9lNNjNOjXTs53K8o55BAcoYsGVO+XYnosc2xZtTAHVzGqsZqLK2iHFKfUE1HYcGs1CqnNEsDXeaZ8cJ88G0iX8I0d4kYLisZ39ZxmmIkspDw4qwJugu+PHe0BeNbJJ+aLfdAk7BrUVnF3icwj6hYK+Y0AgTaL1FZuWY3o7eTzlkxN5jm8CBmxk+M7qmG0WkMDHBFwJZZt9EGijc9yqLCUXx7VdwmKsxiMudKKoEmazMMNlXCNxK1X7uQMjZOdj0fJBGSMOz7HnZyDK5hkddBBS6apuK5ZDoLRHAPzo59IldM9XsqLNq0CafOpWeqOqsk7E4iduPcwZgcantsFKkdPOLRTp8NHl7AivHEmJCqP5nkOGKHCNU1lh4MHYdE7NoZ8jLHxWkX/XSbN9CI8ARy7dfYrRpTthoTXnWHW3ZCrvFTwc32DXUqqspvuzRkNyew/cjLH4I7WAj7HYbtEaBwuL3DP55lKc3mCT3qmsoOccKMvRuc8HVl613zJ/f+aviEJSMKyuYiLQpePZzCnfcV4kLbt/c+8SLwYezH9j0mT8L/xIWRoIrUeXrl0FueHbpSSEMTySoGHo7tEmhyA1qDHAzlL0ISqtY8XknBBXaa8EDPNqwwu05WOms99rFEQakQMTiWAE3epQjVFQCZF85i7CNPacZx7kvbQ239i3PFXjOlJeidaCycnTqMgFXd11wZCqrbdpLKgSdldpDZRJ6InmwO59qMuRc2SslQbCfpPKqeW4/q4nggubDr6frgZxRr45X71FeDt4eZssLSfZFs/rSFtdMyrfSq1FiDc7mUgKq6SlUaphIEsB37O7F+4hLwTWUyEupfXBvEzzNyD8uW3WgRVuDnYHDXMt08re5bieDfuuZCHnyVyhv3pNsExlUrtcPm3uy1QkTwWvfIg+mJd27wvAtFuHrkCSQ++zf/kTLq9ohtzSQW29hKEvbEkirdbLOxZAfZVWeyfRkQWjPDPj3axZYZcCXLYl8vT5GR4ITK+grZEFKadi4hU65hXMujG6qXVMMzXR9lvlfDdJjwqNvRWH9GY914MpLGjwRb0hkW3J4/EDeGMcWpLfdvT4tXl0mG0Z5r/osUWWBPDSwUG4Eet29DPpVhgMA+6pbuAPQM2foyeH2SOuNW4P91N92C+WOhH8TYfC4b67jerQ3wLlq0O6sR9oicdsXPetHuxezqoe65NcfHfa9bGf2YAdhByS5wr6q47dhPjMM3F3sjRofyTkh9nvpKK6McJJvCgMVgsIyQP80J9YZ4LmSPEe1b14piZGFwVpmWlCvsvRhGOX0ADwtz+4YfSer+0nOe26T1SynyMdD7nPhEYnXvFo23FdrYZ0ija+TRp0gN+CjabWfMeyk3h3vks6TRAHKI0ySEPirHBz9R2ovIjVHHNXhE6rTFZr2Ordrag5bJcU8uZHKy5xbGnb+cHRfFxq7zvivxIc2ufWs5l9D3Tc/K9bbCtnf/Ha39Lcx3tjl+rfF+2QqqvbnCUX28hyLN+Tj79r/+337dp+7XnVBN51RBFGiOUcjxE21Ugqx76TVk87LL1YRK3grqoJYn7s3WvfO1yS3N4M35/e1bFAGg8cpoxO2g4pSqdl4dBGsaKlAe9N/xzfEpT0gGmZDr6v09YvBfvLzY1pMxQM8S4JotWKOxyhAkULOs8p0q8jxlkFSLX83q7merP/hnSwVnXwowAKy8l98ww+5Fom1QNhx5M3fPrGrJGUH3HJefZijtQMfUY4Q3V1ECuV61Yju6h64oNMbNzAl6/VGRNxJo8jfbe9Bfjbwlz5SVBdzx6tM9GlOP7dh9C70vaWSrIUZ0CVxH/xHzcTSGe7o9++2GzGz5xXMzITEThn0MtvacW0gAc15GdvectHFzFW+uOjhKyhORea47UJ3II6WFpMsTtr/tgO1wEJV3NtVyJcWiQkESoWtra7RGLBlSRnzlsmAGcn1p1YU5EucAeLAkE1tx2j6uuBNKLyXMfrtpBy9S45xEEsoa1ZFKhY5Supxk8wHhp3S5xJQD9kep5N2s5WdoRQuFV/kaZIZK/vP5jU2A9Z7iXvRhu1om8vaVOFDrNF98GA1i7zeN0dra67QLH7IA+b1H81Uv6Ym7Az9G2G0SFqYFk3u3IsGRY1bHSNeK+f6k1oIIT6VwRT6sZ7/dnJEPVDJ6eXFmU4zKVapN02FvqGeaW6v4hba/AWB3vK3vI3jD1NjMa8OwW6k1jE1VqfB2KkNNkYqlilytiOZqHrPtUDADUowDECgQM/Fe+8k2DD7RhrKn95476ksBku0uNAehc3NUt3bbQCVAk1TEj+PCKmfxyROlCboNn+24jEfYS+05d9DWCmqdF1LImjbCzjE4WR8hk361Pzwdwa0NS1Pfw3xDcsvaNYXSIB3UM3MECGxRQzX56Z216cruVP1kbtmNY9Jp9yZu0w0yyxDi8WSiKZiKmKYvbBB66ayreA1ZLiSVa6LN32zmpFGp26Q0FUvGI/84alSd4BwKnLG6i9umD3SZDz2JRZax9pjaYNrezrGPlg8AJpBCRz/o4Y4jnKPU+/ugS9JxoV1e3gQ1hPcAlo0MjHEFUqszUuQJ1aCsKWg5uRdSO9ApwB6ywK4U7aDwSr3j+zpX85G50KuNNyLY0dVYde5phBblBc58bYN7pTXvLAN3sqKxbs5Xp60rxXUACyKHakhWMFeWg7y5t4O/rXgi6WLB4hbrPExxR3bFhdIiA1kZRP7HhnU+Nno5K/+MVohR8cG9jPlq4CfvzBW/MkOyRRR6KZAtD270Pw9fjGk0xmbeTOAuKxI0jZStGBWk0HGRNJjKsXMconKsQh0XnZ3jEHRoGY4Lzmqo4IUfLvE2jKkrirGnRTNkrMVBwC3UMHpQ+WZh/bZeMvaxLMaiAQNzCSywu5ngJKV8WZi1enN5efO2tEv2pWwP02Qsynqtlz3p2dOAGZckv6X3pGEvrT0ABUMpdY9/T40+1hrUlf6ea7Cn3h+LhvrRsCcN+50Or1CQ9nQ3R9O8NY90x0XAq1gXWWcYdn6heEoQlhZxXOTMBv3mjFO5xhCKN18zavyS5g2DjbDJ3ouEgNzNC65hL7daouzBhMRMSBYshf1i7QH8zcuC0eEfdUkQ/FhNbKLeqDGusmREMK9/wcyXRpIo9x5vlZXhPeKtpm1IzTwV8SO0n4RDkVMjYzOSX73ds0i2Xz0EySHJPHKOfjRGKsyByS0+UuxKGsQ0Ta2Ocw5odQvgvrmdUCkaryWPoOvygpgBFUnZI5DP99cPV/dESHJ/dX55dX82JHDgS8YhMh8Mh/+Kxqvala4suOO9ne/MUrZ5dRtc22JNAB23E0CRzsgdKVFwpz3kPtm8sJbVXbWXIFlw7na84z12T7YHRiyynGo2ZynT655b7d61cqQuUzGnaZTMy4MFkghNm4iJ/c7ULaRfh8rrHzgtuXTKYPN5b+t9aQWwegOQS5aZg7Z6Kdx+a2NrKljtUv/+jtwxassGwBYgT8yXSmAkJMKcYtZd9XBkyBFrZmww5CjSQ4sDs2mGoty/8t6J9JQu7dPREg5fepe2Tx52NCgd1W7wyYh0upSR4+ir3SIfQl2U0a/DURimddVJCgtibYK3utio9Ob1uDcXNiL6h5HK+MCkMv4aSJ3T+BGfJUfxivIlRK4K0ySWYLer7PKyj83uLKcmduqyABRO7St7LdgTuNxOheYE5kJsO5k6yVJayGEt1lgX9YZJXWTVkjl2J+CZ8UQ8T+w8g/o5rRXnXIebigo7v71Wq+jd/HxXKtKu2N+x0uSfgVLdB9NY4Sqjaer7+/eRvMAaFLahqy0p5ifqSNWzeREucYjGj0UeSdDGvhc8ckXJhjz2H1qKWth5yxyN8gYTpU8Looo8F9IyKReM63eMv0MjUgJuDrIAqgsJaC3WL0grof1W+YlKAnsFocYaxWmuVkK/GC9cfVDcjTRNPXkel9UztMVlwcR6lgB2T96LATGNVxCtmI7QFJ3MC7P7BqS9/uyqWf/Ilatxb57s9BbVboBtXbFIwZDbdz/Q9whBge7D7XzGIsd9ukcW8f5eV6lsaq+xMPXc+V54CPeevzJRkRaRszhy62OqL2l0YC70niHUZQBwD9Px/nIW+sMl/VoQgZVouUigDNdsPeiK3Ge0RTZjMLLPF19KP5jtb5+krkVh40s2kTE8EXaMZ7iVdTmlKSz0SMRJyChDhz94sIFhTF81czMJsSyh2szPK/X2D1FCWbr26/PNJtZ9XglvDrbxZBg/KxdjzAfEsx+OfT8cP4KeKPbHS6Vgou9eyqs1am18wmFrxW2tpUgsIjH/D8R6+L0VPEGzM7Rgs7soTculxieMHdLnzoRj5c4NE0ic78//muXMH4j2NfeIi/Xrw8Nddfza2jQCLSAbu5394NbujEhYUpmk4B6drvOOc7jEvhzUYtjA/I+rhw3cRri87DHeRsMWvHkxIt67T4Pj7bmCHQTy5dXN1cPV0KhXXRkUg2D+9er8cid53iYLQo0pDB9nm9JwEMqebI5jcVZIZlc3V9MH8hEXHd95G0U3sFRYSiIVU85P/PhmM5/OH7IOi7072Zkdx1AvQRfytZDvwZyC/pSNudvq3qWZy9VWQOhIcb/1lIhnngqavMzK2GWpMOBm2+3Itq257BtjlQuO9/2uGj4lc5F0vD0v8pcm1yOwa+bMLrzttMabwX62v+YEW+X8x6+bRZkGFLcfv371jdlxOmJrUdgap7usm91xtKp2Cwxd6++IkOT7XsJ+GpOwn75+tXEZeULCfL7ZgmHlprWGPW5jjs86y0G+8zKHoZ8yIhKLLMfcs1IksYp0WMitjQVaVJ1cyk2JZXowp2gOpeLt5wca8t67OSlLIKW5shk3HazBtcKNXLHDXaxjwQ78RPmC9317t/QH+XFlyhQ/ZZmy2W17mbIXLOJ7ZzvKzNgfQ1S4N2LgK1hkoBRdQtC0prtE3uzDzLXZuad6KCDS1eAJunjMPsw8LpLYxg9s8xFqiOsWFd3HxQdHy11JyrC1B5u8MjvAvvF2e+B2RrTIWbwD2luhMd0KE1xcf4vxINeahyV+Nrtb2imwl0621xKWnecJ3jvtS5pt6DgWXagAAuzupbAWnsh90bJUG858LIYuwVqHjDqr7Jg0X9fbvS0QBclFyuKdRL+LhnfX/ImmLDnXWrJ5oWHocvBHUBW2CizH+ZbQEipG8JklgLyzNd6+UnNun9V+W/6C/J/Zx1tbQz4WUkKsbSpjRnVvV4CtXLwVTrf8afhou11wEbBzT/rvIZHsCfiDuEy/jEotQsXrt0w4Y6OlY9BBaudBODLGpwIrV/NvjSV5IB2zD7MPguvVg7ikGmY5cP1pdjkI6HhF5dL2bbDsrteetL3ZqNRl5UKXjB7TFHhC8amsXrnHP7Y+XXBKt10BfDnS5PtyUpPvtyMr07oKZI4fEV3udYU9wPOaPJfiK8uwXnrVisjCIlzwdzbcnJSGlbvjbRHJyoh1i5tAStfDJV91bKIQUJVJ4ObGNKZmeSoJFGWRZRkkjGpIO0IiJS1c6OiJKda0Todxtes6wR5gZJGy5aojplEiOwmqTfZpyeCJppXzt6M8GFEaF6mX172QeX91XGhlbHW+9m2fhUt0wemdrUDs65ctkFWzWPPQa54k/jDq4SFkuV774hfjlAXdYM/53XXZNZtqkjC7wy13CfUEdCSmAa/U7ckv9Bve8248th8N+yxm9tvM6czauLV3X2yQzkn1oQ7unuSG+dN1UDpJC6IN5nTbir5tz3jtekrFuzOmst/Gibps7AtseHbVulEchqrs+HKR0vhxJdKxOmaUrV8qb3FNMrNJjXlF5n56IkWjHnMP7Ftxj98/IWh/UiB4QrcBxq0yMl53yzc42rGEogfvDiJRXjSqY1MLcYSDjxIlMkD/7dWeHVOapmP0c6oapxsrql5y0Ng2NnMPA7s0jhFAJ0bfTmEMnPUm7+UylW9cN0G6jFj/NesBLhivlH7CMuDKtvhWSsQMjQe8mqyEpymqTzk/SlCfcn6wmP7r7vb1WzkPBeeQzvRwNztBewUgGoef4HtI8wGLDVvUGfmOMJ7g015FLj9+vkVP//vgj5/u7K8u/nHnfhJ+ejV7OL+4uZ79enWJv/yOMFUVeKNp6hLbEUxPCNSSf0k13WK+7E7/hoUXNnUyEuE4sgOibXbLvpAavbNCOP8vAAD//0YcFdw=" + return "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" } From 098bac28065551e2a6d7bc12ce23f55d89cdcaab Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Thu, 11 Apr 2024 18:12:54 +0000 Subject: [PATCH 26/38] Updated fields description, updated test script --- metricbeat/docs/fields.asciidoc | 2 +- .../module/aws/awshealth/_meta/fields.yml | 2 +- .../module/aws/awshealth/awshealth_test.go | 43 ------------------- x-pack/metricbeat/module/aws/fields.go | 2 +- 4 files changed, 3 insertions(+), 46 deletions(-) diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index f4337174b6bd..5974a0d3d001 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -1695,7 +1695,7 @@ type: text *`aws.awshealth.affected_entities`*:: + -- -Information about an entity affected by a Health event. +Information about an entity affected by a AWS Health event. type: array diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml index 1ea0691210be..56658d74d79a 100644 --- a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml @@ -63,7 +63,7 @@ - name: affected_entities type: array description: > - Information about an entity affected by a Health event. + Information about an entity affected by a AWS Health event. - name: affected_entities.aws_account_id type: keyword diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go index eecaeaae5cd3..bca658ccdade 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go @@ -3,46 +3,3 @@ // you may not use this file except in compliance with the Elastic License. package awshealth - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestGetCurrentDateTime(t *testing.T) { - cdt := getCurrentDateTime() - assert.NotEmpty(t, cdt) -} - -func TestGenerateEventID(t *testing.T) { - cdt := getCurrentDateTime() - e_arn := "arn:aws:health:us-east-1::event/LAMBDA/AWS_LAMBDA_OPERATIONAL_NOTIFICATION/AWS_LAMBDA_OPERATIONAL_NOTIFICATION_e76969649ab96dd" - sc := "" - eventID := cdt + e_arn + sc - eid := generateEventID(eventID) - assert.NotEmpty(t, eid) -} - -func TestGetValueOrDefault(t *testing.T) { - // Test case 1: Test with non-nil string pointer - inputString := "hello" - resultString := getValueOrDefault(&inputString, "") - assert.Equal(t, "hello", resultString, "Result should match input string") - - // Test case 2: Test with nil string pointer - var nilString *string - resultString = getValueOrDefault(nilString, "") - assert.Equal(t, "", resultString, "Result should be an empty string") - - // Test case 3: Test with non-nil time pointer - now := time.Now() - resultTime := getValueOrDefault(&now, time.Time{}) - assert.Equal(t, now, resultTime, "Result should match current time") - - // Test case 4: Test with nil time pointer - var nilTime *time.Time - resultTime = getValueOrDefault(nilTime, time.Time{}) - assert.Equal(t, time.Time{}, resultTime, "Result should be zero time") -} diff --git a/x-pack/metricbeat/module/aws/fields.go b/x-pack/metricbeat/module/aws/fields.go index 26c1fc3e9a2e..782dbc2ff515 100644 --- a/x-pack/metricbeat/module/aws/fields.go +++ b/x-pack/metricbeat/module/aws/fields.go @@ -19,5 +19,5 @@ func init() { // AssetAws returns asset data. // This is the base64 encoded zlib format compressed contents of module/aws. func AssetAws() string { - return "eJzsvV1z4zbyL3yfT4Ham8xs2U4ySbaeysVTZcvOxmc9Hseyk5wrLkS2JKxJgAOA9ii1H/4UGgAJvumVlJ1//edmN5YE/LrRaHQ3Gt2n5AlWPxH6or4iRDOdwk/kb+e/T//2FSEJqFiyXDPBfyL//1eEEPJv+qL+TTKRFCmQWKQpxFqR89+nJBOcaSEZX5AMtGSxInMpMvxskooieaE6Xp59RYiEFKiCn8iCfkXInEGaqJ9w9FPCaQYejfmnV7n5ohRF7v7SAao+SDiQpgt19vfyz348MfsPxDr4s/1DZD99gtWLkEn3x1FG85zxhfvu3/7+t+B7ndjsvwe6MAOTZ5oWQHLKpOMPfVFEghKFjEGdtShQ35/NivgJ9Jn57xYlbaxrMNzSDIiYE0qm3xM3amvChGXAFRP8jTDuIwpTCKsF+eu/nzmRO/v72d+/3hF1IopZCmOAVkQvqSYSdCE5JHa9q71Azu+uyecC5KpNUsr4EyQRjWNRcN2iKNwQpEP+w6FYUvtzv+RsoMn8u74khYKEaEFYAlyz+cpBJQ7qWSeGhuweiMLKsSQ0ZVRtDyjQLkugqV5uZGupqWag6XYrb9TdLzi6V4NbLhOdzyHWkESGCs1ARUIvQapOts1TQfVuTHtYAuFFNgOJKsDNVqkeQyzVlpV6CQSegWvyshQKiNJUF4rElHOhyQzIM0g2Z5B0r3ablBx4wvjiaLTgvsvoikj4XDAJhMZmrG3hmoHSZ+jeOKPhTQQx7C0h89Va2MCTSLOefZVQ3fygjpF0gjQ/I5QnxAxMXpbAA1kAnkByRqYic39RyGKDeUmfze/MV3CMHsTmRxGVfDhVYEAXnH0uwO9/BpLMhaxwn+GXLAnn97dkSRV+OBcyo5pQyX+iL+onqxJ+wu+dSliYCe1/fTO9uv/tenL1zdVvV7cP0cP/vbuKJp8ua/99d/M4ja4v19GtYpFDFItkQE34sGSK5FTSDDRIonKIDQeUWTqjPZBQp44sB5gilOTFLGUxOc/on4KT32FGpiCfWezZZHQr9wr01I0ae3aep6l4gcSaMopQCeTu8eLmenJCzieTT4+3D9H07mpy/bP5i5Dk9tPt1RlZwxk8aWOqYSHkaljZsPSYQYifgJglOCN3Qik2SyEkgylVwIkn/FYYcYqpGR8JUfESjOGbTJaUL9YKuSVp4LXeKOo4vJV3J90MjfPISXB0eTWd3F/fPVx/uu1Gn1KloyI3e/gQ7dIJPhPKaLfYAF2raF7MqW4xdKO023NY1rY3gyL3OA9OahR3pVI6USn7s7FhVefHbBVquZ+FJPCFZnkKJ+Rq8sFI7P3ltAerplIPvcBrF3UGC9pzklnzYoTtEkqcs2Fqy9ipBEQO/ITEqVCQnCA5RR6LjPHFug0foOmkQcOXPYyGBDRlKSThd7eQxJZF0wmJSkmb6naT/c+tXjEw6EwU2h76mulVTSxp7dCpQG6H9oy+KO/6REO6L3373M3lbTS0xmLBNWXc2golbZbWLbl+Zr8dFTIdlobH+xsvBYchQ7EfFtv15YHQjnUEoZLCpcbdZIV449HTxvsa2qu943bVCF4CDrHGu32INTaKlQNrmFkS2gb5Ty2LHL/pTXL6ok7ddnWffOO+wJK2qz9jaVr3O7sd/TWr8W83xr/rGgGUZhn6y/GSygUopHIlCokhAK9RGG8EP/2/vtDCuhDBlZ9zYqfsXLhUtPzsGnUf6ReWFVkPAQ77mlDOpJASeLy3nX7Vmjd2IxrJ6ZnUaerbA8JI3npCY85LZNbHjG4Y55mQmv0JyUSo5mneLVh9SxqOSrNGjK8+ZCs+2UleCY3ERm30jOmnNJzunbCbmZtmbA3p57pIMXDw9ljmgB2NYbX5etl1a7Rgavj6qOgCzrtwvTLjKoikMBiPwbyeOfv5+Mhnb1XwSmhHE73GjP1MM6z9taB4or4xpuGqf3bYjsK0+oy9TLO+dIdBuv3ZZEaw7rM5mSRoyeCZ8QWex2bJVLfryZOD5r1y4drdZkURiBKYM856/d195OQJmjK3iZoWRca0VBpvod3dWy5BYaya4v2roZSWgdKkE2dwf7zKuwRzKEjGBMHYpJh3AKnze7aq3ceS/ttNsvleluxwzdkiqO2tGBVL4EueCgnS4jU+SXnfrVqGeVwaxQfZ5tUwDfM8Cy9gX0ACUbGkub+ELZMSfseL2Jcli5fVAB2pDApDWCuSsPkcpPkPQ4fKaVy3Feu5Df7fOqO+HGdY57EcNpB1jMjhhXPAf0Jz1pEFsOI0E8nsoNXxgxxpbcwPL3HKy4tDXa323W0/C/rGCsebFnEMSs2L9B4+F6D0DdXG5zmjz01vjex4MLbXnzgZoM8gzRGW2rmMllElDrxnBGW0kCjZRowLaANk5Z+mWgLNmqxwQAqn10Ixw8BKDpKJRgxlK4Zk9MtoDPHu3ltkyCeeMg7XPIEvdyBj4Jou4E6KhQSlRhWTvJzOMCQWWZ4CRnhRX1DC4YUsUjGjKVEQC55QuSLMACVMkRkYgmmS2NQBSjSdpdBP550Uz0wxwSH5XTINE5rTmOnVI2d6XDqrG/i8wkBeDAgSOxRo5SlnJSAleBnaQ/9WVN4DTV6bSAk0GZzGieCqyI5NoFdqFaFdxMUOGxHP7ha8czuedE6jBFmJgsSUEy1p/ESW4oVkRbw0s2GIL+StXkpRLJZ5gbethWpGjrdjmSqyXpZ1hPR2YJgqsr8ol46sH9qS1akb/npMG122/kp8uoc8dUkdx7TBIKW58pTPQL+AOVu5v2wiTENGaJ4DRQOC2avz0uZQaHMYnd05k+Bg/EpDmNXo9uIaLez2yJRjamH5CzeZ0/8bzu8O/h3DZPsfw78HSbmyeX0Twecpi/VoAnjuhE/Cf+xFoaHlNIVnCKzdpADM+axw0dRsXoSmSl7HgtuLmq64GqmGE5YZimaA06ndWDGSrhKapm+VDef2uq3PZNQsZX/ifjuKoqp7A5uMyALRVVfQnVng64mtH1hvhtrOM21ncqcrpSG7klLIMc/hHV1Xq9gWwEG2o8f2H+Xkl4eHO/Ljt9+W6d8igQMc3IngCbP7arKE+OlnzGxy3v+YzKnsublNpqJaQ5ZbbuUg50JmZl97dHbp12zYO5vNHpyEE5SCY5CAp5E99NwyUgmIWAM3BLWPss5RZ4W2P8fUbS40WYEmM6PigsEOtBRo8rCUQusUrjBffCQO3XdJPxIHX2JA+xD6NVnnkAO5yJ78scV8Zw4EFnPKMqa7o1mCE1q+UiDvlLG/qaqxhFsWvO/nAer3tykHdR0/piC4Y+8j/WJ2hVprMh+mKrzBvD4+YlMcKSczsA+oZqsg5b9NB/GPDVBaSCJAodKgeZ6urNo5TSBDo9lwSRk2dTNpnWat2PRgRrkxJtobZlglEZbUble2ETMV85DTmLbdYp6uWB3TXIW5Sj1mJ028EeAAbyGuSE+h1qjwrvX43Z6Ox1yQTlvsba+IhTzqkrzphXh9XfKRfgm8DJTfPr9qzADGYf7Uki2W0Mpfsv9aYzVkf4Oc78K4Xh/tdTjXFMNupoU/WbNH9+RamYMzC22n3S/JYaaOeD9+dTE9LF1h6Ivx30RaZLgxL1ZGmx3u9Pugl2J/ouAAjZd2f4jc+LtM8NCLdVFoNBFzbUzeZ4SkjJtI46W/1rxlWorTGTUKjnGlKY/hhLwszfroIKLQSO/xf+4Igm9ymC1rcOuNyhu7Df6SzDFy8ykfgjNG4WiMEjbswJIvCkO/LYj4JoNla07sYB3Hw9pYxAPB/lpAATfAF3o5EN4GV83h3pS7Moj1QplGCRTGpHAJCShZB5D0UHq8VXrFQLTVD6rrbz6F65CDdEcKeXf96W76niSQsmeQkPjnPHYtzYe1U25u/WsXw7u6mLrNd0YezT57YXoZ5hnYAabTy3KPCp6uNrElvJEeRURdnvaahVfkHa+yu7UgH378x78ahtH76jpxvRQMw5uLQip9QVOjxwbgRoXpnxhzTcldIXOhACG9W+Qf3p+QSkDJp1yzDLnxy+Uleaf0d+/thdREpP5v8Xfv68RYehMwW7/5SlN3SmksITFG5zsjaQYEwWcxJYza50p/hxBwYgkZZTy4aJsZhrVqCnWLHF7GYHDQLNi6UND+6tDuOGXkxBo/NE1b+ty98xxGvRgANtR1ZKpau2lIsq6T9BgErcVo89C4cOsn2xRbI7mYZUzXHm6WNnr84TAbPf5wTBt98uEwGz3OizPk9FneSgy3xKuYppBEe5ayqWsSmqYixjv4q8kHlLtCQxgaoBLcGz+dGqeKFAr8/ag3Frvf2xlCrBKK8NFPJy2bHjxuKsczuXssNV25sUJseBCbbxWB47sJ78weHqMgBorlxELgltG8wryk+KxdFpAQxcxfmC2skdKCo+GOOp3K3pfOhhhVyDwtVHQEotxUdYrwcgovpSqVx0nBMXIU+BpWRZifTe4eJziCO71dwT2myJ8gxbaUqsi+A+2uPXAwqUhLJ8Fmr3ChSU5ZQhLxwg3J7fW21oBVK3pZGAUaF7ZoT1JeY1oSegqygX4R8umM8bOcmkN7v8fE3ZQ2tbybAd+ys2cjehxPLgeCMK5BzmkMqrX1GPdVJo0x0+UU9lMU5SAjBfEIGrBNW2Dmoy43VtfWZK6nSBT6iIu0O/o9Fikg6X/KKjF+Nlvp7R/l+2oHXT/aY/lwmKPtMJztKCtn6QrWbXcSN4vi6y/c0XbdK67cUDsuYeqJiTPjDRxv5XDV/Cajzsw3VJTrobSQUMVHnylL8WbB1dPcY91ahI60bhcVWcFy7U3hWmLQd3uVZQvTmo6ybgGpoy6cJyxYuz1p3CyGzXLEaxduq8WpAhXN8Myxt5itN7ZupXancdJL3RA7bZfYTqdwjrmc7bjUcTfeuMvZou7w3bfPatrU3LN4CfFTZNNbByL1HnIhdb2SbC26kFOFyR5CL+sf+nRhg8k9owCiMBG6/pmLHadUaZIxXvTVDe4gMrLjHZnWMQjx87wCKd0rti0x5aERC7lOkxjzbgHNdze7h+iEdDXKNp9Y5acsows4G7qEZFXiEMcvK9Db0Nou+KpIMJYRHLAGxDVPWIxJ4l4SylqiQfiZKQLc6KIehVoCzSV7phrOEq6iYYv5Y0DZjk4ub6e1YrstD2FLlKyZheIksfnnHaBd3z3/QGiSSFCKUKVEzDDmjbd6e2HFGtxjMdQW+G7yc0updNAG5KJnnMNxZZQLi8n1XfnJO8Pg92QmCl62INiVpbiFznoLce6tiHDcJg9PbCb8d/84nTFNCq7YgmNEGifZCunw696JlLxz7RfIf4ksOLf/Ty0LrRlfnGKU+b9Eg8wYR5n+r7FYsCCQ/7+QvN9AkV4aA9c6OkZVj3UUuHnQ3PLHQseFX3pY5RpIj1m05uqmu17NqyXlXdD4CXgyEZxbq3ugB2z1pYzL4UO2cqGDoizpioDSdJYytTTGpnuFiQaKoAlxN1KytDMlLJjSmF3jZXNNjvAvDw93E5FA5CiOPvzxx8BU4iu6D3/8QSSoXHAF9h2df3yHSasHgv5+HNDfjwr6h3FA/zAq6B/HAf3jKKCvbi7G5HKcMuwKY1QDglZ11K09uiXkEXmsQD6DHASye2s2zMPPZoKky4OsYikIt9KWGe17iYum0jNN17xIzlmaimeQw0Fv5836d3ilVi+f3s8gpoWyWcGqkFhgE+wFvVH3a2QEq4GvfhGe6Ye+e6kz3RYbX1UbLNx1aORj1ZEtpWNqKAuTaIcA28vmdyjgqUHLQb5vSsu7h0n4aZln4K1CKQqfbktbfOin8ZGPvCQFH3ZRhiv3Uq0G5qe52iQnhHGf0XZizULM7rV9BpoGCxqAunq7b9nfoepJwTVLWwEb6Xq1KSgtH3eALIEmINecEGUJ9vObi/NYs2eoLD27kMOwqKqqXjP6XC4YMWIZyilFKJZx9nBR3hNs23ole+sfme9TuQC9Jfk+/flm8jhU2nMX1XWQjTdf724mj+/Dl3PneVlYgNyYX15slO2Qplt4Od56cnhpLWRosR9vNe+kME4DDPaQqI9kd7Htp9t+0cp62NVXD3VU60Md0WcNyH1z7mu3ThvD0nkD2myCYz/cTG9hITSjpbs+hmn6cDOtEYkVwEPr2TkFtp8lS9CbL9UBoUSBUlha1IdN6wS7IkwUJ0Izfb3TEP3MvkAS3bujLxqD5rmZ4rQ8XWkrYlFFKzaAvYeESYj1KDClG3wQgI8yjW5YxnR0hZUzIDki5lgUacK/1vXHX6Hj8Hh/46+pynXBJHQjWtb8MQ5FavYOtvPi5P/715bu5/d//DEKrUFIxRJtsFofFKkWki0w/tqjDLZ3+MeD3+P2D4n/xzHx98QABsX/7bcj4v/22xGBfxgT+IcRgX8/JvDvRwT+w5jAfxgS+PXd8z8aBvYY9lSHad02EvC1uAG0Hu6IETozfBV+KTOSd4sgdrhpY7D01R20tyY2PyBB6+Xn3oUrx1igTRdgnaHSOilLrPZk6y8wbMPeLNQTDP26MexqUXbif5HC1TNNC5tcNzS4It0sLgv2DLb8nQ3PSWxubAtWOGIoJ0tRrNniI0SX9oop7RIlHTmo69RF8DJUcMUSjHi6cO8rhpzXoSvD0e2AjktUOTSYUw1zxEDOrZ30jQZxfk7Fy5AhzDUBnHkqXhR5V788ed8+Hzeddw3g0cPkbnzw5oQfjYCb6REIuJmORsDj5RFW4PFyuBX4K54bR4hDNrlvZGZJeaKW9Mm7OK7Es7sc5xWWqmmAD2EYM8RGGv3l6FpjvVJFY5npPeKz1lp3B5aLhm1ViDukBTf3aG5H/54emqY34mScEMbjtMBr9YfJ3TfXd5tvY+vQR1uQDvih6K9r04Dr8ZfY2SFFbn9baVpD3eQusrorugcFQwbn2wkbCjR5dz99eF9/bm8fgJWXJ2JL2Fc3F6+Ced+cKYPZCtOrs9qy17Lasv1/PaIhPaInxkGxwyqjujGO5QvZMnv/spN2+kKv2D/0n6DvIRYyUdFQ6Q27NELzD9+xQzQE4UDHLtdf6YRkQFUhNzb96hfogNBrbbSMkOcL+MjSlLnUqnFJX5TPJ/ABnEQs+DIzTQNwJKZp6hIx6cLIliZ0OG6Yf+cLzIo0v/Jdh2OoZcB71wOHsgWBgLewO3Ia2LEWVPAkXtsu1UCzrdbmGK3TbOIcfXJP2wMCyme3wwqc+9+j9HGRjpSOPaWWVCbDUua67R6FsqCjbteSuZfSQ+mLax6LjPHF+FqxVbIlfKSSF9rvoroS2ESYrYRvjwvnPGAdFDMDSsRd4XiIO7z8r5Cjm7njJfs4/PGyPSaHnHLDZ8dDcKr8+hHO15ZT1suaQvkU/4q4qmDyvnumovUV1HgHIQOogYokr+qO1zE7UHi2c5h1KwY3jSqJfkUbcCdZVUMK63GMDk93n9QOa3wExG0jt4cd0U0fuVNDuqL9VBPj9GjXTg73K8o5JJCcIEvGlG9XInpsc6wdNXAHl7GqsRpLpyiH1CdU01FYMC21yjHN0kCXeWa8Mh98m8jXMM1dIobLSsa3dZymGIksJLw6a4Lugq/PHW3B+BbJx2bLPdAk7FpUVrH3CcwjKtaKOa0AgfZLVFau2c7o7aVzWswMphk8iKnxE6N7qmF0GgMDXBGwZdZttIHiTY+yqHAU314Vt4kKs5jMuZJKoMnKDINNlfCNRO3XLqSMjZNdzwdJhCQM+76HnRyDa1jkdVCBi6apeCmZzgIR3IGzY5/IFVP9ngqLNjXh1Ln0QlVvlYTtScRunFsYk0Ntj0aR2sEjHt302eDhBSwZT4wJqdYnkxxG7BChutbSg6Fjn4hdN0Ne57g47qIfb/MGGhGeQa78GrtVY8pWY8Kr7nDLnpFr/FRws31DnYqq8us+DdnPCWw/8vqH4BYWwm6HYXcEKBxu5/CPZ1lKs1lCD7qmskMcMWPvBid8W9l61/zZvb8aPmHJiIKyuUjzglcPp3DnfYG40PbtvU+8CHwY+7F9j8mT8D9xYSSoInWeXjn0hmeHrhTS0ESyioH7Y7sEmtyA1iAHQ/mzkISqFY+XUnCBnSY80JOGFWbXyUpnrcc+ligoFSIGxxKgyWmKUF0BkFnhLMZ15CnNOM59aXuorX52rthbprQEvRWNhbNThxGwqvuaK0NBdddOUjnwpMwOMpvIE7Emm8O5NmPuhUYpGYrtJJ1HtebWo7o4Hkgu7Hq6PvgZxdp45T711eDtYaassPRfJJs/bWDtpEwrvSo11uBcLiWgqq5SlYapBAFsx/5erI9cAr6pTEZC/bNrg/j7lNzDomM3WoQV+BkY3LVMN0+r+1Yi+NeuuZAHX6XyxmvSbQLjqpPaYXNvdlohInite+Te9MRbN3jehiJcPfIMEp/9m/9IGXV7xLZmEvNNbCUJe2ZJlW7WbCzZQ3bVmWxXBoTWzLBPj7axZQZcybLY1+tTZCQ4obK+QjaElKa9S8iUaxjX8eiG6gXV8EJXB5nv1TA9JjzqdjTWX9BYN56MpPETwZZ0hgW35w/EjWFMcWrL/dvT4s1lkmG055r/LEUW2FMDC0Uj0OP2bcinMgwQ2Ef90h2AniJbXwevT1Jn3Ar8b3eTDZg/FfpBjM3nsrGO693aAu+iRduzGmGPyGlX/Gwt2p2YXT3UPbfm+LjvdSujHzMAeyjZBu5VFbcd+4lx+OZiZ8ToUN4Jqc9TX2lllIOkKQxYDAbLCPnTnFBviOdCrjGifetaUYwsDM4q05Jyhb0XwyinD+BhYW7f8CNJ3V/WnOc2af1SinwM9D4nPpFY3btD422ENvYZ0uoaefApUgM+inbbGvNOys3hHvksaTWAHOI0CaGPyvHBT5TuInJj1HENHpE6bdGs17FRW3vQMjnsyYVMjvbcwrjzl9PDotjYdd53Jd6n2bVvLecS+r5as3JrW2Hbu/+e1v4W5qltjl9rvF+2gupurnBQH++hSHM+zq79r/+3X/ex+3UnVNMZVRAFmmMUcvxEjUqQdS+9hmxWdrk6o5J3gtqr5Yl7s3XvfG1ySzN4d35/+x5FAGi8NBpxM6g4paqbV3vBmoQKlAf9d3xzfMoTkkEm5Kp6f48Y/BcvLzb1ZAzQswS4ZnPWaqwyBAnULKs8VUWepwySavGrWd39bPUH/2yp4OxzAQaAlffyG2bYnUi0DcqGI2/q7plVLTkj6J7j8tMMpT3omHqK8OYqSiDXy05sB/fQFYXGuJk5Qa8/KfJOAk2+sb0H/dXIe/JCWVnAHa8+3aMx9dSN3bfQ+5xGthpiRBfAdfQfMRtHY7in29Nfb8jUll88NxMSM2HYx2Bjz7m5BDDnZWR3z1EbN1fx5qqDo6Q8EZnnugPVizxSWki6OGL72x7YDgdReW9TLVdSLCoUJBG6trZGa8SSIWXEVy4LZiDXl1ZdmCNxBoAHS3JmK07bxxV3QumFhOmvN93gRWqck0hCWaM6UqnQUUoXZ9lsQPgpXSww5YD9WSp5N2v5GVrRQuFVvgaZoZL//fzGJsB6T3En+rBdLRN590rsqXXaLz6MBrH3m8Zo7ex12ocPWYD83qH5qpf0xN2BHyLsNgkL04LJvVuR4Mgxq2Oka8l8f1JrQYSnUrgiH1fTX29OyEcqGb28OLEpRuUq1abpsTfUC82tVfxK298AsDve1vcRvGVqNPPaMOxWag1jU1UqvJvKUFOkYqEiVyuivZqHbDsUzIAU4wAECsRMvNN+sg2Dj7Sh7Om94476XIBk2wvNXujcHNWt3SZQCdAkFfHTuLDKWXzyRGmCbsJnOy7jEfZae84dtLWCWueFFLKmjbBzDE62jpCz9Wp/eDqCWxuWpr6HeUNyy9o1hdIgHdQTcwQIbFFDNfnx1Np0ZXeq9WRu2I1j0mn3Jm7TBpllCPFwMtEUTEVM01c2CL101lW8hiwXksoV0eZvNnPSqNRNUpqKBeORfxw1qk5wDgXOWN3FbdIHusyHPotFlrHumNpg2t7OsYuWDwAmkEJPP+jhjiOco9T7u6BL0nGhXV7eBDWEdwCWjQyMcQVSqxNS5AnVoKwpaDm5E1I70DHA7rPArhTtoPBKveP7OlfzkZnQy8YbEezoaqw69zRCi/ICZ7aywb3SmneWgTtZ0Vg356vT1pXi2oMFkUM1JCuYK8tB3t3bwd9XPJF0Pmdxh3Ueprgju+JCaZGBrAwi/2PDOh8bvZyWf0YrxKj44F7GfDXwk7fmil+ZIdkiCr0QyJYHN/pfhy/GNBpjMzcTuMuKBG0jZSNGBSn0XCQNpnLsHPuoHKtQx0Vn59gHHVqG44KzGip44YdLvAlj6opi7GjRDBlrcRBwC7WMHlS+WVi/bS0Zu1gWY9GAgbkE5tjdTHCSUr4ozFq9u7y8eV/aJbtStoNpMhZla62XHenZ0YAZlyS/pXekYSetPQAFQyl1j39HjT7WGtSV/o5rsKPeH4uG+tGwIw27nQ5vUJB2dDdH07w1j3TLRcCrWBdZZxh2fqV4ShCWFnFc5MwG/WaMU7nCEIo3XzNq/JL2DYONsMm1FwkBuc0LrmEvtzqi7MGExExI5iyF3WLtAfzmZcHo8A+6JAh+rM5sot6oMa6yZEQwr3/BzBdGkij3Hm+VleE94o2mbUjNLBXxE3SfhEORUyOjGcmv3u5ZJJuvHoLkkGQWOUc/GiMVZs/kFh8pdiUNYpqmVsc5B7S6BXDf3EyoFK3XkgfQdXlBzICKpOwJyO/31w9X90RIcn91fnl1fzIkcOALxiEyHwyH/4rGy9qVriy4472d78RS1ry6Da5tsSaAjrsJoEhn5I6UKLjTHnKfNC+sZXVX7SVIFpy7He94j92T7YERiyynms1YyvRqza322rVypC5SMaNplMzKgwWSCE2biIndztQNpF+HyuufOC25dMqg+by38760Ali9Acgly8xBW70U7r61sTUVrHapf39L7hi1ZQNgc5BH5kslMBISYU4x6656ODLkiDUzGgw5iPTQ4sBsmqEo96+8tyI9pQv7dLSEwxfepV0nD1salI5qN/jZiHS6lJHD6KvdIu9DXZTRL8NRGKZ11UkKC2I1wVtdbFR6+3rcmwuNiP5+pDI+MKmMvwVSZzR+wmfJUbykfAGRq8J0Fkuw21X2edmHZneWUxM7dVkACqf2lb3m7BlcbqdCcwJzITadTL1kKS3ksBZrrIt6w6Q+smrJHNsT8MJ4Il7O7DyD+jmdFedch5uKCju/vVar6G1+vi0VaV/s71Bp8s9AqV4H01jhKqNp6vv7ryN5jjUobENXW1LMT9STqmfzIlziEI2fijySoI19L3jkipINeew/dBS1sPOWORrlDSZKnxZEFXkupGVSLhjXp4yfohEpATcHmQPVhQS0FusXpJXQfq38RCWBawWhxhrFaa6WQr8aL1x9UNyNNE09eR6X1TO0w2XBxHqWAHZP3okBMY2XEC2ZjtAUPZsVZvcNSHv92VW7/pErV+PePNnpLartANu6YpGCIbfvbqDvEYICvQ638xmLHPfpDlnEu3tdpbKpvcbC1HPne+EhvPb8lYmKtIicxZFbH1N9TqM9c6F3DKEuAoA7mI73l9PQHy7p14IIrETLRQJluGbjQVfkPqMtshmDkX2++Fr6wWx/+yR1JQobX7KJjOGJsGU8w62syylNYa5HIk5CRhk6/MGDDQxj+qqZzSTEsoRqOz+v1NvfRwll6cqvz1dNrLu8Em4O1ngyjJ+VizHmA+Lp94e+H46fQJ8p9udrpWCi717KqzVqbXzCYevEba2lSMwjMfsPxHr4vRU8QbMzdGCzuyhNy6XGJ4w90ufOhEPlzg0TSJzvz/+W5cwfiPY194iL9cvDw111/NraNAItIBu7nX7v1u6ESFhQmaTgHp2u8p5zuMS+GNRiaGD+59VDA7cRLi97jHfRsAFvXoyI9+5xcLxrrmAHgXx5dXP1cDU06mVfBsUgmH+5Or/cSp43yYJQYwrDp2lTGvZCuSab41CcFZLp1c3V5IF8wkXHd95G0Q0sFZaSSMWU8yM/vmnm0/lD1mGxdydbs+MQ6iXoQr4V8j2YY9CfsjF3W927NHO52goIHSlebz0l4oWngiavszJ2WSoMuNm2O7Jtay77xljlguN9v6uGT8lMJD1vz4v8tcn1COyaObMLbzut8Wawn+yuOcFWOf/hS7Mo04Di9sOXL74xO05HbC0KW+N0m3WzO45W1W6BoWv9LRGSfLeWsB/HJOzHL19sXEYekTCfbzZnWLlppWGH25jDs85ykKde5jD0U0ZEYpHlmHtWiiRWkQ4LuXWxQIuqk0u5KbFMD+YUzaBUvOv5gYa8926OyhJIaa5sxk0Pa3CtcCNX7HAX61iwAz9RvuD9ur1b+oP8sDJlih+zTNn0trtM2SsW8b2zHWWm7M8hKtwbMfAVLDJQii4gaFrTXyJv+nHq2uzcUz0UEOlq8ARdPKYfpx4XSWzjB9Z8hBriukVF92n+0dFyV5IybO3BNq/MDrBvvN0euJ0SLXIWb4H2VmhMt8IEF9ffYjzIteZhiZ/N7pZuCuylk+21hGXneYL3TruSZhs6jkUXKoAAu3sprIUncle0LNWGM5+KoUuw1iGjzio7Js1W9XZvc0RBcpGyeCvR76Ph9Jo/05Ql51pLNis0DF0O/gCqwlaB5ThfE1pCxQg+swSQU1vj7Qs15/ZJ7bflL8j/mX66tTXkYyElxNqmMmZUr+0KsJGLt8Lplr8MH223Cy4Cdu5I/z0kkj0DfxCX6edRqUWoeP2WCWdsdHQM2kvtPAhHxvhUYOVq/rWxJPekY/px+lFwvXwQl1TDNAeuH6eXg4COl1QubN8Gy+567Unbm41KXVYudMnoMU2BJxSfyuqle/xj69MFp3TXFcDnA02+z0c1+X49sDKtq0Dm+BHRxU5X2AM8r8lzKb6wDOulV62ILCzCBT+14eakNKzcHW+HSFZGrFvcBFK6Gi75qmcThYCqTAI3N6YxtctTSaAoiyzLIGFUQ9oTEilp4UJHz0yxtnU6jKtd1wn2ACPzlC2WPTGNEtlRUDXZpyWDZ5pWzt+W8mBEaVykXl53Qub91XGhlbHV2cq3fRYu0QWnd7YCsa9fNkBW7WLNQ695kvjDaA0PIcv1yhe/GKcsaIM953fXZddsqknC7A633CXUE9CTmAa8UrdHv9Bvec/b8dh+NOyzmOmvU6cza+PW3n2xQTon1Yfau3uSG+Yv10HpKC2IGszptxV9257x2vWUindrTGW/jSN12dgV2PDsqnWj2A9V2fHlIqXx01KkY3XMKFu/VN7iimRmkxrzisz89ESKVj3mNbBvxT1+/4ig/UmB4AndBBi3ysh43S3f4GjHEoo1eLcQifKiUR2aWogj7H2UKJEB+m9v9uyY0DQdo59T1TjdWFH1koPGtrGZexjYpXGMAHox+nYKY+CsN3kvl6l849oE6TJi/desBzhnvFL6CcuAK9viWykRMzQe8GqyEp62qD7n/CBBfc753mL6293t27dyHgrOIZ3q4W52gvYKQDQOf4bvIc0HLDZsUSfkW8J4gk97Fbn89PstevrfBX98vLO/uvjnnftJ+OnV9OH84uZ6+svVJf7yW8JUVeCNpqlLbEcwa0KglvxLqukG82V7+hsWXtjUyUiE48gWiDbZLbtCavXOCuH8vwAAAP//7Pv0Bg==" + return "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" } From e3c1153ca7ebec887417e2e7e7ed1b2f266a23ec Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Fri, 12 Apr 2024 03:49:30 +0000 Subject: [PATCH 27/38] Updated the field description --- x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml | 2 +- x-pack/metricbeat/module/aws/fields.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml index 56658d74d79a..8ec1c4b28c51 100644 --- a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml @@ -84,7 +84,7 @@ - name: affected_entities.status_code type: keyword description: > - The most recent status of the entity affected by the event. + The most recent status of the event. Possible values are open , closed , and upcoming. - name: affected_entities.entity_arn type: keyword description: > diff --git a/x-pack/metricbeat/module/aws/fields.go b/x-pack/metricbeat/module/aws/fields.go index 782dbc2ff515..222cbae9dcbb 100644 --- a/x-pack/metricbeat/module/aws/fields.go +++ b/x-pack/metricbeat/module/aws/fields.go @@ -19,5 +19,5 @@ func init() { // AssetAws returns asset data. // This is the base64 encoded zlib format compressed contents of module/aws. func AssetAws() string { - return "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" + return "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" } From 8eb55337ed69659f6277225cae4842464adcac4a Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Fri, 12 Apr 2024 03:52:01 +0000 Subject: [PATCH 28/38] Updated the field description --- metricbeat/docs/fields.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 5974a0d3d001..4d03dc8fa6be 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -1745,7 +1745,7 @@ type: date *`aws.awshealth.affected_entities.status_code`*:: + -- -The most recent status of the entity affected by the event. +The most recent status of the event. Possible values are open , closed , and upcoming. type: keyword From 20e8f007541bbf5ad234bb74a88ecc34fc280f90 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Fri, 12 Apr 2024 06:39:30 +0000 Subject: [PATCH 29/38] Updating fields_go --- x-pack/metricbeat/module/aws/fields.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/metricbeat/module/aws/fields.go b/x-pack/metricbeat/module/aws/fields.go index 222cbae9dcbb..1d895b21f798 100644 --- a/x-pack/metricbeat/module/aws/fields.go +++ b/x-pack/metricbeat/module/aws/fields.go @@ -19,5 +19,5 @@ func init() { // AssetAws returns asset data. // This is the base64 encoded zlib format compressed contents of module/aws. func AssetAws() string { - return "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" + return "eJzsvVtz4zbyN3yfT4Ham8xs2U4ySbbeysVbZcvOxs96PI5lJ3muuBDZkrAmAQ4A2qPUfvin0ABI8KQjKTv/+s/NbiwJ+PUBjUaj0X1KnmD1E6Ev6itCNNMp/ET+dv779G9fEZKAiiXLNRP8J/L/f0UIIf+mL+rfJBNJkQKJRZpCrBU5/31KMsGZFpLxBclASxYrMpciw88mqSiSF6rj5dlXhEhIgSr4iSzoV4TMGaSJ+glHPyWcZuDRmH96lZsvSlHk7i8doOqDhANpulBnfy//7McTs/9ArIM/2z9E9tMnWL0ImXR/HGU0zxlfuO/+7e9/C77Xic3+e6ALMzB5pmkBJKdMOv7QF0UkKFHIGNRZiwL1/dmsiJ9An5n/blHSxroGwy3NgIg5oWT6PXGjtiZMWAZcMcHfCOM+ojKFsFqQv/77mVO5s7+f/f3rHVEnopilMAZoRfSSaiJBF5JDYuVdrQVyfndNPhcgV22SUsafIIloHIuC6xZF4YIgHfofDsWS2p/7NWcDTebf9SUpFCREC8IS4JrNVw4qcVDPOjE0dPdAFFaPJaEpo2p7QIF1WQJN9XIjW0tLNQNNt5O8MXe/4OjeDG4pJjqfQ6whiQwVmoGKhF6CVJ1sm6eC6t2Y9rAEwotsBhJNgJutMj2GWKotK/USCDwD1+RlKRQQpakuFIkp50KTGZBnkGzOIOmWdpuUHHjC+OJotOC6y+iKSPhcMAmExmasbeGagdJn6F44o+FNBDHsLSHz1VrYwJNIs551lVDd/KCOkXSCND8jlCfEDExelsADXQCeQHJGpiJzf1HIYoN5SZ/N78xXcIwexOZHEZV8OFNgQBecfS7Ar38GksyFrHCf4ZcsCef3t2RJFX44FzKjmlDJf6Iv6idrEn7C751KWJgJ7X99M726/+16cvXN1W9Xtw/Rw/+9u4omny5r/3138ziNri/X0a1ikUMUi2RAS/iwZIrkVNIMNEiicogNB5QRnbEeSKgzR5YDTBFK8mKWspicZ/RPwcnvMCNTkM8s9mwytpV7A3rqRo09O8/TVLxAYl0ZRagEcvd4cXM9OSHnk8mnx9uHaHp3Nbn+2fxFSHL76fbqjKzhDO60MdWwEHI1rG5YeswgxE9AjAjOyJ1Qis1SCMlgShVw4gm/FUadYmrGR0JUvATj+CaTJeWLtUpuSRpY1htVHYe3+u60m6FzHjkNji6vppP767uH60+33ehTqnRU5GYNH2JdOsFnQhnrFhugaw3Ni9nVLYZulHZ5Dsva9mJQ5B7nwUmN4a5MSicqZX82Nqxq/5itQiv3s5AEvtAsT+GEXE0+GI29v5z2YNVU6qEFvFaoM1jQnp3MuhcjLJdQ45wPUxNjpxEQOfATEqdCQXKC5BR5LDLGF+sWfICmkwYNX/ZwGhLQlKWQhN/dQhNbHk0nJColbZrbTf4/t3bFwKAzUWi76WumVzW1pKEf3AC6HeIz+qL88Sca8gjTt9bdXN5PQ48sFlxTxq2/UNJn6d2S82f221Eh02FpeLy/8ZpwGDJU/WGxXV8eCO1Y2xAaKhQ1riiryBu3nzbet2fBiDdhZBsb1qschzjr3UeMNS6MVRHrt1lRtP31n1oOO37Te+z0RZ26lew++cZ9gSXtSMCMpWn9WNodB1gjqH+7Mf5dNxagNMvwOB0vqVyAQipXopBoGb2xYbwRG/X/+iIP6yIIV37OiZ2yU3CpaB3Da9R9pF9YVmQ9BDjsayI9k0JK4PHebvxVa97YjWg0p2dSZ8RvD4gyeecKfT2vkVkfM7phnGdCavYnJBOhmpt9t2L1iTQclWaNEGB9yFb4spO8EhqJjUXpGdNPaTjdO2E3MzfN2BrSz3WRYlzh7bHMATsaw2rz9bLr1ljB1PD1UdEFnHfhemXGVRBJYTAeg3k9c/bz8ZHP3qrildCOpnqNGfuZZlj7a0FxR31jTEOpf3bYjsK0+oy9TLNH7Q5fdfu9yYxgT9dmZ5KgJYNnxhe4HxuRqe6TKU8OmvfKRXN3mxVVIEpgzjjrPQ7voydP0NS5TdS0KDKupdJ4Se2u5nIJCkPZFK9nDaW0jKMmnTiD6+VV3qWYQ0EyLgiGLsW8A0id37NV7bqW9F9+ks3XtmSHW9AWQe2DjDGxBL7kqZAgLV4yW1XX4arlmMelU3yQb14N03DPs/B+9gUkEBVLmvs72jJn4Xe8p31ZsnhZDdCR6aAwwrUiCZvPQZr/MHSonMZ1X7Ge+uD/rXPqy3GGPVeWwwa6jgE7vI8O+E9ozjqSBFacZiKZHSQdP8iRZGN+eIlTXl4cetRqX+32s6BvrHC8aRHHoNS8SO/hcwFK31Btzjxn9Ll5WiM7boxt+ROnA/QZpNnCUjuXsTKqxIHXkKCMFRIl24g5AtrYWfmnqZZAsyYrHJDC2bVQzTDmkoNkohFe2YohGf0yGkP8ce8tMuQTTxmHa57AlzuQMXBNF3AnxUKCUqOqSV5OZxgSiyxPAQPAaC8o4fBCFqmY0ZQoiAVPqFwRZoASpsgMDME0SWxmASWazlLop/NOimemmOCQ/C6ZhgnNacz06pEzPS6d1QV9XmEgLwYEiR0K9PKU8xKQErwr7aF/KyrvgSavTaQEmgxO40RwVWTHJtAbtYrQLuJih42IZ3dJ3rkcTzqnUYKsREFiyomWNH4iS/FCsiJemtkwxBfyVi+lKBbLvMDL2EI1g8rbsUwVWS/LOkJ6OzBMFdlflEtHtg9tzeq0DX89po2uW38lPt1Dnrqcj2P6YJDSXHnKZ6BfwOyt3N9DEaYhIzTPgaIDwezNeulzKPQ5jM3unElwMOdKQ5i16PZOCD3s9siUY+Zh+Qs3mbP/G/bvDv4dw2X7H8O/B0m5sml/E8HnKYv1aAp47pRPwn/sJa2h5TSFZwi83aQATAmtcNHULF6Epkpex4Lbi5quuBqphhOWGYpmgNOp3Vgxkq0SmqZvlQ3n9rqtz2XULGV/4no7iqGqnwY2OZEFoqtSlTqTxNcTW9+w3gy1nXvazuROV0pDdiWlkGPuwzseXa1hWwAH2Y4e23+Uk18eHu7Ij99+W2aHiwQOOOBOBE+YXVeTJcRPP2Pikzv9j8mcyp+b21wrqjVkueVWDnIuZGbWtUdnRb9mwd7ZZPdgJ5ygFhyDBNyN7KbnxEglIGIN3BDU3so6R50V2v4cM7u50GQFmsyMiQsGO9BToMnDUgqtU7jCdPKROHTfpf1IHHyJAf1D6LdknUMOdET25I+t5jtzIPCYU5Yx3R3NEpzQ8hEDeaeM/01VjSXcsuB9Pw/Qvr9NPajb+DEVwW17H+kXsyrUWpf5MFPhHeb18RGb/Ug5mYF9XzVbBS8C2nQQ/xYBtYUkAhQaDZrn6cqandMEMnSaDZeUYVM3k9ZZ1opND2aUG+OivWGGVRphSe0+yjZipmIechqzulvM0xWrY5qrMFepx+2kiXcCHOAt1BXpKdQaE94lj9/t7nhMgXT6Ym9bIhbyqCJ504J4fVvykX4JThmov33nqjEDGIedp5ZssYRW/pL91xqrofsb9HwXxvWe0V6Hc0017GZa+JM1a3RPrpU5OLPQd9r9khxm6oj341cX08PSFYa+GP9NpEWGC/NiZazZ4Yd+H/RS7E9UHKDx0q4PkZvzLhM8PMW6KDS6iLk2Lu8zQlLmmEjjpb/WvGVaitMZNQaOcaUpj+GEvCyNfHQQUWik9/g/dwTBNx2YLWtw6Y3KG7sM/pLMMXrzKR+CM8bgaIwSNvzAki8KQ78tiPhcg2VrduxAjuNhbQjxQLC/FlDADfCFXg6Et8FVs7k39a4MYr1QplEDhXEpXEICatYBJD2UJ94qvWIg2uob1fU3n0I55CDdlkLeXX+6m74nCaTsGSQk/qWPlaX5sLbLze352sXwri6mbvGdkUezzl6YXoZ5BnaA6fSyXKOCp6tNbAlvpEdRUZenvUbwirzjVXa3FuTDj//4V8Mxel9dJ67XgmF4c1FIpS9oauzYANyoMP0TY64puStkLhQgpHeL/MP7E1IpKPmUa5YhN365vCTvlP7uvb2QmojU/y3+7n2dGEtvAmbpNx9x6k4tjSUkxul8ZzTNgCD4LKaEUftc6e8QAk4sIaOMBxdtM8OwVsmhbpXDyxgMDhqBrQsF7W8O7YpTRk+s80PTtGXP3RPQYcyLAWBDXUemqrWahiTrOkmPQdBajDYPjQsnP9mm2DrJxSxjuvams/TR4w+H+ejxh2P66JMPh/nocV6cIafP8lZiuCVexTSFJNqz0k3dktA0FTHewV9NPqDeFRrC0ACV4N746dQcqkihwN+Pemex+72dIcQaoQgf/XTSsunB46ZqPZO7x9LSlQsrxIYbsflWERx8N+Gd2c1jFMRAsdpYCNwymleYlxRfvMsCEqKY+QuzdTdSWnB03NGmU9n7CNoQowqZp4WKjkCUm6pOEV5O4aVUZfI4KThGjoKzhjUR5meTu8cJjuB2b1ePjynyJ0ixLaUqsu9Au8sSHEwq0tJJsFkrXGiSU5aQRLxwQ3Jb3tYbsGZFLwtjQOPC1vRJymtMS0JPvTbQL0I+nTF+llOzae/3mLib0qaVdzPgM3f2bFSP487lQBDGNcg5jUG1lh7jvgilcWa6DoX9FEU5yEhBPIIFbNMWuPloy43XtTWZ6ykShT6ikHZHv4eQApL+p0iJ8bPZSm//KN9XO+j60R7iw2GOtsJwtqNIztIVyG13Ejer4usL7mir7hUlN9SKS5h6YuLMnAaOJzmUml9k1Ln5hopSHkoLCVV89JmyFG8WXLnNPeTWInQkuV1UZAXi2pvCtcTg2e1VxBamNR1FbgGpowrOExbIbk8aN6ths1rxWsFtJZwqUNEMzxx7idlSZOsktTuNk17qhlhpu8R2OpVzTHG241LHXXjjirNF3eGrbx9p2tTcs3gJ8VNk01sHIvUeciF1vdBsLbqQU4XJHkIv6x/6dGGDyT2jAKIwEbr+mYsdp1RpkjFe9JUV7iAysuMdmdYxCPHzvAIp3RLblphy04iFXGdJjHu3gOa7m91DdEK6GmWbd6zyU5bRBZwNXV2yqn6I45cF6m1obRd8VSQYKwwOWAPimicsxiRxrwllqdEg/MwUAW5sUY9BLYHmkj1TDWcJV9Gwtf4xoGxHJ5e301ot3tYJYUuUrJmF4jSx+ecdoF3fPf9AaJJIUIpQpUTMMOaNt3p7YcUS3WMx1Nb/bvJzS6100Abkomecw3FljAuLyfVd+ck7w+D3ZCYKXnYo2JWluITOemt07m2IcNwmD09sJvx3/zidMU0KrtiCY0QaJ9kK6fBy70RK3rnuDOS/RBac2/+nloXWjC9OMcr8X6JBZoyjTv/XeCxYEMj/X0jeb6BIL42Daw86xlSPtRW4edDd8ttCx4VfeljlGkiPWbTm6qa7Xs2rJeVd0PgJeDIRnFuve6AHbHVRxuXwIVu50EFRlnRFQGk6S5laGmfTvcJEB0XQhLgbKVn6mRIWTGnMrvG6uSZH+JeHh7uJSCByFEcf/vhjYCrxFd2HP/4gElQuuAL7js4/vsOk1QNBfz8O6O9HBf3DOKB/GBX0j+OA/nEU0Fc3F2NyOU4ZNo0xpgFBqzrq1hrdEvKIPFYgn0EOAtm9NRvm4WczQdLlQVaxFIRbWcuM9r3ERVfpmaZrXiTnLE3FM8jhoLfzZv07vNKql0/vZxDTQtmsYFVILLAJ9oLemPs1OoLVwFe/CM/0Q9+91Jlui42vqgUWrjp08rHqyJbaMTWUhUm0Q4DtZfM7VPDUoOUg3ze15d3DJPy0zDPwXqEUhU+3pS0+9NP4yEcWScGHFcpw5V4qaWB+mqtNckIY9xltJ9YtxOxe24Kg6bCgA6irt/uW/R2mnhRcs7QVsJGulZuC0vNxG8gSaAJyzQ5RlmA/v7k4jzV7hsrTs4IchkVVVfWa0+dywYhRy1BPKUKxjLObi/InwbavV7K3/pH5PpUL0FuS79OfbyaPQ6U9d1FdB9l48/XuZvL4Pnw5d56XhQXIjfnlxUbdDmm6hZfjyZPDS0uQocd+PGneSWEODTDYQ6I+kt3Ftp9ue6GV9bCrrx56UK0PdcQza0Dumzu+dtu0MTydN2DNJjj2w830FhZCM1oe18dwTR9upjUisQJ46D27Q4Ftd8kSPM2X5oBQokApLC3qw6Z1gl0RJooToZu+/tAQ/cy+QBLdu60vGoPmuZnitNxdaStiUUUrNoC9h4RJiPUoMKUbfBCAjzKNbljGdHSFlTMgOSLmWBRpwr/W9cdf4cHh8f7GX1OVcsEkdKNa1v0xB4rUrB3s9MXJ//evLY+f3//xxyi0BiEVS7TBas+gSLWQbIHx1x5jsP2Bfzz4Pcf+IfH/OCb+nhjAoPi//XZE/N9+OyLwD2MC/zAi8O/HBP79iMB/GBP4D0MCv757/kfDwR7Dn+pwrdtOAr4WN4DWwx0xQmeGr8IvZUbybhHEjmPaGCx99QPaW1ObH5Cg9fpz78KVYwho0wVYZ6i0TsoSqz3Z+gsMu7Q3C/UEQ79uDLsSyk78L1K4eqZpYZPrhgZXpJvVZcGewZa/s+E5ib2PbcEKRwzlZCmKNUt8hOjSXjGlXaKkIwd1nbkIXoYKrliCEU8X7n3FkPM6dGU4uh3QcYkqhwZzqmGOGMi5tZO+0SDOz6l4GTKEuSaAM0/FiyLv6pcn79v746b9rgE8epjcjQ/e7PCjEXAzPQIBN9PRCHi8PIIEHi+Hk8Bfcd84QhyyyX2jM0vKE7WkT/6I40o8u8txXmGpmgb4EIZxQ2yk0V+OrnXWK1M0lpveoz5rvXW3Yblo2FaFuENacHGPduzoX9ND0/RGDhknhPE4LfBa/WFy98313ebb2Dr00QTSAT9U/XVtGlAef4mVHVLk1rfVpjXUTe4ia7uie1AwZHC+nbChQJN399OH9/Xn9vYBWHl5IraEfXVz8SqY982ZMpitMr06qy17Last2//3RDTkieiJcVDssMqoboxjnYVsmb1/2Uk7z0Kv2D/0n6DvIRYyUdFQ6Q27NELzD9+xQzQE4UDHLtdf6YRkQFUhNzb96lfogNBrbayMkOcL+MjSlLnUqnFJX5TPJ/ABnEQs+DIzTQNwJKZp6hIx6cLoliZ0OG6Yf+cLzIo0v/Jdh2OoZcD7owcOZQsCAW9hd+Q0sGMtqOBJvLZdqoFmW8nmGK3TbOIcfXJP2wMCyme3wyqc+9+j9HGRjpSONaWWVCbDUua67R6FsqCjbpfI3EvpoezFNY9FxvhifKvYKtkSPlLJC+1XUd0IbCLMVsK324U7PGAdFDMDasRd4XiIK7z8r5Cjm7njNfs4/PG6PSaHnHHDZ8dDcKr8+hH219ahrJc1hfIp/hVxVcHkfddMResrmPEOQgYwAxVJ3tQdr2N2YPBs5zB7rBjcNao0+hV9wJ10VQ2prMdxOjzdfVo7rPMRELeN3h62RTfPyJ0W0hXtp5qYQ4927eRwvaKeQwLJCbJkTP12JaLHdsfaUQO3cRmvGquxdKpySH1CNR2FBdPSqhzTLQ1smWfGK/PBt4l8DdfcJWK4rGR8W8dpipHIQsKrsyboLvj63NEWjG+RfGy23ANNwq5FZRV7n8A8omGtmNMKEGgvorJyzXZOby+d02JmMM3gQUzNOTG6pxpGpzFwwBUBW2bdRhso3vQoiwpH8e1VcZmoMIvJ7CupBJqszDDYVAnfSNR+7ULK2DjZ9XyQREjCsO972MkxuIZFXgcVuGiaipeS6SxQwR04O/aOXDHVr6mwaFMTTp1LL1T1VknYnkTsxrmFMznU8mgUqR084tFNnw0eXsCS8cS4kGp9MslhxA4RqmuJHgwd+0TsuhnyOtvFcYV+vMUbWER4BrnyMnZSY8pWY8Kr7nDJnpFr/FRws3xDm4qm8us+C9nPCWw/8vqb4BYewm6bYXcEKBxu5/CPZ1lKs1lCD7qmskMcMWPvBid8W9l61/zZvb8aPmHJqIKyuUjzglcPp3DlfYG40PbtvU+8CM4w9mP7HpMn4X+iYCSoInUnvXLoDc8OXSmkoYlkFQP3x3YJNLkBrUEOhvJnIQlVKx4vpeACO014oCcNL8zKyWpnrcc+ligoDSIGxxKgyWmKUF0BkFnhPMZ15CnNOM59aXuorX52R7G3TGkJeisaC+enDqNgVfc1V4aC6q6VpHLgSZkdZBaRJ2JNNoc72oy5FhqlZCi2k3QnqjW3HtXF8UB6YeXp+uBnFGvjlevUV4O3m5myytJ/kWz+tIG1kzKt9Kq0WINzudSAqrpKVRqmUgSwHft7sT5yCfimMhkJ9c+uDeLvU3IPi47VaBFW4GdgcNcy3Tyt7luJ4F+75kIefJXKG69Jtwmcq05qh8292UlCRPBa98i96Ym3bvC8DUUoPfIMEp/9m/9IGXVrxLZmEvNNbCUJe2ZJlW7WbCzZQ3bVmWxXBoTezLBPj7bxZQaUZFns6/UpMhqcUFmXkA0hpWmvCJlyDeM6Ht1QvaAaXujqIPe9GqbHhUfbjs76Czrr5iQjafxEsCWdYcHt+QNxYxhXnNpy/3a3eHOZZBjtueY/S5EF/tTAStEI9Lh1G/KpDAME/lG/dgegp8jW18Hrk9QZtwr/291kA+ZPhX4QY/O5bKzjere2wLto0fasRtgjctoVP1uLdidmVw91z607Pu573crpxwzAHkq2gXtVxW3HfmIcvrnYGTEeKO+E1Oepr7QyykbSVAYsBoNlhPxuTqh3xHMh1zjRvnWtKEZWBueVaUm5wt6LYZTTB/CwMLdv+JGk7i9r9nObtH4pRT4Gep8Tn0is7t1h8TZCG3sPaXWNPHgXqQEfxbptjXkn4+Zwj7yXtBpADrGbhNBH5fjgO0p3Ebkx6rgGj0idtWjW69horT1omRz25EImR3tuYY7zl9PDotjYdd53Jd6n2bVvLecS+r5aI7m1rbDt3X9Pa38L89Q2x6813i9bQXU3Vzioj/dBpDW6Xdtyffa4LilfuPpB35qF9V0/9v9t3f1KrbsTqumMKogCIzIKOX6iRlHI+oG9hmxWNrw6o5J3gtqr+4l7vnXvjt3klmbw7vz+9j2qANB4aYzjZlBxSlU3r/aCNQltKQ9a8fg++ZQnJINMyFX1FB8x+C9eXmxqzxigZwlwzeas1WNlCBKoEas8VUWepwySSvjVrO6qtvqDf8FUcPa5AAPA6nv5DTPsTiTaXmXDkTd1V86qlqcRNNJxqWqG0h50TD1FeIkVJZDrZSe2g9vpikJjCM1sptefFHkngSbf2DaE/pbkPXmhrKzljreg7v2YeurG7rvpfU4jWxgxogvgOvqPmI1jMdwr7umvN2RqKzGemwmJmTBsabCx/dxcApitM7Kr56g9nKvQc9XMUVKeiMxz3YHqRR4pLSRdHLETbg9sh4OovLe/lqsuFhUKkghPubZca8SSIXXEFzELZiDXl9ZcmC1xBoAbS3Jmi0/bdxZ3QumFhOmvN93gRWrOKZGEslx1pFKho5QuzrLZgPBTulhg9gH7szTybtbyM3SohcJbfQ0yQyP/+/mNzYX1h8ad6MPOtUzk3ZLY0+q0H38YC2KvOo3/2tn2tA8fsgD5vUMfVq/pibsOP0TZbT4WZgiTeyeRYMsx0jHatWS+Van1IMJdKZTIx9X015sT8pFKRi8vTmy2USml2jQ9/oZ6obn1il9p+RsAdsXbUj+Ct1yNZoobRuBKq2F8qsqEd1MZWopULFTkyka0pXnIskPFDEgxB4DAgJiJd1pPtnfwkRaU3b13XFGfC5Bse6XZC52bo7rA2wQqAZqkIn4aF1Y5i8+jKF3QTfhs82Xcwl5rzbmNtlZb67yQQtasETaRwcnWEXK23uwPT0dwgcPS1Lczb2huWcamUBqkg3pitgCB3WqoJj+eWp+ubFS1nswNq3FMOu3axGXaILOMJh5OJrqCqYhp+soOodfOuonXkOVCUrki2vzNJlEak7pJS1OxYDzy76RGtQnuQIEzVtdym+yBLlOjz2KRZaw7vDaYtbdz7GLlA4AJpNDTGnq47QjnKO3+LuiSdFxol5c3QTnhHYBlIwNjXIHU6oQUeUI1KOsKWk7uhNQOdAyw+wjYVaUdFF5pd3yL52o+MhN62Xgugs1djVfnXkloUd7lzFY2uFd6884zcDsrOutmf3XWujJce7AgcqiGZAVzFTrIu3s7+PuKJ5LO5yzu8M7DbHdkV1woLTKQlUPkf2xY52Ojl9Pyz+iFGBMfXNGYrwbn5K254iUzJFtEoRcC2fLgRv/r8MW4RmMs5mYud1mcoO2kbMSoIIWeO6XBTI6dYx+TYw3quOjsHPugQ89wXHDWQgWP/VDEmzCmrj7Gjh7NkLEWBwGXUMvpQeObhaXc1pKxi2cxFg0YmEtgjo3OBCcp5YvCyOrd5eXN+9Iv2ZWyHVyTsShb673sSM+ODsy4JPklvSMNO1ntASgYyqh7/Dta9LFkUDf6O8pgR7s/Fg31rWFHGnbbHd6gIu143BzN8tZOpFsKAa9iXWSdYdj5leIpQVhaxHGRMxv0mzFO5QpDKN59zag5l7RvGGyETa69SAjIbV5wDXu51RFlDyYkZkIyZynsFmsP4DcvC0aHf9AlQfBjdWZz9kaNcZXVI4J5/WNmvjCaRLk/8VZZGf5EvNG1DamZpSJ+gu6dcChyamQ0I/nVMz6LZPPVQ5Ackswid9CPxkiF2TO5xUeKXXWDmKaptXHuAFrdArhvbiZUitbDyQPourwgZkBFUvYE5Pf764ereyIkub86v7y6PxkSOPAF4xCZD4bDf0XjZe1KVxbc8d7Od2Ipa17dBte2WB5Ax90EUKQzcltKFNxpD7lOmhfWsrqr9hokC87dine8x8xMu2HEIsupZjOWMr1ac6u9VlaO1EUqZjSNklm5sUASoWsTMbHbnrqB9OvQeP0TpyWXzhg0X/p23pdWAKvnALlkmdloq0fD3bc2tryCtS7172/JHWO2bABsDvLIfKkURkIizC5mj6sejgw5Yt2MBkMOIj30ODCbZijK/YPvrUhP6cK+Ii3h8IU/0q7Thy0dSke1G/xsRDpdyshh9NVukfehLsrol+EoDNO66iSFtbGa4K0tNia9fT3u3YVGRH8/UhkfmFTG3wKpMxo/4QvlKF5SvoDIFWQ6iyXY5Sr7TtmHZneWUxM7dVkLCqf2Rb7m7BlcbqdCdwJzITbtTL1kKS3ksB5rrIt676Q+smrJHNsT8MJ4Il7O7DyDnnM6i8+5ZjcVFXZ+e61W0dv8fFsq0r7Y36Ha5F+EUr0OpvHCVUbT1Lf6X0fyHMtR2N6utrqYn6gnVc/mRbjEIRo/FXkkQRv/XvDI1Scbctt/6KhvYectczTKG0zUPi2IKvJcSMukXDCuTxk/RSdSAi4OMgeqCwnoLdYvSCul/Vr5iUoC1ypCjTWK01wthX41XrhSobgaaZp68jwua2dox5EFE+tZAthIeScGxDReQrRkOkJX9GxWmNU3IO31MvPtUkiuco1782Snt6i2A2xLjEUKhly+u4G+RwgK9Drc7sxY5LhOd8gi3v3UVRqb2mssTD13Zy/chNfuvzJRkRaR8zhye8ZUn9Noz1zoHUOoiwDgDq7j/eU0PA+X9GtBBBal5SKBMlyzcaMrcp/RFtmMwci+ZHwt+2CWv32duhKFjS/ZRMZwR9gynuEk63JKU5jrkYiTkFGGB/7gwQaGMX0BzWYSYllNtZ2fV9rt76OEsnTl5fNVE+suD4abgzVeD+NnpTDGfEs8/f7Qp8TxE+gzxf58rRRMPLuX+mqdWhufcNg6cVtvKRLzSMz+A7Eefm0FT9DsDB3Y7CpK01LU+ISxR/vcnnCo3rlhAo3zrfrfsp75DdE+7B5RWL88PNxV268tUyPQA7Kx2+n3TnYnRMKCyiQF9+h0lffswyX2xaAeQwPzP68eGriNcnndY7yLhg1482JEvHePg+NdcwU7COTLq5urh6uhUS/7MigGwfzL1fnlVvq8SReEGlMZPk2b2rAXyjXZHIfirJBMr26uJg/kEwod33kbQzewVlhKIhVTzo/8+KaZT+c3WYfF3p1szY5DqJegC/lWyPdgjkF/ysZcbfXTpZnL1VZA6Ejxeu8pES88FTR5HclYsVQYcLFtt2XbLl32jbHKBcf7flcYn5KZSHrenhf5a5PrEViZObcLbzut82awn+xuOcEWPP/hS7M+04Dq9sOXL75HO05HbC0KW+50G7nZFUerwrfA8Gj9LRGyr5COI+zHMQn78csXG5eRRyTM55vNGRZxWmnY4Tbm8KyzHOSp1zkM/ZQRkVhkOeaelSqJBaXDmm5dLNCiaupSLkos04M5RTMoDe96fqAj7083R2UJpDRXNuOmhzUoK1zIFTvcxToW7MBPlK99v27tludBfljFMsWPWbFsettdsewV6/ne2eYyU/bnEMXujRr4ChYZKEUXEPSv6a+WN/04dR137qkeCoh0NXiChh7Tj1OPiyS2BwRrPkINcd2iofs0/+houStJGbYMYZtXZgXYN95uDdxOiRY5i7dAeys0plthgotrdTEe5FofscTPZldLNwX20sm2XcIK9DzBe6ddSbO9HceiCw1AgN29FNbCE7krWpZqw5lPxdDVWOuQ0WaVzZNmq3rntzmiILlIWbyV6vfRcHrNn2nKknOtJZsVGoauDH8AVWHXwHKcrwktoWIEn1kCyKmt8faFmn37pPbb8hfk/0w/3dpy8rGQEmJtUxkzqtc2CNjIxVvhbMtfho+28QUXATt3pP8eEsmegT+Iy/TzqNQiVLx+y4RzNjqaB+1ldh6EI2N8KrCINf/aeJJ70jH9OP0ouF4+iEuqYZoD14/Ty0FAx0sqF7aFg2V3vfakbdNGpS4rF7pk9JimwBOKT2X10j3+sfXpgl266wrg84Eu3+ejuny/Hlik1lUgc/yI6GKnK+wBntfkuRRfWIal06uuRBYW4YKf2nBzUjpW7o63QyUrJ9YJN4GUroZLvupZRCGgKpPAzY1pTO3yVBIo6iLLMkgY1ZD2hERKWrjQ0TNTrO2dDnPUrtsEu4GRecoWy56YRonsKKia7NOSwTNNq8PflvpgVGlcpF5fd0Lmz6vjQitjq7OV7wAtXKILTu98BWJfv2yArNp1m4eWeZL4zWgNDyHL9coXvxinLGiDPed312UDbapJwuwKt9wl1BPQk5gGvDK3R7/Qb52et+Ox/WjYZzHTX6fOZtbGrb37YoM0UaoPtXcjJTfMX66Z0lG6ETWY0+8r+g4+43XuKQ3v1pjK1htHarixK7Dh2VVrTLEfqrL5y0VK46elSMdqnlF2galOiyuSmUVq3Csy89MTKVr1mNfAvhX3+P0jgvY7BYIndBNgXCoj43W3fIOjHUsp1uDdQiXKi0Z1aGohjrD3VqJEBnh+e7N7x4Sm6Ritnaoe6saLqpccNL6NzdzDwC6NYwTQi9G3UxgDZ73feymm8o1rE6TLiPVfsyfAOeOV0U9YBlzZbt9KiZih84BXk5XytFX1OecHKepzzvdW09/ubt++l/NQcA7pVA93sxO0VwCicfgzfA9pPmCxYYs6Id8SxhN82qvI5affb/Gk/13wx8c7+6uLf965n4SfXk0fzi9urqe/XF3iL78lTFUF3miausR2BLMmBGrJv6SabnBftqe/4eGF/Z2MRjiObIFok9+yK6RWG60Qzv8LAAD//y5DAW8=" } From 8476273e8c97f0370fb5c9d20cf6e399e0641f27 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Fri, 12 Apr 2024 06:45:04 +0000 Subject: [PATCH 30/38] Removed extra spaces from field description --- metricbeat/docs/fields.asciidoc | 2 +- x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml | 2 +- x-pack/metricbeat/module/aws/fields.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index a05911603364..5ed3ebb49d8f 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -1745,7 +1745,7 @@ type: date *`aws.awshealth.affected_entities.status_code`*:: + -- -The most recent status of the event. Possible values are open , closed , and upcoming. +The most recent status of the event. Possible values are open, closed, and upcoming. type: keyword diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml index 8ec1c4b28c51..358e74210e4a 100644 --- a/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/fields.yml @@ -84,7 +84,7 @@ - name: affected_entities.status_code type: keyword description: > - The most recent status of the event. Possible values are open , closed , and upcoming. + The most recent status of the event. Possible values are open, closed, and upcoming. - name: affected_entities.entity_arn type: keyword description: > diff --git a/x-pack/metricbeat/module/aws/fields.go b/x-pack/metricbeat/module/aws/fields.go index 1d895b21f798..ce27511a9e60 100644 --- a/x-pack/metricbeat/module/aws/fields.go +++ b/x-pack/metricbeat/module/aws/fields.go @@ -19,5 +19,5 @@ func init() { // AssetAws returns asset data. // This is the base64 encoded zlib format compressed contents of module/aws. func AssetAws() string { - return "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" + return "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" } From 8056ac47e5acd06d09d52c518e6095643d90a938 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Fri, 12 Apr 2024 15:59:35 +0000 Subject: [PATCH 31/38] Test script updated. Linter fixes added --- .../module/aws/awshealth/awshealth.go | 5 +- .../module/aws/awshealth/awshealth_test.go | 241 ++++++++++++++++++ 2 files changed, 243 insertions(+), 3 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 4a9fc0c3c73e..55a9da4a55c5 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -140,7 +140,7 @@ func (m *MetricSet) getEventDetails( ctx context.Context, awsHealth *health.Client, ) []mb.Event { - var events []mb.Event + //var events []mb.Event eventFilter := types.EventFilter{ EventStatusCodes: []types.EventStatusCode{ types.EventStatusCodeUpcoming, @@ -280,7 +280,7 @@ func (m *MetricSet) getEventDetails( } healthDetails = append(healthDetails, healthDetailsTemp...) } - + var events = make([]mb.Event, 0, len(healthDetails)) for _, detail := range healthDetails { event := mb.Event{ MetricSetFields: mapstr.M{ @@ -305,7 +305,6 @@ func (m *MetricSet) getEventDetails( }, Service: "aws-health", } - events = append(events, event) } return events diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go index bca658ccdade..d6a9d186632d 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go @@ -3,3 +3,244 @@ // you may not use this file except in compliance with the Elastic License. package awshealth + +import ( + "context" + "testing" + "time" + + "github.com/aws/aws-sdk-go-v2/service/health" + "github.com/stretchr/testify/assert" + + aws "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/health/types" +) + +// HealthClient interface defines the methods used by the MetricSet +type HealthClient interface { + DescribeEvents(ctx context.Context, input *health.DescribeEventsInput, optFns ...func(*health.Options)) (*health.DescribeEventsOutput, error) + DescribeEventDetails(ctx context.Context, input *health.DescribeEventDetailsInput, optFns ...func(*health.Options)) (*health.DescribeEventDetailsOutput, error) + DescribeAffectedEntities(ctx context.Context, input *health.DescribeAffectedEntitiesInput, optFns ...func(*health.Options)) (*health.DescribeAffectedEntitiesOutput, error) +} + +// MockAWSHealthClient implements the HealthClient interface +type MockAWSHealthClient struct{} + +func (m *MockAWSHealthClient) DescribeEvents(ctx context.Context, input *health.DescribeEventsInput, optFns ...func(*health.Options)) (*health.DescribeEventsOutput, error) { + // Mock implementation of DescribeEvents method + output := &health.DescribeEventsOutput{ + Events: []types.Event{ + { + Arn: aws.String("mock-event-arn-1"), + EndTime: aws.Time(time.Now()), + EventScopeCode: MapScopeCode("PUBLIC"), + EventTypeCategory: MapEventTypeCategory("issue"), + EventTypeCode: aws.String("mock-event-type-1"), + LastUpdatedTime: aws.Time(time.Now()), + Region: aws.String("mock-region-1"), + Service: aws.String("mock-service-1"), + StartTime: aws.Time(time.Now()), + StatusCode: MapEventStatusCode("open"), + }, + // add more mock events as needed + }, + } + return output, nil +} + +func (m *MockAWSHealthClient) DescribeEventDetails(ctx context.Context, input *health.DescribeEventDetailsInput, optFns ...func(*health.Options)) (*health.DescribeEventDetailsOutput, error) { + // Mock implementation of DescribeEventDetails method + ev_desc := "mock-event-description" + event_arn := "mock-entity-arn-1" + output := &health.DescribeEventDetailsOutput{ + SuccessfulSet: []types.EventDetails{ + { + Event: &types.Event{ + Arn: &event_arn, + }, + EventDescription: &types.EventDescription{ + LatestDescription: &ev_desc, + }, + }, + // add more successful items as needed + }, + } + return output, nil +} + +func (m *MockAWSHealthClient) DescribeAffectedEntities(ctx context.Context, input *health.DescribeAffectedEntitiesInput, optFns ...func(*health.Options)) (*health.DescribeAffectedEntitiesOutput, error) { + // Mock implementation of DescribeAffectedEntities method + output := &health.DescribeAffectedEntitiesOutput{ + Entities: []types.AffectedEntity{ + { + AwsAccountId: aws.String("mock-account-id-1"), + EntityUrl: aws.String("mock-entity-url-1"), + EntityValue: aws.String("mock-entity-value-1"), + LastUpdatedTime: aws.Time(time.Now()), + StatusCode: MapStatusCode("PENDING"), + EntityArn: aws.String("mock-entity-arn-1"), + }, + // add more affected entities as needed + }, + } + return output, nil +} + +// ConvertToHealthClient converts MockAWSHealthClient to *health.Client +func (m *MockAWSHealthClient) ConvertToHealthClient() *health.Client { + return &health.Client{ + // initialize with required options + } +} + +// MapEventStatusCode maps a string status code to its corresponding EventStatusCode enum value +func MapEventStatusCode(eventStatusCode string) types.EventStatusCode { + switch eventStatusCode { + case "open": + return types.EventStatusCodeOpen + case "closed": + return types.EventStatusCodeClosed + default: + return types.EventStatusCodeUpcoming // Or any default value you prefer + } +} + +// MapEventTypeCategory maps a string status code to its corresponding EventTypeCategory enum value +func MapEventTypeCategory(eventTypeCategory string) types.EventTypeCategory { + switch eventTypeCategory { + case "issue": + return types.EventTypeCategoryIssue + case "accountNotification": + return types.EventTypeCategoryAccountNotification + case "scheduledChange": + return types.EventTypeCategoryScheduledChange + default: + return types.EventTypeCategoryInvestigation // Or any default value you prefer + } +} + +// MapScopeCode maps a string status code to its corresponding EventScopeCode enum value +func MapScopeCode(scopeCode string) types.EventScopeCode { + switch scopeCode { + case "PUBLIC": + return types.EventScopeCodePublic + case "ACCOUNT_SPECIFIC": + return types.EventScopeCodeAccountSpecific + default: + return types.EventScopeCodeNone // Or any default value you prefer + } +} + +// MapStatusCode maps a string status code to its corresponding EntityStatusCode enum value +func MapStatusCode(statusCode string) types.EntityStatusCode { + switch statusCode { + case "PENDING": + return types.EntityStatusCodeImpaired + case "RESOLVED": + return types.EntityStatusCodeUnimpaired + default: + return types.EntityStatusCodeUnknown // Or any default value you prefer + } +} + +func TestGetEventDetails(t *testing.T) { + // Mock context + ctx := context.Background() + + // Create a mock AWSHealth client + awsHealth := &MockAWSHealthClient{} + // Call DescribeEvents + eventsOutput, err := awsHealth.DescribeEvents(ctx, &health.DescribeEventsInput{}) + assert.NoError(t, err) + // Validate eventsOutput.Events is not empty + assert.NotEmpty(t, eventsOutput.Events) + + // Create a slice to store AWSHealthMetrics + var awsHealthMetrics []AWSHealthMetric + + for _, event := range eventsOutput.Events { + // Create a new instance of AWSHealthMetric + awsHealthMetric := AWSHealthMetric{ + EventArn: *event.Arn, + EndTime: *event.EndTime, + EventScopeCode: aws.ToString((*string)(&event.EventScopeCode)), + EventTypeCategory: aws.ToString((*string)(&event.EventTypeCategory)), + EventTypeCode: *event.EventTypeCode, + LastUpdatedTime: *event.LastUpdatedTime, + Region: *event.Region, + Service: *event.Service, + StartTime: *event.StartTime, + StatusCode: aws.ToString((*string)(&event.StatusCode)), + } + // Call DescribeEventDetails for the current event + eventDetailsOutput, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ + EventArns: []string{*event.Arn}, + }) + assert.NoError(t, err) + + // Validate eventDetailsOutput.SuccessfulSet is not empty + assert.NotEmpty(t, eventDetailsOutput.SuccessfulSet) + + // Update EventDescription in awsHealthMetric + if len(eventDetailsOutput.SuccessfulSet) > 0 { + awsHealthMetric.EventDescription = *eventDetailsOutput.SuccessfulSet[0].EventDescription.LatestDescription + } + + // Call DescribeAffectedEntities for the current event + affectedEntitiesOutput, err := awsHealth.DescribeAffectedEntities(ctx, &health.DescribeAffectedEntitiesInput{ + Filter: &types.EntityFilter{ + EventArns: []string{*event.Arn}, + }, + }) + assert.NoError(t, err) + + // Validate affectedEntitiesOutput.Entities is not empty + assert.NotEmpty(t, affectedEntitiesOutput.Entities) + + // Count affected entities by status + var pending, resolved, others int32 + for _, entity := range affectedEntitiesOutput.Entities { + switch aws.ToString((*string)(&entity.StatusCode)) { + case "PENDING": + pending++ + case "RESOLVED": + resolved++ + default: + others++ + } + awsHealthMetric.AffectedEntities = append(awsHealthMetric.AffectedEntities, + AffectedEntityDetails{ + AwsAccountId: *entity.AwsAccountId, + EntityUrl: *entity.EntityUrl, + EntityValue: *entity.EntityValue, + LastUpdatedTime: *entity.LastUpdatedTime, + StatusCode: string(entity.StatusCode), + EntityArn: *entity.EntityArn, + }, + ) + } + + // Update affected entities counts in awsHealthMetric + awsHealthMetric.AffectedEntitiesPending = pending + awsHealthMetric.AffectedEntitiesResolved = resolved + awsHealthMetric.AffectedEntitiesOthers = others + + // Append awsHealthMetric to the slice + awsHealthMetrics = append(awsHealthMetrics, awsHealthMetric) + } + for _, metric := range awsHealthMetrics { + assert.NotEmpty(t, metric.EventArn) + assert.NotEmpty(t, metric.EventScopeCode) + assert.NotEmpty(t, metric.EventTypeCategory) + assert.NotEmpty(t, metric.EventTypeCode) + assert.NotEmpty(t, metric.Region) + assert.NotEmpty(t, metric.Service) + assert.NotEmpty(t, metric.StatusCode) + assert.NotEmpty(t, metric.LastUpdatedTime) + assert.NotEmpty(t, metric.StartTime) + assert.NotEmpty(t, metric.EndTime) + assert.NotEmpty(t, metric.EventDescription) + assert.NotEmpty(t, metric.AffectedEntities) + assert.GreaterOrEqual(t, (metric.AffectedEntitiesOthers + metric.AffectedEntitiesPending + metric.AffectedEntitiesResolved), int32(0)) + } +} From 48958e99f5c5d72801ff516cf8ec39cb20201632 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Fri, 12 Apr 2024 17:20:22 +0000 Subject: [PATCH 32/38] Fixes test file lint issues --- .../module/aws/awshealth/awshealth_test.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go index d6a9d186632d..18d6d33308ea 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go @@ -156,21 +156,22 @@ func TestGetEventDetails(t *testing.T) { assert.NotEmpty(t, eventsOutput.Events) // Create a slice to store AWSHealthMetrics - var awsHealthMetrics []AWSHealthMetric + var awsHealthMetrics = make([]AWSHealthMetric, 0, len(eventsOutput.Events)) - for _, event := range eventsOutput.Events { + for i, event := range eventsOutput.Events { // Create a new instance of AWSHealthMetric + awsHealthMetric := AWSHealthMetric{ EventArn: *event.Arn, EndTime: *event.EndTime, - EventScopeCode: aws.ToString((*string)(&event.EventScopeCode)), - EventTypeCategory: aws.ToString((*string)(&event.EventTypeCategory)), + EventScopeCode: aws.ToString((*string)(&eventsOutput.Events[i].EventScopeCode)), + EventTypeCategory: aws.ToString((*string)(&eventsOutput.Events[i].EventTypeCategory)), EventTypeCode: *event.EventTypeCode, LastUpdatedTime: *event.LastUpdatedTime, Region: *event.Region, Service: *event.Service, StartTime: *event.StartTime, - StatusCode: aws.ToString((*string)(&event.StatusCode)), + StatusCode: aws.ToString((*string)(&eventsOutput.Events[i].StatusCode)), } // Call DescribeEventDetails for the current event eventDetailsOutput, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ @@ -199,8 +200,8 @@ func TestGetEventDetails(t *testing.T) { // Count affected entities by status var pending, resolved, others int32 - for _, entity := range affectedEntitiesOutput.Entities { - switch aws.ToString((*string)(&entity.StatusCode)) { + for j, entity := range affectedEntitiesOutput.Entities { + switch aws.ToString((*string)(&affectedEntitiesOutput.Entities[j].StatusCode)) { case "PENDING": pending++ case "RESOLVED": From fc656850290e6af99122f8a6f583669dc11bf1e2 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Sat, 13 Apr 2024 04:54:30 +0000 Subject: [PATCH 33/38] Updated in-line commments --- .../module/aws/awshealth/awshealth.go | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index 55a9da4a55c5..a87627a2ca4d 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -132,15 +132,13 @@ func (m *MetricSet) Fetch(ctx context.Context, report mb.ReporterV2) error { return nil } -// getEventDetails retrieves a AWS Health events which are upcoming -// or open. It uses the DescribeEvents API to get a list of events. Each event is -// identified by a Event ARN. The function returns a slice of mb.Event structs -// containing the summarized event info. +// getEventDetails retrieves AWS health events and their details using the provided AWS Health client. +// It returns a list of Metricbeat events containing relevant AWS health information. func (m *MetricSet) getEventDetails( ctx context.Context, awsHealth *health.Client, ) []mb.Event { - //var events []mb.Event + // Define event filter to fetch only upcoming and open events eventFilter := types.EventFilter{ EventStatusCodes: []types.EventStatusCode{ types.EventStatusCodeUpcoming, @@ -161,29 +159,30 @@ func (m *MetricSet) getEventDetails( Filter: &eventFilter, } - // Create an instance of DescribeEventsPaginatorOptions with desired options + // Define options for DescribeEventsPaginator deOptions := &health.DescribeEventAggregatesPaginatorOptions{ Limit: 10, StopOnDuplicateToken: true, } - // Create a function option to apply the options to the paginator + // Function option to apply options to the paginator deOptFn := func(options *health.DescribeEventsPaginatorOptions) { // Apply the provided options options.Limit = deOptions.Limit options.StopOnDuplicateToken = deOptions.StopOnDuplicateToken } - + // Define options for DescribeAffectedEntitiesPaginator affOptions := &health.DescribeAffectedEntitiesPaginatorOptions{ Limit: 10, StopOnDuplicateToken: true, } + // Function option to apply options to the paginator affOptFn := func(options *health.DescribeAffectedEntitiesPaginatorOptions) { // Apply the provided options options.Limit = affOptions.Limit options.StopOnDuplicateToken = affOptions.StopOnDuplicateToken } - + // Create DescribeEventsPaginator with AWS Health client and options dePage := health.NewDescribeEventsPaginator(awsHealth, &deInputParams, deOptFn) for dePage.HasMorePages() { @@ -197,6 +196,7 @@ func (m *MetricSet) getEventDetails( } deEvents = currentPage.Events eventArns := make([]string, len(deEvents)) + // Iterate through events to extract relevant information for i := range deEvents { healthDetailsTemp = append(healthDetailsTemp, AWSHealthMetric{ EventArn: awssdk.ToString(deEvents[i].Arn), @@ -212,7 +212,7 @@ func (m *MetricSet) getEventDetails( }) eventArns[i] = awssdk.ToString(deEvents[i].Arn) } - + // Fetch event details for the current page of events eventDetails, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ EventArns: eventArns, Locale: &locale, @@ -221,7 +221,7 @@ func (m *MetricSet) getEventDetails( m.Logger().Errorf("[AWS Health] DescribeEventDetails failed with : %w", err) break } - + // Fetch event description for the current page of events successSet := eventDetails.SuccessfulSet for x := range successSet { for y := range healthDetailsTemp { @@ -230,8 +230,7 @@ func (m *MetricSet) getEventDetails( } } } - // Fetch the details of all the affected Entities related to the EvenARNs in the present page of DescribeEvents API call - + // Fetch affected entities related to event ARNs in the current page affInputParams = health.DescribeAffectedEntitiesInput{ Filter: &types.EntityFilter{ EventArns: eventArns, @@ -244,11 +243,13 @@ func (m *MetricSet) getEventDetails( ) for affPage.HasMorePages() { + // Fetch current page of affected entities affCurrentPage, err := affPage.NextPage(ctx) if err != nil { m.Logger().Errorf("[AWS Health] DescribeAffectedEntitie failed with : %w", err) break } + // Extract relevant details of affected entities and match them with event details for k := range affCurrentPage.Entities { affEntityTemp = AffectedEntityDetails{ AwsAccountId: awssdk.ToString(affCurrentPage.Entities[k].AwsAccountId), @@ -278,8 +279,10 @@ func (m *MetricSet) getEventDetails( } } + // Append current page's health details to the overall list healthDetails = append(healthDetails, healthDetailsTemp...) } + // Convert health details to Metricbeat events var events = make([]mb.Event, 0, len(healthDetails)) for _, detail := range healthDetails { event := mb.Event{ From 0768b174faddfdb424fc0a63b9021978765c5671 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Tue, 16 Apr 2024 08:00:30 +0000 Subject: [PATCH 34/38] Optimised by improving the readability --- .../module/aws/awshealth/awshealth.go | 46 +++++++++---------- .../module/aws/awshealth/awshealth_test.go | 8 ++-- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth.go b/x-pack/metricbeat/module/aws/awshealth/awshealth.go index a87627a2ca4d..a86ac1b5da4f 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth.go @@ -197,20 +197,20 @@ func (m *MetricSet) getEventDetails( deEvents = currentPage.Events eventArns := make([]string, len(deEvents)) // Iterate through events to extract relevant information - for i := range deEvents { + for i, de := range deEvents { healthDetailsTemp = append(healthDetailsTemp, AWSHealthMetric{ - EventArn: awssdk.ToString(deEvents[i].Arn), - EndTime: awssdk.ToTime(deEvents[i].EndTime), - EventScopeCode: awssdk.ToString((*string)(&deEvents[i].EventScopeCode)), - EventTypeCategory: awssdk.ToString((*string)(&deEvents[i].EventTypeCategory)), - EventTypeCode: awssdk.ToString(deEvents[i].EventTypeCode), - LastUpdatedTime: awssdk.ToTime(deEvents[i].LastUpdatedTime), - Region: awssdk.ToString(deEvents[i].Region), - Service: awssdk.ToString(deEvents[i].Service), - StartTime: awssdk.ToTime(deEvents[i].StartTime), - StatusCode: awssdk.ToString((*string)(&deEvents[i].StatusCode)), + EventArn: awssdk.ToString(de.Arn), + EndTime: awssdk.ToTime(de.EndTime), + EventScopeCode: string(de.EventScopeCode), + EventTypeCategory: string(de.EventTypeCategory), + EventTypeCode: awssdk.ToString(de.EventTypeCode), + LastUpdatedTime: awssdk.ToTime(de.LastUpdatedTime), + Region: awssdk.ToString(de.Region), + Service: awssdk.ToString(de.Service), + StartTime: awssdk.ToTime(de.StartTime), + StatusCode: string(de.StatusCode), }) - eventArns[i] = awssdk.ToString(deEvents[i].Arn) + eventArns[i] = awssdk.ToString(de.Arn) } // Fetch event details for the current page of events eventDetails, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ @@ -250,20 +250,19 @@ func (m *MetricSet) getEventDetails( break } // Extract relevant details of affected entities and match them with event details - for k := range affCurrentPage.Entities { + for _, ace := range affCurrentPage.Entities { affEntityTemp = AffectedEntityDetails{ - AwsAccountId: awssdk.ToString(affCurrentPage.Entities[k].AwsAccountId), - EntityUrl: awssdk.ToString(affCurrentPage.Entities[k].EntityUrl), - EntityValue: awssdk.ToString(affCurrentPage.Entities[k].EntityValue), - LastUpdatedTime: awssdk.ToTime(affCurrentPage.Entities[k].LastUpdatedTime), - StatusCode: awssdk.ToString((*string)(&affCurrentPage.Entities[k].StatusCode)), - EntityArn: awssdk.ToString(affCurrentPage.Entities[k].EntityArn), + AwsAccountId: awssdk.ToString(ace.AwsAccountId), + EntityUrl: awssdk.ToString(ace.EntityUrl), + EntityValue: awssdk.ToString(ace.EntityValue), + LastUpdatedTime: awssdk.ToTime(ace.LastUpdatedTime), + StatusCode: string(ace.StatusCode), + EntityArn: awssdk.ToString(ace.EntityArn), } - for l := range healthDetailsTemp { - - if awssdk.ToString(affCurrentPage.Entities[k].EventArn) == healthDetailsTemp[l].EventArn { + for l, hd := range healthDetailsTemp { + if awssdk.ToString(ace.EventArn) == hd.EventArn { healthDetailsTemp[l].AffectedEntities = append(healthDetailsTemp[l].AffectedEntities, affEntityTemp) - switch awssdk.ToString((*string)(&affCurrentPage.Entities[k].StatusCode)) { + switch string(ace.StatusCode) { case "PENDING": healthDetailsTemp[l].AffectedEntitiesPending++ case "RESOLVED": @@ -277,7 +276,6 @@ func (m *MetricSet) getEventDetails( } } } - } // Append current page's health details to the overall list healthDetails = append(healthDetails, healthDetailsTemp...) diff --git a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go index 18d6d33308ea..ee285cfccf4a 100644 --- a/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go +++ b/x-pack/metricbeat/module/aws/awshealth/awshealth_test.go @@ -158,20 +158,20 @@ func TestGetEventDetails(t *testing.T) { // Create a slice to store AWSHealthMetrics var awsHealthMetrics = make([]AWSHealthMetric, 0, len(eventsOutput.Events)) - for i, event := range eventsOutput.Events { + for _, event := range eventsOutput.Events { // Create a new instance of AWSHealthMetric awsHealthMetric := AWSHealthMetric{ EventArn: *event.Arn, EndTime: *event.EndTime, - EventScopeCode: aws.ToString((*string)(&eventsOutput.Events[i].EventScopeCode)), - EventTypeCategory: aws.ToString((*string)(&eventsOutput.Events[i].EventTypeCategory)), + EventScopeCode: string(event.EventScopeCode), + EventTypeCategory: string(event.EventTypeCategory), EventTypeCode: *event.EventTypeCode, LastUpdatedTime: *event.LastUpdatedTime, Region: *event.Region, Service: *event.Service, StartTime: *event.StartTime, - StatusCode: aws.ToString((*string)(&eventsOutput.Events[i].StatusCode)), + StatusCode: string(event.StatusCode), } // Call DescribeEventDetails for the current event eventDetailsOutput, err := awsHealth.DescribeEventDetails(ctx, &health.DescribeEventDetailsInput{ From 2986dd60585019a22406d0a465407f6384ebfbed Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Tue, 16 Apr 2024 08:01:19 +0000 Subject: [PATCH 35/38] Updated the data.json based on new fields def --- .../module/aws/awshealth/_meta/data.json | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/data.json b/x-pack/metricbeat/module/aws/awshealth/_meta/data.json index 86a5ed50c4f8..840e428d4896 100644 --- a/x-pack/metricbeat/module/aws/awshealth/_meta/data.json +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/data.json @@ -6,25 +6,26 @@ { "aws_account_id": "627286350134", "entity_url": "", - "entity_value": "arn:aws:eks:us-east-2:627286350134:cluster/michaliskatsoulisfargate", - "last_updated_time": "2024-02-26T21:44:05.825Z", - "status_code": "", - "entity_arn": "arn:aws:health:us-east-2:627286350134:entity/g1vUSeoFZcvk3ucsO-BHDR55XHsSYYfs6wqo1QhqQeEto=1g" + "entity_value": "arn:aws:eks:us-east-2:627286350134:cluster/tkravchenko", + "last_updated_time": "2024-04-12T12:56:29.7Z", + "status_code": "PENDING", + "entity_arn": "arn:aws:health:us-east-2:627286350134:entity/g1LKdVRHv2pW-kQsjjXgOstZvUwFJjOd22QT0hfqYFEcc=1g" } ], "affected_entities_others": 0, - "affected_entities_pending": 0, + "affected_entities_pending": 1, "affected_entities_resolved": 0, "end_time": "0001-01-01T00:00:00Z", - "event_arn": "arn:aws:health:us-east-2::event/EKS/AWS_EKS_OPERATIONAL_NOTIFICATION/AWS_EKS_OPERATIONAL_NOTIFICATION_5edf7d286ca1fbcdd70306479c60f8fd560afa53f174d79ae319faaedfc94646", + "event_arn": "arn:aws:health:us-east-2::event/EKS/AWS_EKS_PLANNED_LIFECYCLE_EVENT/AWS_EKS_PLANNED_LIFECYCLE_EVENT_a7e64e77680080d19971a80f0131ff2239909cdbe7647dd57710b764b988f476", + "event_description": "On May 1, 2024, standard support for Kubernetes version 1.25 in Amazon EKS will end. From May 2, 2024 all Amazon EKS clusters running on 1.25 will enter extended support and will remain in extended support until May 1, 2025.\n\nAfter May 1, 2025, Kubernetes 1.25 will no longer be supported on Amazon EKS, and all Amazon EKS clusters running on 1.25 will be automatically updated to Kubernetes version 1.26.\n\nYou are receiving this message because you currently have 1 or more Amazon EKS clusters running on Kubernetes version 1.25. A list of your impacted clusters can be found in the \"Affected resources\" tab.\n\nExtended support is currently in free preview and is available to all customers. Effective April 1 2024, your Amazon EKS clusters running on a Kubernetes version in extended support will be charged at $0.60 per cluster hour.\n\nIf you do not want to use extended support, we recommend that you update your 1.25 clusters to Kubernetes version 1.26 or newer before May 1, 2024. To learn more about the extended support for Kubernetes versions pricing, see our announcement [1]. For instructions on how to update your cluster(s), see the Amazon EKS service 'Updating an Amazon EKS cluster Kubernetes version' documentation [2].\n\nTo learn more on Kubernetes version support, see the 'Amazon EKS Kubernetes versions' documentation [3].\n\nFor any questions or assistance, please contact AWS Support [4].\n\n\n[1] https://aws.amazon.com/blogs/containers/amazon-eks-extended-support-for-kubernetes-versions-pricing/\n[2] https://docs.aws.amazon.com/eks/latest/userguide/update-cluster.html\n[3] https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html\n[4] https://aws.amazon.com/support", "event_scope_code": "ACCOUNT_SPECIFIC", - "event_type_category": "accountNotification", - "event_type_code": "AWS_EKS_OPERATIONAL_NOTIFICATION", - "last_updated_time": "2024-02-26T22:00:11.574Z", + "event_type_category": "scheduledChange", + "event_type_code": "AWS_EKS_PLANNED_LIFECYCLE_EVENT", + "last_updated_time": "2024-04-12T13:12:39.273Z", "region": "us-east-2", "service": "EKS", - "start_time": "2024-02-26T21:35:00Z", - "status_code": "open" + "start_time": "2024-05-01T07:00:00Z", + "status_code": "upcoming" } }, "cloud.provider": "aws", @@ -38,6 +39,6 @@ "period": 10000 }, "service": { - "type": "aws" + "type": "aws-health" } } \ No newline at end of file From 743b90e05509ff2882f6c95d008c341bcf0820e1 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Tue, 16 Apr 2024 08:32:47 +0000 Subject: [PATCH 36/38] Updated asciidoc --- .../module/aws/awshealth/_meta/docs.asciidoc | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc b/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc index 84b211ca52a4..92fe73802722 100644 --- a/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc @@ -1 +1,21 @@ -This is the awshealth metricset of the module aws. +AWS Health metrics provide insights into the health of your AWS environment by monitoring various aspects such as open issues, scheduled maintenance events, security advisories, compliance status, notification counts, and service disruptions. These metrics help you proactively identify and address issues impacting your AWS resources, ensuring the reliability, security, and compliance of your infrastructure. + +[float] +=== AWS Permissions +To collect AWS Health metrics using Elastic Metricbeat, you would need specific AWS permissions to access the necessary data. Here's a list of permissions required for an IAM user to collect AWS Health metrics: +---- +health:DescribeAffectedEntities +health:DescribeEventDetails +health:DescribeEvents +---- + +[float] +=== Configuration example +[source,yaml] +---- + +- module: aws + period: 1d + metricsets: + - awshealth +---- From eb896c067bad1bf3724a07f5faf43ec053765f27 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Tue, 16 Apr 2024 08:41:11 +0000 Subject: [PATCH 37/38] Minor correctionsadded --- x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc b/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc index 92fe73802722..a95db3fc2e75 100644 --- a/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/docs.asciidoc @@ -15,7 +15,7 @@ health:DescribeEvents ---- - module: aws - period: 1d + period: 24h metricsets: - awshealth ---- From 3dff9584d0adadd1f4cc790898c7c9a4a49aeda5 Mon Sep 17 00:00:00 2001 From: Agi K Thomas Date: Tue, 16 Apr 2024 08:47:51 +0000 Subject: [PATCH 38/38] Updated the data.json --- x-pack/metricbeat/module/aws/awshealth/_meta/data.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/metricbeat/module/aws/awshealth/_meta/data.json b/x-pack/metricbeat/module/aws/awshealth/_meta/data.json index 840e428d4896..ec0ffd5ad67b 100644 --- a/x-pack/metricbeat/module/aws/awshealth/_meta/data.json +++ b/x-pack/metricbeat/module/aws/awshealth/_meta/data.json @@ -4,12 +4,12 @@ "awshealth": { "affected_entities": [ { - "aws_account_id": "627286350134", + "aws_account_id": "12301234013123", "entity_url": "", - "entity_value": "arn:aws:eks:us-east-2:627286350134:cluster/tkravchenko", + "entity_value": "arn:aws:eks:us-east-2:627286350134:cluster/XXXXXXXXXXXXX", "last_updated_time": "2024-04-12T12:56:29.7Z", "status_code": "PENDING", - "entity_arn": "arn:aws:health:us-east-2:627286350134:entity/g1LKdVRHv2pW-kQsjjXgOstZvUwFJjOd22QT0hfqYFEcc=1g" + "entity_arn": "arn:aws:health:us-east-2:627286350134:entity/YYYYYYYYYYYYYYYYYYYY" } ], "affected_entities_others": 0,