class DataBuilder
Gathers and builds body payload to be sent to Treblle
in json format. Hides sensitive data based on default values and additional ones provided via env variable.
Constants
- DEFAULT_SENSITIVE_FIELDS
Attributes
ended_at[RW]
env[RW]
exception[RW]
headers[RW]
json_response[RW]
request[RW]
started_at[RW]
status[RW]
Public Class Methods
new(params)
click to toggle source
# File lib/treblle/data_builder.rb, line 25 def initialize(params) @ended_at = params[:ended_at] @env = params[:env] @exception = params[:exception] @headers = params[:headers] @json_response = params[:json_response] @request = params[:request] @started_at = params[:started_at] @status = params[:status] end
Public Instance Methods
call()
click to toggle source
# File lib/treblle/data_builder.rb, line 36 def call time_spent = ended_at - started_at user_agent = env['HTTP_USER_AGENT'] ip = env['action_dispatch.remote_ip'].calculate_ip request_method = env['REQUEST_METHOD'] project_id = ENV.fetch('TREBLLE_PROJECT_ID') { '' } request_body = request_method.downcase == 'get' ? request.query_parameters : safe_to_json(request.raw_post) data = { api_key: ENV.fetch('TREBLLE_API_KEY') { '' }, project_id: project_id, version: Treblle::TREBLLE_VERSION, sdk: 'ruby', data: { server: { ip: server_ip, timezone: Time.zone.name, software: request_headers.try(:[], 'SERVER_SOFTWARE'), signature: '', protocol: request_headers.try(:[], 'SERVER_PROTOCOL'), os: {} }, language: { name: 'ruby', version: RUBY_VERSION }, request: { timestamp: started_at.to_formatted_s(:db), ip: ip, url: request.original_url, user_agent: user_agent, method: request_method, headers: request_headers, body: without_sensitive_attrs(request_body) }, response: { headers: headers || {}, code: status, size: json_response&.to_json&.bytesize || 0, load_time: time_spent, body: without_sensitive_attrs(json_response), errors: build_error_object(exception) } } } data.to_json end
Private Instance Methods
build_error_object(exception)
click to toggle source
# File lib/treblle/data_builder.rb, line 112 def build_error_object(exception) return [] unless exception.present? [ { source: 'onError', type: exception.class.to_s || 'Unhandled error', message: exception.message, file: exception.backtrace.try(:first) || '' } ] end
request_headers()
click to toggle source
# File lib/treblle/data_builder.rb, line 129 def request_headers @request_headers ||= request.headers.env.reject { |key| key.to_s.include?('.') } end
safe_to_json(obj)
click to toggle source
# File lib/treblle/data_builder.rb, line 133 def safe_to_json(obj) JSON.parse(obj) rescue StandardError => e {} end
sensitive_attrs()
click to toggle source
# File lib/treblle/data_builder.rb, line 103 def sensitive_attrs @sensitive_attrs ||= user_sensitive_fields.merge(DEFAULT_SENSITIVE_FIELDS) end
server_ip()
click to toggle source
# File lib/treblle/data_builder.rb, line 125 def server_ip Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address end
user_sensitive_fields()
click to toggle source
# File lib/treblle/data_builder.rb, line 107 def user_sensitive_fields fields = ENV.fetch('TREBLLE_SENSITIVE_FIELDS') { '' }.gsub(/\s+/, '') fields.split(',').to_set end
without_sensitive_attrs(obj)
click to toggle source
# File lib/treblle/data_builder.rb, line 87 def without_sensitive_attrs(obj) return {} unless obj.present? obj.each do |k, v| value = v || k if value.is_a?(Hash) || value.is_a?(Array) without_sensitive_attrs(value) elsif sensitive_attrs.include?(k.to_s) obj[k] = '*' * v.to_s.length end end obj rescue StandardError => e Rails.logger.error e.message end