nice_http 1.6.5 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9134ed46c6d297b4e68c88b5e3e7e868100301bf24e3faaaa2aa17e0d75a989
4
- data.tar.gz: 9ab95966908fb2365dd6573c9ddfbda4cb429741f06989fe589fb4176b4f927b
3
+ metadata.gz: 74ab2804913e2aaa1677a20d5819d9e8a30f4689ffc3f2cc9805ec1f1bd5a9f6
4
+ data.tar.gz: 24d575ea5251c1e9a39d9af68ca794c07d0f858e95d30c72dfccdcbefa40633e
5
5
  SHA512:
6
- metadata.gz: 508f31aa41e757f510b95ae162ff145dce5e7a493fa0e09564414dae12b069fca20a4acb480ffd4633cb63b5cae993c2ad3620b3517e74f80e9e71b89714cd69
7
- data.tar.gz: f99a4e393761bb8e69faf913ff22895f753dd531f2094b7d38eefaa66200c52bd3e454c95354823515ac0db2af3badd8e05b5dddab7a2445ed1e61f4949d5e20
6
+ metadata.gz: 69591afdbafca487154dd816af0eaff06edb3bfd09f877204124b9aa0978cf37f8b84a6f76d9c7f2baa5e19058d32277806226ff63b6603622065039bf7805b8
7
+ data.tar.gz: 3e0f852310ae7ecc1a47d4bed3b45df81ddd28cbde1c516c06da867562dcfb315530b508899742850aaae360477d68096117f61507b51ba1525ebfa1b5a514fa
data/README.md CHANGED
@@ -351,6 +351,197 @@ Example posting a csv file:
351
351
 
352
352
  ```
353
353
 
354
+ ## Http logs
355
+
356
+ You can set where the http logs will be stored by using the log attribute of the NiceHttp.
357
+ By default they will be stored in your root directory with the name nice_http.log.
358
+ ```ruby
359
+ # you can specify the default for all connections
360
+ NiceHttp.log = :file_run
361
+
362
+ # also you can specify for a concrete connection
363
+ http = NiceHttp.new({host: 'www.example.com', log: './example.log'})
364
+ ```
365
+
366
+ Other values you can supply:
367
+ * :fix_file, will log the communication on nice_http.log. (default).
368
+ * :no, won't generate any logs.
369
+ * :screen, will print the logs on the screen.
370
+ * :file, will be generated a log file with name: nice_http_YY-mm-dd-HHMMSS.log.
371
+ * :file_run, will generate a log file with the name where the object was created and extension .log, fex: myfile.rb.log
372
+ * String, the path and file name where the logs will be stored.
373
+
374
+ Example of logs:
375
+ ```
376
+ I, [2019-03-22T18:38:58.518964 #29412] INFO -- : (47266856647720): Http connection created. host:www.reqres.in, port:443, ssl:true, mode:, proxy_host: , proxy_port:
377
+ I, [2019-03-22T18:38:58.537106 #29412] INFO -- : (47266856647720): Http connection: https://www.reqres.in:443
378
+
379
+
380
+ - - - - - - - - - - - - - - - - - - - - - - - - -
381
+ POST Request: Doom.example
382
+ path: /api/users
383
+ headers: {Loop:44, Cookie:, Boom:33, Content-Type:application/json, }
384
+ data: {
385
+ "name": "peter",
386
+ "job": "leader",
387
+ "products": [
388
+ {
389
+ "one": "uno",
390
+ "two": 2
391
+ },
392
+ {
393
+ "one": "uno",
394
+ "two": 22
395
+ }
396
+ ]
397
+ }
398
+
399
+ I, [2019-03-22T18:38:58.873935 #29412] INFO -- :
400
+ RESPONSE:
401
+ 201:Created
402
+ time_elapsed_total: '0.335720719'
403
+ time_elapsed: '0.335728095'
404
+ date: 'Fri, 22 Mar 2019 18:38:58 GMT'
405
+ content-type: 'application/json; charset=utf-8'
406
+ content-length: '172'
407
+ connection: 'keep-alive'
408
+ set-cookie: '__cfduid=dfb962e62cd8386ce4ab9bad601611553272738; expires=Sat, 21-Mar-20 18:38:58 GMT; path=/; domain=.reqres.in; HttpOnly'
409
+ x-powered-by: 'Express'
410
+ access-control-allow-origin: '*'
411
+ etag: 'W/"ac-EMh4XBmK5vry/OeKaGWILGtmHU0"'
412
+ expect-ct: 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"'
413
+ server: 'cloudflare'
414
+ cf-ray: '4bb99958090dbf89-AMS'
415
+ data: '{
416
+ "name": "peter",
417
+ "job": "leader",
418
+ "products": [
419
+ {
420
+ "one": "uno",
421
+ "two": 2
422
+ },
423
+ {
424
+ "one": "uno",
425
+ "two": 22
426
+ }
427
+ ],
428
+ "id": "628",
429
+ "createdAt": "2019-03-22T18:43:33.619Z"
430
+ }'
431
+
432
+ I, [2019-03-22T18:38:58.874190 #29412] INFO -- : set-cookie added to Cookie header as required
433
+ I, [2019-03-22T18:38:59.075293 #29412] INFO -- :
434
+
435
+ - - - - - - - - - - - - - - - - - - - - - - - - -
436
+ GET Request: Doom.example
437
+ path: /api/users
438
+ Same headers and data as in the previous request.
439
+ I, [2019-03-22T18:38:59.403459 #29412] INFO -- :
440
+ RESPONSE:
441
+ 200:OK
442
+ time_elapsed_total: '0.327002338'
443
+ time_elapsed: '0.327004766'
444
+ date: 'Fri, 22 Mar 2019 18:38:59 GMT'
445
+ content-type: 'application/json; charset=utf-8'
446
+ transfer-encoding: 'chunked'
447
+ connection: 'keep-alive'
448
+ x-powered-by: 'Express'
449
+ access-control-allow-origin: '*'
450
+ etag: 'W/"1bb-D+c3sZ5g5u/nmLPQRl1uVo2heAo"'
451
+ expect-ct: 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"'
452
+ server: 'cloudflare'
453
+ cf-ray: '4bb9995b5c20bf89-AMS'
454
+ data: '{
455
+ "page": 1,
456
+ "per_page": 3,
457
+ "total": 12,
458
+ "total_pages": 4,
459
+ "data": [
460
+ {
461
+ "id": 1,
462
+ "first_name": "George",
463
+ "last_name": "Bluth",
464
+ "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"
465
+ },
466
+ {
467
+ "id": 2,
468
+ "first_name": "Janet",
469
+ "last_name": "Weaver",
470
+ "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"
471
+ },
472
+ ]
473
+ }'
474
+
475
+ ```
476
+
477
+ ## Http stats
478
+
479
+ If you want to get a summarize stats of your http communication you need to set `NiceHttp.create_stats = true`
480
+
481
+ Then whenever you want to access the stats: `NiceHttp.stats`
482
+
483
+ Also it is very convenient to store the stats on a file, for example on YAML format. You can use the at_exit method to be run at the end of the run:
484
+
485
+ ```ruby
486
+ at_exit do
487
+ require 'yaml'
488
+ NiceHttp.stats.keys.each do |key|
489
+ File.open("./nice_http_stats_#{key}.yaml", "w") { |file| file.write(NiceHttp.stats[key].to_yaml) }
490
+ end
491
+ end
492
+ ```
493
+
494
+ This is an example of the output:
495
+
496
+ ```yaml
497
+ ---
498
+ www.reqres.in:443:
499
+ :num_requests: 11
500
+ :time_elapsed:
501
+ :total: 2.947269038
502
+ :maximum: 0.357101109
503
+ :minimum: 0.198707111
504
+ :average: 0.2679335489090909
505
+ "/api/users":
506
+ :num_requests: 11
507
+ :time_elapsed:
508
+ :total: 2.947269038
509
+ :maximum: 0.357101109
510
+ :minimum: 0.198707111
511
+ :average: 0.2679335489090909
512
+ :method:
513
+ POST:
514
+ :num_requests: 8
515
+ :time_elapsed:
516
+ :total: 2.3342455970000002
517
+ :maximum: 0.357101109
518
+ :minimum: 0.198707111
519
+ :average: 0.29178069962500003
520
+ :response:
521
+ '201':
522
+ :num_requests: 8
523
+ :time_elapsed:
524
+ :total: 2.3342455970000002
525
+ :maximum: 0.357101109
526
+ :minimum: 0.198707111
527
+ :average: 0.29178069962500003
528
+ GET:
529
+ :num_requests: 3
530
+ :time_elapsed:
531
+ :total: 0.613023441
532
+ :maximum: 0.210662528
533
+ :minimum: 0.200197583
534
+ :average: 0.20434114699999997
535
+ :response:
536
+ '200':
537
+ :num_requests: 3
538
+ :time_elapsed:
539
+ :total: 0.613023441
540
+ :maximum: 0.210662528
541
+ :minimum: 0.200197583
542
+ :average: 0.20434114699999997
543
+ ```
544
+
354
545
  ## Contributing
355
546
 
356
547
  Bug reports are very welcome on GitHub at https://github.com/marioruiz/nice_http.
@@ -9,7 +9,7 @@ require_relative "nice_http/http_methods"
9
9
  # Attributes you can access using NiceHttp.the_attribute:
10
10
  # :host, :port, :ssl, :headers, :debug, :log, :proxy_host, :proxy_port,
11
11
  # :last_request, :last_response, :request_id, :use_mocks, :connections,
12
- # :active, :auto_redirect, :values_for
12
+ # :active, :auto_redirect, :values_for, :create_stats, :stats
13
13
  #
14
14
  # @attr [String] host The host to be accessed
15
15
  # @attr [Integer] port The port number
@@ -41,6 +41,8 @@ require_relative "nice_http/http_methods"
41
41
  # my_http.logger.info "add this to the log file"
42
42
  # @see https://ruby-doc.org/stdlib-2.5.0/libdoc/logger/rdoc/Logger.html
43
43
  # @attr [Hash] values_for The default values to set on the data in case not specified others
44
+ # @attr [Boolean] create_stats If true, NiceHttp will create stats of the http communication and store them on NiceHttp.stats hash
45
+ # @attr [Hash] stats It contains detailed stats of the http communication
44
46
  ######################################################
45
47
  class NiceHttp
46
48
  include NiceHttpManageRequest
@@ -64,7 +66,7 @@ class NiceHttp
64
66
  class << self
65
67
  attr_accessor :host, :port, :ssl, :headers, :debug, :log, :proxy_host, :proxy_port,
66
68
  :last_request, :last_response, :request_id, :use_mocks, :connections,
67
- :active, :auto_redirect, :log_files, :values_for
69
+ :active, :auto_redirect, :log_files, :values_for, :create_stats, :stats
68
70
  end
69
71
 
70
72
  ######################################################
@@ -88,6 +90,21 @@ class NiceHttp
88
90
  @active = 0
89
91
  @auto_redirect = true
90
92
  @log_files = {}
93
+ @create_stats = false
94
+ @stats = {
95
+ all: {
96
+ num_requests: 0,
97
+ time_elapsed: {
98
+ total: 0,
99
+ maximum: 0,
100
+ minimum: 100000,
101
+ average: 0,
102
+ },
103
+ method: {},
104
+ },
105
+ path: {},
106
+ name: {},
107
+ }
91
108
  end
92
109
  reset!
93
110
 
@@ -104,7 +121,7 @@ class NiceHttp
104
121
  ######################################################
105
122
  # Change the default values for NiceHttp supplying a Hash
106
123
  #
107
- # @param par [Hash] keys: :host, :port, :ssl, :headers, :debug, :log, :proxy_host, :proxy_port, :use_mocks, :auto_redirect, :values_for
124
+ # @param par [Hash] keys: :host, :port, :ssl, :headers, :debug, :log, :proxy_host, :proxy_port, :use_mocks, :auto_redirect, :values_for, :create_stats
108
125
  ######################################################
109
126
  def self.defaults=(par = {})
110
127
  @host = par[:host] if par.key?(:host)
@@ -118,6 +135,7 @@ class NiceHttp
118
135
  @proxy_port = par[:proxy_port] if par.key?(:proxy_port)
119
136
  @use_mocks = par[:use_mocks] if par.key?(:use_mocks)
120
137
  @auto_redirect = par[:auto_redirect] if par.key?(:auto_redirect)
138
+ @create_stats = par[:create_stats] if par.key?(:create_stats)
121
139
  end
122
140
 
123
141
  ######################################################
@@ -184,6 +202,7 @@ class NiceHttp
184
202
  @auto_redirect = false #set it up at the end of initialize
185
203
  auto_redirect = self.class.auto_redirect
186
204
  @num_redirects = 0
205
+ @create_stats = self.class.create_stats
187
206
 
188
207
  #todo: set only the cookies for the current domain
189
208
  #key: path, value: hash with key is the name of the cookie and value the value
@@ -191,7 +191,7 @@ module NiceHttpManageRequest
191
191
 
192
192
  headers_ts = ""
193
193
  headers_t.each { |key, val| headers_ts += key.to_s + ":" + val.to_s() + ", " }
194
- message = "#{"- " * 25}\n"
194
+ message = "\n\n#{"- " * 25}\n"
195
195
  if arguments.size == 1 and arguments[0].kind_of?(Hash) and arguments[0].key?(:name)
196
196
  message += "#{method_s.upcase} Request: #{arguments[0][:name]}"
197
197
  else
@@ -203,7 +203,7 @@ module NiceHttpManageRequest
203
203
  message += " data: " + data_s.to_s() + "\n"
204
204
  message = @message_server + "\n" + message
205
205
  else
206
- message += " Same as the last request."
206
+ message += " Same#{" headers" if headers_t != {}}#{" and" if headers_t != {} and data.to_s != ""}#{" data" if data.to_s != ""} as in the previous request."
207
207
  end
208
208
  if path.to_s().scan(/^https?:\/\//).size > 0 and path.to_s().scan(/^https?:\/\/#{@host}/).size == 0
209
209
  # the path is for another server than the current
@@ -219,6 +219,10 @@ module NiceHttpManageRequest
219
219
  @prev_request[:path] = path
220
220
  @prev_request[:data] = data
221
221
  @prev_request[:headers] = headers_t
222
+ @prev_request[:method] = method_s.upcase
223
+ if arguments.size == 1 and arguments[0].kind_of?(Hash) and arguments[0].key?(:name)
224
+ @prev_request[:name] = arguments[0][:name]
225
+ end
222
226
  return path, data, headers_t
223
227
  rescue Exception => stack
224
228
  @logger.fatal(stack)
@@ -24,6 +24,9 @@ module NiceHttpManageResponse
24
24
  else
25
25
  @response[:time_elapsed] = nil
26
26
  end
27
+
28
+ create_stats(resp) if @create_stats
29
+
27
30
  begin
28
31
  # this is to be able to access all keys as symbols
29
32
  new_resp = Hash.new()
@@ -90,8 +93,8 @@ module NiceHttpManageResponse
90
93
 
91
94
  @response[:code] = resp.code
92
95
  message = "\nRESPONSE: \n " + @response[:code].to_s() + ":" + @response[:message].to_s()
93
- if @debug or @prev_response[:'content-type']!=@response[:'content-type'] or @prev_response[:'content-length']!=@response[:'content-length'] or
94
- @prev_response[:data]!=@response[:data] or @prev_response[:code]!=@response[:code] or @prev_response[:message]!= @response[:message]
96
+ if @debug or @prev_response[:'content-type'] != @response[:'content-type'] or @prev_response[:'content-length'] != @response[:'content-length'] or
97
+ @prev_response[:data] != @response[:data] or @prev_response[:code] != @response[:code] or @prev_response[:message] != @response[:message]
95
98
  self.class.last_response = message if @debug
96
99
  @response.each { |key, value|
97
100
  if value.to_s() != ""
@@ -180,4 +183,97 @@ module NiceHttpManageResponse
180
183
  @logger.fatal "manage_response Error on method #{method_s} "
181
184
  end
182
185
  end
186
+
187
+ private
188
+
189
+ def set_stats(hash)
190
+ unless hash.key?(:num_requests)
191
+ # to add to the end the previous keys so num_requests and time_elapsed come first
192
+ keys = hash.keys
193
+ hash.keys.each do |k|
194
+ hash.delete(k)
195
+ end
196
+
197
+ hash[:num_requests] = 0
198
+ hash[:time_elapsed] = {
199
+ total: 0,
200
+ maximum: 0,
201
+ minimum: 100000,
202
+ average: 0,
203
+ }
204
+
205
+ # to add to the end the previous keys so num_requests and time_elapsed come first
206
+ keys.each do |k|
207
+ hash[k] = {}
208
+ end
209
+ end
210
+ hash[:num_requests] += 1
211
+ hash[:time_elapsed][:total] += @response[:time_elapsed]
212
+ hash[:time_elapsed][:maximum] = @response[:time_elapsed] if @response[:time_elapsed] > hash[:time_elapsed][:maximum]
213
+ hash[:time_elapsed][:minimum] = @response[:time_elapsed] if @response[:time_elapsed] < hash[:time_elapsed][:minimum]
214
+ hash[:time_elapsed][:average] = hash[:time_elapsed][:total] / hash[:num_requests]
215
+ end
216
+
217
+ private
218
+
219
+ def create_stats(resp)
220
+ # all
221
+ set_stats(self.class.stats[:all])
222
+ # all method
223
+ unless self.class.stats[:all][:method].key?(@prev_request[:method])
224
+ self.class.stats[:all][:method][@prev_request[:method]] = {
225
+ response: {},
226
+ }
227
+ end
228
+ set_stats(self.class.stats[:all][:method][@prev_request[:method]])
229
+ # all method response
230
+ unless self.class.stats[:all][:method][@prev_request[:method]][:response].key?(resp.code)
231
+ self.class.stats[:all][:method][@prev_request[:method]][:response][resp.code] = {}
232
+ end
233
+ set_stats(self.class.stats[:all][:method][@prev_request[:method]][:response][resp.code])
234
+
235
+ # server
236
+ server = "#{@host}:#{@port}"
237
+ unless self.class.stats[:path].key?(server)
238
+ self.class.stats[:path][server] = {}
239
+ end
240
+ set_stats(self.class.stats[:path][server])
241
+ # server path
242
+ unless self.class.stats[:path][server].key?(@prev_request[:path])
243
+ self.class.stats[:path][server][@prev_request[:path]] = {method: {}}
244
+ end
245
+ set_stats(self.class.stats[:path][server][@prev_request[:path]])
246
+ # server path method
247
+ unless self.class.stats[:path][server][@prev_request[:path]][:method].key?(@prev_request[:method])
248
+ self.class.stats[:path][server][@prev_request[:path]][:method][@prev_request[:method]] = {
249
+ response: {},
250
+ }
251
+ end
252
+ set_stats(self.class.stats[:path][server][@prev_request[:path]][:method][@prev_request[:method]])
253
+ # server path method response
254
+ unless self.class.stats[:path][server][@prev_request[:path]][:method][@prev_request[:method]][:response].key?(resp.code)
255
+ self.class.stats[:path][server][@prev_request[:path]][:method][@prev_request[:method]][:response][resp.code] = {}
256
+ end
257
+ set_stats(self.class.stats[:path][server][@prev_request[:path]][:method][@prev_request[:method]][:response][resp.code])
258
+
259
+ if @prev_request.key?(:name)
260
+ # name
261
+ unless self.class.stats[:name].key?(@prev_request[:name])
262
+ self.class.stats[:name][@prev_request[:name]] = {method: {}}
263
+ end
264
+ set_stats(self.class.stats[:name][@prev_request[:name]])
265
+ # name method
266
+ unless self.class.stats[:name][@prev_request[:name]][:method].key?(@prev_request[:method])
267
+ self.class.stats[:name][@prev_request[:name]][:method][@prev_request[:method]] = {
268
+ response: {},
269
+ }
270
+ end
271
+ set_stats(self.class.stats[:name][@prev_request[:name]][:method][@prev_request[:method]])
272
+ # name method response
273
+ unless self.class.stats[:name][@prev_request[:name]][:method][@prev_request[:method]][:response].key?(resp.code)
274
+ self.class.stats[:name][@prev_request[:name]][:method][@prev_request[:method]][:response][resp.code] = {}
275
+ end
276
+ set_stats(self.class.stats[:name][@prev_request[:name]][:method][@prev_request[:method]][:response][resp.code])
277
+ end
278
+ end
183
279
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nice_http
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.5
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mario Ruiz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-19 00:00:00.000000000 Z
11
+ date: 2019-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nice_hash