skylight 4.2.1 → 5.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  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 +24 -100
  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 +116 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ede826fca6195e25afd161caa9a43b42fe531edaecb92d3ed8481ffdf52ec171
4
- data.tar.gz: ba7c98bced8569efe632d815a204ed4f5a7ecafcfeb052276bba0ebe2099fb8a
3
+ metadata.gz: d7cc16a9f8a59047a74b34d19ed0f85e696e893d0f5c1c6984604a1358df6efb
4
+ data.tar.gz: b50cb4b7962f3b78bbccb5b3025bc051febcf6c8cd95303439add2f3df5cb75e
5
5
  SHA512:
6
- metadata.gz: 3710c84daafcfddd6fa3aa1cf37c206acf815e7ede78d56566611b4f1ca0e9ab8a9465ef2bef5ce39ad6740a2b09ebfa6e91c7cf87575d3171e54a0d46640dc6
7
- data.tar.gz: d6365e6dfbd8618ad0ef55ee19b32df4ee60c7abb2c15de995d09fa37635b27906c9ab088d60abc9b0bf4dad04578684f7accac25103a1479713d9328299436a
6
+ metadata.gz: dc3445e94e0b3c5dc4936569df35f60b7ce9ac5f82492f92c247aca1cb44f9570092b11f532d28a6d795b39d2a65eae4bac16b5ca1a9c4e7b1ae2b47eb6c87ff
7
+ data.tar.gz: c591bb63cd56354d0954955f93720f1183afb0f71bd6c0fd2df7cfb8f32dab2a4988eaa20fe3018615cbb47531163b09dddd1c849f430989ffb589f98b03f7c5
@@ -1,4 +1,31 @@
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`
15
+
16
+ ## 4.3.1 (June 24, 2020)
17
+ * [BUGFIX] Fix an issue in which `Mime::NullType` would result in an exception
18
+
19
+ ## 4.3.0 (March 18, 2020)
20
+ * [IMPROVEMENT] Fix Ruby 2.7 warnings
21
+ * [IMPROVEMENT] Update Grape normalizer for version 1.3.1
22
+ * [BUGFIX] Fix an issue where GraphQL normalizers could fail to load in non-Rails contexts
23
+
24
+ ## 4.2.2 (February 25, 2020)
25
+ * Support graphql-ruby version 1.10
26
+
1
27
  ## 4.2.1 (January 14, 2020)
28
+ * [IMPROVEMENT] Enable instrumentation for ActionMailer::MailDeliveryJob
2
29
  * [BUGFIX] Improved handling for non-SPEC compliant Rack middleware
3
30
 
4
31
  ## 4.2.0 (October 30, 2019)
@@ -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
  ```
@@ -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:
@@ -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,15 +470,31 @@ 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
 
512
494
  static VALUE
513
- trace_span_started(VALUE self) {
495
+ trace_span_started(VALUE self, VALUE span) {
514
496
  UNUSED(self);
497
+ UNUSED(span);
515
498
  return Qnil;
516
499
  }
517
500
 
@@ -524,71 +507,14 @@ trace_span_set_exception(VALUE self, VALUE span, VALUE exception, VALUE exceptio
524
507
  return Qnil;
525
508
  }
526
509
 
527
- static VALUE
528
- trace_span_get_correlation_header(VALUE self, VALUE span_id) {
529
- UNUSED(self);
530
- UNUSED(span_id);
531
- return Qnil;
532
- }
533
-
534
- static VALUE
535
- lex_sql(VALUE klass, VALUE rb_sql) {
536
- sky_buf_t sql;
537
- sky_buf_t title;
538
- sky_buf_t statement;
539
- uint8_t title_store[128];
540
- VALUE rb_statement;
541
- VALUE ret;
542
-
543
- UNUSED(klass);
544
- CHECK_TYPE(rb_sql, T_STRING);
545
-
546
- sql = STR2BUF(rb_sql);
547
- title = (sky_buf_t) {
548
- .data = title_store,
549
- .len = sizeof(title_store),
550
- };
551
-
552
- // The statement cannot be longer than the original sql string
553
- rb_statement = rb_str_buf_new(RSTRING_LEN(rb_sql));
554
- statement = (sky_buf_t) {
555
- .data = RSTRING_PTR(rb_statement),
556
- .len = RSTRING_LEN(rb_sql),
557
- };
558
-
559
- CHECK_FFI(sky_lex_sql(sql, &title, &statement),
560
- "Skylight#lex_sql");
561
-
562
- // Set the statement return
563
- rb_str_set_len(rb_statement, statement.len);
564
- rb_enc_associate(rb_statement, rb_utf8_encoding());
565
-
566
- ret = rb_ary_new2(2);
567
-
568
- if (title.len > 0) {
569
- rb_ary_store(ret, 0, BUF2STR(title));
570
- }
571
- else {
572
- rb_ary_store(ret, 0, Qnil);
573
- }
574
-
575
- rb_ary_store(ret, 1, rb_statement);
576
-
577
- return ret;
578
- }
579
-
580
510
  void Init_skylight_native() {
581
511
  rb_mSkylight = rb_define_module("Skylight");
582
512
 
583
513
  rb_eNativeError = rb_const_get(rb_mSkylight, rb_intern("NativeError"));
584
514
 
585
515
  rb_define_singleton_method(rb_mSkylight, "load_libskylight", load_libskylight, 1);
586
- rb_define_singleton_method(rb_mSkylight, "lex_sql", lex_sql, 1);
587
-
588
- rb_mCore = rb_define_module_under(rb_mSkylight, "Core");
589
516
 
590
- // FIXME: Don't put these under Core
591
- rb_mUtil = rb_define_module_under(rb_mCore, "Util");
517
+ rb_mUtil = rb_define_module_under(rb_mSkylight, "Util");
592
518
  rb_cClock = rb_define_class_under(rb_mUtil, "Clock", rb_cObject);
593
519
  rb_define_method(rb_cClock, "native_hrtime", clock_high_res_time, 0);
594
520
 
@@ -611,12 +537,10 @@ void Init_skylight_native() {
611
537
  rb_define_method(rb_cTrace, "native_span_set_meta", trace_span_set_meta, 2);
612
538
  rb_define_method(rb_cTrace, "native_span_started", trace_span_started, 1);
613
539
  rb_define_method(rb_cTrace, "native_span_set_exception", trace_span_set_exception, 3);
614
- rb_define_method(rb_cTrace, "native_span_get_correlation_header", trace_span_get_correlation_header, 1);
615
540
 
616
541
  rb_cInstrumenter = rb_const_get(rb_mSkylight, rb_intern("Instrumenter"));
617
542
  rb_define_singleton_method(rb_cInstrumenter, "native_new", instrumenter_new, 2);
618
543
  rb_define_method(rb_cInstrumenter, "native_start", instrumenter_start, 0);
619
544
  rb_define_method(rb_cInstrumenter, "native_stop", instrumenter_stop, 0);
620
545
  rb_define_method(rb_cInstrumenter, "native_submit_trace", instrumenter_submit_trace, 1);
621
- rb_define_method(rb_cInstrumenter, "native_track_desc", instrumenter_track_desc, 2);
622
546
  }
@@ -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