appsignal 4.6.0-java → 4.7.1-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/.yardoc/checksums +132 -0
- data/.yardoc/complete +0 -0
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/CHANGELOG.md +59 -0
- data/CLAUDE.md +15 -0
- data/build_matrix.yml +9 -0
- data/lib/appsignal/config.rb +2 -0
- data/lib/appsignal/environment.rb +1 -0
- data/lib/appsignal/hooks/code_ownership.rb +25 -0
- data/lib/appsignal/hooks.rb +1 -0
- data/lib/appsignal/integrations/code_ownership.rb +21 -0
- data/lib/appsignal/integrations/railtie.rb +17 -7
- data/lib/appsignal/integrations/sidekiq.rb +12 -1
- data/lib/appsignal/loaders/hanami.rb +1 -4
- data/lib/appsignal/loaders/padrino.rb +1 -1
- data/lib/appsignal/loaders/sinatra.rb +1 -1
- data/lib/appsignal/rack/event_handler.rb +21 -3
- data/lib/appsignal/rack/event_middleware.rb +114 -0
- data/lib/appsignal/rack/instrumentation_middleware.rb +2 -2
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +2 -1
- data/sig/appsignal.rbi +1 -1
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1641ec17d40f22ec483215b1102868d419f67a4034088a40e2403a314aa1479
|
4
|
+
data.tar.gz: 277298cd6d723946a42c66fb574176220fc8d68ff2b5b9953c5fc649a7a77ff0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be6a2ef13cf9047e5790c0191835cc7595136deb6ae878bbd836ab38707b90ad3fecc8578f02ab7579dbba891585f390cddb52672a707df6509888cb7fdc2c9c
|
7
|
+
data.tar.gz: 67483b66bc177ba413f290b9f8baca5449600c8cad89028629246609e5654b2c2369cebf881a484fd7ae46b21298f20c6022e0e8479d02f3b2d59b7c715ee923
|
data/.yardoc/checksums
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
lib/appsignal.rb 66edad2106bea39dddc857dce9cf2ee66427a331
|
2
|
+
lib/appsignal/cli.rb db1ebf0c49bfc51822d218587c931a7047b6903e
|
3
|
+
lib/appsignal/demo.rb daee00ade75c3427a1bad928f7a4498eebc2261a
|
4
|
+
lib/appsignal/rack.rb 713550d983e18ff066521f7278abeec6f92f1346
|
5
|
+
lib/appsignal/span.rb 42075501993e50ae794be3ad754a23bd1962ffcc
|
6
|
+
lib/appsignal/hooks.rb 6bb70aa06b5cea30a1ebc57fcc3f439cb10a923a
|
7
|
+
lib/appsignal/utils.rb 988cac4ba65773012e692fd58e7ae26533d20e22
|
8
|
+
lib/appsignal/config.rb aebd8ca5e7ebb6eea9afe40c4ae0eedbc7328ae1
|
9
|
+
lib/appsignal/logger.rb 863b9a720043632af5a042f2cb5709a2a4623d68
|
10
|
+
lib/appsignal/marker.rb e66f08914ab3bb1c5a5b634701db4345ba98b488
|
11
|
+
lib/appsignal/probes.rb 4f7f902d9f7c524de33ed5a7327e7b39898db568
|
12
|
+
lib/appsignal/system.rb 905087ae561fdec4a784b0ca027aa9d834d94f9a
|
13
|
+
lib/appsignal/loaders.rb a1b13f2ef1b7da9f4690252e04fa7c0ede5de00b
|
14
|
+
lib/appsignal/version.rb e20aaf225ec904965a40ea8266d81c7a23540ee6
|
15
|
+
lib/appsignal/check_in.rb da21a8220078db8fbb5a48a2ebea233b745a9309
|
16
|
+
lib/appsignal/cli/demo.rb 41076a71123964e673aeab042774fdad1cf2df62
|
17
|
+
lib/appsignal/extension.rb 80f1757fd0cb1b10bc37786af00a99183ff0fa38
|
18
|
+
lib/appsignal/hooks/gvl.rb f49cb93a91c7ace49b52950ffbe863fed5756498
|
19
|
+
lib/appsignal/hooks/mri.rb a8bd8a1c64d7131af0aeae1b080bcb773c29bbb8
|
20
|
+
lib/appsignal/hooks/que.rb 37ff09fe4b651fa5ef966c006e16ee4c348fd3a0
|
21
|
+
lib/appsignal/auth_check.rb 11752555dde4d43657d5eb7c74cad147b059169e
|
22
|
+
lib/appsignal/capistrano.rb e9a0f7194fc4b9b9f4983759ecdc6f8fc78a0c00
|
23
|
+
lib/appsignal/hooks/http.rb 49ac855859f0c9ce5a3697b6ea9fdbf39cc8f37d
|
24
|
+
lib/appsignal/hooks/puma.rb 8ea7f884c3eb1a1caa5b998a9885fd9b22864c4c
|
25
|
+
lib/appsignal/hooks/rake.rb aa22fca3d7d304ecd66d876715735f901d512b47
|
26
|
+
lib/appsignal/probes/gvl.rb 40621e23747f18d18e1b3ae7902803d9ac1e4d61
|
27
|
+
lib/appsignal/probes/mri.rb fdc96477171782f769371303b1d2185723724920
|
28
|
+
lib/appsignal/utils/data.rb 272f47900c83be4d2ad6767a8a21da7011c7256b
|
29
|
+
lib/appsignal/utils/json.rb 3d1ab5d70a2f969ccd567deae251d79f96864750
|
30
|
+
lib/appsignal/cli/helpers.rb ece01ef348935931453a72b2d61bc54e498a3b08
|
31
|
+
lib/appsignal/cli/install.rb 58ed474a9e75fd71f172032e8ee8cced6fc0f4b0
|
32
|
+
lib/appsignal/environment.rb 3bbab88bc0f39efced39ff4d0704a82734e17a06
|
33
|
+
lib/appsignal/hooks/excon.rb a54a5abae9a049dc4410b16ef4cbfc9c72ce7421
|
34
|
+
lib/appsignal/hooks/redis.rb 9a70a1bbee74456f59ba0a1a2aabd4305019ef3b
|
35
|
+
lib/appsignal/sample_data.rb 6cd3f1edbf7d3dbf0e7ed8396919d651ff8d4124
|
36
|
+
lib/appsignal/transaction.rb 5389997e5c9a0153ed81ea1021698f57209bb0d0
|
37
|
+
lib/appsignal/transmitter.rb c9e546368c9ca91b7e559cc585d6cee2998b8472
|
38
|
+
lib/puma/plugin/appsignal.rb 56f45a1819f4268626e00a8b03d45f9c045843ea
|
39
|
+
lib/appsignal/cli/diagnose.rb fac1b6d30960251512a0da5a8efced1ca60dc274
|
40
|
+
lib/appsignal/hooks/resque.rb ddc3bc68c6efdd8fdf71946df8086ab2c8e1680e
|
41
|
+
lib/appsignal/hooks/sequel.rb ce4cf7aeb15e9b9ad1c172f77d5e99ceaaad9b04
|
42
|
+
lib/appsignal/utils/ndjson.rb 9e37982dae178494f86db0d689e2b5d6381fb639
|
43
|
+
lib/appsignal/check_in/cron.rb 31ee09304ad2b95fa05e86de2b260e710c4228a8
|
44
|
+
lib/appsignal/custom_marker.rb 7c03fcb423b8a0a4a9e764af9ca8d4058254446c
|
45
|
+
lib/appsignal/hooks/at_exit.rb 9d500bf8022e6306ea080a5e55503353caa55412
|
46
|
+
lib/appsignal/hooks/sidekiq.rb 47363db942f3ba5c03ee36b843fc0aa882ec1de4
|
47
|
+
lib/appsignal/hooks/unicorn.rb 849811ad49a1e167adfa1a4473bf66757b2e53ae
|
48
|
+
lib/appsignal/loaders/grape.rb ee67e520fd81487cfe7cd5e3f274430f1f010460
|
49
|
+
lib/appsignal/check_in/event.rb e12992100bb5ed0929f20c9e39b1430bd2856953
|
50
|
+
lib/appsignal/hooks/net_http.rb 354ad06f444444bfab2ee9afa828e1a50e01ac31
|
51
|
+
lib/appsignal/loaders/hanami.rb 148e07afebc7107d01da7ac31883eb69b114a931
|
52
|
+
lib/appsignal/probes/helpers.rb 63ccc305a4d151427ecf92b095e9073e092b7710
|
53
|
+
lib/appsignal/probes/sidekiq.rb 1eec4acd55c2994fc84a6aecf0ea4bbc3930929b
|
54
|
+
lib/appsignal/event_formatter.rb b381c5f7c19fc12ede31eafff503e29897af5acf
|
55
|
+
lib/appsignal/extension/jruby.rb 3606120b6dd40e29274f9374a7748f524ab6cc19
|
56
|
+
lib/appsignal/helpers/metrics.rb 7ed5894743f2f9d5d47df864ba1531e7782279d3
|
57
|
+
lib/appsignal/hooks/celluloid.rb b0e39f3de8d9ab2757fd65a5f0aae866020c7d41
|
58
|
+
lib/appsignal/hooks/ownership.rb 286189e09afb0ab2f9bf2385bdc00517067ae48c
|
59
|
+
lib/appsignal/hooks/passenger.rb 46771e1ced6fbc90fb291a23cd4946f2de595bc3
|
60
|
+
lib/appsignal/hooks/shoryuken.rb 3e402b842a767a36198d2a827f80bb43e9ff3ca5
|
61
|
+
lib/appsignal/internal_errors.rb 4d775b12b66d5fd7962a93c931310f9fa0d1e6c1
|
62
|
+
lib/appsignal/loaders/padrino.rb fbf33e69aa9d613b0bb094e86e914b25f85ca002
|
63
|
+
lib/appsignal/loaders/sinatra.rb 793c9da7a2218076b8c453af3dad761b666a3733
|
64
|
+
lib/appsignal/hooks/active_job.rb defcc95f8fb12a340e822852b3817a0e1865fef2
|
65
|
+
lib/appsignal/hooks/webmachine.rb 02f35096d4d58a4fb87f372e45fa859d840d1bcd
|
66
|
+
lib/appsignal/integrations/que.rb 098ee55bb54ac8d63744c4a55747d4bce79a2c5d
|
67
|
+
lib/appsignal/hooks/data_mapper.rb f51b139a6237954db634a2205ff21f69f54a0d75
|
68
|
+
lib/appsignal/hooks/delayed_job.rb b6feb82fbbe73ac671ba7b21017082bf35b2a362
|
69
|
+
lib/appsignal/hooks/dry_monitor.rb 26e3909a7bb2a4b2b8ba94aaf5191e586d75f9e0
|
70
|
+
lib/appsignal/integrations/http.rb 8db05e03ef8866bf02659a93648697534c0cb2c4
|
71
|
+
lib/appsignal/integrations/puma.rb 54e350af5b1144ba6ae7ea3554576ba12e4027b5
|
72
|
+
lib/appsignal/integrations/rake.rb 2453ec4594b32c07859f308204b08a333e2a4bc6
|
73
|
+
lib/appsignal/rack/body_wrapper.rb 4716bd661ea0d771d26ec5a32d5485aad4e8b199
|
74
|
+
lib/appsignal/check_in/scheduler.rb 385a26f761664ded050e5e83eb91c231078dfc63
|
75
|
+
lib/appsignal/cli/diagnose/paths.rb f91c0f59098d63aa84977744c4cebdfaf745b4a2
|
76
|
+
lib/appsignal/cli/diagnose/utils.rb 3705ee19b0c61b64e11596de5971600a8d387532
|
77
|
+
lib/appsignal/garbage_collection.rb d3c15b529902faa9aaadbba4f8f66cc7a8b6e8b5
|
78
|
+
lib/appsignal/hooks/action_cable.rb d79ea8aa05c439707dc9eda8f0e2f339204b1cf4
|
79
|
+
lib/appsignal/hooks/redis_client.rb f832f3d47cfa2da941570124987ae643fefcd55c
|
80
|
+
lib/appsignal/integrations/excon.rb 7f25d4c567cad1330772a824a03de510769c0632
|
81
|
+
lib/appsignal/integrations/redis.rb 2767d5d1c30648c94e1b9f5151eae735216af478
|
82
|
+
lib/appsignal/rack/event_handler.rb ada1934464bd42b592f0dca039d1174d74fd0047
|
83
|
+
lib/appsignal/utils/rails_helper.rb 40047e913fd1b03e34e1dc2d1d3f6f594cde8125
|
84
|
+
lib/appsignal/hooks/action_mailer.rb 721fe17441c469f2026bc4878c702a740a15cdc4
|
85
|
+
lib/appsignal/integrations/object.rb 737bfabf786be2b64bb1a15e60637a75d3858ec3
|
86
|
+
lib/appsignal/integrations/resque.rb b66ff57aeb4adcfd123e000028ca5a200fd4654a
|
87
|
+
lib/appsignal/hooks/code_ownership.rb 399f948116f481402255075b8385f4fc7ee2e555
|
88
|
+
lib/appsignal/integrations/railtie.rb 9bfdae1cfcf23dd5734e91957d937023c95881a0
|
89
|
+
lib/appsignal/integrations/sidekiq.rb fb7f94b9f2fb98ceea6540482da343d1f08363e7
|
90
|
+
lib/appsignal/integrations/unicorn.rb 0f85f9d7adfcc9c13c4424d9794eae3fb1d89438
|
91
|
+
lib/appsignal/integrations/net_http.rb f3f4b0aa755cd25608779c8b5165799782f23ece
|
92
|
+
lib/appsignal/rack/event_middleware.rb c8f00f99785bcf73028af7ed78772620db1cb9b4
|
93
|
+
lib/appsignal/rack/grape_middleware.rb 19a42821235ea1df52624be2805bb7cfafa879e8
|
94
|
+
lib/appsignal/integrations/ownership.rb cd87fcbdaf1e090c03813ae84b97413442a35b54
|
95
|
+
lib/appsignal/integrations/shoryuken.rb 58759e9c37e06b59c0f66cedf57d4e29564b13e9
|
96
|
+
lib/appsignal/rack/hanami_middleware.rb 547d5e6140d329f818a499ddefe56f30a9f03300
|
97
|
+
lib/appsignal/helpers/instrumentation.rb d9dd2be5ef1963e0372819dbb495bcd8abae7096
|
98
|
+
lib/appsignal/hooks/mongo_ruby_driver.rb 107ec60626d5088b69d2164472b0a4a2212d716b
|
99
|
+
lib/appsignal/integrations/webmachine.rb fe009df5c9a6a0ea6df6ded1c1fc3351b9169353
|
100
|
+
lib/appsignal/integrations/data_mapper.rb 9b1ea78f9ea9eb4ecd560482f5e51e98945f7ce8
|
101
|
+
lib/appsignal/integrations/dry_monitor.rb b80261d5f3e2d9eb78bd34916712bc2cb3441c12
|
102
|
+
lib/appsignal/rack/abstract_middleware.rb f71cc57cc6c94b0fe9886a569a057060cc23fdc4
|
103
|
+
lib/appsignal/utils/integration_logger.rb 7ecb02fa3de92139b38af9ea9607ae50e484d009
|
104
|
+
lib/appsignal/integrations/action_cable.rb 704524c87fe40928e147805e6f1b1eff68517d84
|
105
|
+
lib/appsignal/integrations/redis_client.rb c2aeebd51d0828ad00a199b85c6cc51dc33ced89
|
106
|
+
lib/appsignal/rack/rails_instrumentation.rb 59d8413b3ed1486781a32c9f3fba61f0d808e550
|
107
|
+
lib/appsignal/integrations/code_ownership.rb 235e5c309ea96ed0bd9521b144a3e8ad6f137b30
|
108
|
+
lib/appsignal/utils/sample_data_sanitizer.rb 061bff99244f75de00466291bb20e1944501cec0
|
109
|
+
lib/appsignal/rack/sinatra_instrumentation.rb 04bdaaefc0ad729f1a66457240f1487d90afed7c
|
110
|
+
lib/appsignal/utils/query_params_sanitizer.rb 5d718b4dd7934d8f910eb7832e5fbebf790d4b26
|
111
|
+
lib/sequel/extensions/appsignal_integration.rb 11afd6a09a188861382305572f6361261fec0803
|
112
|
+
lib/appsignal/integrations/mongo_ruby_driver.rb 13e213612656fd2f27be93a3df9936be9046660c
|
113
|
+
lib/appsignal/integrations/delayed_job_plugin.rb 4f7c561f5c135cf4bff4f8c9a7ca41fb98f811a8
|
114
|
+
lib/appsignal/rack/instrumentation_middleware.rb a9893e69b88a0e3f442fb369a80dc6a5805d4da1
|
115
|
+
lib/appsignal/utils/integration_memory_logger.rb 10f8f4b32d2e18d898cc1a6c69c955440d569d70
|
116
|
+
lib/appsignal/utils/stdout_and_logger_message.rb 7788e16c07e28f18779ad6ee61e33bea875ac4dc
|
117
|
+
lib/appsignal/event_formatter/rom/sql_formatter.rb c94b4d23863323babb58696a678572bda8b60f66
|
118
|
+
lib/appsignal/hooks/active_support_notifications.rb 7eaf6f838ced6a24931355a4e11e97319e6d8cec
|
119
|
+
lib/appsignal/event_formatter/sequel/sql_formatter.rb 69b9c037a80234d037923bdeb23fd53bd577c018
|
120
|
+
lib/appsignal/event_formatter/faraday/request_formatter.rb 93c62a8926468b70ba838a0863ed5e981e0165de
|
121
|
+
lib/appsignal/integrations/active_support_notifications.rb 54737fe5142bc2d8b25d22372a77eea030d72ba4
|
122
|
+
lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb 67f6c21a691d49738fbecc1cbf4ba466686b53f4
|
123
|
+
lib/appsignal/event_formatter/active_record/sql_formatter.rb 6a21fd648cf525b864af09a80229512a67b7e4dd
|
124
|
+
lib/appsignal/event_formatter/action_view/render_formatter.rb 7cf5e19b711e5300079c8ba40815dd5178d52ef7
|
125
|
+
lib/appsignal/event_formatter/elastic_search/search_formatter.rb a358ec7a5a2e3669a80cb65c13a7650d78097a31
|
126
|
+
lib/appsignal/event_formatter/view_component/render_formatter.rb 9cc8ef5855a193ea8c297203bcc13fa5942f26f2
|
127
|
+
lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb 1d357c7a51561349d475cd4b7217c73f9fa05099
|
128
|
+
lib/appsignal/event_formatter/active_record/instantiation_formatter.rb 255077b4c9fb4925e749449de5ab12713a8efb96
|
129
|
+
ext/base.rb 666e9305b03cf9e9867d336de83d1882cea61909
|
130
|
+
ext/agent.rb 3fc4e641fb5cf96ce6bd0b8e22e9666cbd1c844c
|
131
|
+
ext/extconf.rb 8c48bb9264d1b676ec225e1696dbea6c6e8f485d
|
132
|
+
ext/appsignal_extension.c 7b7099fdc4c05a5e03279debcbdb8702dd2553a1
|
data/.yardoc/complete
ADDED
File without changes
|
Binary file
|
Binary file
|
data/.yardoc/proxy_types
ADDED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,64 @@
|
|
1
1
|
# AppSignal for Ruby gem Changelog
|
2
2
|
|
3
|
+
## 4.7.1
|
4
|
+
|
5
|
+
_Published on 2025-09-19._
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- Add support for the [CodeOwnership](https://github.com/rubyatscale/code_ownership) gem, which allows engineering teams to declare ownership of specific parts of a codebase.
|
10
|
+
|
11
|
+
When an error is reported, the AppSignal gem will tag the transaction with the owner of the file that caused the error.
|
12
|
+
|
13
|
+
This feature is enabled by default. To disable it, set the [`instrument_code_ownership` configuration option](https://docs.appsignal.com/ruby/configuration/options.html#option-instrument_code_ownership) to `false`.
|
14
|
+
|
15
|
+
(patch [40860cb2](https://github.com/appsignal/appsignal-ruby/commit/40860cb2c64f9f0ff93dbba253514ddb06020a5f))
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- Do not patch `Rack::Events` when using recent Rack versions. When using versions 3.2.1 and above,
|
20
|
+
which contain a fix for the bug where using `Rack::Events` breaks requests with streaming bodies,
|
21
|
+
use `Rack::Events` directly, instead of our patched subclass.
|
22
|
+
|
23
|
+
(patch [64f5b0ee](https://github.com/appsignal/appsignal-ruby/commit/64f5b0eebe07e6937a6397ab089d2b6bf1bd234d))
|
24
|
+
|
25
|
+
### Fixed
|
26
|
+
|
27
|
+
- Fix Rails version detection when only one of Rails's gems is present.
|
28
|
+
|
29
|
+
This prevents loading errors when non-Rails code defines a Rails constant without the full Rails framework.
|
30
|
+
|
31
|
+
(patch [f06952d9](https://github.com/appsignal/appsignal-ruby/commit/f06952d9ac095bb9c7455acd8ab563beb84d8433))
|
32
|
+
|
33
|
+
## 4.7.0
|
34
|
+
|
35
|
+
_Published on 2025-08-29._
|
36
|
+
|
37
|
+
### Added
|
38
|
+
|
39
|
+
- Add Sidekiq worker-level job status metric: `worker_job_count`. This new counter metric's `status` tag will be `processed` for each job that's processed and reports another counter with the `failure` status if the job encountered an error. (minor [fa9859af](https://github.com/appsignal/appsignal-ruby/commit/fa9859af3c82c34201cf68c80858596014fe9c34))
|
40
|
+
|
41
|
+
### Fixed
|
42
|
+
|
43
|
+
- Support streaming bodies. AppSignal's Rack instrumentation now supports streaming bodies in responses, such as those produced by `Async::Cable`. This fixes an issue where AppSignal's Rack instrumentation would cause requests with streaming bodies to crash.
|
44
|
+
|
45
|
+
If you use our Rack instrumentation through a framework that is automatically instrumented by AppSignal, such as Rails, Hanami, Padrino or Sinatra, this fix is applied automatically.
|
46
|
+
|
47
|
+
If your application instruments Rack manually, you must remove the following line from your application's initial setup:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
use Rack::Events, [Appsignal::Rack::EventHandler.new]
|
51
|
+
```
|
52
|
+
|
53
|
+
And replace it with the following line:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
use Appsignal::Rack::EventMiddleware
|
57
|
+
```
|
58
|
+
|
59
|
+
(minor [c94315e3](https://github.com/appsignal/appsignal-ruby/commit/c94315e337801347620826504a24f44ba3ee2b53))
|
60
|
+
- Avoid instrumenting Rails when AppSignal is not active. If AppSignal is configured to start when the Rails application loads, rather than after it has initialised, only add Rails' instrumentation middlewares if AppSignal was actually started. (patch [0239a2c3](https://github.com/appsignal/appsignal-ruby/commit/0239a2c32d0835af00a4659cc7533465ef17f451))
|
61
|
+
|
3
62
|
## 4.6.0
|
4
63
|
|
5
64
|
_Published on 2025-07-29._
|
data/CLAUDE.md
CHANGED
@@ -142,6 +142,21 @@ rake extension:install
|
|
142
142
|
cd ext && rake
|
143
143
|
```
|
144
144
|
|
145
|
+
### Type signatures
|
146
|
+
|
147
|
+
The Ruby gem includes type signatures for better IDE support and static analysis:
|
148
|
+
|
149
|
+
- `sig/appsignal.rbi` - Sorbet type signatures
|
150
|
+
- `sig/appsignal.rbs` - RBS type signatures
|
151
|
+
|
152
|
+
To regenerate type signatures from YARD documentation:
|
153
|
+
|
154
|
+
```bash
|
155
|
+
script/generate_signatures
|
156
|
+
```
|
157
|
+
|
158
|
+
This script uses [sord](https://github.com/AaronC81/sord) to generate both RBI and RBS files from YARD comments in the source code.
|
159
|
+
|
145
160
|
## File organization
|
146
161
|
|
147
162
|
### Configuration files
|
data/build_matrix.yml
CHANGED
@@ -115,6 +115,7 @@ matrix:
|
|
115
115
|
- "rails-7.1"
|
116
116
|
- "rails-7.2"
|
117
117
|
- "rails-8.0"
|
118
|
+
- "rails-8.1"
|
118
119
|
|
119
120
|
ruby:
|
120
121
|
- ruby: "3.5.0-preview1"
|
@@ -130,6 +131,7 @@ matrix:
|
|
130
131
|
- gem: "no_dependencies"
|
131
132
|
- gem: "capistrano2"
|
132
133
|
- gem: "capistrano3"
|
134
|
+
- gem: "code_ownership"
|
133
135
|
- gem: "dry-monitor"
|
134
136
|
only:
|
135
137
|
ruby:
|
@@ -243,6 +245,13 @@ matrix:
|
|
243
245
|
- "3.4.1"
|
244
246
|
- "3.3.4"
|
245
247
|
- "3.2.5"
|
248
|
+
- gem: "rails-8.1"
|
249
|
+
only:
|
250
|
+
ruby:
|
251
|
+
- "3.5.0-preview1"
|
252
|
+
- "3.4.1"
|
253
|
+
- "3.3.4"
|
254
|
+
- "3.2.5"
|
246
255
|
- gem: "sequel"
|
247
256
|
- gem: "sinatra"
|
248
257
|
- gem: "webmachine2"
|
data/lib/appsignal/config.rb
CHANGED
@@ -112,6 +112,7 @@ module Appsignal
|
|
112
112
|
:ignore_errors => [],
|
113
113
|
:ignore_logs => [],
|
114
114
|
:ignore_namespaces => [],
|
115
|
+
:instrument_code_ownership => true,
|
115
116
|
:instrument_http_rb => true,
|
116
117
|
:instrument_net_http => true,
|
117
118
|
:instrument_ownership => true,
|
@@ -186,6 +187,7 @@ module Appsignal
|
|
186
187
|
:enable_rake_performance_instrumentation =>
|
187
188
|
"APPSIGNAL_ENABLE_RAKE_PERFORMANCE_INSTRUMENTATION",
|
188
189
|
:files_world_accessible => "APPSIGNAL_FILES_WORLD_ACCESSIBLE",
|
190
|
+
:instrument_code_ownership => "APPSIGNAL_INSTRUMENT_CODE_OWNERSHIP",
|
189
191
|
:instrument_http_rb => "APPSIGNAL_INSTRUMENT_HTTP_RB",
|
190
192
|
:instrument_net_http => "APPSIGNAL_INSTRUMENT_NET_HTTP",
|
191
193
|
:instrument_ownership => "APPSIGNAL_INSTRUMENT_OWNERSHIP",
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
class Hooks
|
5
|
+
# @!visibility private
|
6
|
+
class CodeOwnershipHook < Appsignal::Hooks::Hook
|
7
|
+
register :code_ownership
|
8
|
+
|
9
|
+
def dependencies_present?
|
10
|
+
defined?(::CodeOwnership) &&
|
11
|
+
Gem::Specification.find_by_name("code_ownership").version < Gem::Version.new("2.0") &&
|
12
|
+
Appsignal.config && Appsignal.config[:instrument_code_ownership]
|
13
|
+
end
|
14
|
+
|
15
|
+
def install
|
16
|
+
require "appsignal/integrations/code_ownership"
|
17
|
+
|
18
|
+
Appsignal::Transaction.before_complete <<
|
19
|
+
Appsignal::Integrations::CodeOwnershipIntegration.method(:before_complete)
|
20
|
+
|
21
|
+
Appsignal::Environment.report_enabled("code_ownership")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/appsignal/hooks.rb
CHANGED
@@ -80,6 +80,7 @@ require "appsignal/hooks/action_mailer"
|
|
80
80
|
require "appsignal/hooks/active_job"
|
81
81
|
require "appsignal/hooks/active_support_notifications"
|
82
82
|
require "appsignal/hooks/celluloid"
|
83
|
+
require "appsignal/hooks/code_ownership"
|
83
84
|
require "appsignal/hooks/delayed_job"
|
84
85
|
require "appsignal/hooks/gvl"
|
85
86
|
require "appsignal/hooks/dry_monitor"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
module Integrations
|
5
|
+
# @!visibility private
|
6
|
+
module CodeOwnershipIntegration
|
7
|
+
class << self
|
8
|
+
def before_complete(transaction, error)
|
9
|
+
team = ::CodeOwnership.for_backtrace(error.backtrace)
|
10
|
+
transaction.add_tags(:owner => team.name)
|
11
|
+
rescue => ex
|
12
|
+
logger = Appsignal.internal_logger
|
13
|
+
logger.error(
|
14
|
+
"Error while looking up CodeOwnership team: #{ex.class}: #{ex.message}\n" \
|
15
|
+
"#{ex.backtrace.join("\n")}"
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
rails_version = Rails.respond_to?(:version) ? Rails.version : "unknown"
|
4
|
+
Appsignal.internal_logger.debug("Loading Rails (#{rails_version}) integration")
|
4
5
|
|
5
6
|
require "appsignal/utils/rails_helper"
|
6
7
|
require "appsignal/rack/rails_instrumentation"
|
@@ -28,11 +29,19 @@ module Appsignal
|
|
28
29
|
|
29
30
|
def self.on_load(app)
|
30
31
|
load_default_config
|
31
|
-
Appsignal::Integrations::Railtie.add_instrumentation_middleware(app)
|
32
32
|
|
33
|
-
|
33
|
+
Appsignal::Integrations::Railtie.start if app.config.appsignal.start_at == :on_load
|
34
34
|
|
35
|
-
|
35
|
+
# If AppSignal is supposed to start after initialization, we need to add the
|
36
|
+
# instrumentation middleware now, even if AppSignal may not actually start
|
37
|
+
# later, because the middleware stack will be frozen after initialization.
|
38
|
+
#
|
39
|
+
# Otherwise, only add the instrumentation middleware if AppSignal did actually
|
40
|
+
# start before this point, preventing the middleware from being added when
|
41
|
+
# AppSignal is not active.
|
42
|
+
return unless app.config.appsignal.start_at == :after_initialize || Appsignal.started?
|
43
|
+
|
44
|
+
add_instrumentation_middleware(app)
|
36
45
|
end
|
37
46
|
|
38
47
|
def self.after_initialize(app)
|
@@ -52,14 +61,15 @@ module Appsignal
|
|
52
61
|
|
53
62
|
def self.start
|
54
63
|
Appsignal.start
|
55
|
-
|
64
|
+
return unless Appsignal.started?
|
65
|
+
|
66
|
+
initialize_error_reporter
|
56
67
|
end
|
57
68
|
|
58
69
|
def self.add_instrumentation_middleware(app)
|
59
70
|
app.middleware.insert(
|
60
71
|
0,
|
61
|
-
::Rack::
|
62
|
-
[Appsignal::Rack::EventHandler.new]
|
72
|
+
::Appsignal::Rack::EventMiddleware
|
63
73
|
)
|
64
74
|
app.middleware.insert_after(
|
65
75
|
ActionDispatch::DebugExceptions,
|
@@ -66,8 +66,9 @@ module Appsignal
|
|
66
66
|
|
67
67
|
def call(_worker, item, _queue, &block)
|
68
68
|
job_status = nil
|
69
|
+
action_name = formatted_action_name(item)
|
69
70
|
transaction = Appsignal::Transaction.create(Appsignal::Transaction::BACKGROUND_JOB)
|
70
|
-
transaction.set_action_if_nil(
|
71
|
+
transaction.set_action_if_nil(action_name)
|
71
72
|
|
72
73
|
formatted_metadata(item).each do |key, value|
|
73
74
|
transaction.set_metadata key, value
|
@@ -93,14 +94,24 @@ module Appsignal
|
|
93
94
|
Appsignal::Transaction.complete_current! unless exception
|
94
95
|
|
95
96
|
queue = item["queue"] || "unknown"
|
97
|
+
|
96
98
|
if job_status
|
97
99
|
increment_counter "queue_job_count", 1,
|
98
100
|
:queue => queue,
|
99
101
|
:status => job_status
|
102
|
+
increment_counter "worker_job_count", 1,
|
103
|
+
:worker => action_name,
|
104
|
+
:queue => queue,
|
105
|
+
:status => job_status
|
100
106
|
end
|
101
107
|
increment_counter "queue_job_count", 1,
|
102
108
|
:queue => queue,
|
103
109
|
:status => :processed
|
110
|
+
increment_counter "worker_job_count", 1,
|
111
|
+
:worker => action_name,
|
112
|
+
:queue => queue,
|
113
|
+
:status => :processed
|
114
|
+
|
104
115
|
end
|
105
116
|
end
|
106
117
|
|
@@ -21,10 +21,7 @@ module Appsignal
|
|
21
21
|
require "appsignal/rack/hanami_middleware"
|
22
22
|
|
23
23
|
hanami_app_config = ::Hanami.app.config
|
24
|
-
hanami_app_config.middleware.use(
|
25
|
-
::Rack::Events,
|
26
|
-
[Appsignal::Rack::EventHandler.new]
|
27
|
-
)
|
24
|
+
hanami_app_config.middleware.use(Appsignal::Rack::EventMiddleware)
|
28
25
|
hanami_app_config.middleware.use(Appsignal::Rack::HanamiMiddleware)
|
29
26
|
|
30
27
|
return unless Gem::Version.new(Hanami::VERSION) < Gem::Version.new("2.2.0")
|
@@ -18,7 +18,7 @@ module Appsignal
|
|
18
18
|
Padrino::Application.prepend(Appsignal::Loaders::PadrinoLoader::PadrinoIntegration)
|
19
19
|
|
20
20
|
Padrino.before_load do
|
21
|
-
Padrino.use
|
21
|
+
Padrino.use Appsignal::Rack::EventMiddleware
|
22
22
|
Padrino.use Appsignal::Rack::SinatraBaseInstrumentation,
|
23
23
|
:instrument_event_name => "process_action.padrino"
|
24
24
|
end
|
@@ -16,7 +16,7 @@ module Appsignal
|
|
16
16
|
def on_start
|
17
17
|
require "appsignal/rack/sinatra_instrumentation"
|
18
18
|
|
19
|
-
::Sinatra::Base.use(
|
19
|
+
::Sinatra::Base.use(Appsignal::Rack::EventMiddleware)
|
20
20
|
::Sinatra::Base.use(Appsignal::Rack::SinatraBaseInstrumentation)
|
21
21
|
end
|
22
22
|
end
|
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
module Appsignal
|
4
4
|
module Rack
|
5
|
-
# Instrumentation
|
5
|
+
# Instrumentation event handler for `Rack::Events`.
|
6
6
|
#
|
7
|
-
#
|
8
|
-
# {
|
7
|
+
# Using this middleware directly with `Rack::Events` is deprecated.
|
8
|
+
# We recommend using {EventMiddleware} instead, which is compatible with
|
9
|
+
# streaming bodies, in combination with the {InstrumentationMiddleware}.
|
9
10
|
#
|
10
11
|
# This middleware will report the response status code as the
|
11
12
|
# `response_status` tag on the sample. It will also report the response
|
@@ -38,10 +39,12 @@ module Appsignal
|
|
38
39
|
|
39
40
|
# @api private
|
40
41
|
attr_reader :id
|
42
|
+
attr_writer :using_appsignal_event_middleware
|
41
43
|
|
42
44
|
# @api private
|
43
45
|
def initialize
|
44
46
|
@id = SecureRandom.uuid
|
47
|
+
@using_appsignal_event_middleware = false
|
45
48
|
end
|
46
49
|
|
47
50
|
# @api private
|
@@ -51,6 +54,8 @@ module Appsignal
|
|
51
54
|
|
52
55
|
# @api private
|
53
56
|
def on_start(request, _response)
|
57
|
+
emit_warning_once
|
58
|
+
|
54
59
|
return unless Appsignal.active?
|
55
60
|
|
56
61
|
event_handler = self
|
@@ -152,6 +157,19 @@ module Appsignal
|
|
152
157
|
namespace
|
153
158
|
end
|
154
159
|
end
|
160
|
+
|
161
|
+
def emit_warning_once
|
162
|
+
return if @using_appsignal_event_middleware
|
163
|
+
|
164
|
+
Appsignal.internal_logger.warn <<~MSG
|
165
|
+
Rack::Events is not compatible with streaming bodies. Using `Appsignal::Rack::EventHandler`#{" "}
|
166
|
+
with `Rack::Events` will break streaming responses in your application and is deprecated.#{" "}
|
167
|
+
To silence this warning, use `Appsignal::Rack::EventMiddleware` instead, which is compatible#{" "}
|
168
|
+
with streaming bodies.#{" "}
|
169
|
+
See https://docs.appsignal.com/ruby/integrations/rack.html for more information.
|
170
|
+
MSG
|
171
|
+
@using_appsignal_event_middleware = true
|
172
|
+
end
|
155
173
|
end
|
156
174
|
end
|
157
175
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
module Rack
|
5
|
+
# @api private
|
6
|
+
def self.rack_3_2_1_or_newer?
|
7
|
+
return false unless ::Rack.respond_to?(:release)
|
8
|
+
|
9
|
+
Gem::Version.new(::Rack.release) >= Gem::Version.new("3.2.1")
|
10
|
+
end
|
11
|
+
|
12
|
+
# Modified version of the {::Rack::Events} instrumentation
|
13
|
+
# middleware.
|
14
|
+
#
|
15
|
+
# We recommend using this instead of {::Rack::Events}, as it
|
16
|
+
# is compatible with streaming bodies when using Rack versions
|
17
|
+
# before 3.2.0.
|
18
|
+
#
|
19
|
+
# We do not recommend using this middleware directly, instead
|
20
|
+
# recommending the use of {EventMiddleware}, which is a
|
21
|
+
# convenience wrapper around this middleware that includes
|
22
|
+
# AppSignal's {EventHandler}.
|
23
|
+
#
|
24
|
+
# See the original implementation at:
|
25
|
+
# https://github.com/rack/rack/blob/8d3d7857fcd9e5df057a6c22458bab35b3a19c12/lib/rack/events.rb
|
26
|
+
|
27
|
+
if rack_3_2_1_or_newer?
|
28
|
+
Events = ::Rack::Events
|
29
|
+
else
|
30
|
+
class Events < ::Rack::Events
|
31
|
+
# A stub for {::Rack::Events::EventedBodyProxy}. It
|
32
|
+
# allows the same initialization arguments, but
|
33
|
+
# otherwise behaves identically to {::Rack::BodyProxy}.
|
34
|
+
#
|
35
|
+
# It does not implement `#each`, fixing an issue
|
36
|
+
# where the evented body proxy would break
|
37
|
+
# streaming responses by always responding to `#each`
|
38
|
+
# even if the proxied body did not implement it.
|
39
|
+
#
|
40
|
+
# Because it ignores the handlers passed to it and
|
41
|
+
# behaves like a normal body proxy, the `on_send`
|
42
|
+
# event on the handlers is never called.
|
43
|
+
class EventedBodyProxy < ::Rack::BodyProxy
|
44
|
+
def initialize(body, _request, _response, _handlers, &block)
|
45
|
+
super(body, &block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# The `call` method, exactly as implemented by {::Rack::Events},
|
50
|
+
# but redefined here so that it uses our {EventedBodyProxy}
|
51
|
+
# instead of the original {::Rack::Events::EventedBodyProxy}.
|
52
|
+
#
|
53
|
+
# This fixes streaming bodies, but it also means that the
|
54
|
+
# `on_send` event on the handlers is never called.
|
55
|
+
#
|
56
|
+
# See the original implementation at:
|
57
|
+
# https://github.com/rack/rack/blob/8d3d7857fcd9e5df057a6c22458bab35b3a19c12/lib/rack/events.rb#L111-L129
|
58
|
+
def call(env)
|
59
|
+
request = make_request env
|
60
|
+
on_start request, nil
|
61
|
+
|
62
|
+
begin
|
63
|
+
status, headers, body = @app.call request.env
|
64
|
+
response = make_response status, headers, body
|
65
|
+
on_commit request, response
|
66
|
+
rescue StandardError => e
|
67
|
+
on_error request, response, e
|
68
|
+
on_finish request, response
|
69
|
+
raise
|
70
|
+
end
|
71
|
+
|
72
|
+
body = EventedBodyProxy.new(body, request, response, @handlers) do
|
73
|
+
on_finish request, response
|
74
|
+
end
|
75
|
+
[response.status, response.headers, body]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Instrumentation middleware using Rack's Events module.
|
81
|
+
#
|
82
|
+
# A convenience wrapper around our {Events} middleware,
|
83
|
+
# modified to be compatible with streaming bodies,
|
84
|
+
# that automatically includes AppSignal's {EventHandler}.
|
85
|
+
#
|
86
|
+
# We recommend using this in combination with the
|
87
|
+
# {InstrumentationMiddleware}.
|
88
|
+
#
|
89
|
+
# This middleware will report the response status code as the
|
90
|
+
# `response_status` tag on the sample. It will also report the response
|
91
|
+
# status as the `response_status` metric.
|
92
|
+
#
|
93
|
+
# This middleware will ensure the AppSignal transaction is always completed
|
94
|
+
# for every request.
|
95
|
+
#
|
96
|
+
# @example Add EventMiddleware to a Rack app
|
97
|
+
# # Add this middleware as the first middleware of an app
|
98
|
+
# use Appsignal::Rack::EventMiddleware
|
99
|
+
#
|
100
|
+
# # Then add the InstrumentationMiddleware
|
101
|
+
# use Appsignal::Rack::InstrumentationMiddleware
|
102
|
+
#
|
103
|
+
# @see https://docs.appsignal.com/ruby/integrations/rack.html
|
104
|
+
# Rack integration documentation.
|
105
|
+
# @api public
|
106
|
+
class EventMiddleware < Events
|
107
|
+
def initialize(app)
|
108
|
+
super(app, [Appsignal::Rack::EventHandler.new.tap do |handler|
|
109
|
+
handler.using_appsignal_event_middleware = true
|
110
|
+
end])
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -27,8 +27,8 @@ module Appsignal
|
|
27
27
|
# require "appsignal"
|
28
28
|
# # Configure and start AppSignal
|
29
29
|
#
|
30
|
-
# # Add the
|
31
|
-
# use
|
30
|
+
# # Add the EventMiddleware first
|
31
|
+
# use Appsignal::Rack::EventMiddleware
|
32
32
|
# # Add the instrumentation middleware second
|
33
33
|
# use Appsignal::Rack::InstrumentationMiddleware
|
34
34
|
#
|
data/lib/appsignal/version.rb
CHANGED
data/lib/appsignal.rb
CHANGED
@@ -643,7 +643,8 @@ require "appsignal/rack/body_wrapper"
|
|
643
643
|
require "appsignal/rack/abstract_middleware"
|
644
644
|
require "appsignal/rack/instrumentation_middleware"
|
645
645
|
require "appsignal/rack/event_handler"
|
646
|
-
require "appsignal/
|
646
|
+
require "appsignal/rack/event_middleware"
|
647
|
+
require "appsignal/integrations/railtie" if defined?(::Rails::Railtie)
|
647
648
|
require "appsignal/transaction"
|
648
649
|
require "appsignal/version"
|
649
650
|
require "appsignal/transmitter"
|
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: 4.
|
4
|
+
version: 4.7.1
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Robert Beekman
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
- Tom de Bruijn
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: logger
|
@@ -174,6 +174,11 @@ extensions:
|
|
174
174
|
- ext/Rakefile
|
175
175
|
extra_rdoc_files: []
|
176
176
|
files:
|
177
|
+
- ".yardoc/checksums"
|
178
|
+
- ".yardoc/complete"
|
179
|
+
- ".yardoc/object_types"
|
180
|
+
- ".yardoc/objects/root.dat"
|
181
|
+
- ".yardoc/proxy_types"
|
177
182
|
- CHANGELOG.md
|
178
183
|
- CLAUDE.md
|
179
184
|
- CODE_OF_CONDUCT.md
|
@@ -230,6 +235,7 @@ files:
|
|
230
235
|
- lib/appsignal/hooks/active_support_notifications.rb
|
231
236
|
- lib/appsignal/hooks/at_exit.rb
|
232
237
|
- lib/appsignal/hooks/celluloid.rb
|
238
|
+
- lib/appsignal/hooks/code_ownership.rb
|
233
239
|
- lib/appsignal/hooks/data_mapper.rb
|
234
240
|
- lib/appsignal/hooks/delayed_job.rb
|
235
241
|
- lib/appsignal/hooks/dry_monitor.rb
|
@@ -256,6 +262,7 @@ files:
|
|
256
262
|
- lib/appsignal/integrations/active_support_notifications.rb
|
257
263
|
- lib/appsignal/integrations/capistrano/appsignal.cap
|
258
264
|
- lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb
|
265
|
+
- lib/appsignal/integrations/code_ownership.rb
|
259
266
|
- lib/appsignal/integrations/data_mapper.rb
|
260
267
|
- lib/appsignal/integrations/delayed_job_plugin.rb
|
261
268
|
- lib/appsignal/integrations/dry_monitor.rb
|
@@ -293,6 +300,7 @@ files:
|
|
293
300
|
- lib/appsignal/rack/abstract_middleware.rb
|
294
301
|
- lib/appsignal/rack/body_wrapper.rb
|
295
302
|
- lib/appsignal/rack/event_handler.rb
|
303
|
+
- lib/appsignal/rack/event_middleware.rb
|
296
304
|
- lib/appsignal/rack/grape_middleware.rb
|
297
305
|
- lib/appsignal/rack/hanami_middleware.rb
|
298
306
|
- lib/appsignal/rack/instrumentation_middleware.rb
|
@@ -346,7 +354,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
346
354
|
- !ruby/object:Gem::Version
|
347
355
|
version: '0'
|
348
356
|
requirements: []
|
349
|
-
rubygems_version: 3.6.
|
357
|
+
rubygems_version: 3.6.9
|
350
358
|
specification_version: 4
|
351
359
|
summary: Logs performance and exception data from your app to appsignal.com
|
352
360
|
test_files: []
|