Module: LaunchDarkly::Impl::Util Private

Defined in:
lib/ldclient-rb/impl/util.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Since:

  • 5.5.0

Constant Summary collapse

TIMEOUT_MAX =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The longest wait to pass to Concurrent::Event#wait, in seconds. A wait above about 1e19 seconds raises RangeError. About 31 years is the same in practice as honoring a longer wait.

Since:

  • 5.5.0

1_000_000_000

Class Method Summary collapse

Class Method Details

.add_payload_filter_key(uri, config) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Append the payload filter key query parameter to the provided URI.

Parameters:

  • uri (String)
  • config (Config)

Returns:

  • (String)

Since:

  • 5.5.0



122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/ldclient-rb/impl/util.rb', line 122

def self.add_payload_filter_key(uri, config)
  return uri if config.payload_filter_key.nil?

  begin
    parsed = URI.parse(uri)
    new_query_params = URI.decode_www_form(String(parsed.query)) << ["filter", config.payload_filter_key]
    parsed.query = URI.encode_www_form(new_query_params)
    parsed.to_s
  rescue URI::InvalidURIError
    config.logger.warn { "[LDClient] URI could not be parsed. No filtering will be applied." }
    uri
  end
end

.application_header_value(application) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generate an HTTP Header value containing the application meta information (@see #application).

Returns:

  • (String)

Since:

  • 5.5.0



51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/ldclient-rb/impl/util.rb', line 51

def self.application_header_value(application)
  parts = []
  unless  application[:id].empty?
    parts << "application-id/#{application[:id]}"
  end

  unless  application[:version].empty?
    parts << "application-version/#{application[:version]}"
  end

  parts.join(" ")
end

.bool?(aObject) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)

Since:

  • 5.5.0



11
12
13
# File 'lib/ldclient-rb/impl/util.rb', line 11

def self.bool?(aObject)
   [true,false].include? aObject
end

.classify_http_status(status) ⇒ Symbol

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Classifies an HTTP error status.

400, 408, 429 and every status outside the 4xx range are normal. Every other 4xx, including 401 and 403, is unexpected.

Parameters:

  • status (Integer)

Returns:

  • (Symbol) —

    :normal or :unexpected

Since:

  • 5.5.0



182
183
184
185
186
187
188
# File 'lib/ldclient-rb/impl/util.rb', line 182

def self.classify_http_status(status)
  if status >= 400 && status < 500 && !NORMAL_4XX_STATUSES.include?(status)
    :unexpected
  else
    :normal
  end
end

.current_time_millis ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 5.5.0



15
16
17
# File 'lib/ldclient-rb/impl/util.rb', line 15

def self.current_time_millis
  (Time.now.to_f * 1000).to_i
end

.default_http_headers(sdk_key, config) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 5.5.0



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/ldclient-rb/impl/util.rb', line 30

def self.default_http_headers(sdk_key, config)
  ret = { "Authorization" => sdk_key, "User-Agent" => "RubyClient/" + LaunchDarkly::VERSION }

  ret["X-LaunchDarkly-Instance-Id"] = config.instance_id unless config.instance_id.nil?

  if config.wrapper_name
    ret["X-LaunchDarkly-Wrapper"] = config.wrapper_name +
      (config.wrapper_version ? "/" + config.wrapper_version : "")
  end

  app_value = application_header_value config.application
  ret["X-LaunchDarkly-Tags"] = app_value unless app_value.nil? || app_value.empty?

  ret
end

.failure_log_level(kind) ⇒ Symbol

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the log level for a failure of this kind.

Parameters:

  • kind (Symbol) —

    :normal or :unexpected

Returns:

  • (Symbol) —

    the log level for a failure of this kind

Since:

  • 5.5.0



224
225
226
# File 'lib/ldclient-rb/impl/util.rb', line 224

def self.failure_log_level(kind)
  kind == :unexpected ? :error : :warn
end

.http_error_description(status, context) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • status (Integer)
  • context (String) —

    what failed, such as "polling request"

Returns:

  • (String)

Since:

  • 5.5.0



205
206
207
208
# File 'lib/ldclient-rb/impl/util.rb', line 205

def self.http_error_description(status, context)
  desc = (status == 401 || status == 403) ? " (invalid SDK key)" : ""
  "HTTP error #{status}#{desc} for #{context}"
end

.http_error_message(status, context, recoverable_message) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 5.5.0



194
195
196
197
198
# File 'lib/ldclient-rb/impl/util.rb', line 194

def self.http_error_message(status, context, recoverable_message)
  desc = (status == 401 || status == 403) ? " (invalid SDK key)" : ""
  message = http_error_recoverable?(status) ? recoverable_message : "giving up permanently"
  "HTTP error #{status}#{desc} for #{context} - #{message}"
end

.http_error_recoverable?(status) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)

Since:

  • 5.5.0



190
191
192
# File 'lib/ldclient-rb/impl/util.rb', line 190

def self.http_error_recoverable?(status)
  classify_http_status(status) == :normal
end

.http_error_retry_message(status, context, delay) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • status (Integer)
  • context (String) —

    what failed, such as "polling request"

  • delay (Numeric) —

    seconds until the next attempt

Returns:

  • (String)

Since:

  • 5.5.0



216
217
218
# File 'lib/ldclient-rb/impl/util.rb', line 216

def self.http_error_retry_message(status, context, delay)
  "#{http_error_description(status, context)} - #{retry_message(delay)}"
end

.log_exception(logger, message, exc) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 5.5.0



164
165
166
167
# File 'lib/ldclient-rb/impl/util.rb', line 164

def self.log_exception(logger, message, exc)
  logger.error { "[LDClient] #{message}: #{exc.inspect}" }
  logger.debug { "[LDClient] Exception trace: #{exc.backtrace}" }
end

.monotonic_seconds ⇒ Float

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Seconds on the monotonic clock. Use this for measuring intervals and durations; use the wall clock only for values reported outside the process.

Returns:

  • (Float)

Since:

  • 5.5.0



26
27
28
# File 'lib/ldclient-rb/impl/util.rb', line 26

def self.monotonic_seconds
  Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
end

.new_http_client(http_config) ⇒ HTTP::Client

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creates a new persistent HTTP client with the given configuration.

Parameters:

  • http_config (LaunchDarkly::Impl::DataSystem::HttpConfigOptions) —

    HTTP connection settings

Returns:

  • (HTTP::Client)

Since:

  • 5.5.0



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/ldclient-rb/impl/util.rb', line 142

def self.new_http_client(http_config)
  http_client_options = {}
  if http_config.socket_factory
    http_client_options[:socket_class] = http_config.socket_factory
  end
  proxy = URI.parse(http_config.base_uri).find_proxy
  unless proxy.nil?
    http_client_options[:proxy] = {
      proxy_address: proxy.host,
      proxy_port: proxy.port,
      proxy_username: proxy.user,
      proxy_password: proxy.password,
    }
  end
  HTTP::Client.new(**http_client_options)
    .timeout(
      read: http_config.read_timeout,
      connect: http_config.connect_timeout
    )
    .persistent(http_config.base_uri)
end

.retry_message(delay) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • delay (Numeric) —

    seconds until the next attempt

Returns:

  • (String)

Since:

  • 5.5.0



232
233
234
# File 'lib/ldclient-rb/impl/util.rb', line 232

def self.retry_message(delay)
  format("will retry in %.1fs", delay)
end

.validate_application_info(app, logger) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • app (Hash)
  • logger (Logger)

Returns:

  • (Hash)

Since:

  • 5.5.0



93
94
95
96
97
98
# File 'lib/ldclient-rb/impl/util.rb', line 93

def self.validate_application_info(app, logger)
  {
    id: validate_application_value(app[:id], :id, logger),
    version: validate_application_value(app[:version], :version, logger),
  }
end

.validate_application_value(value, name, logger) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • value (String)
  • name (Symbol)
  • logger (Logger)

Returns:

  • (String)

Since:

  • 5.5.0



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/ldclient-rb/impl/util.rb', line 70

def self.validate_application_value(value, name, logger)
  value = value.to_s

  return "" if value.empty?

  if value.length > 64
    logger.warn { "Value of application[#{name}] was longer than 64 characters and was discarded" }
    return ""
  end

  if /[^a-zA-Z0-9._-]/.match?(value)
    logger.warn { "Value of application[#{name}] contained invalid characters and was discarded" }
    return ""
  end

  value
end

.validate_payload_filter_key(value, logger) ⇒ String?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • value (String, nil)
  • logger (Logger)

Returns:

  • (String, nil)

Since:

  • 5.5.0



105
106
107
108
109
110
111
112
113
# File 'lib/ldclient-rb/impl/util.rb', line 105

def self.validate_payload_filter_key(value, logger)
  return nil if value.nil?
  return value if value.is_a?(String) && /^[a-zA-Z0-9][._\-a-zA-Z0-9]*$/.match?(value)

  logger.warn {
    "Invalid payload filter configured, full environment will be fetched. Ensure the filter key is not empty and was copied correctly from LaunchDarkly settings."
  }
  nil
end