treblle 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c7e8150492d3a4b39eff0b9d64a12e75e459fe4d74ac42a6eb172f860f6cc6e0
4
- data.tar.gz: b96ad0f8f9697838523d4db9945a3214e7810865033f9fc27fe1666f1d108589
3
+ metadata.gz: 33af7f59af8142ab9221eeae5e96157831ebd85f103d282bbfe94527f3430a50
4
+ data.tar.gz: 46a242aba5acb59cc02eb83b7ddfecbdcafdaccf6b096a1d3130d1f5176b0898
5
5
  SHA512:
6
- metadata.gz: 2aa83b4cda17c255dc307f9135fb9e60839af43abab4e39639eecc165e67b2cee4dd8b8b6dc93b0162ff6f7113722000e1b7791c6bb9d3d7d1236282f41baa97
7
- data.tar.gz: 10da084dcceb356776492b26473c5564fa1675b5a801d6afc235023cc77085eeeb4b84c563aa051d8b1995dfd628e84faa5b84d29f5f97260207e441318989ce
6
+ metadata.gz: c4c40f9be2cdf09ef85ba0c2a9b8fc5ff8da22fd96356c8154602d1d48003ccb47a126f35cd27abf44b865d0299d6c6b8a25f7507d836fa38422156d7034f70a
7
+ data.tar.gz: 2546afe677f060122e034453992bf565d6008dd62fff234bf48aef93ac6c6251e34e4879baf1464a8e9669aeeba5f04eba77ceeeb4aeb4e28c1f26e04526795d
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'socket'
4
+
5
+ # Gathers and builds body payload to be sent to Treblle in json format.
6
+ # Hides sensitive data based on default values and additional ones provided via env variable.
7
+ class DataBuilder
8
+ DEFAULT_SENSITIVE_FIELDS = Set[
9
+ 'card_number',
10
+ 'cardNumber',
11
+ 'cc',
12
+ 'ccv',
13
+ 'credit_score',
14
+ 'creditScore',
15
+ 'password',
16
+ 'password_confirmation',
17
+ 'passwordConfirmation',
18
+ 'pwd',
19
+ 'secret',
20
+ 'ssn'
21
+ ].freeze
22
+
23
+ attr_accessor :env, :status, :started_at, :ended_at, :request, :headers, :json_response, :exception
24
+
25
+ def initialize(params)
26
+ @ended_at = params[:ended_at]
27
+ @env = params[:env]
28
+ @exception = params[:exception]
29
+ @headers = params[:headers]
30
+ @json_response = params[:json_response]
31
+ @request = params[:request]
32
+ @started_at = params[:started_at]
33
+ @status = params[:status]
34
+ end
35
+
36
+ def call
37
+ time_spent = ended_at - started_at
38
+ user_agent = env['HTTP_USER_AGENT']
39
+ ip = env['action_dispatch.remote_ip'].calculate_ip
40
+ request_method = env['REQUEST_METHOD']
41
+ project_id = ENV.fetch('TREBLLE_PROJECT_ID') { '' }
42
+ request_body = request_method.downcase == 'get' ? request.query_parameters : safe_to_json(request.raw_post)
43
+
44
+ data = {
45
+ api_key: ENV.fetch('TREBLLE_API_KEY') { '' },
46
+ project_id: project_id,
47
+ version: Treblle::TREBLLE_VERSION,
48
+ sdk: 'ruby',
49
+ data: {
50
+ server: {
51
+ ip: server_ip,
52
+ timezone: Time.zone.name,
53
+ software: request_headers.try(:[], 'SERVER_SOFTWARE'),
54
+ signature: '',
55
+ protocol: request_headers.try(:[], 'SERVER_PROTOCOL'),
56
+ os: {}
57
+ },
58
+ language: {
59
+ name: 'ruby',
60
+ version: RUBY_VERSION
61
+ },
62
+ request: {
63
+ timestamp: started_at.to_formatted_s(:db),
64
+ ip: ip,
65
+ url: request.original_url,
66
+ user_agent: user_agent,
67
+ method: request_method,
68
+ headers: request_headers,
69
+ body: without_sensitive_attrs(request_body)
70
+ },
71
+ response: {
72
+ headers: headers || {},
73
+ code: status,
74
+ size: json_response&.to_json&.bytesize || 0,
75
+ load_time: time_spent,
76
+ body: without_sensitive_attrs(json_response),
77
+ errors: build_error_object(exception)
78
+ }
79
+ }
80
+ }
81
+
82
+ begin
83
+ data.to_json
84
+ rescue Exception
85
+ JSON.dump(data)
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ def without_sensitive_attrs(obj)
92
+ return {} unless obj.present?
93
+
94
+ obj.each do |k, v|
95
+ value = v || k
96
+ if value.is_a?(Hash) || value.is_a?(Array)
97
+ without_sensitive_attrs(value)
98
+ elsif sensitive_attrs.include?(k.to_s)
99
+ obj[k] = '*' * v.to_s.length
100
+ end
101
+ end
102
+ obj
103
+ rescue StandardError => e
104
+ Rails.logger.error e.message
105
+ end
106
+
107
+ def sensitive_attrs
108
+ @sensitive_attrs ||= user_sensitive_fields.merge(DEFAULT_SENSITIVE_FIELDS)
109
+ end
110
+
111
+ def user_sensitive_fields
112
+ fields = ENV.fetch('TREBLLE_SENSITIVE_FIELDS') { '' }.gsub(/\s+/, '')
113
+ fields.split(',').to_set
114
+ end
115
+
116
+ def build_error_object(exception)
117
+ return [] unless exception.present?
118
+
119
+ [
120
+ {
121
+ source: 'onError',
122
+ type: exception.class.to_s || 'Unhandled error',
123
+ message: exception.message,
124
+ file: exception.backtrace.try(:first) || ''
125
+ }
126
+ ]
127
+ end
128
+
129
+ def server_ip
130
+ Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address
131
+ end
132
+
133
+ def request_headers
134
+ @request_headers ||= request.headers.env.reject { |key| key.to_s.include?('.') }
135
+ end
136
+
137
+ def safe_to_json(obj)
138
+ JSON.parse(obj)
139
+ rescue StandardError => e
140
+ {}
141
+ end
142
+ end
data/lib/treblle.rb CHANGED
@@ -78,7 +78,6 @@ class Treblle
78
78
  req['Content-Type'] = 'application/json'
79
79
  req['x-api-key'] = ENV.fetch('TREBLLE_API_KEY') { '' }
80
80
  req.body = data
81
- puts data
82
81
  res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
83
82
  http.request(req)
84
83
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: treblle
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hrvoje Grdic
@@ -17,6 +17,7 @@ extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
19
  - lib/treblle.rb
20
+ - lib/treblle/data_builder.rb
20
21
  homepage: https://rubygems.org/gems/treblle
21
22
  licenses:
22
23
  - MIT