appsignal 4.10.4-java → 5.0.0-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 +108 -0
- data/Rakefile +195 -4
- data/appsignal.gemspec +8 -0
- data/build_matrix.yml +12 -0
- data/ext/appsignal_extension.c +14 -0
- data/lib/appsignal/backends.rb +55 -0
- data/lib/appsignal/cli/diagnose.rb +2 -10
- data/lib/appsignal/config.rb +377 -13
- data/lib/appsignal/demo.rb +12 -10
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +34 -22
- data/lib/appsignal/event_formatter/active_job/perform_formatter.rb +35 -0
- data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +19 -0
- data/lib/appsignal/event_formatter/elastic_search/search_formatter.rb +27 -0
- data/lib/appsignal/event_formatter/recorded_elsewhere.rb +17 -0
- data/lib/appsignal/event_formatter/rom/sql_formatter.rb +24 -0
- data/lib/appsignal/event_formatter/sequel/sql_formatter.rb +5 -0
- data/lib/appsignal/event_formatter/view_component/render_formatter.rb +21 -10
- data/lib/appsignal/event_formatter.rb +78 -0
- data/lib/appsignal/extension.rb +4 -0
- data/lib/appsignal/helpers/instrumentation.rb +324 -20
- data/lib/appsignal/helpers/metrics.rb +3 -24
- data/lib/appsignal/hooks/action_cable.rb +26 -8
- data/lib/appsignal/hooks/active_job.rb +184 -47
- data/lib/appsignal/hooks/at_exit.rb +4 -1
- data/lib/appsignal/hooks/excon.rb +20 -0
- data/lib/appsignal/hooks/faraday.rb +16 -0
- data/lib/appsignal/hooks/http.rb +5 -0
- data/lib/appsignal/hooks/resque.rb +1 -1
- data/lib/appsignal/hooks/sequel.rb +32 -2
- data/lib/appsignal/hooks/shoryuken.rb +3 -3
- data/lib/appsignal/hooks/sidekiq.rb +1 -1
- data/lib/appsignal/integrations/action_cable.rb +5 -2
- data/lib/appsignal/integrations/active_support_notifications.rb +59 -19
- data/lib/appsignal/integrations/data_mapper.rb +14 -2
- data/lib/appsignal/integrations/delayed_job_plugin.rb +81 -8
- data/lib/appsignal/integrations/dry_monitor.rb +39 -15
- data/lib/appsignal/integrations/excon/appsignal_middleware.rb +21 -0
- data/lib/appsignal/integrations/excon.rb +52 -15
- data/lib/appsignal/integrations/faraday.rb +47 -12
- data/lib/appsignal/integrations/http.rb +43 -1
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +73 -4
- data/lib/appsignal/integrations/net_http.rb +31 -2
- data/lib/appsignal/integrations/puma.rb +4 -1
- data/lib/appsignal/integrations/que.rb +256 -37
- data/lib/appsignal/integrations/railtie.rb +4 -1
- data/lib/appsignal/integrations/rake.rb +9 -3
- data/lib/appsignal/integrations/redis.rb +22 -1
- data/lib/appsignal/integrations/redis_client.rb +22 -1
- data/lib/appsignal/integrations/resque.rb +81 -11
- data/lib/appsignal/integrations/shoryuken.rb +159 -12
- data/lib/appsignal/integrations/sidekiq.rb +94 -16
- data/lib/appsignal/integrations/webmachine.rb +56 -5
- data/lib/appsignal/loaders/padrino.rb +2 -1
- data/lib/appsignal/logger/extension_backend.rb +24 -0
- data/lib/appsignal/logger/opentelemetry_backend.rb +66 -0
- data/lib/appsignal/logger.rb +13 -9
- data/lib/appsignal/metrics/extension_backend.rb +47 -0
- data/lib/appsignal/metrics/opentelemetry_backend.rb +89 -0
- data/lib/appsignal/opentelemetry/attributes.rb +31 -0
- data/lib/appsignal/opentelemetry/dependencies.rb +35 -0
- data/lib/appsignal/opentelemetry/error_type.rb +37 -0
- data/lib/appsignal/opentelemetry/http_client_request.rb +83 -0
- data/lib/appsignal/opentelemetry/http_method.rb +59 -0
- data/lib/appsignal/opentelemetry/http_response.rb +30 -0
- data/lib/appsignal/opentelemetry/http_server_request.rb +79 -0
- data/lib/appsignal/opentelemetry/messaging.rb +82 -0
- data/lib/appsignal/opentelemetry/proxied_exporter.rb +83 -0
- data/lib/appsignal/opentelemetry/rendering.rb +29 -0
- data/lib/appsignal/opentelemetry/sql_db_system.rb +89 -0
- data/lib/appsignal/opentelemetry.rb +495 -0
- data/lib/appsignal/rack/abstract_middleware.rb +66 -4
- data/lib/appsignal/rack/body_wrapper.rb +18 -5
- data/lib/appsignal/rack/event_handler.rb +44 -4
- data/lib/appsignal/rack/grape_middleware.rb +1 -0
- data/lib/appsignal/rack/hanami_middleware.rb +2 -1
- data/lib/appsignal/rack/instrumentation_middleware.rb +1 -0
- data/lib/appsignal/rack/rails_instrumentation.rb +1 -0
- data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -0
- data/lib/appsignal/rack.rb +68 -12
- data/lib/appsignal/sample_data.rb +4 -0
- data/lib/appsignal/transaction/base_backend.rb +128 -0
- data/lib/appsignal/transaction/extension_backend.rb +229 -0
- data/lib/appsignal/transaction/opentelemetry_backend.rb +847 -0
- data/lib/appsignal/transaction.rb +714 -164
- data/lib/appsignal/utils/request_headers.rb +78 -0
- data/lib/appsignal/utils/stdout_and_logger_message.rb +9 -0
- data/lib/appsignal/utils.rb +1 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +10 -0
- data/sig/appsignal.rbi +630 -37
- data/sig/appsignal.rbs +582 -27
- metadata +25 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: aa6ecd3d80cea2a3d5b0f3e00c40b3248c633e352337a4640843e7255fc84c49
|
|
4
|
+
data.tar.gz: 98d1d112ded643cc555d7e54b1dd14d3a4d564db310386383e772b298697ba4d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dd8c19f24a975e360e54d133ab29ec6b8143663e2f55acc97f2f3b7b0556db527188beb808259fb427faa9e3b055036deec2c7bc0f9163db0abcee3503e42756
|
|
7
|
+
data.tar.gz: b727d0b3c91e179f332b198107d0bb8b4ab2bcfab929483b017744cd57746b5d2291674447d317fe305856e05df583af2d07bf7a9d61f329bbccc9f806e8beab
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,80 @@
|
|
|
1
1
|
# AppSignal for Ruby gem Changelog
|
|
2
2
|
|
|
3
|
+
## 5.0.0
|
|
4
|
+
|
|
5
|
+
_Published on 2026-09-28._
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Release the final package version. See the pre-release changelog entries for the changes in this version. (major)
|
|
10
|
+
|
|
11
|
+
## 5.0.0.rc.2
|
|
12
|
+
|
|
13
|
+
_Published on 2026-09-23._
|
|
14
|
+
|
|
15
|
+
This release also includes all the changes from AppSignal for Ruby version 4.10.4 and below.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Detect the revision that is being deployed from the environment variables set by Heroku, Render, Kamal and Scalingo: `HEROKU_SLUG_COMMIT`, `RENDER_GIT_COMMIT`, `KAMAL_VERSION` and `CONTAINER_VERSION`. Applications deployed on those platforms now report their revision without setting the `revision` configuration option.
|
|
20
|
+
|
|
21
|
+
This affects collector mode, where deploys were reported as `unknown` when the revision was not configured.
|
|
22
|
+
|
|
23
|
+
(patch [bf606432](https://github.com/appsignal/appsignal-ruby/commit/bf606432aab96d3f9b3a20cbb4b0c48aa7748702))
|
|
24
|
+
- Detect the hostname of the machine the application runs on. On Heroku this is the name of the dyno, and everywhere else it is the name the host reports for itself. Set the `hostname` configuration option to report a different name.
|
|
25
|
+
|
|
26
|
+
This affects collector mode, where all data was reported for a host named `unknown` when the hostname was not configured.
|
|
27
|
+
|
|
28
|
+
(patch [bf606432](https://github.com/appsignal/appsignal-ruby/commit/bf606432aab96d3f9b3a20cbb4b0c48aa7748702))
|
|
29
|
+
- Report the host, the port and the HTTP version of an incoming web request in collector mode. These are sent as the `server.address`, `server.port` and `network.protocol.version` OpenTelemetry attributes. The host is read from the `Forwarded` and `X-Forwarded-Host` headers when a proxy sets them, so it is the host the client used rather than the one the proxy connected to. (patch [85460ff3](https://github.com/appsignal/appsignal-ruby/commit/85460ff3d8ae5235515fe291b9a6baea6ad0c47c))
|
|
30
|
+
- Report the request environment in collector mode. The `request_headers` configuration option is an allowlist of Rack environment names, and some of those names are not request headers. Those values are now reported as `appsignal.environment.*` OpenTelemetry attributes and shown in the request's Environment panel, instead of being left out.
|
|
31
|
+
|
|
32
|
+
Values that describe the request itself are not repeated there, because they are already reported as the request's method, path, host, port and protocol version.
|
|
33
|
+
|
|
34
|
+
(patch [85460ff3](https://github.com/appsignal/appsignal-ruby/commit/85460ff3d8ae5235515fe291b9a6baea6ad0c47c))
|
|
35
|
+
- Add the `keep_request_headers` and `keep_request_environment` configuration options, which are used in collector mode. They replace `request_headers`, which is deprecated in collector mode.
|
|
36
|
+
|
|
37
|
+
`keep_request_headers` lists the request headers to report, using the names OpenTelemetry uses for them, such as `accept` and `content-length`. `keep_request_environment` lists the Rack environment values to report that are not request headers, using the names Rack uses for them, such as `REMOTE_ADDR`.
|
|
38
|
+
|
|
39
|
+
Both options default to a value derived from `request_headers`, which lists Rack environment keys and mixes the two kinds together. So an application that only ever set `request_headers` keeps reporting the same values when it moves to collector mode.
|
|
40
|
+
|
|
41
|
+
The `request_headers` configuration option is deprecated in collector mode, and a warning will be emitted at startup, containing the values of `keep_request_headers` and `keep_request_environment` that should be used to replace it.
|
|
42
|
+
|
|
43
|
+
In agent mode, `request_headers` still lists every Rack environment key to report, and the two new options have no effect.
|
|
44
|
+
|
|
45
|
+
(patch [992a60c8](https://github.com/appsignal/appsignal-ruby/commit/992a60c8d0f68b3edcb00150a1e9f14985619a4f))
|
|
46
|
+
- Add the `Appsignal.add_request_headers` and `Appsignal.add_request_environment` helpers.
|
|
47
|
+
|
|
48
|
+
Use `add_request_headers` to report request headers, naming each header in lowercase and with dashes, such as `content-length`. Use `add_request_environment` to report the values a Rack environment holds that are not request headers, naming each one the way Rack names it, such as `REMOTE_ADDR`.
|
|
49
|
+
|
|
50
|
+
In agent mode, both write to the "Environment" sample data, formatted as Rack environment keys. In collector mode, they write different span attributes.
|
|
51
|
+
|
|
52
|
+
Together they replace `Appsignal.add_headers`, which is now deprecated, as it accepts Rack environment keys and works out which ones are headers.
|
|
53
|
+
|
|
54
|
+
(patch [992a60c8](https://github.com/appsignal/appsignal-ruby/commit/992a60c8d0f68b3edcb00150a1e9f14985619a4f))
|
|
55
|
+
- Report request headers for Webmachine applications. (patch [fcfb7a0d](https://github.com/appsignal/appsignal-ruby/commit/fcfb7a0d2545a2144aa61efa61d445c0e11c7749), [b47f5bd2](https://github.com/appsignal/appsignal-ruby/commit/b47f5bd2b4611f5a6089bff28f91d47eac94422f), [992a60c8](https://github.com/appsignal/appsignal-ruby/commit/992a60c8d0f68b3edcb00150a1e9f14985619a4f))
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- Report `app` instead of `unknown` as the OpenTelemetry service name when the `service_name` configuration option is not set and collector mode is in use. (patch [7078181c](https://github.com/appsignal/appsignal-ruby/commit/7078181ccfc5aa5bb1200d99aa7c612c5acbbd00))
|
|
60
|
+
- The `filter_parameters` and `send_params` configuration options are deprecated in collector mode. Use `filter_request_payload`, `filter_function_parameters` and `filter_request_query_parameters` to filter different kinds of parameters, and `send_request_payload`, `send_request_query_parameters` and `send_function_parameters` to choose which kinds of parameters to report.
|
|
61
|
+
|
|
62
|
+
In collector mode, each kind of parameter is now filtered and reported according to its own options, and the deprecated options' values are only used to fill in values when the new options are unset. AppSignal logs which values to set to keep reporting what it reports now.
|
|
63
|
+
|
|
64
|
+
In agent mode, `filter_parameters` and `send_params` still apply to every kind of parameter, and the new options have no effect.
|
|
65
|
+
|
|
66
|
+
(patch [992a60c8](https://github.com/appsignal/appsignal-ruby/commit/992a60c8d0f68b3edcb00150a1e9f14985619a4f))
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- The `ignore_logs` option now filters out the log lines that match its patterns in collector mode. (patch [bf606432](https://github.com/appsignal/appsignal-ruby/commit/bf606432aab96d3f9b3a20cbb4b0c48aa7748702))
|
|
71
|
+
- In collector mode, backtrace lines from your own application are now shown as paths relative to your application's root, and are recognized as your application's code. (patch [bf606432](https://github.com/appsignal/appsignal-ruby/commit/bf606432aab96d3f9b3a20cbb4b0c48aa7748702))
|
|
72
|
+
- The `ca_file_path` and `http_proxy` options now apply to the data sent to the collector in collector mode. Before this change they only applied to the data sent by the agent, so a custom certificate authority file or a proxy had no effect in collector mode. (patch [e99c6b68](https://github.com/appsignal/appsignal-ruby/commit/e99c6b689b20fb433ecdcdc9fb8c6173e1ea8cda))
|
|
73
|
+
- Remove an incorrect warning about the `filter_metadata` configuration option being ignored in collector mode. (patch [992a60c8](https://github.com/appsignal/appsignal-ruby/commit/992a60c8d0f68b3edcb00150a1e9f14985619a4f))
|
|
74
|
+
- Report request headers in collector mode. (patch [992a60c8](https://github.com/appsignal/appsignal-ruby/commit/992a60c8d0f68b3edcb00150a1e9f14985619a4f))
|
|
75
|
+
- Report no response headers in collector mode until the `response_headers` configuration option names some. The option had no effect at all, so every response header captured by the application's own OpenTelemetry instrumentation was reported whatever the option said. (patch [992a60c8](https://github.com/appsignal/appsignal-ruby/commit/992a60c8d0f68b3edcb00150a1e9f14985619a4f))
|
|
76
|
+
- Read an array configuration option written as a null in `config/appsignal.yml` as the empty list it means. Options such as `filter_parameters` and `ignore_actions` raised a `NoMethodError` when AppSignal started, and `filter_metadata` and `filter_session_data` raised one while a transaction was sampled. (patch [992a60c8](https://github.com/appsignal/appsignal-ruby/commit/992a60c8d0f68b3edcb00150a1e9f14985619a4f))
|
|
77
|
+
|
|
3
78
|
## 4.10.4
|
|
4
79
|
|
|
5
80
|
_Published on 2026-09-22._
|
|
@@ -27,6 +102,20 @@ _Published on 2026-09-10._
|
|
|
27
102
|
|
|
28
103
|
(patch [74f509b0](https://github.com/appsignal/appsignal-ruby/commit/74f509b0e8438140bab79a5189c2ed421bbbdf6d))
|
|
29
104
|
|
|
105
|
+
## 3.13.2
|
|
106
|
+
|
|
107
|
+
_Published on 2026-09-09._
|
|
108
|
+
|
|
109
|
+
### Changed
|
|
110
|
+
|
|
111
|
+
- Update the agent to handle high traffic apps. On high-traffic apps that would exceed the maximum accepted internal payload size, send data to the Push API more frequently. (patch [c69fbf57](https://github.com/appsignal/appsignal-ruby/commit/c69fbf57242b13c86af2196baae8f295285de947))
|
|
112
|
+
- Update the agent from version 0.35.19 to version 0.37.0. The 3.x series of the Ruby gem was several agent releases behind, so this update also brings the improvements from every agent release in between. Those include better sanitisation of SQL queries, host metric collection that keeps working when a disk mount is frozen, and no more leftover `[timeout]` processes on Alpine Linux containers. (patch [c69fbf57](https://github.com/appsignal/appsignal-ruby/commit/c69fbf57242b13c86af2196baae8f295285de947))
|
|
113
|
+
|
|
114
|
+
### Fixed
|
|
115
|
+
|
|
116
|
+
- Fix events showing as unknown in long-running applications. An application process that kept running for thirty days without restarting could lose the names and queries of the events it recorded, both in slow traces and in the "Slow events" panel. (patch [c69fbf57](https://github.com/appsignal/appsignal-ruby/commit/c69fbf57242b13c86af2196baae8f295285de947))
|
|
117
|
+
- Prevent `gc` events from appearing in the "Slow events" panel. (patch [c69fbf57](https://github.com/appsignal/appsignal-ruby/commit/c69fbf57242b13c86af2196baae8f295285de947))
|
|
118
|
+
|
|
30
119
|
## 4.10.2
|
|
31
120
|
|
|
32
121
|
_Published on 2026-09-09._
|
|
@@ -75,6 +164,25 @@ _Published on 2026-09-09._
|
|
|
75
164
|
|
|
76
165
|
(patch [fe82dc60](https://github.com/appsignal/appsignal-ruby/commit/fe82dc60bc8b52d466c0c9b673adbae29f79449e))
|
|
77
166
|
|
|
167
|
+
## 5.0.0.rc.1
|
|
168
|
+
|
|
169
|
+
_Published on 2026-08-21._
|
|
170
|
+
|
|
171
|
+
### Added
|
|
172
|
+
|
|
173
|
+
- Add a `collector_endpoint` configuration option (`APPSIGNAL_COLLECTOR_ENDPOINT` environment variable) that puts the integration in _collector mode_. In collector mode AppSignal reports traces, metrics and logs to an AppSignal Collector, over OTLP/HTTP.
|
|
174
|
+
|
|
175
|
+
Collector mode requires Ruby 3.1 or newer, and the OpenTelemetry gems, which are not installed by default. Add the `appsignal-opentelemetry` gem alongside `appsignal` to install them. When they are missing or too old, AppSignal logs a warning and keeps reporting through its agent.
|
|
176
|
+
|
|
177
|
+
(major [84d83b65](https://github.com/appsignal/appsignal-ruby/commit/84d83b657d65a93859ba73f295216a3b0ee9cab1), [90768626](https://github.com/appsignal/appsignal-ruby/commit/9076862677444c7772e6f8fbe1e3d5a646a4849d))
|
|
178
|
+
- Add configuration options that map to OpenTelemetry resource attributes in collector mode: `service_name`, `filter_attributes`, `filter_function_parameters`, `filter_request_query_parameters`, `filter_request_payload`, `response_headers`, `send_function_parameters`, `send_request_query_parameters` and `send_request_payload`.
|
|
179
|
+
|
|
180
|
+
In collector mode, existing options are passed to the collector as resource attributes as well: `name`, environment, `hostname`, `revision`, `ignore_actions`, `ignore_errors`, `ignore_namespaces`, `request_headers`, `filter_session_data` and `send_session_data`.
|
|
181
|
+
|
|
182
|
+
Setting any of these without `collector_endpoint`, or setting `filter_parameters`, `filter_metadata` or `send_params` with it, logs a warning at startup.
|
|
183
|
+
|
|
184
|
+
(minor [84d83b65](https://github.com/appsignal/appsignal-ruby/commit/84d83b657d65a93859ba73f295216a3b0ee9cab1), [90768626](https://github.com/appsignal/appsignal-ruby/commit/9076862677444c7772e6f8fbe1e3d5a646a4849d))
|
|
185
|
+
|
|
78
186
|
## 4.10.1
|
|
79
187
|
|
|
80
188
|
_Published on 2026-08-20._
|
data/Rakefile
CHANGED
|
@@ -20,6 +20,8 @@ VERSION_MANAGERS = {
|
|
|
20
20
|
}
|
|
21
21
|
}.freeze
|
|
22
22
|
|
|
23
|
+
SPEC_COVERAGE_AUDIT_JOB_NAME = "Spec coverage audit"
|
|
24
|
+
|
|
23
25
|
def build_job(ruby_version, ruby_gem: nil, runs_on: DEFAULT_RUNS_ON)
|
|
24
26
|
name = "Ruby #{ruby_version}"
|
|
25
27
|
name = "#{name} - #{ruby_gem}" if ruby_gem
|
|
@@ -57,6 +59,89 @@ def build_job(ruby_version, ruby_gem: nil, runs_on: DEFAULT_RUNS_ON)
|
|
|
57
59
|
}
|
|
58
60
|
end
|
|
59
61
|
|
|
62
|
+
# Every test job uploads the example list its run wrote, named after the job so
|
|
63
|
+
# the audit can say which combination is missing one. Uploaded even when the run
|
|
64
|
+
# fails, because the list is written either way and the audit needs to tell a
|
|
65
|
+
# crashed job apart from a combination that legitimately runs nothing.
|
|
66
|
+
def example_list_upload_step(key)
|
|
67
|
+
{
|
|
68
|
+
"name" => "Upload example list",
|
|
69
|
+
"if" => "always()",
|
|
70
|
+
"uses" => "actions/upload-artifact@v4",
|
|
71
|
+
"with" => {
|
|
72
|
+
"name" => key,
|
|
73
|
+
"path" => "tmp/examples-*.json",
|
|
74
|
+
"if-no-files-found" => "error",
|
|
75
|
+
"retention-days" => 1
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Compares the examples defined in the source against the union of every job's
|
|
81
|
+
# example list.
|
|
82
|
+
#
|
|
83
|
+
# It cannot wait for the test jobs through `needs`. Naming all 426 of them puts
|
|
84
|
+
# the workflow over a limit on how many dependency edges GitHub accepts, and
|
|
85
|
+
# GitHub then refuses to create the run without reporting anything: no run
|
|
86
|
+
# appears, the pull request shows no checks, and the runs API stays empty.
|
|
87
|
+
# Grouping the dependencies behind intermediate jobs does not help, because the
|
|
88
|
+
# same number of edges still has to exist. So this job starts with the others
|
|
89
|
+
# and waits by polling the run it belongs to.
|
|
90
|
+
def spec_coverage_audit_job
|
|
91
|
+
{
|
|
92
|
+
"name" => SPEC_COVERAGE_AUDIT_JOB_NAME,
|
|
93
|
+
"needs" => "validation",
|
|
94
|
+
"runs-on" => DEFAULT_RUNS_ON,
|
|
95
|
+
# Reports without failing the build. The examples it currently finds are
|
|
96
|
+
# covered by separate work; removing this line is what makes it enforcing.
|
|
97
|
+
"continue-on-error" => true,
|
|
98
|
+
# Long enough for the whole matrix, and short enough that a stuck job does
|
|
99
|
+
# not hold a runner for the six hours GitHub would otherwise allow.
|
|
100
|
+
"timeout-minutes" => 180,
|
|
101
|
+
"permissions" => {
|
|
102
|
+
"actions" => "read",
|
|
103
|
+
"contents" => "read"
|
|
104
|
+
},
|
|
105
|
+
"steps" => [
|
|
106
|
+
{
|
|
107
|
+
"name" => "Check out repository",
|
|
108
|
+
"uses" => "actions/checkout@v4"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name" => "Install Ruby",
|
|
112
|
+
"uses" => "ruby/setup-ruby@v1",
|
|
113
|
+
"with" => { "ruby-version" => "3.4" }
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name" => "Wait for the test jobs to upload their example lists",
|
|
117
|
+
"env" => { "GH_TOKEN" => "${{ secrets.GITHUB_TOKEN }}" },
|
|
118
|
+
"run" => <<~SHELL
|
|
119
|
+
jobs="repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/jobs"
|
|
120
|
+
filter='.jobs[]
|
|
121
|
+
| select(.name != "#{SPEC_COVERAGE_AUDIT_JOB_NAME}")
|
|
122
|
+
| select(.status != "completed")
|
|
123
|
+
| .name'
|
|
124
|
+
while :; do
|
|
125
|
+
pending=$(gh api --paginate "$jobs?per_page=100" --jq "$filter" | wc -l)
|
|
126
|
+
if [ "$pending" -eq 0 ]; then break; fi
|
|
127
|
+
echo "Waiting for $pending jobs."
|
|
128
|
+
sleep 60
|
|
129
|
+
done
|
|
130
|
+
SHELL
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"name" => "Download example lists",
|
|
134
|
+
"uses" => "actions/download-artifact@v4",
|
|
135
|
+
"with" => { "path" => "artifacts" }
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"name" => "Audit spec coverage",
|
|
139
|
+
"run" => "ruby script/audit_spec_coverage.rb artifacts"
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
end
|
|
144
|
+
|
|
60
145
|
def build_matrix_key(ruby_version, ruby_gem: nil, runs_on: DEFAULT_RUNS_ON)
|
|
61
146
|
base = "ruby_#{ruby_version}"
|
|
62
147
|
base = "#{base}__#{ruby_gem}" if ruby_gem
|
|
@@ -72,7 +157,50 @@ GITHUB_ACTION_WORKFLOW_FILE = ".github/workflows/ci.yml"
|
|
|
72
157
|
PRIMARY_JOB_GEMSET = "no_dependencies"
|
|
73
158
|
DEFAULT_RUNS_ON = "ubuntu-latest"
|
|
74
159
|
|
|
160
|
+
COLLECTOR_GEMFILE_PARTIAL = "collector.rb"
|
|
161
|
+
|
|
75
162
|
namespace :build_matrix do
|
|
163
|
+
namespace :gemfiles do
|
|
164
|
+
# Generates a `<base>-collector.gemfile` next to each base gemfile. The
|
|
165
|
+
# variant layers the optional OpenTelemetry gems (`gemfiles/collector.rb`)
|
|
166
|
+
# on top of the base, so collector-mode test runs resolve them while the
|
|
167
|
+
# base gemfiles (and the gemspec) stay OpenTelemetry-free. Regenerate
|
|
168
|
+
# whenever a base gemfile is added or removed.
|
|
169
|
+
task :generate do
|
|
170
|
+
base_gemfiles =
|
|
171
|
+
Dir["gemfiles/*.gemfile"]
|
|
172
|
+
.map { |path| File.basename(path) }
|
|
173
|
+
.reject { |name| name.end_with?("-collector.gemfile") }
|
|
174
|
+
.sort
|
|
175
|
+
|
|
176
|
+
base_gemfiles.each do |base|
|
|
177
|
+
name = base.sub(/\.gemfile\z/, "")
|
|
178
|
+
contents =
|
|
179
|
+
"# DO NOT EDIT\n" \
|
|
180
|
+
"# This is a generated file by the " \
|
|
181
|
+
"`rake build_matrix:gemfiles:generate` task.\n" \
|
|
182
|
+
"# It layers the optional OpenTelemetry gems (gemfiles/" \
|
|
183
|
+
"#{COLLECTOR_GEMFILE_PARTIAL}) on top of #{base}.\n" \
|
|
184
|
+
"\n" \
|
|
185
|
+
"eval_gemfile File.expand_path(#{base.inspect}, __dir__)\n" \
|
|
186
|
+
"eval_gemfile File.expand_path(" \
|
|
187
|
+
"#{COLLECTOR_GEMFILE_PARTIAL.inspect}, __dir__)\n"
|
|
188
|
+
File.write("gemfiles/#{name}-collector.gemfile", contents)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
puts "Generated #{base_gemfiles.count} `-collector` gemfiles."
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
task :validate => :generate do
|
|
195
|
+
output = `git status --porcelain gemfiles`
|
|
196
|
+
if output.include?("-collector.gemfile")
|
|
197
|
+
puts "The `-collector` gemfiles are out of date. The changes were not committed."
|
|
198
|
+
puts "Please run `rake build_matrix:gemfiles:generate` and commit the changes."
|
|
199
|
+
exit 1
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
76
204
|
namespace :github do
|
|
77
205
|
task :generate do
|
|
78
206
|
yaml = YAML.load_file("build_matrix.yml")
|
|
@@ -107,12 +235,31 @@ namespace :build_matrix do
|
|
|
107
235
|
"name" => "Run tests without extension",
|
|
108
236
|
"run" => "./script/bundler_wrapper exec rake test:failure"
|
|
109
237
|
}
|
|
238
|
+
job["steps"] << example_list_upload_step(build_matrix_key(ruby["ruby"]))
|
|
110
239
|
builds[build_matrix_key(ruby["ruby"])] = job
|
|
111
240
|
else
|
|
112
241
|
job["needs"] = build_matrix_key(ruby["ruby"])
|
|
113
242
|
job["steps"] << test_step
|
|
114
|
-
|
|
243
|
+
gem_key = build_matrix_key(ruby["ruby"], :ruby_gem => ruby_gem["gem"])
|
|
244
|
+
job["steps"] << example_list_upload_step(gem_key)
|
|
245
|
+
builds[gem_key] = job
|
|
115
246
|
end
|
|
247
|
+
|
|
248
|
+
# On collector-capable Rubies, additionally run the gem's
|
|
249
|
+
# `-collector` gemfile (base gems + optional OpenTelemetry gems) so
|
|
250
|
+
# collector-mode specs are exercised. These always depend on the
|
|
251
|
+
# primary job for the Ruby version and run on Ubuntu only.
|
|
252
|
+
next unless collector_ruby?(matrix, ruby_version)
|
|
253
|
+
|
|
254
|
+
collector_gem = "#{ruby_gem["gem"]}-collector"
|
|
255
|
+
collector_job = build_job(ruby_version, :ruby_gem => collector_gem)
|
|
256
|
+
collector_job["env"] = matrix["env"]
|
|
257
|
+
.merge("BUNDLE_GEMFILE" => "gemfiles/#{collector_gem}.gemfile")
|
|
258
|
+
collector_job["needs"] = build_matrix_key(ruby["ruby"])
|
|
259
|
+
collector_job["steps"] << test_step
|
|
260
|
+
collector_key = build_matrix_key(ruby["ruby"], :ruby_gem => collector_gem)
|
|
261
|
+
collector_job["steps"] << example_list_upload_step(collector_key)
|
|
262
|
+
builds[collector_key] = collector_job
|
|
116
263
|
end
|
|
117
264
|
|
|
118
265
|
# Add build for macOS
|
|
@@ -130,9 +277,13 @@ namespace :build_matrix do
|
|
|
130
277
|
"name" => "Run tests without extension",
|
|
131
278
|
"run" => "./script/bundler_wrapper exec rake test:failure"
|
|
132
279
|
}
|
|
133
|
-
|
|
280
|
+
macos_key = build_matrix_key(ruby["ruby"], :runs_on => runs_on)
|
|
281
|
+
job["steps"] << example_list_upload_step(macos_key)
|
|
282
|
+
builds[macos_key] = job
|
|
134
283
|
end
|
|
135
284
|
|
|
285
|
+
builds["spec_coverage_audit"] = spec_coverage_audit_job
|
|
286
|
+
|
|
136
287
|
github["jobs"] = github["jobs"].merge(builds)
|
|
137
288
|
|
|
138
289
|
job_count = github["jobs"].count
|
|
@@ -191,6 +342,14 @@ namespace :build_matrix do
|
|
|
191
342
|
out << "#{bundler_version} #{gemfile_env} ./script/bundler_wrapper install --quiet || { echo 'Bundling failed'; exit 1; }"
|
|
192
343
|
out << "echo 'Running #{gemfile} in #{ruby_version}'"
|
|
193
344
|
out << "#{bundler_version} #{gemfile_env} ./script/bundler_wrapper exec rspec || { echo 'Running specs failed'; exit 1; }"
|
|
345
|
+
|
|
346
|
+
next unless collector_ruby?(matrix, ruby_version)
|
|
347
|
+
|
|
348
|
+
collector_env = "env BUNDLE_GEMFILE=gemfiles/#{gemfile}-collector.gemfile"
|
|
349
|
+
out << "echo 'Bundling #{gemfile}-collector in #{ruby_version}'"
|
|
350
|
+
out << "#{bundler_version} #{collector_env} ./script/bundler_wrapper install --quiet || { echo 'Bundling failed'; exit 1; }"
|
|
351
|
+
out << "echo 'Running #{gemfile}-collector in #{ruby_version}'"
|
|
352
|
+
out << "#{bundler_version} #{collector_env} ./script/bundler_wrapper exec rspec || { echo 'Running specs failed'; exit 1; }"
|
|
194
353
|
end
|
|
195
354
|
# rubocop:enable Layout/LineLength
|
|
196
355
|
out << ""
|
|
@@ -207,6 +366,10 @@ namespace :build_matrix do
|
|
|
207
366
|
end
|
|
208
367
|
end
|
|
209
368
|
|
|
369
|
+
def collector_ruby?(matrix, ruby_version)
|
|
370
|
+
Array(matrix.dig("collector", "ruby")).include?(ruby_version)
|
|
371
|
+
end
|
|
372
|
+
|
|
210
373
|
def gemset_for_ruby(ruby, matrix)
|
|
211
374
|
gems = matrix["gems"]
|
|
212
375
|
if ruby["gems"]
|
|
@@ -288,6 +451,23 @@ namespace :build do
|
|
|
288
451
|
desc "Build all gem versions"
|
|
289
452
|
task :all => ["ruby:gem", "jruby:gem"]
|
|
290
453
|
|
|
454
|
+
desc "Build every package in this repository"
|
|
455
|
+
task :packages => :all do
|
|
456
|
+
# Build the companion gem by delegating to its own Rakefile rather than
|
|
457
|
+
# duplicating its build logic here. mono builds each package directly, so
|
|
458
|
+
# this task is only a convenience for developers building from the root.
|
|
459
|
+
#
|
|
460
|
+
# Clear the Bundler environment first so the sub-build resolves against the
|
|
461
|
+
# package's own Gemfile instead of inheriting this repository's
|
|
462
|
+
# BUNDLE_GEMFILE. Install its dependencies first, then build it.
|
|
463
|
+
Bundler.with_unbundled_env do
|
|
464
|
+
Dir.chdir("packages/opentelemetry") do
|
|
465
|
+
sh "bundle install"
|
|
466
|
+
sh "bundle exec rake build:all"
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|
|
291
471
|
desc "Clean up all gem build artifacts"
|
|
292
472
|
task :clean do
|
|
293
473
|
FileUtils.rm_rf File.expand_path("pkg", __dir__)
|
|
@@ -361,14 +541,25 @@ begin
|
|
|
361
541
|
excludes << "spec/lib/appsignal/extension/jruby_spec.rb" unless is_jruby
|
|
362
542
|
exclude_pattern = "--exclude-pattern=#{excludes.join(",")}" if excludes.any?
|
|
363
543
|
|
|
544
|
+
# Written alongside the human-readable output so the coverage audit can tell
|
|
545
|
+
# which examples this Ruby and gemfile combination actually ran. Every CI job
|
|
546
|
+
# uploads its list. Nothing else reveals that a dependency guard is false in
|
|
547
|
+
# every combination, because a guarded example is then never defined at all.
|
|
548
|
+
def example_list_opts(name)
|
|
549
|
+
"--format json --out tmp/examples-#{name}.json"
|
|
550
|
+
end
|
|
551
|
+
|
|
364
552
|
desc "Run the AppSignal gem test suite."
|
|
365
553
|
RSpec::Core::RakeTask.new :test do |t|
|
|
366
|
-
t.rspec_opts = "#{exclude_pattern} --format documentation"
|
|
554
|
+
t.rspec_opts = "#{exclude_pattern} --format documentation " \
|
|
555
|
+
"#{example_list_opts("test")}"
|
|
367
556
|
end
|
|
368
557
|
|
|
369
558
|
namespace :test do
|
|
370
559
|
RSpec::Core::RakeTask.new :rspec_failure do |t|
|
|
371
|
-
t.rspec_opts = "#{exclude_pattern} --
|
|
560
|
+
t.rspec_opts = "#{exclude_pattern} --format documentation " \
|
|
561
|
+
"--tag extension_installation_failure " \
|
|
562
|
+
"#{example_list_opts("failure")}"
|
|
372
563
|
end
|
|
373
564
|
|
|
374
565
|
desc "Intentionally fail the extension installation"
|
data/appsignal.gemspec
CHANGED
|
@@ -7,6 +7,7 @@ IGNORED_PATHS = [
|
|
|
7
7
|
".changesets/",
|
|
8
8
|
".github/",
|
|
9
9
|
"gemfiles/",
|
|
10
|
+
"packages/",
|
|
10
11
|
"script/",
|
|
11
12
|
"spec/",
|
|
12
13
|
|
|
@@ -60,6 +61,13 @@ Gem::Specification.new do |gem|
|
|
|
60
61
|
# Needs 2.0+ because we rely on Rack::Events
|
|
61
62
|
gem.add_dependency "rack", ">= 2.0.0"
|
|
62
63
|
|
|
64
|
+
# The OpenTelemetry SDK and OTLP exporters are *optional* and intentionally
|
|
65
|
+
# not declared here: they're only needed in collector mode (Ruby 3.1+), so
|
|
66
|
+
# bundling them would break Ruby 2.7 and burden non-collector users. Apps
|
|
67
|
+
# that enable collector mode add them to their own Gemfile; the minimum
|
|
68
|
+
# versions live in `lib/appsignal/opentelemetry/dependencies.rb` and are
|
|
69
|
+
# enforced at boot by `Appsignal::OpenTelemetry.configure`.
|
|
70
|
+
|
|
63
71
|
gem.add_development_dependency "pry"
|
|
64
72
|
# Reached through webmock's addressable. Version 7 requires Ruby 3.2 and
|
|
65
73
|
# version 6 requires 3.0, so an older Ruby cannot resolve the development
|
data/build_matrix.yml
CHANGED
|
@@ -107,6 +107,18 @@ matrix:
|
|
|
107
107
|
JRUBY_OPTS: ""
|
|
108
108
|
COV: "1"
|
|
109
109
|
|
|
110
|
+
# Ruby versions that additionally run each gem's `-collector` gemfile (the
|
|
111
|
+
# optional OpenTelemetry gems layered on top). Collector mode requires Ruby
|
|
112
|
+
# 3.1+ (the OTel metrics SDK's fork hooks rely on `Process._fork`) and does
|
|
113
|
+
# not support JRuby's forking model, so only these versions are listed.
|
|
114
|
+
collector:
|
|
115
|
+
ruby:
|
|
116
|
+
- "4.0.0"
|
|
117
|
+
- "3.4.1"
|
|
118
|
+
- "3.3.4"
|
|
119
|
+
- "3.2.5"
|
|
120
|
+
- "3.1.6"
|
|
121
|
+
|
|
110
122
|
gemsets: # By default all gems are tested
|
|
111
123
|
none:
|
|
112
124
|
- "no_dependencies"
|
data/ext/appsignal_extension.c
CHANGED
|
@@ -834,10 +834,23 @@ static VALUE add_distribution_value(VALUE self, VALUE key, VALUE value, VALUE ta
|
|
|
834
834
|
return Qnil;
|
|
835
835
|
}
|
|
836
836
|
|
|
837
|
+
// Per-thread running total of object allocations, incremented on every Ruby
|
|
838
|
+
// NEWOBJ event. Thread-local because MRI maps each Ruby thread to its own OS
|
|
839
|
+
// thread, so this attributes allocations to the thread doing the work, which is
|
|
840
|
+
// the thread the transaction runs on. Collector mode reads it through
|
|
841
|
+
// Appsignal::Extension.allocation_count and diffs two snapshots to get the
|
|
842
|
+
// allocations made during a transaction or an event.
|
|
843
|
+
static __thread unsigned long long appsignal_thread_allocation_count = 0;
|
|
844
|
+
|
|
837
845
|
static void track_allocation(rb_event_flag_t flag, VALUE arg1, VALUE arg2, ID arg3, VALUE arg4) {
|
|
846
|
+
appsignal_thread_allocation_count++;
|
|
838
847
|
appsignal_track_allocation();
|
|
839
848
|
}
|
|
840
849
|
|
|
850
|
+
static VALUE allocation_count(VALUE self) {
|
|
851
|
+
return ULL2NUM(appsignal_thread_allocation_count);
|
|
852
|
+
}
|
|
853
|
+
|
|
841
854
|
static VALUE install_allocation_event_hook(VALUE self) {
|
|
842
855
|
// This event hook is only available on Ruby 2.1 and 2.2
|
|
843
856
|
#if defined(RUBY_INTERNAL_EVENT_NEWOBJ)
|
|
@@ -956,6 +969,7 @@ void Init_appsignal_extension(void) {
|
|
|
956
969
|
|
|
957
970
|
// Other helper methods
|
|
958
971
|
rb_define_singleton_method(Extension, "install_allocation_event_hook", install_allocation_event_hook, 0);
|
|
972
|
+
rb_define_singleton_method(Extension, "allocation_count", allocation_count, 0);
|
|
959
973
|
rb_define_singleton_method(Extension, "running_in_container?", running_in_container, 0);
|
|
960
974
|
rb_define_singleton_method(Extension, "set_environment_metadata", set_environment_metadata, 2);
|
|
961
975
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "appsignal/metrics/extension_backend"
|
|
4
|
+
require "appsignal/metrics/opentelemetry_backend"
|
|
5
|
+
require "appsignal/logger/extension_backend"
|
|
6
|
+
require "appsignal/logger/opentelemetry_backend"
|
|
7
|
+
require "appsignal/transaction/base_backend"
|
|
8
|
+
require "appsignal/transaction/extension_backend"
|
|
9
|
+
require "appsignal/transaction/opentelemetry_backend"
|
|
10
|
+
|
|
11
|
+
module Appsignal
|
|
12
|
+
# @!visibility private
|
|
13
|
+
#
|
|
14
|
+
# Looks up the active backend for each AppSignal subsystem. In normal
|
|
15
|
+
# operation, subsystems route through the C-extension (and its agent).
|
|
16
|
+
# When collector mode is configured and the OpenTelemetry SDK has booted
|
|
17
|
+
# successfully, supported subsystems route through OTel instead.
|
|
18
|
+
#
|
|
19
|
+
# Centralizes the mode-check so per-subsystem call sites don't repeat the
|
|
20
|
+
# "if collector? then OTel else Extension" branch. Future subsystems plug
|
|
21
|
+
# in by adding one more lookup method here.
|
|
22
|
+
module Backends
|
|
23
|
+
class << self
|
|
24
|
+
def metrics
|
|
25
|
+
if collector?
|
|
26
|
+
Appsignal::Metrics::OpenTelemetryBackend
|
|
27
|
+
else
|
|
28
|
+
Appsignal::Metrics::ExtensionBackend
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def logger
|
|
33
|
+
if collector?
|
|
34
|
+
Appsignal::Logger::OpenTelemetryBackend
|
|
35
|
+
else
|
|
36
|
+
Appsignal::Logger::ExtensionBackend
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def transaction
|
|
41
|
+
if collector?
|
|
42
|
+
Appsignal::Transaction::OpenTelemetryBackend
|
|
43
|
+
else
|
|
44
|
+
Appsignal::Transaction::ExtensionBackend
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def collector?
|
|
51
|
+
Appsignal.config&.collector_mode? || false
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -201,6 +201,7 @@ module Appsignal
|
|
|
201
201
|
|
|
202
202
|
# No config loaded yet, try loading as normal
|
|
203
203
|
Appsignal._load_config!(env_option) unless Appsignal.config
|
|
204
|
+
Appsignal.config.apply_overrides
|
|
204
205
|
Appsignal._start_logger
|
|
205
206
|
Appsignal.config.write_to_environment
|
|
206
207
|
Appsignal.internal_logger.info("Starting AppSignal diagnose")
|
|
@@ -472,16 +473,7 @@ module Appsignal
|
|
|
472
473
|
config = Appsignal.config
|
|
473
474
|
data[:config] = {
|
|
474
475
|
:options => config.config_hash.merge(:env => config.env),
|
|
475
|
-
:sources =>
|
|
476
|
-
:default => Appsignal::Config::DEFAULT_CONFIG,
|
|
477
|
-
:system => config.system_config,
|
|
478
|
-
:loaders => config.loaders_config,
|
|
479
|
-
:initial => config.initial_config,
|
|
480
|
-
:file => config.file_config,
|
|
481
|
-
:env => config.env_config,
|
|
482
|
-
:override => config.override_config,
|
|
483
|
-
:dsl => config.dsl_config
|
|
484
|
-
}
|
|
476
|
+
:sources => config.config_sources
|
|
485
477
|
}
|
|
486
478
|
print_config_options(config)
|
|
487
479
|
end
|