Skip to content

Commit

Permalink
update the Zlib algorith and add only compress the value if the JSON …
Browse files Browse the repository at this point in the history
…string exceeds certain byte size
  • Loading branch information
GustavoCaso committed Oct 4, 2023
1 parent 733d010 commit 5b10018
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 13 deletions.
34 changes: 23 additions & 11 deletions lib/datadog/appsec/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ module Event
].map!(&:downcase).freeze

MAX_ENCODED_SCHEMA_SIZE = 25000
# For more information about this number
# please check https://github.com/DataDog/dd-trace-rb/pull/3177#issuecomment-1747221082
MIN_SCHEMA_SIZE_FOR_COMPRESSION = 260

# Record events for a trace
#
Expand Down Expand Up @@ -75,7 +78,7 @@ def record_via_span(span, *events)
end
end

# rubocop: disable Metrics/MethodLength
# rubocop:disable Metrics/MethodLength
def build_service_entry_tags(event_group)
waf_events = []
entry_tags = event_group.each_with_object({ '_dd.origin' => 'appsec' }) do |event, tags|
Expand Down Expand Up @@ -106,19 +109,21 @@ def build_service_entry_tags(event_group)

parsed_value_size = parsed_value.size

compressed_data = compressed_and_base64_encoded(parsed_value)
compressed_data_size = compressed_data.size
schema_value = if parsed_value_size >= MIN_SCHEMA_SIZE_FOR_COMPRESSION
compressed_and_base64_encoded(parsed_value)
else
parsed_value
end
next unless schema_value

if compressed_data_size >= MAX_ENCODED_SCHEMA_SIZE && parsed_value_size >= MAX_ENCODED_SCHEMA_SIZE
if schema_value.size >= MAX_ENCODED_SCHEMA_SIZE
Datadog.logger.debug do
"Schema key: #{key} exceeds the max size value. It will not be included as part of the span tags"
end
next
end

derivative_value = parsed_value_size > compressed_data_size ? compressed_data : parsed_value

tags[key] = derivative_value
tags[key] = schema_value
end

tags
Expand All @@ -128,25 +133,32 @@ def build_service_entry_tags(event_group)
entry_tags['_dd.appsec.json'] = appsec_events if appsec_events
entry_tags
end
# rubocop: enable Metrics/MethodLength
# rubocop:enable Metrics/MethodLength

private

def compressed_and_base64_encoded(value)
Base64.encode64(gzip(value))
rescue TypeError
rescue TypeError => e
Datadog.logger.debug do
"Failed to compress and encode value when populating AppSec::Event. Error: #{e.message}"
end
nil
end

def json_parse(value)
JSON.dump(value)
rescue ArgumentError
rescue ArgumentError => e
Datadog.logger.debug do
"Failed to parse value to JSON when populating AppSec::Event. Error: #{e.message}"
end
nil
end

def gzip(value)
sio = StringIO.new
gz = Zlib::GzipWriter.new(sio, Zlib::DEFAULT_COMPRESSION, Zlib::DEFAULT_STRATEGY)
# For an in depth comparison of Zlib options check https://github.com/DataDog/dd-trace-rb/pull/3177#issuecomment-1747215473
gz = Zlib::GzipWriter.new(sio, Zlib::BEST_SPEED, Zlib::DEFAULT_STRATEGY)
gz.write(value)
gz.close
sio.string
Expand Down
1 change: 1 addition & 0 deletions sig/datadog/appsec/event.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Datadog
ALLOWED_RESPONSE_HEADERS: untyped

MAX_ENCODED_SCHEMA_SIZE: Numeric
MIN_SCHEMA_SIZE_FOR_COMPRESSION: Numeric

def self.record: (Datadog::Tracing::SpanOperation, *untyped events) -> (nil | untyped)

Expand Down
6 changes: 4 additions & 2 deletions spec/datadog/appsec/event_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,18 @@
end

context 'JSON payload' do
it 'uses JSON string as is smaller than the compressed value' do
it 'uses JSON string when do not exceeds MIN_SCHEMA_SIZE_FOR_COMPRESSION' do
stub_const('Datadog::AppSec::Event::MIN_SCHEMA_SIZE_FOR_COMPRESSION', 3000)
meta = top_level_span.meta

expect(meta['_dd.appsec.s.req.headers']).to eq('[{"host":[8],"version":[8]}]')
end
end

context 'Compressed payload' do
it 'uses compressed value when is smaller than JSON string' do
it 'uses compressed value when JSON string is bigger than MIN_SCHEMA_SIZE_FOR_COMPRESSION' do
result = "H4sIAOYoHGUAA4aphwAAAA=\n"
stub_const('Datadog::AppSec::Event::MIN_SCHEMA_SIZE_FOR_COMPRESSION', 1)
expect(described_class).to receive(:compressed_and_base64_encoded).and_return(result)

meta = top_level_span.meta
Expand Down

0 comments on commit 5b10018

Please sign in to comment.