nice_http 1.6.5 → 1.7.0

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: 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