files.com 1.1.783 → 1.1.784
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 +4 -4
- data/_VERSION +1 -1
- data/lib/files.com/api_client.rb +37 -9
- data/lib/files.com/util.rb +31 -12
- data/lib/files.com/version.rb +1 -1
- data/spec/lib/api_client_spec.rb +58 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cd5e31f4e4c09fa7272e5c337ddc01c434546c93f177fe8fecd887839326f060
|
|
4
|
+
data.tar.gz: 143a0c464a2530296c1e67243d5f8d2e3640cff840c897ae2067517147af45b7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0d5eca777f0554ded3ad22b322bd8dcf959885c986c461a1d478c8097ffb00e2ee6d6741fd426cd36d0031796890f7d6ec7d0400f8c37072ae9079484a856fc7
|
|
7
|
+
data.tar.gz: f377e72e2cdb7e3f49391059d4c4c6115e506053cf7c371e6a0c2957018e701e8f3fd09ef8daeb099c498de22d8ce490826ea66cf596511bc43f8dd3f1fbaa89
|
data/_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.1.
|
|
1
|
+
1.1.784
|
data/lib/files.com/api_client.rb
CHANGED
|
@@ -8,8 +8,29 @@ module Files
|
|
|
8
8
|
QUERY_METHODS = %i[get head delete].freeze
|
|
9
9
|
private_constant :QUERY_METHODS
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
# The default for a logging option this client does not set itself.
|
|
12
|
+
USE_GLOBAL = Object.new.freeze
|
|
13
|
+
private_constant :USE_GLOBAL
|
|
14
|
+
|
|
15
|
+
# Creates a client that sends requests through +conn+, or through a new default connection when +conn+ is nil.
|
|
16
|
+
#
|
|
17
|
+
# By default the client logs its ordinary API requests, responses and errors through the library-wide Files.logger and
|
|
18
|
+
# Files.log_level, read as each message is logged. Pass either option to give this client its own setting
|
|
19
|
+
# instead, without changing the library-wide one or any other client:
|
|
20
|
+
#
|
|
21
|
+
# logger:: A Logger, or any object with the same +log+ method, that receives this client's ordinary API messages. Its own
|
|
22
|
+
# level decides which are written, and the client never changes it. Pass nil for no logger even when
|
|
23
|
+
# Files.logger is set.
|
|
24
|
+
# log_level:: Without a logger, the lowest level written to standard output and error: nil, Files::LEVEL_DEBUG,
|
|
25
|
+
# Files::LEVEL_INFO or Files::LEVEL_ERROR, or "debug" or "info", as Files.log_level= accepts. It
|
|
26
|
+
# is ignored when the client has a logger. Pass nil to write nothing there even when
|
|
27
|
+
# Files.log_level is set.
|
|
28
|
+
#
|
|
29
|
+
# A client created with logger: nil, log_level: nil logs no ordinary API messages.
|
|
30
|
+
def initialize(conn = nil, logger: USE_GLOBAL, log_level: USE_GLOBAL)
|
|
12
31
|
self.conn = conn || self.class.default_conn
|
|
32
|
+
@logger = logger
|
|
33
|
+
@log_level = log_level.equal?(USE_GLOBAL) ? log_level : Util.normalize_log_level(log_level)
|
|
13
34
|
@system_profiler = SystemProfiler.new
|
|
14
35
|
@last_request_metrics = nil
|
|
15
36
|
end
|
|
@@ -375,7 +396,7 @@ module Files
|
|
|
375
396
|
else
|
|
376
397
|
"The Files.com API returned an error without a message (HTTP response code was #{resp.http_status})"
|
|
377
398
|
end
|
|
378
|
-
Util.log_error("API error", status: resp.http_status, error_message: message)
|
|
399
|
+
Util.log_error("API error", { status: resp.http_status, error_message: message }, log_settings)
|
|
379
400
|
|
|
380
401
|
api_error_class(resp.data[:type]).new(message,
|
|
381
402
|
http_body: resp.http_body,
|
|
@@ -462,7 +483,7 @@ module Files
|
|
|
462
483
|
error.message.empty? ? error.response[:body] : error.message
|
|
463
484
|
end
|
|
464
485
|
|
|
465
|
-
Util.log_error("Network error", error_message: error_message)
|
|
486
|
+
Util.log_error("Network error", { error_message: error_message }, log_settings)
|
|
466
487
|
message = "Could not connect to Files.com at URL #{base_url}. Please check your internet connection and try again. If this problem persists, you should check Files.com's service status at https://status.files.com, or contact your primary account representative."
|
|
467
488
|
message += " Request was retried #{num_retries} times." if num_retries > 0
|
|
468
489
|
message += "\n\n(Network error: #{error_message})"
|
|
@@ -508,18 +529,25 @@ module Files
|
|
|
508
529
|
end
|
|
509
530
|
|
|
510
531
|
private def log_request(context, num_retries, no_body: false)
|
|
511
|
-
Util.log_info("Request", method: context.method, num_retries: num_retries, path: context.path)
|
|
512
|
-
Util.log_debug("Request details", body: context.body, query_params: context.query_params) unless no_body
|
|
532
|
+
Util.log_info("Request", { method: context.method, num_retries: num_retries, path: context.path }, log_settings)
|
|
533
|
+
Util.log_debug("Request details", { body: context.body, query_params: context.query_params }, log_settings) unless no_body
|
|
513
534
|
end
|
|
514
535
|
|
|
515
536
|
private def log_response(context, request_start, status, body, no_body: false)
|
|
516
|
-
Util.log_info("Response", elapsed: Time.now - request_start, method: context.method, path: context.path, status: status)
|
|
517
|
-
Util.log_debug("Response details", body: body) unless no_body
|
|
537
|
+
Util.log_info("Response", { elapsed: Time.now - request_start, method: context.method, path: context.path, status: status }, log_settings)
|
|
538
|
+
Util.log_debug("Response details", { body: body }, log_settings) unless no_body
|
|
518
539
|
end
|
|
519
540
|
|
|
520
541
|
private def log_response_error(context, request_start, error)
|
|
521
|
-
Util.log_error("Error", elapsed: Time.now - request_start, error_type: error.class, method: context.method, path: context.path)
|
|
522
|
-
Util.log_debug("Error details", error_message: error.message)
|
|
542
|
+
Util.log_error("Error", { elapsed: Time.now - request_start, error_type: error.class, method: context.method, path: context.path }, log_settings)
|
|
543
|
+
Util.log_debug("Error details", { error_message: error.message }, log_settings)
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
# This client's own logger and level where it set them, and the library-wide ones otherwise.
|
|
547
|
+
private def log_settings
|
|
548
|
+
Util::LogSettings.new(@logger.equal?(USE_GLOBAL) ? Files.logger : @logger,
|
|
549
|
+
@log_level.equal?(USE_GLOBAL) ? Files.log_level : @log_level
|
|
550
|
+
)
|
|
523
551
|
end
|
|
524
552
|
|
|
525
553
|
class RequestLogContext
|
data/lib/files.com/util.rb
CHANGED
|
@@ -34,29 +34,48 @@ module Files
|
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
# Where log messages go: to +logger+ when there is one, which then filters by its own level, and otherwise to
|
|
38
|
+
# standard output or error at +log_level+ and above. A nil +log_level+ without a logger logs nothing.
|
|
39
|
+
LogSettings = Struct.new(:logger, :log_level)
|
|
40
|
+
|
|
41
|
+
# The library-wide Files.logger and Files.log_level, read when each message is logged.
|
|
42
|
+
def self.global_log_settings
|
|
43
|
+
LogSettings.new(Files.logger, Files.log_level)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# The same values Files.log_level= accepts: nil, a level constant, or "debug" or "info".
|
|
47
|
+
def self.normalize_log_level(val)
|
|
48
|
+
val = { "debug" => LEVEL_DEBUG, "info" => LEVEL_INFO }.fetch(val, val)
|
|
49
|
+
if !val.nil? && ![ LEVEL_DEBUG, LEVEL_ERROR, LEVEL_INFO ].include?(val)
|
|
50
|
+
raise ArgumentError,
|
|
51
|
+
"log_level should only be set to `nil`, `debug` or `info`"
|
|
52
|
+
end
|
|
53
|
+
val
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.log_error(message, data = {}, settings = global_log_settings)
|
|
57
|
+
if !settings.logger.nil? ||
|
|
58
|
+
(!settings.log_level.nil? && settings.log_level <= Files::LEVEL_ERROR)
|
|
40
59
|
log_internal(message, data, color: :cyan, level: Files::LEVEL_ERROR,
|
|
41
|
-
logger:
|
|
60
|
+
logger: settings.logger, out: $stderr
|
|
42
61
|
)
|
|
43
62
|
end
|
|
44
63
|
end
|
|
45
64
|
|
|
46
|
-
def self.log_info(message, data = {})
|
|
47
|
-
if !
|
|
48
|
-
(!
|
|
65
|
+
def self.log_info(message, data = {}, settings = global_log_settings)
|
|
66
|
+
if !settings.logger.nil? ||
|
|
67
|
+
(!settings.log_level.nil? && settings.log_level <= Files::LEVEL_INFO)
|
|
49
68
|
log_internal(message, data, color: :cyan, level: Files::LEVEL_INFO,
|
|
50
|
-
logger:
|
|
69
|
+
logger: settings.logger, out: $stdout
|
|
51
70
|
)
|
|
52
71
|
end
|
|
53
72
|
end
|
|
54
73
|
|
|
55
|
-
def self.log_debug(message, data = {})
|
|
56
|
-
if !
|
|
57
|
-
(!
|
|
74
|
+
def self.log_debug(message, data = {}, settings = global_log_settings)
|
|
75
|
+
if !settings.logger.nil? ||
|
|
76
|
+
(!settings.log_level.nil? && settings.log_level <= Files::LEVEL_DEBUG)
|
|
58
77
|
log_internal(message, data, color: :blue, level: Files::LEVEL_DEBUG,
|
|
59
|
-
logger:
|
|
78
|
+
logger: settings.logger, out: $stdout
|
|
60
79
|
)
|
|
61
80
|
end
|
|
62
81
|
end
|
data/lib/files.com/version.rb
CHANGED
data/spec/lib/api_client_spec.rb
CHANGED
|
@@ -344,6 +344,64 @@ RSpec.describe Files::ApiClient do
|
|
|
344
344
|
end
|
|
345
345
|
end
|
|
346
346
|
|
|
347
|
+
describe "client loggers" do
|
|
348
|
+
around do |example|
|
|
349
|
+
original = [ Files.logger, Files.log_level, Files.max_network_retries ]
|
|
350
|
+
Files.max_network_retries = 0
|
|
351
|
+
example.run
|
|
352
|
+
ensure
|
|
353
|
+
Files.logger, Files.log_level, Files.max_network_retries = original
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
it "logs each client's requests to its own logger without changing the library-wide settings" do
|
|
357
|
+
connection = Faraday.new do |builder|
|
|
358
|
+
builder.response :raise_error
|
|
359
|
+
builder.adapter :test do |stub|
|
|
360
|
+
(1..5).each do |id|
|
|
361
|
+
stub.get("/api/rest/v1/workspaces/#{id}") { [ 200, { "Content-Type" => "application/json" }, { id: id }.to_json ] }
|
|
362
|
+
end
|
|
363
|
+
stub.get("/api/rest/v1/workspaces/6") { [ 404, { "Content-Type" => "application/json" }, { error: "Not Found", type: "not-found" }.to_json ] }
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
global_output = StringIO.new
|
|
367
|
+
global_logger = Logger.new(global_output, level: Logger::INFO)
|
|
368
|
+
Files.logger = global_logger
|
|
369
|
+
Files.log_level = Files::LEVEL_INFO
|
|
370
|
+
a_output = StringIO.new
|
|
371
|
+
a_logger = Logger.new(a_output, level: Logger::INFO)
|
|
372
|
+
b_output = StringIO.new
|
|
373
|
+
b_logger = Logger.new(b_output, level: Logger::ERROR)
|
|
374
|
+
client_a = described_class.new(connection, logger: a_logger)
|
|
375
|
+
client_b = described_class.new(connection, logger: b_logger, log_level: Files::LEVEL_DEBUG)
|
|
376
|
+
|
|
377
|
+
Files::Workspace.find(1, {}, api_key: "key", client: client_a)
|
|
378
|
+
Files::Workspace.find(2, {}, api_key: "key", client: client_b)
|
|
379
|
+
Files::Workspace.find(3, {}, api_key: "key", client: client_a)
|
|
380
|
+
|
|
381
|
+
expect(a_output.string).to include("message=Request method=get num_retries=0 path=/workspaces/1", "message=Request method=get num_retries=0 path=/workspaces/3")
|
|
382
|
+
expect(a_output.string.scan(/message=Response .*status=200/).size).to eq(2)
|
|
383
|
+
expect(a_output.string).not_to include("/workspaces/2")
|
|
384
|
+
expect(b_output.string).to be_empty
|
|
385
|
+
expect(global_output.string).to be_empty
|
|
386
|
+
expect([ a_logger.level, b_logger.level ]).to eq([ Logger::INFO, Logger::ERROR ])
|
|
387
|
+
expect(Files.logger).to equal(global_logger)
|
|
388
|
+
expect(Files.log_level).to eq(Files::LEVEL_INFO)
|
|
389
|
+
|
|
390
|
+
expect { Files::Workspace.find(6, {}, api_key: "key", client: client_b) }.to raise_error(Files::NotFoundError)
|
|
391
|
+
expect(b_output.string).to include("message=API error status=404")
|
|
392
|
+
expect(a_output.string).not_to include("API error")
|
|
393
|
+
expect(global_output.string).to be_empty
|
|
394
|
+
expect([ a_logger.level, b_logger.level ]).to eq([ Logger::INFO, Logger::ERROR ])
|
|
395
|
+
|
|
396
|
+
Files::Workspace.find(4, {}, api_key: "key", client: described_class.new(connection))
|
|
397
|
+
expect(global_output.string).to include("message=Request method=get num_retries=0 path=/workspaces/4")
|
|
398
|
+
|
|
399
|
+
quiet_client = described_class.new(connection, logger: nil, log_level: nil)
|
|
400
|
+
expect { Files::Workspace.find(5, {}, api_key: "key", client: quiet_client) }.not_to output.to_stdout
|
|
401
|
+
expect(global_output.string).not_to include("/workspaces/5")
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
347
405
|
describe "network timeouts" do
|
|
348
406
|
around do |example|
|
|
349
407
|
original = [ Files.open_timeout, Files.read_timeout ]
|