chronos-ruby 1.1.3 → 1.2.0.pre.1
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/CHANGELOG.md +9 -26
- data/README.md +14 -13
- data/docs/adr/ADR-010-opentelemetry-interoperability.md +3 -3
- data/docs/compatibility.md +10 -16
- data/docs/configuration.md +7 -3
- data/docs/modules/context.md +1 -1
- data/docs/modules/external-http.md +3 -2
- data/docs/modules/rails-legacy.md +2 -2
- data/docs/modules/sidekiq-legacy.md +3 -3
- data/docs/troubleshooting.md +1 -1
- data/lib/chronos/adapters/fiber_local_context_store.rb +57 -0
- data/lib/chronos/agent.rb +7 -1
- data/lib/chronos/configuration/apm_validation.rb +2 -0
- data/lib/chronos/configuration/snapshot.rb +2 -2
- data/lib/chronos/configuration/validation.rb +2 -2
- data/lib/chronos/configuration.rb +5 -3
- data/lib/chronos/core/trace_context.rb +38 -0
- data/lib/chronos/integrations/active_job.rb +2 -2
- data/lib/chronos/integrations/faraday.rb +76 -0
- data/lib/chronos/integrations/net_http.rb +5 -1
- data/lib/chronos/integrations/opentelemetry.rb +44 -0
- data/lib/chronos/integrations/rack/middleware.rb +8 -2
- data/lib/chronos/integrations/sidekiq.rb +1 -1
- data/lib/chronos/rails/error_reporter_subscriber.rb +39 -0
- data/lib/chronos/rails/installer.rb +8 -14
- data/lib/chronos/rails/notifications_subscriber.rb +12 -0
- data/lib/chronos/rails.rb +2 -13
- data/lib/chronos/version.rb +2 -2
- data/lib/chronos.rb +4 -0
- data/lib/generators/chronos/install/templates/chronos.rb +10 -52
- metadata +42 -44
- data/docs/release-1.1.2-readiness.md +0 -21
- data/docs/release-1.1.3-readiness.md +0 -22
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Chronos
|
|
2
|
+
module Integrations
|
|
3
|
+
# Optional Faraday middleware for outbound timing and W3C propagation.
|
|
4
|
+
# @responsibility Instrument one explicit Faraday connection without global patches.
|
|
5
|
+
# @motivation Modern Rails applications commonly use Faraday for outbound HTTP.
|
|
6
|
+
# @limits It never reads paths, queries, headers other than trace fields, or bodies.
|
|
7
|
+
# @collaborators Faraday middleware stack, TraceContext, and Chronos facade.
|
|
8
|
+
# @thread_safety Calls retain request state in local variables.
|
|
9
|
+
# @compatibility Faraday 1.x and 2.x middleware contracts.
|
|
10
|
+
# @example builder.use Chronos::Integrations::FaradayMiddleware
|
|
11
|
+
# @errors Original client exceptions are recorded by class and re-raised.
|
|
12
|
+
# @performance Two clock reads and one bounded asynchronous event per request.
|
|
13
|
+
class FaradayMiddleware
|
|
14
|
+
def initialize(app, options = {})
|
|
15
|
+
@app = app
|
|
16
|
+
@notifier = options[:notifier] || Chronos
|
|
17
|
+
@clock = options[:clock] || proc { Process.clock_gettime(Process::CLOCK_MONOTONIC) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def call(environment)
|
|
21
|
+
started_at = @clock.call
|
|
22
|
+
inject_headers(environment)
|
|
23
|
+
response = @app.call(environment)
|
|
24
|
+
if response.respond_to?(:on_complete)
|
|
25
|
+
response.on_complete { |completed| record(completed, started_at, nil) }
|
|
26
|
+
else
|
|
27
|
+
record(environment, started_at, nil)
|
|
28
|
+
end
|
|
29
|
+
response
|
|
30
|
+
rescue StandardError => error
|
|
31
|
+
record(environment, started_at, error) if started_at
|
|
32
|
+
raise
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def inject_headers(environment)
|
|
38
|
+
options = integration_options
|
|
39
|
+
return unless options[:trace_headers] && environment.respond_to?(:request_headers)
|
|
40
|
+
|
|
41
|
+
context = @notifier.respond_to?(:propagation_context) ? @notifier.propagation_context : {}
|
|
42
|
+
headers = environment.request_headers
|
|
43
|
+
traceparent = Core::TraceContext.format(context) if options[:w3c_trace_context]
|
|
44
|
+
headers["traceparent"] ||= traceparent if traceparent
|
|
45
|
+
headers["X-Chronos-Trace-ID"] ||= context["trace_id"] if context["trace_id"]
|
|
46
|
+
headers["X-Chronos-Request-ID"] ||= context["request_id"] if context["request_id"]
|
|
47
|
+
rescue StandardError
|
|
48
|
+
nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def record(environment, started_at, error)
|
|
52
|
+
url = environment.url if environment.respond_to?(:url)
|
|
53
|
+
payload = {
|
|
54
|
+
"host" => (url.host.to_s if url && url.respond_to?(:host)),
|
|
55
|
+
"method" => (environment.method.to_s.upcase if environment.respond_to?(:method)),
|
|
56
|
+
"status" => (environment.status.to_i if environment.respond_to?(:status) && environment.status),
|
|
57
|
+
"duration_ms" => ((@clock.call - started_at) * 1000.0).round(3),
|
|
58
|
+
"error_class" => (error.class.name.to_s if error)
|
|
59
|
+
}
|
|
60
|
+
payload.delete_if { |_key, value| value.nil? || value == "" }
|
|
61
|
+
@notifier.record_event("external_http", payload)
|
|
62
|
+
rescue StandardError
|
|
63
|
+
false
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def integration_options
|
|
67
|
+
return {:enabled => true, :trace_headers => true, :w3c_trace_context => false} unless
|
|
68
|
+
@notifier.respond_to?(:external_http_integration_options)
|
|
69
|
+
|
|
70
|
+
@notifier.external_http_integration_options
|
|
71
|
+
rescue StandardError
|
|
72
|
+
{:enabled => false, :trace_headers => false, :w3c_trace_context => false}
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -53,7 +53,8 @@ module Chronos
|
|
|
53
53
|
{
|
|
54
54
|
:notifier => notifier,
|
|
55
55
|
:clock => options[:clock] || proc { monotonic_time },
|
|
56
|
-
:trace_headers => configured.fetch(:trace_headers, true)
|
|
56
|
+
:trace_headers => configured.fetch(:trace_headers, true),
|
|
57
|
+
:w3c_trace_context => configured.fetch(:w3c_trace_context, false)
|
|
57
58
|
}
|
|
58
59
|
end
|
|
59
60
|
|
|
@@ -106,6 +107,9 @@ module Chronos
|
|
|
106
107
|
end
|
|
107
108
|
set_header(request, "X-Chronos-Trace-ID", context["trace_id"] || context[:trace_id])
|
|
108
109
|
set_header(request, "X-Chronos-Request-ID", context["request_id"] || context[:request_id])
|
|
110
|
+
if options[:w3c_trace_context]
|
|
111
|
+
set_header(request, "traceparent", Core::TraceContext.format(context))
|
|
112
|
+
end
|
|
109
113
|
rescue StandardError
|
|
110
114
|
nil
|
|
111
115
|
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Chronos
|
|
2
|
+
module Integrations
|
|
3
|
+
# Optional, dependency-free bridge to an already configured OpenTelemetry SDK.
|
|
4
|
+
module OpenTelemetry
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def current_context
|
|
8
|
+
return {} unless defined?(::OpenTelemetry::Trace) && ::OpenTelemetry::Trace.respond_to?(:current_span)
|
|
9
|
+
|
|
10
|
+
span = ::OpenTelemetry::Trace.current_span
|
|
11
|
+
context = span.context if span && span.respond_to?(:context)
|
|
12
|
+
return {} unless context && (!context.respond_to?(:valid?) || context.valid?)
|
|
13
|
+
|
|
14
|
+
trace_id = hex_identifier(context, :hex_trace_id, :trace_id, 32)
|
|
15
|
+
span_id = hex_identifier(context, :hex_span_id, :span_id, 16)
|
|
16
|
+
return {} if trace_id.empty? || span_id.empty?
|
|
17
|
+
|
|
18
|
+
{"trace_id" => trace_id, "span_id" => span_id,
|
|
19
|
+
"trace_flags" => sampled?(context) ? "01" : "00", "source" => "opentelemetry"}
|
|
20
|
+
rescue StandardError
|
|
21
|
+
{}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def active?
|
|
25
|
+
!current_context.empty?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def hex_identifier(context, hex_method, numeric_method, width)
|
|
29
|
+
value = context.public_send(hex_method) if context.respond_to?(hex_method)
|
|
30
|
+
value ||= context.public_send(numeric_method).to_i.to_s(16) if context.respond_to?(numeric_method)
|
|
31
|
+
value.to_s.downcase.rjust(width, "0")[-width, width]
|
|
32
|
+
rescue StandardError
|
|
33
|
+
""
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def sampled?(context)
|
|
37
|
+
flags = context.trace_flags if context.respond_to?(:trace_flags)
|
|
38
|
+
flags.respond_to?(:sampled?) ? flags.sampled? : flags.to_i.odd?
|
|
39
|
+
rescue StandardError
|
|
40
|
+
false
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -62,7 +62,7 @@ module Chronos
|
|
|
62
62
|
def request_capture_context(env)
|
|
63
63
|
request = request_values(env)
|
|
64
64
|
{
|
|
65
|
-
:context =>
|
|
65
|
+
:context => trace_context(env).merge("request" => request),
|
|
66
66
|
:parameters => parameters(env),
|
|
67
67
|
:user => hash_value(env["chronos.user"])
|
|
68
68
|
}
|
|
@@ -124,7 +124,13 @@ module Chronos
|
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
def trace_id(env)
|
|
127
|
-
env["
|
|
127
|
+
trace_context(env)["trace_id"]
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def trace_context(env)
|
|
131
|
+
parsed = Core::TraceContext.parse(env["HTTP_TRACEPARENT"])
|
|
132
|
+
parsed["trace_id"] = env["chronos.trace_id"] || SecureRandom.hex(16) if parsed.empty?
|
|
133
|
+
parsed
|
|
128
134
|
end
|
|
129
135
|
|
|
130
136
|
def response_size(headers)
|
|
@@ -110,7 +110,7 @@ module Chronos
|
|
|
110
110
|
source = @notifier.propagation_context
|
|
111
111
|
return {} unless source.is_a?(Hash)
|
|
112
112
|
|
|
113
|
-
%w(trace_id request_id).each_with_object({}) do |key, result|
|
|
113
|
+
%w(trace_id span_id trace_flags request_id).each_with_object({}) do |key, result|
|
|
114
114
|
value = source[key] || source[key.to_sym]
|
|
115
115
|
result[key] = value.to_s unless value.to_s.empty?
|
|
116
116
|
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Chronos
|
|
2
|
+
module Rails
|
|
3
|
+
# Sends exceptions observed by the Rails 7 error reporter to Chronos once.
|
|
4
|
+
# @responsibility Translate the public Rails reporter callback into one notice.
|
|
5
|
+
# @motivation Rails can report handled errors that never reach Rack middleware.
|
|
6
|
+
# @limits Only handled, severity, source, and one bounded component are retained.
|
|
7
|
+
# @collaborators ActiveSupport::ErrorReporter and Chronos facade.
|
|
8
|
+
# @thread_safety Instances contain only an immutable notifier reference.
|
|
9
|
+
# @compatibility Rails 7 public error reporter subscriber API.
|
|
10
|
+
# @example Rails.error.subscribe(ErrorReporterSubscriber.new)
|
|
11
|
+
# @errors Agent and context failures are contained and return false.
|
|
12
|
+
# @performance Allocates one small allowlisted metadata hash per report.
|
|
13
|
+
class ErrorReporterSubscriber
|
|
14
|
+
def initialize(notifier = Chronos)
|
|
15
|
+
@notifier = notifier
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def report(error, handled:, severity:, context:, source: nil)
|
|
19
|
+
details = {
|
|
20
|
+
:context => {"rails_error_reporter" => {
|
|
21
|
+
"handled" => handled == true, "severity" => severity.to_s, "source" => source.to_s
|
|
22
|
+
}}
|
|
23
|
+
}
|
|
24
|
+
details[:context]["rails_error_reporter"]["component"] = component(context)
|
|
25
|
+
@notifier.notify_once(error, details)
|
|
26
|
+
rescue StandardError
|
|
27
|
+
false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def component(context)
|
|
33
|
+
return "" unless context.is_a?(Hash)
|
|
34
|
+
|
|
35
|
+
(context[:controller] || context["controller"] || context[:job] || context["job"]).to_s[0, 128]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -34,7 +34,7 @@ module Chronos
|
|
|
34
34
|
|
|
35
35
|
install_middleware(application, options)
|
|
36
36
|
install_active_job
|
|
37
|
-
|
|
37
|
+
install_error_reporter
|
|
38
38
|
@subscriber.install
|
|
39
39
|
self.class.applications[application.object_id] = true
|
|
40
40
|
end
|
|
@@ -66,24 +66,18 @@ module Chronos
|
|
|
66
66
|
Chronos::Integrations::ActiveJob.install(::ActiveJob::Base, @notifier)
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
def
|
|
70
|
-
|
|
71
|
-
return false unless library
|
|
69
|
+
def install_error_reporter
|
|
70
|
+
return false unless defined?(::Rails) && ::Rails.respond_to?(:error)
|
|
72
71
|
|
|
73
|
-
|
|
72
|
+
reporter = ::Rails.error
|
|
73
|
+
return false unless reporter && reporter.respond_to?(:subscribe)
|
|
74
|
+
|
|
75
|
+
reporter.subscribe(ErrorReporterSubscriber.new(@notifier))
|
|
76
|
+
true
|
|
74
77
|
rescue StandardError
|
|
75
78
|
false
|
|
76
79
|
end
|
|
77
80
|
|
|
78
|
-
def sidekiq_library
|
|
79
|
-
return ::Sidekiq if defined?(::Sidekiq)
|
|
80
|
-
|
|
81
|
-
require "sidekiq"
|
|
82
|
-
::Sidekiq if defined?(::Sidekiq)
|
|
83
|
-
rescue LoadError
|
|
84
|
-
nil
|
|
85
|
-
end
|
|
86
|
-
|
|
87
81
|
def environment
|
|
88
82
|
defined?(::Rails) && ::Rails.respond_to?(:env) ? ::Rails.env.to_s : nil
|
|
89
83
|
end
|
|
@@ -17,6 +17,7 @@ module Chronos
|
|
|
17
17
|
process_action.action_controller render_template.action_view sql.active_record
|
|
18
18
|
deliver.action_mailer perform.active_job cache_read.active_support
|
|
19
19
|
cache_write.active_support cache_fetch_hit.active_support
|
|
20
|
+
perform_action.action_cable transmit.action_cable broadcast.action_cable
|
|
20
21
|
).freeze
|
|
21
22
|
|
|
22
23
|
@mutex = Mutex.new
|
|
@@ -105,6 +106,8 @@ module Chronos
|
|
|
105
106
|
when "sql.active_record" then sql(payload, duration)
|
|
106
107
|
when "deliver.action_mailer" then mailer(payload, duration)
|
|
107
108
|
when "perform.active_job" then active_job(payload, duration)
|
|
109
|
+
when "perform_action.action_cable", "transmit.action_cable", "broadcast.action_cable"
|
|
110
|
+
action_cable(name, payload, duration)
|
|
108
111
|
else cache(name, payload, duration)
|
|
109
112
|
end
|
|
110
113
|
end
|
|
@@ -345,6 +348,15 @@ module Chronos
|
|
|
345
348
|
@notifier.record_event("cache", data)
|
|
346
349
|
end
|
|
347
350
|
|
|
351
|
+
def action_cable(name, payload, duration)
|
|
352
|
+
data = {
|
|
353
|
+
"kind" => "action_cable", "operation" => name.split(".").first,
|
|
354
|
+
"channel" => safe_class_name(value(payload, :channel)),
|
|
355
|
+
"action" => value(payload, :action).to_s[0, 128], "duration_ms" => duration
|
|
356
|
+
}
|
|
357
|
+
@notifier.record_event("request", data)
|
|
358
|
+
end
|
|
359
|
+
|
|
348
360
|
def capture_controller_exception(payload)
|
|
349
361
|
exception = value(payload, :exception_object)
|
|
350
362
|
details = value(payload, :exception)
|
data/lib/chronos/rails.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
require "chronos"
|
|
2
2
|
require "chronos/rails/active_record_query_inspector"
|
|
3
3
|
require "chronos/rails/notifications_subscriber"
|
|
4
|
+
require "chronos/rails/error_reporter_subscriber"
|
|
4
5
|
require "chronos/integrations/active_job"
|
|
5
|
-
require "chronos/integrations/sidekiq"
|
|
6
6
|
require "chronos/rails/installer"
|
|
7
7
|
|
|
8
8
|
require "chronos/rails/railtie" if defined?(::Rails::Railtie)
|
|
@@ -15,16 +15,5 @@ module Chronos
|
|
|
15
15
|
# @limits Version 0.5 targets public APIs present in Rails 4.2 and 5.2.
|
|
16
16
|
# @thread_safety Installation and subscriptions are protected against duplication.
|
|
17
17
|
# @compatibility Rails 4.2 through Rails 5.2 with their supported legacy Rubies.
|
|
18
|
-
module Rails
|
|
19
|
-
class << self
|
|
20
|
-
# Returns the namespace that owns the Rails application class.
|
|
21
|
-
def application_name(application = ::Rails.application)
|
|
22
|
-
class_name = application.class.name.to_s
|
|
23
|
-
name = class_name.sub(/::Application\z/, "")
|
|
24
|
-
name.empty? || name == class_name ? nil : name
|
|
25
|
-
rescue StandardError
|
|
26
|
-
nil
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
18
|
+
module Rails; end
|
|
30
19
|
end
|
data/lib/chronos/version.rb
CHANGED
data/lib/chronos.rb
CHANGED
|
@@ -16,6 +16,7 @@ require "chronos/core/sensitive_value_filter"
|
|
|
16
16
|
require "chronos/core/sanitizer"
|
|
17
17
|
require "chronos/core/safe_serializer"
|
|
18
18
|
require "chronos/core/correlation_context"
|
|
19
|
+
require "chronos/core/trace_context"
|
|
19
20
|
require "chronos/core/deploy_normalizer"
|
|
20
21
|
require "chronos/core/payload_serializer"
|
|
21
22
|
require "chronos/core/telemetry_event"
|
|
@@ -32,6 +33,7 @@ require "chronos/internal/memory_backlog"
|
|
|
32
33
|
require "chronos/internal/worker_pool"
|
|
33
34
|
require "chronos/adapters/net_http_transport"
|
|
34
35
|
require "chronos/adapters/thread_local_context_store"
|
|
36
|
+
require "chronos/adapters/fiber_local_context_store"
|
|
35
37
|
require "chronos/core/breadcrumb"
|
|
36
38
|
require "chronos/application/retry_policy"
|
|
37
39
|
require "chronos/application/circuit_breaker"
|
|
@@ -49,6 +51,8 @@ require "chronos/observability_facade"
|
|
|
49
51
|
require "chronos/integrations"
|
|
50
52
|
require "chronos/integrations/rack"
|
|
51
53
|
require "chronos/integrations/rack/middleware"
|
|
54
|
+
require "chronos/integrations/opentelemetry"
|
|
55
|
+
require "chronos/integrations/faraday"
|
|
52
56
|
|
|
53
57
|
# Framework-independent public facade for the Chronos Ruby agent.
|
|
54
58
|
#
|
|
@@ -1,62 +1,20 @@
|
|
|
1
1
|
require "chronos/rails"
|
|
2
2
|
|
|
3
|
-
# Common Chronos settings. Every environment variable is optional unless your
|
|
4
|
-
# Chronos project requires it; omitted values fall back to safe SDK defaults.
|
|
5
|
-
env_boolean = lambda do |name, default|
|
|
6
|
-
normalized = ENV[name].to_s.downcase
|
|
7
|
-
next true if %w(1 true yes on).include?(normalized)
|
|
8
|
-
next false if %w(0 false no off).include?(normalized)
|
|
9
|
-
|
|
10
|
-
default
|
|
11
|
-
end
|
|
12
|
-
|
|
13
3
|
Chronos.configure do |config|
|
|
14
|
-
#
|
|
4
|
+
# Chronos reads only the environment variables explicitly selected here.
|
|
15
5
|
config.project_id = ENV["CHRONOS_PROJECT_ID"]
|
|
16
6
|
config.project_key = ENV["CHRONOS_PROJECT_KEY"]
|
|
17
|
-
config.
|
|
18
|
-
config.
|
|
7
|
+
config.host = ENV["CHRONOS_HOST"]
|
|
8
|
+
config.environment = Rails.env.to_s
|
|
9
|
+
config.service_name = ENV["CHRONOS_SERVICE_NAME"]
|
|
19
10
|
config.app_version = ENV["CHRONOS_APP_VERSION"]
|
|
20
|
-
config.
|
|
21
|
-
|
|
22
|
-
# General behavior and transport
|
|
23
|
-
config.enabled = env_boolean.call("CHRONOS_ENABLED", true)
|
|
24
|
-
config.error_notifications = env_boolean.call("CHRONOS_ERROR_NOTIFICATIONS", true)
|
|
25
|
-
config.ssl_verify = env_boolean.call("CHRONOS_SSL_VERIFY", true)
|
|
26
|
-
config.timeout = ENV.fetch("CHRONOS_TIMEOUT", "5").to_f
|
|
27
|
-
config.open_timeout = ENV.fetch("CHRONOS_OPEN_TIMEOUT", "2").to_f
|
|
28
|
-
config.queue_size = ENV.fetch("CHRONOS_QUEUE_SIZE", "100").to_i
|
|
29
|
-
config.workers = ENV.fetch("CHRONOS_WORKERS", "1").to_i
|
|
30
|
-
config.sampling_rate = ENV.fetch("CHRONOS_SAMPLING_RATE", "1.0").to_f
|
|
31
|
-
config.ignored_environments = ENV.fetch("CHRONOS_IGNORED_ENVIRONMENTS", "")
|
|
32
|
-
.split(",").map(&:strip).reject(&:empty?)
|
|
33
|
-
|
|
34
|
-
# Rails integration and privacy
|
|
35
|
-
config.root_directory = Rails.root.to_s
|
|
36
|
-
config.rails_enabled = env_boolean.call("CHRONOS_RAILS_ENABLED", true)
|
|
37
|
-
config.rails_capture_in_console = env_boolean.call("CHRONOS_RAILS_CAPTURE_IN_CONSOLE", false)
|
|
38
|
-
config.rails_capture_in_test = env_boolean.call("CHRONOS_RAILS_CAPTURE_IN_TEST", false)
|
|
39
|
-
config.anonymize_ip = env_boolean.call("CHRONOS_ANONYMIZE_IP", true)
|
|
40
|
-
|
|
41
|
-
# Application performance monitoring
|
|
42
|
-
config.apm_enabled = env_boolean.call("CHRONOS_APM_ENABLED", true)
|
|
43
|
-
config.apm_slow_query_threshold_ms = ENV.fetch(
|
|
44
|
-
"CHRONOS_APM_SLOW_QUERY_THRESHOLD_MS", "500"
|
|
45
|
-
).to_f
|
|
46
|
-
config.apm_long_transaction_threshold_ms = ENV.fetch(
|
|
47
|
-
"CHRONOS_APM_LONG_TRANSACTION_THRESHOLD_MS", "1000"
|
|
48
|
-
).to_f
|
|
49
|
-
config.apm_n_plus_one_threshold = ENV.fetch("CHRONOS_APM_N_PLUS_ONE_THRESHOLD", "5").to_i
|
|
50
|
-
config.external_http_enabled = env_boolean.call("CHRONOS_EXTERNAL_HTTP_ENABLED", false)
|
|
11
|
+
config.logger = Rails.logger if Rails.respond_to?(:logger)
|
|
51
12
|
|
|
52
|
-
#
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# Chronos safely continues without an application logger.
|
|
57
|
-
nil
|
|
58
|
-
end
|
|
13
|
+
# Safe legacy defaults: test and console integrations remain disabled.
|
|
14
|
+
config.rails_capture_in_test = false
|
|
15
|
+
config.rails_capture_in_console = false
|
|
16
|
+
config.rails_capture_user_agent = false
|
|
59
17
|
end
|
|
60
18
|
|
|
61
|
-
#
|
|
19
|
+
# Safe when the Railtie already ran or will run later; installation is idempotent.
|
|
62
20
|
Chronos::Rails::Installer.new.install(Rails.application)
|
metadata
CHANGED
|
@@ -1,96 +1,91 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: chronos-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1
|
|
4
|
+
version: 1.2.0.pre.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Antonio Jefferson
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '1
|
|
19
|
+
version: '2.1'
|
|
20
|
+
- - "<"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: '3'
|
|
20
23
|
type: :development
|
|
21
24
|
prerelease: false
|
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
26
|
requirements:
|
|
24
|
-
- - "
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '2.1'
|
|
30
|
+
- - "<"
|
|
25
31
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
32
|
+
version: '3'
|
|
27
33
|
- !ruby/object:Gem::Dependency
|
|
28
34
|
name: rake
|
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
|
30
36
|
requirements:
|
|
31
|
-
- - "
|
|
37
|
+
- - ">="
|
|
32
38
|
- !ruby/object:Gem::Version
|
|
33
39
|
version: '12.3'
|
|
34
|
-
- - "
|
|
40
|
+
- - "<"
|
|
35
41
|
- !ruby/object:Gem::Version
|
|
36
|
-
version:
|
|
42
|
+
version: '14'
|
|
37
43
|
type: :development
|
|
38
44
|
prerelease: false
|
|
39
45
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
46
|
requirements:
|
|
41
|
-
- - "
|
|
47
|
+
- - ">="
|
|
42
48
|
- !ruby/object:Gem::Version
|
|
43
49
|
version: '12.3'
|
|
44
|
-
- - "
|
|
50
|
+
- - "<"
|
|
45
51
|
- !ruby/object:Gem::Version
|
|
46
|
-
version:
|
|
52
|
+
version: '14'
|
|
47
53
|
- !ruby/object:Gem::Dependency
|
|
48
54
|
name: rspec
|
|
49
55
|
requirement: !ruby/object:Gem::Requirement
|
|
50
56
|
requirements:
|
|
51
|
-
- - "
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '3.10'
|
|
60
|
+
- - "<"
|
|
52
61
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '
|
|
62
|
+
version: '4'
|
|
54
63
|
type: :development
|
|
55
64
|
prerelease: false
|
|
56
65
|
version_requirements: !ruby/object:Gem::Requirement
|
|
57
66
|
requirements:
|
|
58
|
-
- - "
|
|
67
|
+
- - ">="
|
|
59
68
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '3.
|
|
69
|
+
version: '3.10'
|
|
70
|
+
- - "<"
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '4'
|
|
61
73
|
- !ruby/object:Gem::Dependency
|
|
62
74
|
name: rubocop
|
|
63
75
|
requirement: !ruby/object:Gem::Requirement
|
|
64
76
|
requirements:
|
|
65
77
|
- - "~>"
|
|
66
78
|
- !ruby/object:Gem::Version
|
|
67
|
-
version:
|
|
79
|
+
version: 1.57.0
|
|
68
80
|
type: :development
|
|
69
81
|
prerelease: false
|
|
70
82
|
version_requirements: !ruby/object:Gem::Requirement
|
|
71
83
|
requirements:
|
|
72
84
|
- - "~>"
|
|
73
85
|
- !ruby/object:Gem::Version
|
|
74
|
-
version:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
requirement: !ruby/object:Gem::Requirement
|
|
78
|
-
requirements:
|
|
79
|
-
- - '='
|
|
80
|
-
- !ruby/object:Gem::Version
|
|
81
|
-
version: 1.19.2
|
|
82
|
-
type: :development
|
|
83
|
-
prerelease: false
|
|
84
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
85
|
-
requirements:
|
|
86
|
-
- - '='
|
|
87
|
-
- !ruby/object:Gem::Version
|
|
88
|
-
version: 1.19.2
|
|
89
|
-
description: Cliente oficial do Chronos para capturar e enviar exceções, métricas
|
|
90
|
-
e dados de telemetria de aplicações Ruby e Rails. A gem centraliza sinais de observabilidade
|
|
91
|
-
para facilitar o monitoramento, a análise de desempenho e o diagnóstico de falhas
|
|
92
|
-
no Chronos Monitor. Conheça a plataforma oficial de recebimento e visualização dos
|
|
93
|
-
dados em https://chronosmonitor.com.br.
|
|
86
|
+
version: 1.57.0
|
|
87
|
+
description: Cliente Chronos para excecoes, telemetria e observabilidade em aplicacoes
|
|
88
|
+
Ruby e Rails.
|
|
94
89
|
email:
|
|
95
90
|
- antoniojeferson96@gmail.com
|
|
96
91
|
executables: []
|
|
@@ -169,13 +164,12 @@ files:
|
|
|
169
164
|
- docs/protocol-v1.md
|
|
170
165
|
- docs/release-1.0-readiness.md
|
|
171
166
|
- docs/release-1.1-readiness.md
|
|
172
|
-
- docs/release-1.1.2-readiness.md
|
|
173
|
-
- docs/release-1.1.3-readiness.md
|
|
174
167
|
- docs/security-review.md
|
|
175
168
|
- docs/semver.md
|
|
176
169
|
- docs/troubleshooting.md
|
|
177
170
|
- lib/chronos.rb
|
|
178
171
|
- lib/chronos/adapters.rb
|
|
172
|
+
- lib/chronos/adapters/fiber_local_context_store.rb
|
|
179
173
|
- lib/chronos/adapters/net_http_transport.rb
|
|
180
174
|
- lib/chronos/adapters/thread_local_context_store.rb
|
|
181
175
|
- lib/chronos/agent.rb
|
|
@@ -215,12 +209,15 @@ files:
|
|
|
215
209
|
- lib/chronos/core/sql_normalizer.rb
|
|
216
210
|
- lib/chronos/core/sql_query_analyzer.rb
|
|
217
211
|
- lib/chronos/core/telemetry_event.rb
|
|
212
|
+
- lib/chronos/core/trace_context.rb
|
|
218
213
|
- lib/chronos/errors.rb
|
|
219
214
|
- lib/chronos/integrations.rb
|
|
220
215
|
- lib/chronos/integrations/active_job.rb
|
|
221
216
|
- lib/chronos/integrations/capistrano.rb
|
|
217
|
+
- lib/chronos/integrations/faraday.rb
|
|
222
218
|
- lib/chronos/integrations/job_payload.rb
|
|
223
219
|
- lib/chronos/integrations/net_http.rb
|
|
220
|
+
- lib/chronos/integrations/opentelemetry.rb
|
|
224
221
|
- lib/chronos/integrations/rack.rb
|
|
225
222
|
- lib/chronos/integrations/rack/middleware.rb
|
|
226
223
|
- lib/chronos/integrations/sidekiq.rb
|
|
@@ -237,6 +234,7 @@ files:
|
|
|
237
234
|
- lib/chronos/ports/transport.rb
|
|
238
235
|
- lib/chronos/rails.rb
|
|
239
236
|
- lib/chronos/rails/active_record_query_inspector.rb
|
|
237
|
+
- lib/chronos/rails/error_reporter_subscriber.rb
|
|
240
238
|
- lib/chronos/rails/installer.rb
|
|
241
239
|
- lib/chronos/rails/notifications_subscriber.rb
|
|
242
240
|
- lib/chronos/rails/railtie.rb
|
|
@@ -263,18 +261,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
263
261
|
requirements:
|
|
264
262
|
- - ">="
|
|
265
263
|
- !ruby/object:Gem::Version
|
|
266
|
-
version: 2.
|
|
264
|
+
version: '2.7'
|
|
267
265
|
- - "<"
|
|
268
266
|
- !ruby/object:Gem::Version
|
|
269
|
-
version: '
|
|
267
|
+
version: '3.5'
|
|
270
268
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
271
269
|
requirements:
|
|
272
|
-
- - "
|
|
270
|
+
- - ">"
|
|
273
271
|
- !ruby/object:Gem::Version
|
|
274
|
-
version:
|
|
272
|
+
version: 1.3.1
|
|
275
273
|
requirements: []
|
|
276
274
|
rubygems_version: 3.4.22
|
|
277
275
|
signing_key:
|
|
278
276
|
specification_version: 4
|
|
279
|
-
summary:
|
|
277
|
+
summary: Cliente Ruby para captura de eventos do Chronos
|
|
280
278
|
test_files: []
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Version 1.1.2 release evidence
|
|
2
|
-
|
|
3
|
-
Version `1.1.2` is a backward-compatible maintenance release of the stable legacy line. It simplifies the generated Rails initializer, keeps the official host internal, derives a default Rails service name, preserves application ownership of the logger, and automatically installs the existing optional Sidekiq 4/5 middleware in Rails applications.
|
|
4
|
-
|
|
5
|
-
The release preserves Ruby 2.2.10–2.6.10, Rails 4.2/5.2, Sidekiq 4.2.10/5.2.10, and protocol `schema_version: "1.0"`. It introduces no mandatory framework dependency and no transitional 1.2-only API.
|
|
6
|
-
|
|
7
|
-
## Required gates
|
|
8
|
-
|
|
9
|
-
- complete unit, integration, contract, privacy, concurrency, transport, and lint suite on Ruby 2.2.10–2.6.10;
|
|
10
|
-
- real Rails 4.2 applications on Ruby 2.2.10/2.3.8 and Rails 5.2 applications on Ruby 2.5.9/2.6.10;
|
|
11
|
-
- real Sidekiq 4.2.10 and 5.2.10 client/server middleware smoke tests;
|
|
12
|
-
- generated initializer boot, service-name fallback, logger mutability, optional Sidekiq installation, and idempotency tests;
|
|
13
|
-
- documentation verification, repeatable benchmarks, and the bounded fake-endpoint privacy/load gate;
|
|
14
|
-
- gem build, package inspection, SHA-256 checksum, SPDX SBOM, and RubyGems Trusted Publishing.
|
|
15
|
-
|
|
16
|
-
The release tag must be exactly `v1.1.2` and match `Chronos::VERSION`. Do not publish manually. After the reviewed commit and all gates are green:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
git tag v1.1.2
|
|
20
|
-
git push origin v1.1.2
|
|
21
|
-
```
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Version 1.1.3 release evidence
|
|
2
|
-
|
|
3
|
-
Version `1.1.3` is a backward-compatible documentation and package-metadata maintenance release of the stable legacy line. It clarifies that the gem captures exceptions, metrics, and telemetry from Ruby and Rails applications and identifies https://chronosmonitor.com.br as the official Chronos Monitor platform for receiving and visualizing those observability signals.
|
|
4
|
-
|
|
5
|
-
The release preserves Ruby 2.2.10–2.6.10, Rails 4.2/5.2, Sidekiq 4.2.10/5.2.10, and protocol `schema_version: "1.0"`. It changes no runtime behavior, public API, collected field, framework dependency, or compatibility claim.
|
|
6
|
-
|
|
7
|
-
## Required gates
|
|
8
|
-
|
|
9
|
-
- complete unit, integration, contract, privacy, concurrency, transport, and lint suite on Ruby 2.2.10–2.6.10;
|
|
10
|
-
- real Rails 4.2 applications on Ruby 2.2.10/2.3.8 and Rails 5.2 applications on Ruby 2.5.9/2.6.10;
|
|
11
|
-
- real Sidekiq 4.2.10 and 5.2.10 client/server middleware smoke tests;
|
|
12
|
-
- documentation and pull request description verification;
|
|
13
|
-
- dependency audit with the CI-pinned tooling;
|
|
14
|
-
- repeatable query-analysis and Rack benchmarks plus the bounded fake-endpoint privacy/load gate;
|
|
15
|
-
- gem build, package inspection, SHA-256 checksum, SPDX SBOM, and RubyGems Trusted Publishing.
|
|
16
|
-
|
|
17
|
-
The release tag must be exactly `v1.1.3` and match `Chronos::VERSION`. Do not publish manually. After the reviewed commit and all gates are green:
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
git tag v1.1.3
|
|
21
|
-
git push origin v1.1.3
|
|
22
|
-
```
|