-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
271 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
components/services/app/parsers/cloudwatch_log_event_parser.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
|
||
require "zlib" | ||
require "base64" | ||
require "stringio" | ||
|
||
class CloudWatchLogEventParser | ||
LogEvent = Struct.new( | ||
:timestamp, | ||
:message, | ||
) | ||
|
||
Event = Struct.new( | ||
:event_type, | ||
:log_group, | ||
:log_events, | ||
keyword_init: true | ||
) | ||
|
||
attr_reader :event | ||
|
||
def initialize(event) | ||
@event = event | ||
end | ||
|
||
def parse_event | ||
Event.new( | ||
event_type: :cloudwatch_log_event, | ||
log_group:, | ||
log_events: | ||
) | ||
end | ||
|
||
private | ||
|
||
def raw_data | ||
event.dig("awslogs", "data") | ||
end | ||
|
||
def data_message | ||
@data_message ||= JSON.parse(Zlib::GzipReader.new(StringIO.new(Base64.decode64(raw_data))).read) | ||
end | ||
|
||
def log_group | ||
data_message.fetch("logGroup") | ||
end | ||
|
||
def log_events | ||
data_message.fetch("logEvents").map do |log_event_data| | ||
LogEvent.new( | ||
timestamp: Time.at(log_event_data.fetch("timestamp") / 1000), | ||
message: log_event_data.fetch("message") | ||
) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
components/services/app/parsers/opensips_log_event_parser.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
class OpenSIPSLogEventParser | ||
attr_reader :event | ||
|
||
Event = Struct.new(:level, :message, keyword_init: true) | ||
|
||
def initialize(event) | ||
@event = event | ||
end | ||
|
||
def parse_event | ||
event.log_events.map do |log_event| | ||
log_data = JSON.parse(log_event.message) | ||
|
||
Event.new(level: log_data.fetch("level"), message: log_data.fetch("message")) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
require "zlib" | ||
require "base64" | ||
require "stringio" | ||
|
||
class HandleLogEvents < ApplicationWorkflow | ||
attr_reader :event | ||
|
||
def initialize(event:) | ||
@event = event | ||
end | ||
|
||
def call | ||
if opensips_log_groups.include?(event.log_group) | ||
HandleOpenSIPSLogEvent.call(event:) | ||
end | ||
end | ||
|
||
private | ||
|
||
def opensips_log_groups | ||
[ ENV.fetch("PUBLIC_GATEWAY_LOG_GROUP"), ENV.fetch("CLIENT_GATEWAY_LOG_GROUP") ] | ||
end | ||
end |
47 changes: 47 additions & 0 deletions
47
components/services/app/workflows/handle_opensips_log_event.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
class HandleOpenSIPSLogEvent < ApplicationWorkflow | ||
LOAD_BALANCER_RESPONSE_ERROR_PATTERN = %r{\A(\d{3})-lb-response-error-(((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4})\z} | ||
TIMEOUT_ERROR_CODE = "408" | ||
|
||
attr_reader :event, :error_tracking_client | ||
|
||
LoadBalancerError = Struct.new(:target_ip, :code, keyword_init: true) | ||
|
||
def initialize(event:, error_tracking_client: Sentry) | ||
@event = event | ||
@error_tracking_client = error_tracking_client | ||
end | ||
|
||
def call | ||
if load_balancer_response_errors.any? | ||
error_messages = load_balancer_response_errors.map do |error| | ||
"Error detected on load balancer: #{error.target_ip} - #{error.code}" | ||
end | ||
error_tracking_client.capture_message(error_messages.join("\n")) | ||
else | ||
error_messages = opensips_logs.each do |log| | ||
log.message | ||
end | ||
|
||
error_tracking_client.capture_message(error_messages.join("\n")) | ||
end | ||
end | ||
|
||
def opensips_logs | ||
@opensips_logs ||= OpenSIPSLogEventParser.new(event).parse_event | ||
end | ||
|
||
def load_balancer_response_errors | ||
errors = opensips_logs.select do |log| | ||
log.message.match?(LOAD_BALANCER_RESPONSE_ERROR_PATTERN) | ||
end | ||
|
||
errors.map do |log| | ||
code, ip, = LOAD_BALANCER_RESPONSE_ERROR_PATTERN.match(log.message).captures | ||
LoadBalancerError.new(target_ip: IPAddr.new(ip), code:) | ||
end | ||
end | ||
|
||
def find_errors_by_code(code) | ||
load_balancer_response_errors.select { |error| error.code == code } | ||
end | ||
end |
5 changes: 5 additions & 0 deletions
5
components/services/spec/fixtures/files/cloudwatch_log_event.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"awslogs": { | ||
"data": "H4sIAAAAAAAA/3WQy2rDMBBFf8XM2g4aWYoeO0PdbNpNnV1dipMMRuCHkJSEEPLvxXG77HLuPRwuc4eRYux62t88gYWXal99v9dNU+1qyGG+ThTAQskFV2ZbbiVTkMMw97swnz1Y8OfD4I5F3yW6drcipq53U78yTQrUjWAhUUxrGs+HeAzOJzdPr25IFCLYz/8sX09NfaEpLdgd3GkZoyWWaBBRCKkkMmUUU9wIUyqGUkpWasMEcimYlqhRK8MMcsghuZFi6kYPFhXfGoMcNVM6/3sDWLi3T6wFm7XQkM84z5iyXFi+bSHPWvDutLSaL8dAFxpWuHqrP/Yr8qtbc8F0MRyKQNHPU6SCQphDgYpvUG/YRrbwgMfX4wcsVdvmjAEAAA==" | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
components/services/spec/requests/cloudwatch_log_events_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
require_relative "../spec_helper" | ||
|
||
RSpec.describe "Handle CloudWatch Log Events" do | ||
it "handles public gateway alerts" do | ||
stub_env("PUBLIC_GATEWAY_LOG_GROUP" => "public-gateway") | ||
payload = build_cloudwatch_log_event_payload( | ||
log_group: "public-gateway", | ||
log_events: [ | ||
build_cloudwatch_log_event( | ||
message: build_opensips_message(message: "408-lb-response-error-10.10.1.180") | ||
) | ||
] | ||
) | ||
|
||
invoke_lambda(payload:) | ||
end | ||
|
||
def build_opensips_message(data = {}) | ||
data = { | ||
time: "Sep 22 07:24:26", | ||
pid: 82, | ||
level: "CRITICAL", | ||
message: "error" | ||
}.merge(data) | ||
|
||
{ | ||
"time" => data.fetch(:time), | ||
"pid" => data.fetch(:pid), | ||
"level" => data.fetch(:level), | ||
"message" => data.fetch(:message) | ||
}.to_json | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters