appsignal 5.0.1-java → 5.0.3-java
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 +20 -0
- data/README.md +1 -1
- data/lib/appsignal/config.rb +5 -7
- data/lib/appsignal/opentelemetry/process_resource.rb +137 -0
- data/lib/appsignal/opentelemetry.rb +5 -1
- data/lib/appsignal/version.rb +1 -1
- data/sig/appsignal.rbi +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f511b69fdbdeb226062bbaf05e00fe52eb3bd20854c3eeb202edba0b815b1db5
|
|
4
|
+
data.tar.gz: e1261b245afbc044c149b030ba2b4f4656c7d56f56e37223006ed21a68d1a8be
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a18f025051286fc68ff81d27cdc6d4d2fd91b71f79e3d439a9d957e39c98350c9dd46fc7626738c8dfddd13908f13884f9be13155475dedfc8e2844e10f44021
|
|
7
|
+
data.tar.gz: eb8047d550aaa8afd456483ef40db0d188ba492215e582b6f7ddc5c73b6d7e1d957c39bf0183e2b2d5fa1dbd5531a5064d66ac874a1112193feddf9d90f1cd94
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# AppSignal for Ruby gem Changelog
|
|
2
2
|
|
|
3
|
+
## 5.0.3
|
|
4
|
+
|
|
5
|
+
_Published on 2026-10-08._
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- In collector mode, report counter metrics correctly from processes forked after AppSignal starts, such as Puma workers when using `preload_app!`. Before this change, applications running several forked processes would lose data points or report incorrect values for them. (patch [4e5a3e78](https://github.com/appsignal/appsignal-ruby/commit/4e5a3e781b4ce2b2620b172a15198a2a59e0ebee))
|
|
10
|
+
|
|
11
|
+
## 5.0.2
|
|
12
|
+
|
|
13
|
+
_Published on 2026-10-06._
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Use the revision set by Heroku, Render, Kamal or Scalingo when the application also has a `REVISION` file. Since version 4.6.0, a `REVISION` file took precedence over the `HEROKU_SLUG_COMMIT`, `RENDER_GIT_COMMIT`, `KAMAL_VERSION` and `CONTAINER_VERSION` environment variables, so an application that kept a placeholder `REVISION` file in source control reported that placeholder as its revision. The `revision` config option and the `APP_REVISION` environment variable still take precedence over both.
|
|
18
|
+
|
|
19
|
+
Thanks to @rmm5t for their contribution!
|
|
20
|
+
|
|
21
|
+
(patch [bc14ef9c](https://github.com/appsignal/appsignal-ruby/commit/bc14ef9c6db3de71bf2ca8f23ad088f29294c0ff))
|
|
22
|
+
|
|
3
23
|
## 5.0.1
|
|
4
24
|
|
|
5
25
|
_Published on 2026-10-02._
|
data/README.md
CHANGED
|
@@ -318,7 +318,7 @@ Also see our [SUPPORT.md file](SUPPORT.md).
|
|
|
318
318
|
[custom-instrumentation]: https://docs.appsignal.com/ruby/instrumentation.html
|
|
319
319
|
[front-end-monitoring]: https://docs.appsignal.com/front-end.html
|
|
320
320
|
[exception-handling]: https://docs.appsignal.com/ruby/instrumentation/exception-handling.html
|
|
321
|
-
[tagging]: https://docs.appsignal.com/guides/
|
|
321
|
+
[tagging]: https://docs.appsignal.com/guides/tagging#ruby
|
|
322
322
|
[host-metrics]: https://docs.appsignal.com/metrics/host.html
|
|
323
323
|
[custom-metrics]: https://docs.appsignal.com/metrics/custom.html
|
|
324
324
|
|
data/lib/appsignal/config.rb
CHANGED
|
@@ -177,9 +177,7 @@ module Appsignal
|
|
|
177
177
|
}.freeze
|
|
178
178
|
|
|
179
179
|
# Environment variables set by deployment platforms that name the
|
|
180
|
-
# revision that is being deployed, in the order
|
|
181
|
-
# The agent detects the revision this way as well, but only for the data
|
|
182
|
-
# it sends itself, so the gem has to do it for collector mode.
|
|
180
|
+
# revision that is being deployed, in the order they are read.
|
|
183
181
|
# @!visibility private
|
|
184
182
|
PLATFORM_REVISION_ENV_VARS = [
|
|
185
183
|
"HEROKU_SLUG_COMMIT",
|
|
@@ -812,10 +810,10 @@ module Appsignal
|
|
|
812
810
|
|
|
813
811
|
hash[:enable_at_exit_hook] = "always" if Appsignal::Extension.running_in_container?
|
|
814
812
|
|
|
815
|
-
# Set the revision from
|
|
816
|
-
#
|
|
817
|
-
#
|
|
818
|
-
revision =
|
|
813
|
+
# Set the revision from the environment variable the deployment
|
|
814
|
+
# platform sets, or from a REVISION file in the project root, which
|
|
815
|
+
# helps with Capistrano and Hatchbox.io deployments.
|
|
816
|
+
revision = detect_revision_from_platform || detect_revision_from_file
|
|
819
817
|
hash[:revision] = revision if revision
|
|
820
818
|
|
|
821
819
|
hostname = detect_hostname
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "securerandom"
|
|
4
|
+
|
|
5
|
+
module Appsignal
|
|
6
|
+
module OpenTelemetry
|
|
7
|
+
# @!visibility private
|
|
8
|
+
#
|
|
9
|
+
# The resource attributes that identify the current process:
|
|
10
|
+
# `service.instance.id` and `process.pid`. The OpenTelemetry providers are
|
|
11
|
+
# built once, so a process forked after that inherits its parent's values
|
|
12
|
+
# until {.attach_fork_hook} refreshes them in the child.
|
|
13
|
+
module ProcessResource
|
|
14
|
+
SERVICE_INSTANCE_ID = "service.instance.id"
|
|
15
|
+
PROCESS_PID = "process.pid"
|
|
16
|
+
REFRESH_FAILED = "Could not refresh the OpenTelemetry resource after fork"
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
# A random UUIDv4, generated again when the process ID changes.
|
|
20
|
+
def service_instance_id
|
|
21
|
+
pid = Process.pid
|
|
22
|
+
unless @service_instance_id_pid == pid
|
|
23
|
+
@service_instance_id = SecureRandom.uuid
|
|
24
|
+
@service_instance_id_pid = pid
|
|
25
|
+
end
|
|
26
|
+
@service_instance_id
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def resource
|
|
30
|
+
::OpenTelemetry::SDK::Resources::Resource.create(
|
|
31
|
+
SERVICE_INSTANCE_ID => service_instance_id,
|
|
32
|
+
PROCESS_PID => Process.pid
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def attach_fork_hook
|
|
37
|
+
return if @fork_hook_attached
|
|
38
|
+
|
|
39
|
+
Process.singleton_class.prepend(ForkHook)
|
|
40
|
+
@fork_hook_attached = true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def before_fork
|
|
44
|
+
return unless Appsignal::OpenTelemetry.started?
|
|
45
|
+
|
|
46
|
+
providers.transform_values do |provider|
|
|
47
|
+
current = current_resource(provider)
|
|
48
|
+
current && attribute(current, SERVICE_INSTANCE_ID)
|
|
49
|
+
end
|
|
50
|
+
rescue => e
|
|
51
|
+
log_failure("#{e.class}: #{e.message}")
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def after_fork(instance_ids_before_fork)
|
|
56
|
+
return unless instance_ids_before_fork
|
|
57
|
+
|
|
58
|
+
update = resource
|
|
59
|
+
providers.each do |name, provider|
|
|
60
|
+
refresh(name, provider, update, instance_ids_before_fork[name])
|
|
61
|
+
end
|
|
62
|
+
rescue => e
|
|
63
|
+
log_failure("#{e.class}: #{e.message}")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def providers
|
|
69
|
+
{
|
|
70
|
+
"tracer" => ::OpenTelemetry.tracer_provider,
|
|
71
|
+
"meter" => ::OpenTelemetry.meter_provider,
|
|
72
|
+
"logger" => ::OpenTelemetry.logger_provider
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def refresh(name, provider, update, instance_id_before_fork)
|
|
77
|
+
current = current_resource(provider)
|
|
78
|
+
unless current
|
|
79
|
+
log_failure("the #{name} provider's resource could not be read")
|
|
80
|
+
return
|
|
81
|
+
end
|
|
82
|
+
return unless attribute(current, SERVICE_INSTANCE_ID) == instance_id_before_fork
|
|
83
|
+
|
|
84
|
+
refreshed = current.merge(update)
|
|
85
|
+
write_resource(provider, refreshed)
|
|
86
|
+
return if current_resource(provider).equal?(refreshed)
|
|
87
|
+
|
|
88
|
+
log_failure("the #{name} provider did not keep the new resource")
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# The SDK providers take their resource only in their constructors, and
|
|
92
|
+
# read it from `@resource` when they export.
|
|
93
|
+
def current_resource(provider)
|
|
94
|
+
if provider.respond_to?(:resource)
|
|
95
|
+
resource = provider.resource
|
|
96
|
+
unless provider.respond_to?(:resource=)
|
|
97
|
+
# Without a setter, only `@resource` can be written, and it isn't there.
|
|
98
|
+
return unless provider.instance_variable_defined?(:@resource)
|
|
99
|
+
# The reader returns something else, so writing `@resource` would change nothing.
|
|
100
|
+
return unless provider.instance_variable_get(:@resource).equal?(resource)
|
|
101
|
+
end
|
|
102
|
+
elsif provider.instance_variable_defined?(:@resource)
|
|
103
|
+
resource = provider.instance_variable_get(:@resource)
|
|
104
|
+
end
|
|
105
|
+
# If it's not a resource, it isn't what the provider exports.
|
|
106
|
+
resource if resource.is_a?(::OpenTelemetry::SDK::Resources::Resource)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def write_resource(provider, resource)
|
|
110
|
+
if provider.respond_to?(:resource=)
|
|
111
|
+
provider.resource = resource
|
|
112
|
+
else
|
|
113
|
+
provider.instance_variable_set(:@resource, resource)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def attribute(resource, key)
|
|
118
|
+
resource.attribute_enumerator.each { |k, v| return v if k == key }
|
|
119
|
+
nil
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def log_failure(reason)
|
|
123
|
+
Appsignal.internal_logger.warn("#{REFRESH_FAILED}: #{reason}")
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
module ForkHook
|
|
128
|
+
def _fork
|
|
129
|
+
instance_ids = ProcessResource.before_fork
|
|
130
|
+
pid = super
|
|
131
|
+
ProcessResource.after_fork(instance_ids) if pid.zero?
|
|
132
|
+
pid
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -8,6 +8,7 @@ require "appsignal/opentelemetry/http_method"
|
|
|
8
8
|
require "appsignal/opentelemetry/http_response"
|
|
9
9
|
require "appsignal/opentelemetry/http_server_request"
|
|
10
10
|
require "appsignal/opentelemetry/messaging"
|
|
11
|
+
require "appsignal/opentelemetry/process_resource"
|
|
11
12
|
require "appsignal/opentelemetry/proxied_exporter"
|
|
12
13
|
require "appsignal/opentelemetry/rendering"
|
|
13
14
|
require "appsignal/opentelemetry/sql_db_system"
|
|
@@ -59,7 +60,9 @@ module Appsignal
|
|
|
59
60
|
# `LoggerProvider` take a `resource:` kwarg that replaces (not
|
|
60
61
|
# merges), so we do the merge ourselves and use the same merged
|
|
61
62
|
# resource for the tracer provider to keep all three in sync.
|
|
62
|
-
resource =
|
|
63
|
+
resource = ProcessResource.resource
|
|
64
|
+
.merge(::OpenTelemetry::SDK::Resources::Resource.default)
|
|
65
|
+
.merge(build_resource(config))
|
|
63
66
|
|
|
64
67
|
span_exporter = build_exporter(
|
|
65
68
|
::OpenTelemetry::Exporter::OTLP::Exporter,
|
|
@@ -103,6 +106,7 @@ module Appsignal
|
|
|
103
106
|
)
|
|
104
107
|
|
|
105
108
|
@started = true
|
|
109
|
+
ProcessResource.attach_fork_hook
|
|
106
110
|
rescue LoadError => e
|
|
107
111
|
@started = false
|
|
108
112
|
Appsignal::Utils::StdoutAndLoggerMessage.error(
|
data/lib/appsignal/version.rb
CHANGED
data/sig/appsignal.rbi
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: appsignal
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.0.
|
|
4
|
+
version: 5.0.3
|
|
5
5
|
platform: java
|
|
6
6
|
authors:
|
|
7
7
|
- Robert Beekman
|
|
@@ -306,6 +306,7 @@ files:
|
|
|
306
306
|
- lib/appsignal/opentelemetry/http_response.rb
|
|
307
307
|
- lib/appsignal/opentelemetry/http_server_request.rb
|
|
308
308
|
- lib/appsignal/opentelemetry/messaging.rb
|
|
309
|
+
- lib/appsignal/opentelemetry/process_resource.rb
|
|
309
310
|
- lib/appsignal/opentelemetry/proxied_exporter.rb
|
|
310
311
|
- lib/appsignal/opentelemetry/rendering.rb
|
|
311
312
|
- lib/appsignal/opentelemetry/sql_db_system.rb
|