Class: DatadogLogForwarder
- Inherits:
-
Object
- Object
- DatadogLogForwarder
- Defined in:
- lib/tpt_serverless/datadog_log_forwarder.rb
Class Method Summary collapse
-
.get_datadog_reserved_tags(fallback_env: nil, fallback_service: nil) ⇒ Object
Computes the Datadog unified service tagging reserved tags from environment variables, using the following precedence:.
-
.handler(event:, context:) ⇒ Object
This handler receives CloudWatch log events, parses the events and forwards the extracted logs to Datadog.
Class Method Details
.get_datadog_reserved_tags(fallback_env: nil, fallback_service: nil) ⇒ Object
Computes the Datadog unified service tagging reserved tags from environment variables, using the following precedence:
-
env: DD_ENV → APP_STAGE
-
service: DD_SERVICE → APP_SERVICE_NAME
-
version: DD_VERSION
-
preset: DD_TAGS
138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/tpt_serverless/datadog_log_forwarder.rb', line 138 def (fallback_env: nil, fallback_service: nil) env = ENV['DD_ENV'] || ENV['APP_STAGE'] || fallback_env service = ENV['DD_SERVICE'] || ENV['APP_SERVICE_NAME'] || fallback_service version = ENV['DD_VERSION'] preset = ENV['DD_TAGS'] ? ENV['DD_TAGS'].split(',').map(&:strip).reject(&:empty?) : [] = [] << "env:#{env}" if env << "service:#{service}" if service << "version:#{version}" if version + preset end |
.handler(event:, context:) ⇒ Object
This handler receives CloudWatch log events, parses the events and forwards the extracted logs to Datadog.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/tpt_serverless/datadog_log_forwarder.rb', line 46 def handler(event:, context:) unless ENV['DD_API_KEY'] puts 'ERROR: DD_API_KEY is not set. Skipping log forwarding.' return nil end raw_data = event.fetch('awslogs').fetch('data') unzipped_data = Zlib.gunzip(Base64.decode64(raw_data)) data = JSON.parse(unzipped_data) = data.fetch('messageType') log_group = data.fetch('logGroup') log_stream = data.fetch('logStream') log_events = data.fetch('logEvents') if == 'CONTROL_MESSAGE' puts 'skipping control message' return nil end # Normalize first so lifecycle filtering works even if the raw message didn't have a timestamp normalized_log_events = (log_events) # Drop AWS Lambda platform lifecycle boilerplate filtered_log_events = if should_filter_lifecycle_logs? normalized_log_events.reject { |e| lambda_lifecycle_line?(e[:message]) } else normalized_log_events end puts "message_count=#{log_events.length} forwarded_count=#{filtered_log_events.length}" region = 'unknown' account_id = 'unknown' if context&.respond_to?(:invoked_function_arn) && !context.invoked_function_arn.to_s.empty? arn_parts = context.invoked_function_arn.split(':') region = arn_parts[3] if arn_parts[3] account_id = arn_parts[4] if arn_parts[4] end function_name = log_group&.split('/')&.last function_arn = "arn:aws:lambda:#{region}:#{account_id}:function:#{function_name}" name_parts = (function_name || '').split('-') # Extract the stage (everything from index 2 onwards e.g., "dev" or "dev-ivan") extracted_env = name_parts.length > 2 ? name_parts[2..-1].join('-') : 'unknown' normalized_data = filtered_log_events.map do |log_event| = ( fallback_env: extracted_env, fallback_service: function_name ) { message: log_event[:message], ddsource: ENV['DD_SOURCE'] || 'cwl-aws-lambda', service: ENV['DD_SERVICE'] || ENV['APP_SERVICE_NAME'] || function_name, hostname: function_arn, ddtags: ( + ["region:#{region}"]).reject { |t| t.nil? || t.empty? }.join(','), aws: { awslogs: { logGroup: log_group, logStream: log_stream } }, id: log_event[:id] } end # If we filtered everything out, do nothing. return nil if normalized_data.empty? begin send_json_to_datadog(normalized_data.to_json) puts "Datadog upload successful: sent #{normalized_data.length} log(s) for #{function_name}" rescue => e puts e. puts "Error details: #{e.backtrace.first}" end nil end |