qa 5.2.0 → 5.3.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
  SHA1:
3
- metadata.gz: 69b198054c52dafc00d9cf83f2f61b5fdc3e55cb
4
- data.tar.gz: 00aa3d111681efe0a1c068846190e41531155e21
3
+ metadata.gz: a0d1a1143d74f69697643e818b748496f81e96cd
4
+ data.tar.gz: e1145e427c1f343a44b4d144181697efb89a70e4
5
5
  SHA512:
6
- metadata.gz: c75338fdecba820602eb3c669065679a87387e80bf65e350fdc42d6224dc5eb152439198257b6da3eb38812a9e44e6764472fa3a8fff3f554e782b13da0e4c38
7
- data.tar.gz: bcf795d36f8fc600dbc672d9884b4b37efd084ad9e12a7e53583b491cf122b1247f8335fdcfe216cfda6b2c3c326628ac27f2b6a375aa44feb783daf8ce0f2b5
6
+ metadata.gz: 8abeeb72e16fca93102783671e7b8da5362461422e9b3d6d53ed35a0ee7dc7e169980b5ea1eeb53bf1a00edf7fd4d85f41f6336af0b61acc50b56bf7161d5978
7
+ data.tar.gz: ab5983ff28640f912a06ac673b376d1542d4cdd0a182b1cfedf72ea6b186c4ada32ad17c4d9c7190e7e30c18bb81e8377e0603ff984b268ffa9168c59d10aead
@@ -91,6 +91,7 @@ module Qa
91
91
  end
92
92
 
93
93
  def process_error(e, url)
94
+ Rails.logger.warn("******** RDF::Graph#load failure: exception=#{e.inspect}, url=#{url}")
94
95
  uri = URI(url)
95
96
  raise RDF::FormatError, "Unknown RDF format of results returned by #{uri}. (RDF::FormatError) You may need to include gem 'linkeddata'." if e.is_a? RDF::FormatError
96
97
  response_code = ioerror_code(e)
@@ -1,8 +1,9 @@
1
1
  # Service to construct a request header that includes optional attributes for search and fetch requests.
2
+ require 'geocoder'
2
3
  module Qa
3
4
  module LinkedData
4
5
  class RequestHeaderService
5
- attr_reader :request, :params
6
+ attr_reader :request, :params, :request_id
6
7
 
7
8
  # @param request [HttpRequest] request from controller
8
9
  # @param params [Hash] attribute-value pairs holding the request parameters
@@ -16,6 +17,8 @@ module Qa
16
17
  def initialize(request:, params:)
17
18
  @request = request
18
19
  @params = params
20
+ @request_id = request.request_id
21
+ log_request
19
22
  end
20
23
 
21
24
  # Construct request parameters to pass to search_query (linked data module).
@@ -23,6 +26,8 @@ module Qa
23
26
  # @see Qa::Authorities::LinkedData::SearchQuery
24
27
  def search_header
25
28
  header = {}
29
+ header[:request] = request
30
+ header[:request_id] = request_id
26
31
  header[:subauthority] = params.fetch(:subauthority, nil)
27
32
  header[:user_language] = user_language
28
33
  header[:performance_data] = performance_data?
@@ -37,6 +42,8 @@ module Qa
37
42
  # @see Qa::Authorities::LinkedData::FindTerm
38
43
  def fetch_header
39
44
  header = {}
45
+ header[:request] = request
46
+ header[:request_id] = request_id
40
47
  header[:subauthority] = params.fetch(:subauthority, nil)
41
48
  header[:user_language] = user_language
42
49
  header[:performance_data] = performance_data?
@@ -62,6 +69,13 @@ module Qa
62
69
 
63
70
  private
64
71
 
72
+ def log_request
73
+ gc = request.location
74
+ msg = "******** #{request.path_parameters[:action].upcase}"
75
+ msg += " from IP #{request.ip} in {city: #{gc.city}, state: #{gc.state}, country: #{gc.country}}" unless Qa.config.suppress_ip_data_from_log
76
+ Rails.logger.info(msg)
77
+ end
78
+
65
79
  # filter literals in results to this language
66
80
  def user_language
67
81
  request_language = request.env['HTTP_ACCEPT_LANGUAGE']
@@ -23,4 +23,9 @@ Qa.config do |config|
23
23
  # When false, properties that do not override default optional behavior will be shown whether or not the property has a value in the graph.
24
24
  # When true, properties that do not override default optional behavior will not be shown whn the property does not have a value in the graph.
25
25
  # config.property_map_default_for_optional = false
26
+
27
+ # IP data including IP address, city, state, and country will be logged with each request.
28
+ # When false, IP data is logged
29
+ # When true, IP data will not be logged (default for backward compatibility)
30
+ # config.suppress_ip_data_from_log = true
26
31
  end
@@ -15,8 +15,8 @@ module Qa::Authorities
15
15
  @term_config = term_config
16
16
  end
17
17
 
18
- attr_reader :term_config, :full_graph, :filtered_graph, :language, :id, :uri, :access_time_s, :normalize_time_s, :subauthority, :request_header
19
- private :full_graph, :filtered_graph, :language, :id, :uri, :access_time_s, :normalize_time_s, :subauthority, :request_header
18
+ attr_reader :term_config, :full_graph, :filtered_graph, :language, :id, :uri, :access_time_s, :normalize_time_s, :subauthority, :request_header, :request_id, :request
19
+ private :full_graph, :filtered_graph, :language, :id, :uri, :access_time_s, :normalize_time_s, :subauthority, :request_header, :request_id, :request
20
20
 
21
21
  delegate :term_subauthority?, :prefixes, :authority_name, to: :term_config
22
22
 
@@ -92,6 +92,8 @@ module Qa::Authorities
92
92
 
93
93
  def unpack_request_header(request_header)
94
94
  @request_header = request_header
95
+ @request = request_header.fetch(:request, nil)
96
+ @request_id = request_header.fetch(:request_id, 'UNASSIGNED')
95
97
  @subauthority = request_header.fetch(:subauthority, nil)
96
98
  @format = request_header.fetch(:format, 'json')
97
99
  @performance_data = request_header.fetch(:performance_data, false)
@@ -15,8 +15,8 @@ module Qa::Authorities
15
15
  @search_config = search_config
16
16
  end
17
17
 
18
- attr_reader :search_config, :full_graph, :filtered_graph, :language, :access_time_s, :normalize_time_s, :subauthority, :request_header
19
- private :full_graph, :filtered_graph, :language, :access_time_s, :normalize_time_s, :subauthority, :request_header
18
+ attr_reader :search_config, :full_graph, :filtered_graph, :language, :access_time_s, :normalize_time_s, :subauthority, :request_header, :request_id, :request
19
+ private :full_graph, :filtered_graph, :language, :access_time_s, :normalize_time_s, :subauthority, :request_header, :request_id, :request
20
20
 
21
21
  delegate :subauthority?, :supports_sort?, :prefixes, :authority_name, to: :search_config
22
22
 
@@ -91,6 +91,8 @@ module Qa::Authorities
91
91
 
92
92
  def unpack_request_header(request_header)
93
93
  @request_header = request_header
94
+ @request = request_header.fetch(:request, nil)
95
+ @request_id = request_header.fetch(:request_id, 'UNASSIGNED')
94
96
  @subauthority = request_header.fetch(:subauthority, nil)
95
97
  @context = request_header.fetch(:context, false)
96
98
  @performance_data = request_header.fetch(:performance_data, false)
@@ -54,5 +54,14 @@ module Qa
54
54
  @property_map_default_for_optional = false if @property_map_default_for_optional.nil?
55
55
  @property_map_default_for_optional
56
56
  end
57
+
58
+ # IP data including IP address, city, state, and country will be logged with each request.
59
+ # When false, IP data is logged
60
+ # When true, IP data will not be logged (default for backward compatibility)
61
+ attr_writer :suppress_ip_data_from_log
62
+ def suppress_ip_data_from_log
63
+ @suppress_ip_data_from_log = true if @suppress_ip_data_from_log.nil?
64
+ @suppress_ip_data_from_log
65
+ end
57
66
  end
58
67
  end
@@ -1,3 +1,3 @@
1
1
  module Qa
2
- VERSION = "5.2.0".freeze
2
+ VERSION = "5.3.0".freeze
3
3
  end
@@ -2,6 +2,7 @@ require 'spec_helper'
2
2
  require 'json'
3
3
 
4
4
  describe Qa::LinkedDataTermsController, type: :controller do
5
+ let(:graph_load_failure) { /^\*\*\*\*\*\*\*\* RDF\:\:Graph\#load failure/ }
5
6
  before do
6
7
  @routes = Qa::Engine.routes
7
8
  end
@@ -140,6 +141,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
140
141
  .to_return(status: 500)
141
142
  end
142
143
  it 'returns 500' do
144
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
143
145
  expect(Rails.logger).to receive(:warn).with("Internal Server Error - Search query my_query unsuccessful for authority OCLC_FAST")
144
146
  get :search, params: { q: 'my_query', vocab: 'OCLC_FAST', maximumRecords: '3' }
145
147
  expect(response.code).to eq('500')
@@ -154,6 +156,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
154
156
  end
155
157
  it 'returns 500' do
156
158
  msg = "RDF Format Error - Results from search query my_query for authority OCLC_FAST was not identified as a valid RDF format. You may need to include the linkeddata gem."
159
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
157
160
  expect(Rails.logger).to receive(:warn).with(msg)
158
161
  get :search, params: { q: 'my_query', vocab: 'OCLC_FAST', maximumRecords: '3' }
159
162
  expect(response.code).to eq('500')
@@ -166,6 +169,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
166
169
  .to_return(status: 501)
167
170
  end
168
171
  it 'returns 500' do
172
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
169
173
  expect(Rails.logger).to receive(:warn).with("Internal Server Error - Search query my_query unsuccessful for authority OCLC_FAST")
170
174
  get :search, params: { q: 'my_query', vocab: 'OCLC_FAST', maximumRecords: '3' }
171
175
  expect(response.code).to eq('500')
@@ -179,6 +183,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
179
183
  .to_return(status: 503)
180
184
  end
181
185
  it 'returns 503' do
186
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
182
187
  expect(Rails.logger).to receive(:warn).with("Service Unavailable - Search query my_query unsuccessful for authority OCLC_FAST")
183
188
  get :search, params: { q: 'my_query', vocab: 'OCLC_FAST', maximumRecords: '3' }
184
189
  expect(response.code).to eq('503')
@@ -355,6 +360,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
355
360
  stub_request(:get, 'http://id.worldcat.org/fast/530369').to_return(status: 500)
356
361
  end
357
362
  it 'returns 500' do
363
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
358
364
  expect(Rails.logger).to receive(:warn).with("Internal Server Error - Fetch term 530369 unsuccessful for authority OCLC_FAST")
359
365
  get :show, params: { id: '530369', vocab: 'OCLC_FAST' }
360
366
  expect(response.code).to eq('500')
@@ -380,6 +386,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
380
386
  end
381
387
  it 'returns 500' do
382
388
  msg = "RDF Format Error - Results from fetch term 530369 for authority OCLC_FAST was not identified as a valid RDF format. You may need to include the linkeddata gem."
389
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
383
390
  expect(Rails.logger).to receive(:warn).with(msg)
384
391
  get :show, params: { id: '530369', vocab: 'OCLC_FAST' }
385
392
  expect(response.code).to eq('500')
@@ -391,6 +398,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
391
398
  stub_request(:get, 'http://id.worldcat.org/fast/530369').to_return(status: 501)
392
399
  end
393
400
  it 'returns 500' do
401
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
394
402
  expect(Rails.logger).to receive(:warn).with("Internal Server Error - Fetch term 530369 unsuccessful for authority OCLC_FAST")
395
403
  get :show, params: { id: '530369', vocab: 'OCLC_FAST' }
396
404
  expect(response.code).to eq('500')
@@ -403,6 +411,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
403
411
  stub_request(:get, 'http://id.worldcat.org/fast/530369').to_return(status: 503)
404
412
  end
405
413
  it 'returns 503' do
414
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
406
415
  expect(Rails.logger).to receive(:warn).with("Service Unavailable - Fetch term 530369 unsuccessful for authority OCLC_FAST")
407
416
  get :show, params: { id: '530369', vocab: 'OCLC_FAST' }
408
417
  expect(response.code).to eq('503')
@@ -414,6 +423,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
414
423
  stub_request(:get, 'http://id.worldcat.org/fast/FAKE_ID').to_return(status: 404, body: '', headers: {})
415
424
  end
416
425
  it 'returns 404' do
426
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
417
427
  expect(Rails.logger).to receive(:warn).with('Term Not Found - Fetch term FAKE_ID unsuccessful for authority OCLC_FAST')
418
428
  get :show, params: { id: 'FAKE_ID', vocab: 'OCLC_FAST' }
419
429
  expect(response.code).to eq('404')
@@ -566,6 +576,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
566
576
  stub_request(:get, 'http://localhost/test_default/term?uri=http://id.worldcat.org/fast/530369').to_return(status: 500)
567
577
  end
568
578
  it 'returns 500' do
579
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
569
580
  expect(Rails.logger).to receive(:warn).with("Internal Server Error - Fetch term http://id.worldcat.org/fast/530369 unsuccessful for authority LOD_TERM_URI_PARAM_CONFIG")
570
581
  get :fetch, params: { vocab: 'LOD_TERM_URI_PARAM_CONFIG', uri: 'http://id.worldcat.org/fast/530369' }
571
582
  expect(response.code).to eq('500')
@@ -580,6 +591,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
580
591
  it 'returns 500' do
581
592
  msg = "RDF Format Error - Results from fetch term http://id.worldcat.org/fast/530369 for authority LOD_TERM_URI_PARAM_CONFIG was not identified as a valid RDF format. " \
582
593
  "You may need to include the linkeddata gem."
594
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
583
595
  expect(Rails.logger).to receive(:warn).with(msg)
584
596
  get :fetch, params: { uri: 'http://id.worldcat.org/fast/530369', vocab: 'LOD_TERM_URI_PARAM_CONFIG' }
585
597
  expect(response.code).to eq('500')
@@ -591,6 +603,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
591
603
  stub_request(:get, 'http://localhost/test_default/term?uri=http://id.worldcat.org/fast/530369').to_return(status: 501)
592
604
  end
593
605
  it 'returns 500' do
606
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
594
607
  expect(Rails.logger).to receive(:warn).with("Internal Server Error - Fetch term http://id.worldcat.org/fast/530369 unsuccessful for authority LOD_TERM_URI_PARAM_CONFIG")
595
608
  get :fetch, params: { uri: 'http://id.worldcat.org/fast/530369', vocab: 'LOD_TERM_URI_PARAM_CONFIG' }
596
609
  expect(response.code).to eq('500')
@@ -603,6 +616,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
603
616
  stub_request(:get, 'http://localhost/test_default/term?uri=http://id.worldcat.org/fast/530369').to_return(status: 503)
604
617
  end
605
618
  it 'returns 503' do
619
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
606
620
  expect(Rails.logger).to receive(:warn).with("Service Unavailable - Fetch term http://id.worldcat.org/fast/530369 unsuccessful for authority LOD_TERM_URI_PARAM_CONFIG")
607
621
  get :fetch, params: { uri: 'http://id.worldcat.org/fast/530369', vocab: 'LOD_TERM_URI_PARAM_CONFIG' }
608
622
  expect(response.code).to eq('503')
@@ -614,6 +628,7 @@ describe Qa::LinkedDataTermsController, type: :controller do
614
628
  stub_request(:get, 'http://localhost/test_default/term?uri=http://test.org/FAKE_ID').to_return(status: 404, body: '', headers: {})
615
629
  end
616
630
  it 'returns 404' do
631
+ expect(Rails.logger).to receive(:warn).with(graph_load_failure)
617
632
  expect(Rails.logger).to receive(:warn).with('Term Not Found - Fetch term http://test.org/FAKE_ID unsuccessful for authority LOD_TERM_URI_PARAM_CONFIG')
618
633
  get :fetch, params: { uri: 'http://test.org/FAKE_ID', vocab: 'LOD_TERM_URI_PARAM_CONFIG' }
619
634
  expect(response.code).to eq('404')
@@ -2,8 +2,44 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe Qa::LinkedData::RequestHeaderService do
4
4
  let(:request) { double }
5
+ let(:request_id) { 'anID' }
6
+ let(:some_params) { double }
7
+ let(:location) { double }
8
+ let(:fake_ip) { '111.22.33.4444' }
9
+ let(:city) { 'Ithaca' }
10
+ let(:state) { 'New York' }
11
+ let(:country) { 'US' }
12
+ before do
13
+ allow(request).to receive(:request_id).and_return(request_id)
14
+ allow(request).to receive_message_chain(:path_parameters, :[]).with(:action).and_return('search') # rubocop:disable RSpec/MessageChain
15
+ allow(request).to receive(:location).and_return(location)
16
+ allow(request).to receive(:ip).and_return(fake_ip)
17
+ allow(location).to receive(:city).and_return(city)
18
+ allow(location).to receive(:state).and_return(state)
19
+ allow(location).to receive(:country).and_return(country)
20
+ end
21
+
22
+ describe '#initialize' do
23
+ context 'when Qa.config.suppress_ip_data_from_log is true' do
24
+ before { allow(Qa).to receive_message_chain(:config, :suppress_ip_data_from_log).and_return(true) } # rubocop:disable RSpec/MessageChain
25
+ it 'does not include IP info in log message' do
26
+ expect(Rails.logger).to receive(:info).with("******** SEARCH")
27
+ described_class.new(request: request, params: some_params)
28
+ end
29
+ end
30
+
31
+ context 'when Qa.config.suppress_ip_data_from_log is false' do
32
+ before { allow(Qa).to receive_message_chain(:config, :suppress_ip_data_from_log).and_return(false) } # rubocop:disable RSpec/MessageChain
33
+ it 'does include IP info in log message' do
34
+ expect(Rails.logger).to receive(:info).with("******** SEARCH from IP #{fake_ip} in {city: #{city}, state: #{state}, country: #{country}}")
35
+ described_class.new(request: request, params: some_params)
36
+ end
37
+ end
38
+ end
5
39
 
6
40
  describe '#search_header' do
41
+ let(:request_id) { 's1' }
42
+
7
43
  context 'when optional params are defined' do
8
44
  let(:search_params) do
9
45
  {
@@ -20,6 +56,8 @@ RSpec.describe Qa::LinkedData::RequestHeaderService do
20
56
  it 'uses passed in params' do
21
57
  expected_results =
22
58
  {
59
+ request: request,
60
+ request_id: request_id,
23
61
  context: true,
24
62
  performance_data: true,
25
63
  replacements: { 'maxRecords' => '4' },
@@ -37,6 +75,8 @@ RSpec.describe Qa::LinkedData::RequestHeaderService do
37
75
  it 'returns defaults' do
38
76
  expected_results =
39
77
  {
78
+ request: request,
79
+ request_id: request_id,
40
80
  context: false,
41
81
  performance_data: false,
42
82
  replacements: {},
@@ -53,6 +93,8 @@ RSpec.describe Qa::LinkedData::RequestHeaderService do
53
93
  it 'returns defaults with language set to request language' do
54
94
  expected_results =
55
95
  {
96
+ request: request,
97
+ request_id: request_id,
56
98
  context: false,
57
99
  performance_data: false,
58
100
  replacements: {},
@@ -67,6 +109,7 @@ RSpec.describe Qa::LinkedData::RequestHeaderService do
67
109
  end
68
110
 
69
111
  describe '#fetch_header' do
112
+ let(:request_id) { 'f1' }
70
113
  context 'when optional params are defined' do
71
114
  let(:fetch_params) do
72
115
  {
@@ -84,6 +127,8 @@ RSpec.describe Qa::LinkedData::RequestHeaderService do
84
127
  it 'uses passed in params' do
85
128
  expected_results =
86
129
  {
130
+ request: request,
131
+ request_id: request_id,
87
132
  format: 'n3',
88
133
  performance_data: true,
89
134
  replacements: { 'extra' => 'data', 'even' => 'more data' },
@@ -101,6 +146,8 @@ RSpec.describe Qa::LinkedData::RequestHeaderService do
101
146
  it 'returns defaults' do
102
147
  expected_results =
103
148
  {
149
+ request: request,
150
+ request_id: request_id,
104
151
  format: 'json',
105
152
  performance_data: false,
106
153
  replacements: {},
@@ -117,6 +164,8 @@ RSpec.describe Qa::LinkedData::RequestHeaderService do
117
164
  it 'returns defaults with language set to request language' do
118
165
  expected_results =
119
166
  {
167
+ request: request,
168
+ request_id: request_id,
120
169
  format: 'json',
121
170
  performance_data: false,
122
171
  replacements: {},
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qa
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.0
4
+ version: 5.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Anderson
@@ -16,7 +16,7 @@ authors:
16
16
  autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2019-12-03 00:00:00.000000000 Z
19
+ date: 2019-12-16 00:00:00.000000000 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: activerecord-import
@@ -60,6 +60,20 @@ dependencies:
60
60
  - - ">="
61
61
  - !ruby/object:Gem::Version
62
62
  version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: geocoder
65
+ requirement: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
63
77
  - !ruby/object:Gem::Dependency
64
78
  name: ldpath
65
79
  requirement: !ruby/object:Gem::Requirement