skylight 4.3.2 → 5.0.0.beta

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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -5
  3. data/CONTRIBUTING.md +1 -7
  4. data/ext/extconf.rb +4 -3
  5. data/ext/libskylight.yml +5 -6
  6. data/ext/skylight_native.c +22 -99
  7. data/lib/skylight.rb +204 -14
  8. data/lib/skylight/api.rb +7 -3
  9. data/lib/skylight/cli.rb +4 -3
  10. data/lib/skylight/cli/doctor.rb +3 -2
  11. data/lib/skylight/cli/merger.rb +6 -4
  12. data/lib/skylight/config.rb +603 -126
  13. data/lib/skylight/deprecation.rb +15 -0
  14. data/lib/skylight/errors.rb +17 -2
  15. data/lib/skylight/extensions.rb +99 -0
  16. data/lib/skylight/extensions/source_location.rb +249 -0
  17. data/lib/skylight/fanout.rb +0 -0
  18. data/lib/skylight/formatters/http.rb +19 -0
  19. data/lib/skylight/gc.rb +109 -0
  20. data/lib/skylight/helpers.rb +18 -2
  21. data/lib/skylight/instrumenter.rb +325 -15
  22. data/lib/skylight/middleware.rb +138 -1
  23. data/lib/skylight/native.rb +51 -1
  24. data/lib/skylight/native_ext_fetcher.rb +2 -1
  25. data/lib/skylight/normalizers.rb +151 -0
  26. data/lib/skylight/normalizers/action_controller/process_action.rb +69 -0
  27. data/lib/skylight/normalizers/action_controller/send_file.rb +50 -0
  28. data/lib/skylight/normalizers/action_dispatch/process_middleware.rb +22 -0
  29. data/lib/skylight/normalizers/action_dispatch/route_set.rb +27 -0
  30. data/lib/skylight/normalizers/action_view/render_collection.rb +24 -0
  31. data/lib/skylight/normalizers/action_view/render_layout.rb +25 -0
  32. data/lib/skylight/normalizers/action_view/render_partial.rb +23 -0
  33. data/lib/skylight/normalizers/action_view/render_template.rb +23 -0
  34. data/lib/skylight/normalizers/active_job/perform.rb +81 -0
  35. data/lib/skylight/normalizers/active_model_serializers/render.rb +28 -0
  36. data/lib/skylight/normalizers/active_record/instantiation.rb +16 -0
  37. data/lib/skylight/normalizers/active_record/sql.rb +12 -0
  38. data/lib/skylight/normalizers/active_storage.rb +30 -0
  39. data/lib/skylight/normalizers/active_support/cache.rb +22 -0
  40. data/lib/skylight/normalizers/active_support/cache_clear.rb +16 -0
  41. data/lib/skylight/normalizers/active_support/cache_decrement.rb +16 -0
  42. data/lib/skylight/normalizers/active_support/cache_delete.rb +16 -0
  43. data/lib/skylight/normalizers/active_support/cache_exist.rb +16 -0
  44. data/lib/skylight/normalizers/active_support/cache_fetch_hit.rb +16 -0
  45. data/lib/skylight/normalizers/active_support/cache_generate.rb +16 -0
  46. data/lib/skylight/normalizers/active_support/cache_increment.rb +16 -0
  47. data/lib/skylight/normalizers/active_support/cache_read.rb +16 -0
  48. data/lib/skylight/normalizers/active_support/cache_read_multi.rb +16 -0
  49. data/lib/skylight/normalizers/active_support/cache_write.rb +16 -0
  50. data/lib/skylight/normalizers/coach/handler_finish.rb +46 -0
  51. data/lib/skylight/normalizers/coach/middleware_finish.rb +33 -0
  52. data/lib/skylight/normalizers/couch_potato/query.rb +20 -0
  53. data/lib/skylight/normalizers/data_mapper/sql.rb +12 -0
  54. data/lib/skylight/normalizers/default.rb +32 -0
  55. data/lib/skylight/normalizers/elasticsearch/request.rb +20 -0
  56. data/lib/skylight/normalizers/faraday/request.rb +40 -0
  57. data/lib/skylight/normalizers/grape/endpoint.rb +34 -0
  58. data/lib/skylight/normalizers/grape/endpoint_render.rb +25 -0
  59. data/lib/skylight/normalizers/grape/endpoint_run.rb +41 -0
  60. data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +22 -0
  61. data/lib/skylight/normalizers/grape/format_response.rb +20 -0
  62. data/lib/skylight/normalizers/graphiti/render.rb +22 -0
  63. data/lib/skylight/normalizers/graphiti/resolve.rb +31 -0
  64. data/lib/skylight/normalizers/graphql/base.rb +131 -0
  65. data/lib/skylight/normalizers/render.rb +81 -0
  66. data/lib/skylight/normalizers/sequel/sql.rb +12 -0
  67. data/lib/skylight/normalizers/sql.rb +44 -0
  68. data/lib/skylight/probes.rb +153 -0
  69. data/lib/skylight/probes/action_controller.rb +48 -0
  70. data/lib/skylight/probes/action_dispatch.rb +2 -0
  71. data/lib/skylight/probes/action_dispatch/request_id.rb +29 -0
  72. data/lib/skylight/probes/action_dispatch/routing/route_set.rb +28 -0
  73. data/lib/skylight/probes/action_view.rb +43 -0
  74. data/lib/skylight/probes/active_job.rb +29 -0
  75. data/lib/skylight/probes/active_job_enqueue.rb +37 -0
  76. data/lib/skylight/probes/active_model_serializers.rb +54 -0
  77. data/lib/skylight/probes/delayed_job.rb +62 -0
  78. data/lib/skylight/probes/elasticsearch.rb +38 -0
  79. data/lib/skylight/probes/excon.rb +25 -0
  80. data/lib/skylight/probes/excon/middleware.rb +66 -0
  81. data/lib/skylight/probes/faraday.rb +23 -0
  82. data/lib/skylight/probes/graphql.rb +43 -0
  83. data/lib/skylight/probes/httpclient.rb +44 -0
  84. data/lib/skylight/probes/middleware.rb +125 -0
  85. data/lib/skylight/probes/mongo.rb +163 -0
  86. data/lib/skylight/probes/mongoid.rb +13 -0
  87. data/lib/skylight/probes/net_http.rb +55 -0
  88. data/lib/skylight/probes/redis.rb +60 -0
  89. data/lib/skylight/probes/sequel.rb +33 -0
  90. data/lib/skylight/probes/sinatra.rb +63 -0
  91. data/lib/skylight/probes/sinatra_add_middleware.rb +10 -10
  92. data/lib/skylight/probes/tilt.rb +27 -0
  93. data/lib/skylight/railtie.rb +162 -18
  94. data/lib/skylight/sidekiq.rb +43 -0
  95. data/lib/skylight/subscriber.rb +110 -0
  96. data/lib/skylight/test.rb +146 -0
  97. data/lib/skylight/trace.rb +301 -10
  98. data/lib/skylight/user_config.rb +61 -0
  99. data/lib/skylight/util.rb +12 -0
  100. data/lib/skylight/util/allocation_free.rb +26 -0
  101. data/lib/skylight/util/clock.rb +56 -0
  102. data/lib/skylight/util/component.rb +5 -2
  103. data/lib/skylight/util/deploy.rb +4 -4
  104. data/lib/skylight/util/gzip.rb +20 -0
  105. data/lib/skylight/util/http.rb +4 -10
  106. data/lib/skylight/util/instrumenter_method.rb +26 -0
  107. data/lib/skylight/util/logging.rb +138 -0
  108. data/lib/skylight/util/lru_cache.rb +42 -0
  109. data/lib/skylight/vendor/cli/thor/rake_compat.rb +1 -1
  110. data/lib/skylight/version.rb +5 -1
  111. data/lib/skylight/vm/gc.rb +68 -0
  112. metadata +110 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2bf022bf2ba25bb9f9769526a93435b154a91f313862d068fd7b976d50d1bbb
4
- data.tar.gz: b7e87b5ffd0f1ac492156103cb4c6dadb22e3b245b73ceaaa46ad2b3f1cce3a6
3
+ metadata.gz: d7cc16a9f8a59047a74b34d19ed0f85e696e893d0f5c1c6984604a1358df6efb
4
+ data.tar.gz: b50cb4b7962f3b78bbccb5b3025bc051febcf6c8cd95303439add2f3df5cb75e
5
5
  SHA512:
6
- metadata.gz: b8fb515ffaf327347fba911035032a1827d2f33f96b654da6be32a3296c97ca4a2f863e43215904e7bffa0c8c1addbfb2e20de78c78fab24d79f2d11856737af
7
- data.tar.gz: 0055467bc67cb145b1cbf2f30caa77d52a266e74fcc5f48b851ceffbb8736df2bfe7fd92a45f374547d06e3b4d5257e1738d1a7651374a19336a7b0ca7910377
6
+ metadata.gz: dc3445e94e0b3c5dc4936569df35f60b7ce9ac5f82492f92c247aca1cb44f9570092b11f532d28a6d795b39d2a65eae4bac16b5ca1a9c4e7b1ae2b47eb6c87ff
7
+ data.tar.gz: c591bb63cd56354d0954955f93720f1183afb0f71bd6c0fd2df7cfb8f32dab2a4988eaa20fe3018615cbb47531163b09dddd1c849f430989ffb589f98b03f7c5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
- ## 4.3.2 (December 14, 2020)
2
- * [BUGFIX] Backport an ActionView fix from Skylight 5 (makes Skylight 4 compatible with Rails 6.1)
1
+ ## 5.0.0.beta
2
+ * [BREAKING] Merge skylight-core into skylight. All classes previously namespaced under `Skylight::Core` have been moved to `Skylight`.
3
+ * [BREAKING] Remove `Skylight::Util::Inflector`
4
+ * [BREAKING] Drop support for Rails 4
5
+ * [BREAKING] Drop support for Rails 2.3
6
+ * [IMPROVEMENT] Maintain method visibility when instrumenting with `instrument_method`
7
+ * [IMPROVEMENT] Update probes to use `Module#prepend` where possible
8
+ * [IMPROVEMENT] New tokio-based skylightd
9
+ * [IMPROVEMENT] Support `render_layout` notifications in Rails 6.1
10
+ * [IMPROVEMENT] Support `ActionMailer::MailDeliveryJob` in Rails 6.1
11
+ * [IMPROVEMENT] Better logging config
12
+ * [BUGFIX] Allow multiple probes to be registered under the same key
13
+ * [BUGFIX] Do not refer to Redis constant until the probe is installed
14
+ * [BUGFIX] Fix nested calls to `Normalizers::Faraday::Request.disable`
3
15
 
4
16
  ## 4.3.1 (June 24, 2020)
5
17
  * [BUGFIX] Fix an issue in which `Mime::NullType` would result in an exception
@@ -9,9 +21,6 @@
9
21
  * [IMPROVEMENT] Update Grape normalizer for version 1.3.1
10
22
  * [BUGFIX] Fix an issue where GraphQL normalizers could fail to load in non-Rails contexts
11
23
 
12
- ## 4.2.3 (March 10, 2020)
13
- * [BUGFIX] Fix an issue where the GraphQL probe may not always be installed
14
-
15
24
  ## 4.2.2 (February 25, 2020)
16
25
  * Support graphql-ruby version 1.10
17
26
 
data/CONTRIBUTING.md CHANGED
@@ -18,12 +18,6 @@ If you prefer to run tests in your own environment, you may do so as follows:
18
18
  # Select a gemfile and bundle install
19
19
  export BUNDLE_GEMFILE=$PWD/gemfiles/Gemfile.rails-5.2.x
20
20
  bundle install
21
-
22
- # Run the skylight-core test suite (takes a few seconds)
23
- pushd skylight-core
24
- bundle exec rspec
25
- popd
26
-
27
- # Run the main test suite (takes 5-10 minutes)
21
+ # Run the test suite (takes 5-10 minutes)
28
22
  bundle exec rspec
29
23
  ```
data/ext/extconf.rb CHANGED
@@ -32,7 +32,8 @@ SKYLIGHT_FETCH_LIB = !ENV.key?("SKYLIGHT_FETCH_LIB") || ENV["SKYLIGHT_FETCH_LIB
32
32
 
33
33
  # Directory where skylight.h exists
34
34
  SKYLIGHT_HDR_PATH = ENV["SKYLIGHT_HDR_PATH"] || ENV["SKYLIGHT_LIB_PATH"] || "."
35
- SKYLIGHT_LIB_PATH = ENV["SKYLIGHT_LIB_PATH"] || File.expand_path("../../lib/skylight/native/#{Platform.tuple}", __FILE__)
35
+ SKYLIGHT_LIB_PATH = ENV["SKYLIGHT_LIB_PATH"] ||
36
+ File.expand_path("../../lib/skylight/native/#{Platform.tuple}", __FILE__)
36
37
 
37
38
  SKYLIGHT_SOURCE_URL = ENV["SKYLIGHT_SOURCE_URL"]
38
39
  SKYLIGHT_VERSION = ENV["SKYLIGHT_VERSION"]
@@ -206,8 +207,8 @@ find_header "skylight_dlopen.h", hdrpath
206
207
  fail "could not create Makefile; dlfcn.h missing" unless have_header "dlfcn.h"
207
208
 
208
209
  # For escaping the GVL
209
- unless have_func("rb_thread_call_without_gvl", "ruby/thread.h") || have_func("rb_thread_blocking_region")
210
- abort "Ruby is unexpectedly missing rb_thread_blocking_region. This should not happen."
210
+ unless have_func("rb_thread_call_without_gvl", "ruby/thread.h")
211
+ abort "Ruby is unexpectedly missing rb_thread_call_without_gvl. This should not happen."
211
212
  end
212
213
 
213
214
  # Previous comment stated:
data/ext/libskylight.yml CHANGED
@@ -1,7 +1,6 @@
1
- version: "4.1.0-46806f5"
1
+ version: "5.0.0-45b02dd"
2
2
  checksums:
3
- x86-linux: "4054632757516aa44e812860601fcb7f21c8c5d412b2d585868b46c7a8e3cae6"
4
- x86_64-linux: "4675694fba4448ba14787551237bd4e388443895d5c9e5d8a71c550eccd203db"
5
- x86_64-linux-musl: "7a81880830d0a409a6f0f39ff42f90a1422542b05384e2480ae05515f6b5f831"
6
- x86_64-darwin: "84eef6c330818c2bad1628ff189b9cb88275c9d72a28afac88a0d054d8002230"
7
- x86_64-freebsd: "a86a52203fab4f9a56ad91d5700e14823e6e997b4df1bcb3ae2d9e4296c50b1f"
3
+ x86-linux: "218a51683cbe3f6e7f1d31097a7e732c6bac3e3780a707312f8441dd45d8f3a6"
4
+ x86_64-linux: "2426968fef8cd7fe0fd0ea582fd8098db78025ce936bac9d72b7753995bd1ea9"
5
+ x86_64-linux-musl: "ca07748d43fac0b4a05b38b5ce0fc4cb7e43469a183919c5d9980a8b2e0b01ab"
6
+ x86_64-darwin: "8b19eb2ffd19f78ee6e547b37fcf5cad2e49aa9a8bc2b9615a791ccfc91c2552"
@@ -86,14 +86,6 @@ typedef void* (*blocking_fn_t)(void*);
86
86
  #define WITHOUT_GVL(fn, a) \
87
87
  rb_thread_call_without_gvl((blocking_fn_t)(fn), (a), 0, 0)
88
88
 
89
- // Ruby 1.9
90
- #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
91
-
92
- typedef VALUE (*blocking_fn_t)(void*);
93
- #define WITHOUT_GVL(fn, a) \
94
- rb_thread_blocking_region((blocking_fn_t)(fn), (a), 0, 0)
95
-
96
-
97
89
  #endif
98
90
 
99
91
 
@@ -103,7 +95,6 @@ typedef VALUE (*blocking_fn_t)(void*);
103
95
 
104
96
  VALUE rb_mSkylight;
105
97
  VALUE rb_eNativeError;
106
- VALUE rb_mCore;
107
98
  VALUE rb_mUtil;
108
99
  VALUE rb_cClock;
109
100
  VALUE rb_cTrace;
@@ -140,7 +131,7 @@ load_libskylight(VALUE klass, VALUE path) {
140
131
 
141
132
  /*
142
133
  *
143
- * class Skylight::Core::Util::Clock
134
+ * class Skylight::Util::Clock
144
135
  *
145
136
  */
146
137
 
@@ -152,7 +143,7 @@ clock_high_res_time(VALUE self) {
152
143
 
153
144
  /*
154
145
  *
155
- * class Skylight::Core::Instrumenter
146
+ * class Skylight::Instrumenter
156
147
  *
157
148
  */
158
149
 
@@ -243,33 +234,9 @@ instrumenter_submit_trace(VALUE self, VALUE rb_trace) {
243
234
  return Qnil;
244
235
  }
245
236
 
246
- static VALUE
247
- instrumenter_track_desc(VALUE self, VALUE rb_endpoint, VALUE rb_desc) {
248
- int tracked;
249
- sky_instrumenter_t* instrumenter;
250
-
251
- CHECK_TYPE(rb_endpoint, T_STRING);
252
- CHECK_TYPE(rb_desc, T_STRING);
253
-
254
- tracked = 0;
255
-
256
- My_Struct(instrumenter, sky_instrumenter_t, no_instrumenter_msg);
257
-
258
- CHECK_FFI(
259
- sky_instrumenter_track_desc(instrumenter, STR2BUF(rb_endpoint), STR2BUF(rb_desc), &tracked),
260
- "Instrumenter#native_track_desc");
261
-
262
- if (tracked) {
263
- return Qtrue;
264
- }
265
- else {
266
- return Qfalse;
267
- }
268
- }
269
-
270
237
  /*
271
238
  *
272
- * class Skylight::Core::Trace
239
+ * class Skylight::Trace
273
240
  *
274
241
  */
275
242
 
@@ -503,9 +470,24 @@ trace_span_set_description(VALUE self, VALUE span, VALUE desc) {
503
470
 
504
471
  static VALUE
505
472
  trace_span_set_meta(VALUE self, VALUE span, VALUE meta) {
506
- UNUSED(self);
507
- UNUSED(span);
508
- UNUSED(meta);
473
+ sky_trace_t* trace;
474
+ VALUE rb_source_location;
475
+
476
+ My_Struct(trace, sky_trace_t, consumed_trace_msg);
477
+
478
+ CHECK_TYPE(span, T_FIXNUM);
479
+ CHECK_TYPE(meta, T_HASH);
480
+
481
+ rb_source_location = rb_hash_lookup(meta, ID2SYM(rb_intern("source_location")));
482
+ if (rb_source_location != Qnil) {
483
+ sky_buf_t source_location;
484
+
485
+ CHECK_TYPE(rb_source_location, T_STRING);
486
+ source_location = STR2BUF(rb_source_location);
487
+
488
+ sky_trace_span_add_string_annotation(trace, FIX2UINT(span), 3, source_location);
489
+ }
490
+
509
491
  return Qnil;
510
492
  }
511
493
 
@@ -525,71 +507,14 @@ trace_span_set_exception(VALUE self, VALUE span, VALUE exception, VALUE exceptio
525
507
  return Qnil;
526
508
  }
527
509
 
528
- static VALUE
529
- trace_span_get_correlation_header(VALUE self, VALUE span_id) {
530
- UNUSED(self);
531
- UNUSED(span_id);
532
- return Qnil;
533
- }
534
-
535
- static VALUE
536
- lex_sql(VALUE klass, VALUE rb_sql) {
537
- sky_buf_t sql;
538
- sky_buf_t title;
539
- sky_buf_t statement;
540
- uint8_t title_store[128];
541
- VALUE rb_statement;
542
- VALUE ret;
543
-
544
- UNUSED(klass);
545
- CHECK_TYPE(rb_sql, T_STRING);
546
-
547
- sql = STR2BUF(rb_sql);
548
- title = (sky_buf_t) {
549
- .data = title_store,
550
- .len = sizeof(title_store),
551
- };
552
-
553
- // The statement cannot be longer than the original sql string
554
- rb_statement = rb_str_buf_new(RSTRING_LEN(rb_sql));
555
- statement = (sky_buf_t) {
556
- .data = RSTRING_PTR(rb_statement),
557
- .len = RSTRING_LEN(rb_sql),
558
- };
559
-
560
- CHECK_FFI(sky_lex_sql(sql, &title, &statement),
561
- "Skylight#lex_sql");
562
-
563
- // Set the statement return
564
- rb_str_set_len(rb_statement, statement.len);
565
- rb_enc_associate(rb_statement, rb_utf8_encoding());
566
-
567
- ret = rb_ary_new2(2);
568
-
569
- if (title.len > 0) {
570
- rb_ary_store(ret, 0, BUF2STR(title));
571
- }
572
- else {
573
- rb_ary_store(ret, 0, Qnil);
574
- }
575
-
576
- rb_ary_store(ret, 1, rb_statement);
577
-
578
- return ret;
579
- }
580
-
581
510
  void Init_skylight_native() {
582
511
  rb_mSkylight = rb_define_module("Skylight");
583
512
 
584
513
  rb_eNativeError = rb_const_get(rb_mSkylight, rb_intern("NativeError"));
585
514
 
586
515
  rb_define_singleton_method(rb_mSkylight, "load_libskylight", load_libskylight, 1);
587
- rb_define_singleton_method(rb_mSkylight, "lex_sql", lex_sql, 1);
588
-
589
- rb_mCore = rb_define_module_under(rb_mSkylight, "Core");
590
516
 
591
- // FIXME: Don't put these under Core
592
- rb_mUtil = rb_define_module_under(rb_mCore, "Util");
517
+ rb_mUtil = rb_define_module_under(rb_mSkylight, "Util");
593
518
  rb_cClock = rb_define_class_under(rb_mUtil, "Clock", rb_cObject);
594
519
  rb_define_method(rb_cClock, "native_hrtime", clock_high_res_time, 0);
595
520
 
@@ -612,12 +537,10 @@ void Init_skylight_native() {
612
537
  rb_define_method(rb_cTrace, "native_span_set_meta", trace_span_set_meta, 2);
613
538
  rb_define_method(rb_cTrace, "native_span_started", trace_span_started, 1);
614
539
  rb_define_method(rb_cTrace, "native_span_set_exception", trace_span_set_exception, 3);
615
- rb_define_method(rb_cTrace, "native_span_get_correlation_header", trace_span_get_correlation_header, 1);
616
540
 
617
541
  rb_cInstrumenter = rb_const_get(rb_mSkylight, rb_intern("Instrumenter"));
618
542
  rb_define_singleton_method(rb_cInstrumenter, "native_new", instrumenter_new, 2);
619
543
  rb_define_method(rb_cInstrumenter, "native_start", instrumenter_start, 0);
620
544
  rb_define_method(rb_cInstrumenter, "native_stop", instrumenter_stop, 0);
621
545
  rb_define_method(rb_cInstrumenter, "native_submit_trace", instrumenter_submit_trace, 1);
622
- rb_define_method(rb_cInstrumenter, "native_track_desc", instrumenter_track_desc, 2);
623
546
  }
data/lib/skylight.rb CHANGED
@@ -1,36 +1,226 @@
1
1
  require "skylight/version"
2
- require "skylight/core"
3
2
  require "skylight/trace"
4
3
  require "skylight/instrumenter"
5
4
  require "skylight/middleware"
6
5
  require "skylight/api"
7
6
  require "skylight/helpers"
8
7
  require "skylight/config"
8
+ require "skylight/user_config"
9
9
  require "skylight/errors"
10
10
  require "skylight/native"
11
+ require "skylight/gc"
12
+ require "skylight/vm/gc"
13
+ require "skylight/util"
14
+ require "skylight/deprecation"
15
+ require "skylight/subscriber"
16
+ require "skylight/sidekiq"
17
+ require "skylight/probes"
11
18
 
12
19
  # For prettier global names
13
20
  require "English"
14
21
 
22
+ require "active_support/notifications"
23
+
24
+ # Specifically check for Railtie since we've had at least one case of a
25
+ # customer having Rails defined without having all of Rails loaded.
26
+ if defined?(Rails::Railtie)
27
+ require "skylight/railtie"
28
+ end
29
+
15
30
  module Skylight
16
31
  # Used from the CLI
17
32
  autoload :CLI, "skylight/cli"
33
+ # Is this autoload even useful?
34
+ autoload :Normalizers, "skylight/normalizers"
18
35
 
19
- # Specifically check for Railtie since we've had at least one case of a
20
- # customer having Rails defined without having all of Rails loaded.
21
- if defined?(Rails::Railtie)
22
- require "skylight/railtie"
23
- end
36
+ extend Util::Logging
24
37
 
25
- include Core::Instrumentable
38
+ LOCK = Mutex.new
26
39
 
27
- def self.instrumenter_class
28
- Instrumenter
29
- end
40
+ # @api private
41
+ TIERS = %w[
42
+ rack
43
+ api
44
+ app
45
+ view
46
+ db
47
+ noise
48
+ other
49
+ ].freeze
30
50
 
31
- def self.config_class
32
- Config
33
- end
51
+ # @api private
52
+ TIER_REGEX = /^(?:#{TIERS.join('|')})(?:\.|$)/u.freeze
53
+
54
+ # @api private
55
+ CATEGORY_REGEX = /^[a-z0-9_-]+(?:\.[a-z0-9_-]+)*$/iu.freeze
56
+
57
+ # @api private
58
+ DEFAULT_CATEGORY = "app.block".freeze
59
+
60
+ # @api private
61
+ DEFAULT_OPTIONS = { category: DEFAULT_CATEGORY }.freeze
62
+
63
+ at_exit { stop! }
64
+
65
+ class << self
66
+ extend Util::InstrumenterMethod
67
+
68
+ def instrumenter
69
+ defined?(@instrumenter) && @instrumenter
70
+ end
71
+
72
+ def probe(*args)
73
+ Probes.probe(*args)
74
+ end
75
+
76
+ def enable_normalizer(*names)
77
+ Normalizers.enable(*names)
78
+ end
79
+
80
+ # Start instrumenting
81
+ def start!(config = nil)
82
+ return instrumenter if instrumenter
83
+
84
+ const_get(:LOCK).synchronize do
85
+ return instrumenter if instrumenter
86
+
87
+ config ||= {}
88
+ config = Config.load(config) unless config.is_a?(Config)
89
+
90
+ Probes.install!
91
+
92
+ @instrumenter = Instrumenter.new(config).start!
93
+ end
94
+ rescue => e
95
+ level, message =
96
+ if e.is_a?(ConfigError)
97
+ [:warn, format("Unable to start Instrumenter due to a configuration error: %<message>s",
98
+ message: e.message)]
99
+ else
100
+ [:error, format("Unable to start Instrumenter; msg=%<message>s; class=%<klass>s",
101
+ message: e.message, klass: e.class)]
102
+ end
103
+
104
+ if config&.respond_to?("log_#{level}") && config&.respond_to?(:log_trace)
105
+ config.send("log_#{level}", message)
106
+ config.log_trace e.backtrace.join("\n")
107
+ else
108
+ warn "[#{name.upcase}] #{message}"
109
+ end
110
+ false
111
+ end
112
+
113
+ def started?
114
+ !!instrumenter
115
+ end
116
+
117
+ # Stop instrumenting
118
+ def stop!
119
+ t { "stop!" }
34
120
 
35
- Core::Probes.add_path(File.expand_path("skylight/probes", __dir__))
121
+ const_get(:LOCK).synchronize do
122
+ t { "stop! synchronized" }
123
+ return unless instrumenter
124
+
125
+ # This is only really helpful for getting specs to pass.
126
+ @instrumenter.current_trace = nil
127
+
128
+ @instrumenter.shutdown
129
+ @instrumenter = nil
130
+ end
131
+ end
132
+
133
+ # Check tracing
134
+ def tracing?
135
+ t { "checking tracing?; thread=#{Thread.current.object_id}" }
136
+ instrumenter&.current_trace
137
+ end
138
+
139
+ # Start a trace
140
+ def trace(endpoint = nil, cat = nil, title = nil, meta: nil, segment: nil, component: nil)
141
+ unless instrumenter
142
+ return yield if block_given?
143
+
144
+ return
145
+ end
146
+
147
+ if instrumenter.poisoned?
148
+ spawn_shutdown_thread!
149
+ return yield if block_given?
150
+
151
+ return
152
+ end
153
+
154
+ cat ||= DEFAULT_CATEGORY
155
+
156
+ if block_given?
157
+ instrumenter.trace(endpoint, cat, title, nil, meta: meta, segment: segment, component: component) do |tr|
158
+ yield tr
159
+ end
160
+ else
161
+ instrumenter.trace(endpoint, cat, title, nil, meta: meta, segment: segment, component: component)
162
+ end
163
+ end
164
+
165
+ # @overload instrument(opts)
166
+ # @param [Hash] opts the options for instrumentation.
167
+ # @option opts [String] :category (`DEFAULT_CATEGORY`) The category
168
+ # @option opts [String] :title The title
169
+ # @option opts [String] :description The description
170
+ # @option opts [Hash] :meta The meta
171
+ # @option opts [String] :source_location The source location
172
+ # @option opts [String] :source_file The source file. (Will be sanitized.)
173
+ # @option opts [String] :source_line The source line.
174
+ # @overload instrument(title)
175
+ # Instrument with the specified title and the default category
176
+ # @param [String] title The title
177
+ def instrument(opts = DEFAULT_OPTIONS, &block)
178
+ unless instrumenter
179
+ return yield if block_given?
180
+
181
+ return
182
+ end
183
+
184
+ if opts.is_a?(Hash)
185
+ category = opts[:category] || DEFAULT_CATEGORY
186
+ title = opts[:title]
187
+ desc = opts[:description]
188
+ meta = opts[:meta]
189
+ else
190
+ category = DEFAULT_CATEGORY
191
+ title = opts.to_s
192
+ desc = nil
193
+ meta = nil
194
+ opts = {}
195
+ end
196
+
197
+ meta ||= {}
198
+
199
+ instrumenter.extensions.process_instrument_options(opts, meta)
200
+
201
+ instrumenter.instrument(category, title, desc, meta, &block)
202
+ end
203
+
204
+ instrumenter_method :config
205
+
206
+ instrumenter_method :mute, block: true
207
+ instrumenter_method :unmute, block: true
208
+ instrumenter_method :muted?
209
+
210
+ # End a span
211
+ instrumenter_method :done
212
+
213
+ instrumenter_method :broken!
214
+
215
+ # Temporarily disable
216
+ instrumenter_method :disable, block: true
217
+
218
+ # Runs the shutdown procedure in the background.
219
+ # This should do little more than unsubscribe from all ActiveSupport::Notifications
220
+ def spawn_shutdown_thread!
221
+ @shutdown_thread || const_get(:LOCK).synchronize do
222
+ @shutdown_thread ||= Thread.new { @instrumenter&.shutdown }
223
+ end
224
+ end
225
+ end
36
226
  end