cruft_tracker 0.1.4 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +283 -55
- data/app/controllers/cruft_tracker/methods_controller.rb +0 -2
- data/app/helpers/cruft_tracker/application_helper.rb +53 -0
- data/app/models/cruft_tracker/render_metadata.rb +7 -0
- data/app/models/cruft_tracker/view.rb +27 -0
- data/app/models/cruft_tracker/view_render.rb +8 -0
- data/app/services/cruft_tracker/cleanup_untracked_views.rb +22 -0
- data/app/services/cruft_tracker/increment_view_renders.rb +15 -0
- data/app/services/cruft_tracker/record_arguments.rb +13 -1
- data/app/services/cruft_tracker/record_backtrace.rb +13 -1
- data/app/services/cruft_tracker/record_render_metadata.rb +52 -0
- data/app/services/cruft_tracker/record_view_render.rb +91 -0
- data/app/services/cruft_tracker/track_method.rb +0 -2
- data/app/services/cruft_tracker/track_view.rb +60 -0
- data/config/routes.rb +1 -3
- data/db/migrate/20220628175222_create_cruft_tracker_views.rb +13 -0
- data/db/migrate/20220701125925_create_cruft_tracker_view_renders.rb +18 -0
- data/db/migrate/20220705152409_create_render_metadata.rb +13 -0
- data/lib/cruft_tracker/engine.rb +3 -5
- data/lib/cruft_tracker/version.rb +1 -1
- data/lib/cruft_tracker.rb +35 -3
- metadata +31 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e11661e18988d5a678417bb2295abf479c7eecd17644ab9e3fa3386188e6a25a
|
4
|
+
data.tar.gz: 104b7dc62a4590837655618f9eb82786f609e7a0b5733b629afc85628088ea9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 635d585bc91bc042b6713f40e2da1c782d4e42664c5a69e3b6377089f38cf5bb91744a6f202ff9ef61020d2ce6170b507644d5ec45908ee88b682f685f8a7fa0
|
7
|
+
data.tar.gz: ec22b4e3e545e2adec8094f4a5e6b46156d9d2cf35d0ef3f20f61c347f50e7c2160b98767fd8a1943ba366df13d0459de8391bbfa34f78e2dfa0f79e99d04904
|
data/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# CruftTracker
|
2
2
|
|
3
|
-
Have you ever asked yourself, "Is this method even being used?!" Or, "What the heck is this method receiving?" Does your application use Rails? If the answers
|
3
|
+
Have you ever asked yourself, "Is this method even being used?!" Or, "What the heck is this method receiving?" Or, perhaps, "is this partial being used?" Does your application use Rails? If the answers
|
4
4
|
these questions are yes, this gem may be of use to you!
|
5
5
|
|
6
|
-
Large applications can accrue cruft; old methods that might once have been important, but are now unused or code that is difficult to understand, but dangerous to refactor. Unfortunately,
|
6
|
+
Large applications can accrue cruft; old methods that might once have been important, but are now unused, or code that is difficult to understand, but dangerous to refactor. The same is can be true for views and partials in Rails applications. Unfortunately,
|
7
7
|
software is _complex_ and sometimes it's unclear what's really going on. This adds maintenance burdens, headaches, and uncertainty.
|
8
8
|
|
9
|
-
This gem aims to give you
|
9
|
+
This gem aims to give you some tools to make it easier to know what (and how) your code is being used (or not).
|
10
10
|
|
11
11
|
CruftTracker supports Rails versions 5.2 to 6.1 at this time. As of now the gem only supports MySQL, but contributions for Postgres or other DBMS would be welcome.
|
12
12
|
|
@@ -37,6 +37,26 @@ After that, you can run migrations as you normally would. If you've previously i
|
|
37
37
|
|
38
38
|
## Usage
|
39
39
|
|
40
|
+
### Rails Initializer
|
41
|
+
|
42
|
+
You should configure CruftTracker by creating an initializer in your Rails application's `config/initializers` directory named `cruft_tracker.rb`. The structure of the initializer is:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
CruftTracker.init do
|
46
|
+
# your configuration.... (more on this below)
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Note: you may need to wrap the `CruftTracker.init` call in `Rails.application.reloader.to_prepare` to prevent deprecation warnings related to autoloading constants during initialization. For example:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
Rails.application.reloader.to_prepare do
|
54
|
+
CruftTracker.init do
|
55
|
+
# your configuration.... (more on this below)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
40
60
|
### Tracking method invocations
|
41
61
|
|
42
62
|
CruftTracker is pretty simple. Let's say you have a class (or module) like this...
|
@@ -49,19 +69,17 @@ class SomeOldClass
|
|
49
69
|
end
|
50
70
|
```
|
51
71
|
|
52
|
-
You're unsure if the `some_old_method` method is actually being used. All you need to do is
|
72
|
+
You're unsure if the `some_old_method` method is actually being used. All you need to do is add an instance of the `is_this_method_used? ` to the CruftTracker initializer. This method requires you to pass the class constant and a symbol to identify the name of the method to track. For example:
|
53
73
|
|
54
74
|
```ruby
|
55
|
-
|
56
|
-
def some_old_method
|
57
|
-
# do things
|
58
|
-
end
|
75
|
+
# config/initializers/cruft_tracker.rb
|
59
76
|
|
60
|
-
|
77
|
+
CruftTracker.init do
|
78
|
+
is_this_method_used? SomeOldClass, :some_old_method
|
61
79
|
end
|
62
80
|
```
|
63
81
|
|
64
|
-
What do you get out of this? Well, as soon as
|
82
|
+
What do you get out of this? Well, as soon as Rails runs the CruftTracker initializer, CruftTracker will create a new record
|
65
83
|
in the `cruft_tracker_methods` table that looks like this:
|
66
84
|
|
67
85
|
|
@@ -85,30 +103,28 @@ The fields are:
|
|
85
103
|
- `updated_at` - The last time this record was updated. IE: the last time the tracked method was invoked.
|
86
104
|
|
87
105
|
Looking at this, we can see that the `some_old_method` method has never been invoked. This is nice because it means that
|
88
|
-
you can track uses of methods without changing their behavior and also know when a method has _not_ been used. A similar record is created for every method you
|
89
|
-
with `
|
106
|
+
you can track uses of methods without changing their behavior (or editing their class) and also know when a method has _not_ been used. A similar record is created for every method you track
|
107
|
+
with `is_this_method_used?`.
|
90
108
|
|
91
|
-
|
109
|
+
You should always have records for potentially crufty
|
92
110
|
methods, even if the class itself is never explicitly used.
|
93
111
|
|
94
|
-
So, having
|
112
|
+
So, having configured the method to be tracked, you can check this table after a while. If you see that there have been zero invocations,
|
95
113
|
you have a reasonably good hint that the method may not actually be used. Of course, you should consider that there are
|
96
114
|
some processes that are not run frequently at all, so this gem isn't a panacea. **Think before you delete!**
|
97
115
|
|
98
|
-
`
|
116
|
+
`is_this_method_used?` can be used to track any kind of method (except `initialize`) with any visibility. This includes class and module methods (`self.`), private class methods, eigenclass methods, as well as public, private, and protected instance methods.
|
99
117
|
|
100
118
|
### Comments
|
101
119
|
|
102
120
|
Since you may have to track a method for a while, it might be helpful to have a reminder as to _why_ you're tracking it in the first place. This can be recorded by providing an optional `comments:` named argument. For example:
|
103
121
|
|
104
122
|
```ruby
|
105
|
-
|
106
|
-
def some_old_method
|
107
|
-
# do things
|
108
|
-
end
|
123
|
+
# config/initializers/cruft_tracker.rb
|
109
124
|
|
110
|
-
|
111
|
-
|
125
|
+
CruftTracker.init do
|
126
|
+
is_this_method_used?
|
127
|
+
SomeOldClass,
|
112
128
|
:some_old_method,
|
113
129
|
comment: "I suspect this method is being called via metaprogramming."
|
114
130
|
end
|
@@ -117,13 +133,11 @@ end
|
|
117
133
|
`comment:` can be anything that can be serialized to JSON. For example:
|
118
134
|
|
119
135
|
```ruby
|
120
|
-
|
121
|
-
def some_old_method
|
122
|
-
# do things
|
123
|
-
end
|
136
|
+
# config/initializers/cruft_tracker.rb
|
124
137
|
|
125
|
-
|
126
|
-
|
138
|
+
CruftTracker.init do
|
139
|
+
is_this_method_used?
|
140
|
+
SomeOldClass,
|
127
141
|
:some_old_method,
|
128
142
|
comment: {
|
129
143
|
creator: "Doug Hughes",
|
@@ -139,7 +153,7 @@ The comment is serialized to json and stored in the `comments` field of the `Cru
|
|
139
153
|
By default, CruftTracker will record unique backtraces for each invocation of a tracked method. This data is stored in the `cruft_tracker_backtraces` table and is accessible via the `CruftTracker::Method`'s `backtraces` association. The `cruft_tracker_backtraces` table has the following columns:
|
140
154
|
|
141
155
|
- `id` - Ye olde primary key.
|
142
|
-
- `traceable_type` - The type for the polymorphic `traceable` association. Future versions of CruftTracker may track data in addition to method invocations.
|
156
|
+
- `traceable_type` - The type for the polymorphic `traceable` association. Future versions of CruftTracker may track data in addition to method invocations. (Note: This was originally made polymorphic to support view tracking. Since view tracking can't use the backtraces feature, the polymorphism is vestigial and may be removed in the future.)
|
143
157
|
- `traceable_id` - The ID of the polymorphic `traceable` association. EG: the `CruftTracker::Method` the backtrace is recorded for.
|
144
158
|
- `trace_hash` - Traces are stored as JSON. This column is an MD5 hash of the trace that is indexed to make it easier / faster to know if we've seen a particular trace before.
|
145
159
|
- `trace` - The trace data, stored as a JSON array of hashes.
|
@@ -147,7 +161,7 @@ By default, CruftTracker will record unique backtraces for each invocation of a
|
|
147
161
|
- `created_at` - The first time we saw a particular backtrace.
|
148
162
|
- `updated_at` - The most recent time we saw a particular backtrace.
|
149
163
|
|
150
|
-
Backtraces can be referenced to figure out exactly where a tracked method is being used. It also implicitly tells you other code that is definitely being used. Do note that as code changes, these
|
164
|
+
Backtraces can be referenced to figure out exactly where a tracked method is being used. It also implicitly tells you other code that is definitely being used. Do note that as code changes, these backtrace records are not updated. So, if a backtrace says the tracked method was invoked from line 123 of some file, if that file is edited, the line numbers may no longer match and would be recorded as a new backtrace.
|
151
165
|
|
152
166
|
Future versions of CruftTracker may provide a UI for exploring backtraces.
|
153
167
|
|
@@ -185,42 +199,36 @@ Now, I ask you a few questions:
|
|
185
199
|
2. What options does `do_something_via_metaprogramming` receive? Are they always the same options?
|
186
200
|
3. What classes and methods does `do_something_via_metaprogramming` invoke via metaprogramming?
|
187
201
|
|
188
|
-
The
|
202
|
+
The answers: _Who the heck knows?!_ 🤷
|
189
203
|
|
190
204
|
So, let's start collecting some data about these arguments. We can do this with the `track_arguments:` named argument on `is_this_method_used?`. This argument takes a proc that receives an `args` array as an argument. Whatever the proc returns is serialized to JSON and stored in the `cruft_tracker_arguments` table.
|
191
205
|
|
192
206
|
The naive approach to tracking arguments would be to use something like this:
|
193
207
|
|
194
208
|
```ruby
|
195
|
-
|
196
|
-
def do_something_via_metaprogramming(options)
|
197
|
-
options[:target_class].constantize.send(options[:method], options[:modifiers])
|
198
|
-
YetAnotherClass.do_something_else(options)
|
199
|
-
end
|
209
|
+
# config/initializers/cruft_tracker.rb
|
200
210
|
|
201
|
-
|
202
|
-
|
211
|
+
CruftTracker.init do
|
212
|
+
is_this_method_used?
|
213
|
+
SomeClass,
|
203
214
|
:do_something_via_metaprogramming,
|
204
215
|
track_arguments: -> (args) { args }
|
205
216
|
end
|
206
217
|
```
|
207
218
|
|
208
|
-
This will track all of the values of the options provided to the `do_something_via_metaprogramming` method. This could be a problem. Consider a case where the method is used a zillion times per day and where there's a plethora of complicated data being passed through the method via its `options` argument. It's possible that each set of arguments is different. This could result in one `potential_cruft_arguments` record per invocation of the tracked method. This
|
219
|
+
This will track all of the values of the options provided to the `do_something_via_metaprogramming` method. This could be a problem. Consider a case where the method is used a zillion times per day and where there's a plethora of complicated data being passed through the method via its `options` argument. It's possible that each set of arguments is different. This could result in one `potential_cruft_arguments` record per invocation of the tracked method. This may not be what you want to know... What you probably want to know in this case is:
|
209
220
|
|
210
221
|
- What are the unique sets of keys in the `options` hash?
|
211
222
|
- What classes and methods are we calling via metaprogramming?
|
212
223
|
|
213
|
-
|
224
|
+
Instead, we could write a proc that looks like this:
|
214
225
|
|
215
226
|
```ruby
|
216
|
-
|
217
|
-
def do_something_via_metaprogramming(options)
|
218
|
-
options[:target_class].constantize.send(options[:method], options[:modifiers])
|
219
|
-
YetAnotherClass.do_something_else(options)
|
220
|
-
end
|
227
|
+
# config/initializers/cruft_tracker.rb
|
221
228
|
|
222
|
-
|
223
|
-
|
229
|
+
CruftTracker.init do
|
230
|
+
is_this_method_used?
|
231
|
+
SomeClass,
|
224
232
|
:do_something_via_metaprogramming,
|
225
233
|
track_arguments: -> (args) do
|
226
234
|
options = args.first
|
@@ -306,9 +314,11 @@ Arguments are tracked in the `cruft_tracker_arguments` table which has these col
|
|
306
314
|
- `updated_at` - The most recent time we saw a particular set of arguments.
|
307
315
|
|
308
316
|
|
309
|
-
### Tracking
|
317
|
+
### Tracking All Methods
|
310
318
|
|
311
|
-
So, let's say you've got a class with a bunch of methods. You want to know if any of the methods are being used, and you just don't want to think very hard about it. That's where `
|
319
|
+
So, let's say you've got a class with a bunch of methods. You want to know if any of the methods are being used, and you just don't want to think very hard about it. That's where `are_any_of_these_methods_being_used?` comes to the rescue! Just add this to the CruftTracker initializer as shown below.
|
320
|
+
|
321
|
+
Let's say this is your class:
|
312
322
|
|
313
323
|
```ruby
|
314
324
|
class SomeClass
|
@@ -328,18 +338,236 @@ class SomeClass
|
|
328
338
|
end
|
329
339
|
|
330
340
|
# ... other methods ...
|
341
|
+
end
|
342
|
+
```
|
343
|
+
|
344
|
+
Here's the configuration in the initializer:
|
345
|
+
|
346
|
+
```ruby
|
347
|
+
# config/initializers/cruft_tracker.rb
|
331
348
|
|
332
|
-
|
349
|
+
CruftTracker.init do
|
350
|
+
are_any_of_these_methods_being_used? SomeClass
|
333
351
|
end
|
334
352
|
```
|
335
353
|
|
336
354
|
This will result in a `cruft_tracker_methods` record being created for each method in the `SomeClass` class. It will _not_ track methods that exist in the class' (or module's) ancestors. It's a quick and easy way to see what's being used. This method cannot be used to track arguments, though it does accept a `comments:` named argument.
|
337
355
|
|
338
|
-
You may want to think twice about using this method, or using this method too widely as it may create more data than you expect. CruftTracker is lightweight, but too much of a good thing is still too much. Generally, you should favor
|
356
|
+
You may want to think twice about using this method, or using this method too widely as it may create more data than you expect. CruftTracker is lightweight, but too much of a good thing is still too much. Generally, you should favor tracking only what you are specifically interested in.
|
357
|
+
|
358
|
+
### Tracking Views
|
359
|
+
|
360
|
+
In additon to tracking methods, CruftTracker lets you track details about view rendering. Consider this scenario: You have a large legacy application with a ton views and partials. Over time your controllers have been changed and sometimes deleted. Perhaps a partial was once widely used, but isn't anymore. You might want to be able to easily tell if a given partial or view is being used. Once again, CruftTracker to the rescue!
|
361
|
+
|
362
|
+
Let's say you have this view and you're just not sure it's being used anymore:
|
363
|
+
|
364
|
+
```erb
|
365
|
+
<!-- app/views/something/some_view.html.erb -->
|
366
|
+
|
367
|
+
<div>
|
368
|
+
<%- if @data.present? %>
|
369
|
+
<strong>Woo hoo!</strong>
|
370
|
+
<% end %>
|
371
|
+
</div>
|
372
|
+
```
|
373
|
+
|
374
|
+
You can track renders of this view by using `is_this_view_used?` in the CruftTracker initializer:
|
375
|
+
|
376
|
+
```ruby
|
377
|
+
# config/initializers/cruft_tracker.rb
|
378
|
+
|
379
|
+
CruftTracker.init do
|
380
|
+
is_this_view_used? 'app/views/something/some_view.html.erb'
|
381
|
+
end
|
382
|
+
```
|
383
|
+
|
384
|
+
Note that the path provided is from the application's root.
|
385
|
+
|
386
|
+
As soon as Rails runs the CruftTracker initializer, CruftTracker will create a new record
|
387
|
+
in the `cruft_tracker_views` table that looks like this:
|
388
|
+
|
389
|
+
|
390
|
+
| id | view | renders | comment | deleted_at | created_at | updated_at |
|
391
|
+
| ---- | -------------------------------------- | ------- | ------- | ---------- | ------------------- | ------------------- |
|
392
|
+
| 1 | app/views/something/some_view.html.erb | 0 | null | null | 2022-01-21 14:07:48 | 2022-01-21 14:07:48 |
|
393
|
+
|
394
|
+
This record is accessible using the `CruftTracker::View` model. EG: `CruftTracker::View.find(1)`
|
395
|
+
|
396
|
+
The fields are:
|
397
|
+
|
398
|
+
- `id` - Shockingly, this is the primary key.
|
399
|
+
- `view` - This is the path to the view from the Rails application's root.
|
400
|
+
- `renders` - The number of times the view has been rendered.
|
401
|
+
- `comments` - This is a JSON field containing extra data provided to the option `comments:` argument for the `is_this_view_used?` method.
|
402
|
+
- `deleted_at` - When set, this indicates that the view is no longer being tracked.
|
403
|
+
- `created_at` - The date/time we started tracking the view.
|
404
|
+
- `updated_at` - The last time this record was updated. IE: the last time the tracked view was rendered.
|
405
|
+
|
406
|
+
Looking at this, we can see that the `app/views/something/some_view.html.erb` view has never been rendered. This is nice because it means that
|
407
|
+
you can track renders of views, but you can and also know when a view has _not_ been rendered. A similar record is created for every view you track
|
408
|
+
with `is_this_view_used?` You should always have records for potentially crufty
|
409
|
+
views, even if the view itself is never rendered.
|
410
|
+
|
411
|
+
So, having configured the view to be tracked, you can check this table after a while. If you see that there have been zero renders,
|
412
|
+
you have a reasonably good hint that the view may not actually be used. Of course, some things aren't used frequently. **Think before you delete!**
|
413
|
+
|
414
|
+
`is_this_view_used?` can be used to track ordinary views as well as partials. While only tested with ERB templates, it should work with any other template engine, such as HAML. If you run into problems, please open a Github issue!
|
415
|
+
|
416
|
+
### Tracking View Rendering Details
|
417
|
+
|
418
|
+
Out of the box, you don't get a lot of information when tracking views. Basically, all you know is the number of times a view has been rendered. That's helpful, but not exactly amazing. Happily, CruftTracker provides a view helper that can be used to track a lot more information about view renders. The only downside is that it requires you to add a line of code to your templates.
|
419
|
+
|
420
|
+
Let's say you have this partial and you want to know not just if it's used, but _what uses it_.
|
421
|
+
|
422
|
+
```erb
|
423
|
+
<!-- app/views/shared/whatever.html.erb -->
|
424
|
+
|
425
|
+
<div>I am a partial. Hear me roar.</div>
|
426
|
+
|
427
|
+
<div><%= some_value %></div>
|
428
|
+
```
|
429
|
+
|
430
|
+
You'll still want to configure view tracking in the initializer:
|
431
|
+
|
432
|
+
```ruby
|
433
|
+
# config/initializers/cruft_tracker.rb
|
434
|
+
|
435
|
+
CruftTracker.init do
|
436
|
+
is_this_view_used? 'app/views/shared/whatever.html.erb'
|
437
|
+
end
|
438
|
+
```
|
439
|
+
|
440
|
+
However, to get additional details about renders of this partial, you can invoke the `record_cruft_tracker_view_render` helper into the view. It's recommended to add this on the first line of the view. EG:
|
441
|
+
|
442
|
+
```erb
|
443
|
+
<!-- app/views/shared/whatever.html.erb -->
|
444
|
+
|
445
|
+
<%- record_cruft_tracker_view_render %>
|
446
|
+
|
447
|
+
<div>I am a partial. Hear me roar.</div>
|
448
|
+
|
449
|
+
<div><%= some_value %></div>
|
450
|
+
```
|
451
|
+
|
452
|
+
When the view is actually rendered, CruftTracker will collect information about the render and store it in the `cruft_tracker_view_renders` table, like this:
|
453
|
+
|
454
|
+
| id | view_id | render_hash | controller | endpoint | route | render_stack | occurrences | created_at | updated_at |
|
455
|
+
| ---- | ------- | -------------------------------- | -------------- | ------------ | ---------------------- | ------------ | ----------- | ------------------- | ------------------- |
|
456
|
+
| 1 | 1 | 98cc3bd79cf6f3606c5afe3b9faf925b | SomeController | do_something | /foo/:id/bar(.:format) | [{...}] | 1 | 2022-07-06 15:29:06 | 2022-07-06 15:29:06 |
|
457
|
+
|
458
|
+
This record is represented by the `CruftTracker::ViewRender` model and can be loaded in the usual ways. You can also access it from a specific view record. EG: `CruftTracker::View.find(1).view_renders`, which will return an association of unique renders.
|
459
|
+
|
460
|
+
There's a lot packed into that record. Let's disect it:
|
461
|
+
|
462
|
+
* `id` - This is the primary key for the view render.
|
463
|
+
|
464
|
+
* `view_id` - This is the id of the view that was rendered.
|
465
|
+
|
466
|
+
* `render_hash` - This is the MD5 hash of the combination of the `controller`, `endpoint`, `route`, `http_method`, and the JSON version of the `render_stack`. The combination of these fields must be unique so that we can count the number of occurrences. The `render_hash` is a shortcut used by CruftTracker to easily determine if the combination of these items is unique. Basically, it's for optimization purposes and you shouldn't worry about it. :wink:
|
467
|
+
|
468
|
+
* `controller` - This is the class name for the controller that ultimately triggered rendering this view. Note that this controller is what kicked off the render, not necessarily what directly caused the view to be rendered. In the case of a partial, you could have a deeply nested set of renders. All the `controller` tells you is that a request to the controller ultimately caused the view to be rendered.
|
469
|
+
|
470
|
+
* `endpoint` - This is the method within the controller that caused the view to be rendered. The same caveats apply as with `controller`.
|
471
|
+
|
472
|
+
* `route` - This is the generic route that caused the view to be rendered. Note that this doesn't include the IDs, but the route's pattern for the IDs.
|
473
|
+
|
474
|
+
* `http_method` - This is the HTTP method used to access the `endpoint`.
|
475
|
+
|
476
|
+
* `render_stack` - This is an array that is _similar_ to a backtrace, but isn't actually a backtrace. To explain, if you call `render` in a controller, Rails doesn't actually render the view at that time. Instead, it ensues the view for rendering once the controller's method has finished executing. That means that if, while the view is rendering, you call invoke Ruby's `caller_locations`, you wouldn't see the controller that triggered the render. It was decided that this was generally pretty useless. Instead, what this field stores is the hierarchy of views / partials being rendered, but none of the other related code. It can provide a hint of how a deeply nested partial is rendered. Here's an example that shows a partial being rendered from a regular view:
|
477
|
+
|
478
|
+
```ruby
|
479
|
+
[
|
480
|
+
{ "path": "/app/spec/dummy/app/views/shared/_whatever.html.erb",
|
481
|
+
"label": "_app_views_shared__whatever_html_erb___436643032048620150_11500",
|
482
|
+
"lineno": 1,
|
483
|
+
"base_label": "_app_views_shared__whatever_html_erb___436643032048620150_11500" },
|
484
|
+
{ "path": "/app/spec/dummy/app/views/main/show.html.erb",
|
485
|
+
"label": "_app_views_main_show_html_erb__2350809826889573468_11260",
|
486
|
+
"lineno": 6,
|
487
|
+
"base_label": "_app_views_main_show_html_erb__2350809826889573468_11260"}
|
488
|
+
]
|
489
|
+
```
|
490
|
+
|
491
|
+
* `occurrences` - This is the number of times that this particular set of details have been seen when rendering a particular view.
|
492
|
+
|
493
|
+
* `created_at` - The date/time we first saw this controller, endpoint, route, etc render the view.
|
494
|
+
|
495
|
+
* `updated_at` - The last time we first saw this controller, endpoint, route, etc render the view.
|
496
|
+
|
497
|
+
### Tracking View Render Metadata
|
498
|
+
|
499
|
+
Knowing what caused a view to render is all well and good, but sometimes you might want a little more insight. Similar to how you can track arguments on methods with CruftTracker, you can track metadata for views. This is simply an argument you provide to the `record_cruft_tracker_view_render` method. For example:
|
500
|
+
|
501
|
+
```erb
|
502
|
+
<!-- app/views/shared/whatever.html.erb -->
|
503
|
+
|
504
|
+
<%- record_cruft_tracker_view_render(some_value) %>
|
505
|
+
|
506
|
+
<div>I am a partial. Hear me roar.</div>
|
507
|
+
|
508
|
+
<div><%= some_value %></div>
|
509
|
+
```
|
510
|
+
|
511
|
+
The metadata argument can be anything that is serializable to JSON. When you provide the argument, a record will be created or updated in the `cruft_tracker_render_metadata` table that looks like this:
|
512
|
+
|
513
|
+
| id | view_render_id | metadata_hash | metadata | occurrences | created_at | updated_at |
|
514
|
+
| ---- | -------------- | -------------------------------- | ------------------- | ----------- | ------------------- | ------------------- |
|
515
|
+
| 1 | 1 | a434e71475ff330064970fdc9fb123fc | ...your metadata... | 1 | 2022-07-06 16:07:38 | 2022-07-06 16:07:38 |
|
516
|
+
|
517
|
+
Let's break this down:
|
518
|
+
|
519
|
+
* `id` - Ye olde primary key
|
520
|
+
* `view_render_id` - This is the ID of the `CruftTracker::ViewRender` that this metadata is associated with.
|
521
|
+
* `metadata_hash` - This is the hash of the `metadata` field so that we can easily create a unique index.
|
522
|
+
* `occurrences` - The number of times that this exact metadata has been seen before.
|
523
|
+
* `created_at` - The first time we saw this metadata.
|
524
|
+
* `updated_at` - The most recent time we saw this metadata.
|
525
|
+
|
526
|
+
`CruftTracker::RenderMetadata` can be accessed from a `CruftTracker::ViewRender` via its `render_metadata` association.
|
527
|
+
|
528
|
+
A word of caution: don't track ever variable. Variables are, by definition, variable. Each time a view renders you could have a different value for a variable. Instead, this would be better used to track what variables are available. EG:
|
529
|
+
|
530
|
+
```erb
|
531
|
+
<!-- app/views/shared/whatever.html.erb -->
|
532
|
+
|
533
|
+
<%- record_cruft_tracker_view_render(instance_variables) %>
|
534
|
+
|
535
|
+
<div>I am a partial. Hear me roar.</div>
|
536
|
+
|
537
|
+
<div><%= some_value %></div>
|
538
|
+
```
|
339
539
|
|
340
540
|
### Clean Up
|
341
541
|
|
342
|
-
CruftTacker automatically cleans up after itself. ✨🧹 If you remove
|
542
|
+
CruftTacker automatically cleans up after itself. ✨🧹 If you remove any configured tracking, CruftTracker will recognize this when your application starts up and mark the associated `cruft_tracker_methods` record as deleted.
|
543
|
+
|
544
|
+
## Configuration
|
545
|
+
|
546
|
+
Imagine a scenario where you have a method or view that is used in many places, or maybe as a result of metaprogramming. Perhaps you have some logic that is user-configurable and might lead to a tracked method being called with any number of backtraces. It's not super helpful to track all possible backtraces and it's actively bad, since it wastes space in your database and slows down queries. Besides, it's no fun drinking from the firehose.
|
547
|
+
|
548
|
+
CruftTracker provides a few configurable settings to control the amount of data recorded in some of its tables.
|
549
|
+
|
550
|
+
| Name | Default | Description |
|
551
|
+
| ------------------------------------------------ | ------- | ------------------------------------------------------------ |
|
552
|
+
| `max_argument_variations_per_tracked_method` | 50 | Sets the maximum number of distinct arguments that can be recorded for any tracked method. |
|
553
|
+
| `max_backtrace_variations_per_tracked_method` | 50 | Sets the maximum number of distinct backtraces that can be recorded for any tracked method. |
|
554
|
+
| `max_view_renders_per_view` | 50 | Sets the maximum number of distinct renders that can be recorded for any tracked view. |
|
555
|
+
| `max_render_metadata_variations_per_view_render` | 50 | Sets the maximum number of distinct render metadata records that can be recorded for any specific render of a view. |
|
556
|
+
|
557
|
+
These configuration values can be set within the CruftTracker initializer like this:
|
558
|
+
|
559
|
+
```ruby
|
560
|
+
# config/initializers/cruft_tracker.rb
|
561
|
+
|
562
|
+
CruftTracker.init do
|
563
|
+
config.max_argument_variations_per_tracked_method = 20
|
564
|
+
config.max_backtrace_variations_per_tracked_method = 25
|
565
|
+
config.max_view_renders_per_view = 30
|
566
|
+
config.max_render_metadata_variations_per_view_render = 35
|
567
|
+
|
568
|
+
# ... your configuration for tracking methods or views ...
|
569
|
+
end
|
570
|
+
```
|
343
571
|
|
344
572
|
## API Docs
|
345
573
|
|
@@ -369,10 +597,10 @@ Returns an array of `CruftTracker::Method` instances.
|
|
369
597
|
|
370
598
|
##### Arguments
|
371
599
|
|
372
|
-
| Name
|
373
|
-
|
|
374
|
-
| owner (positional)
|
375
|
-
| comment: (named)
|
600
|
+
| Name | Type | Required? | Default | Description |
|
601
|
+
| ------------------ | :-------------------------------------- | --------- | ------- | ------------------------------------------------------------ |
|
602
|
+
| owner (positional) | a class or module constant | yes | N/A | A reference to the class or module that owns the method. Set this to `self`. |
|
603
|
+
| comment: (named) | anything that can be serialized to json | no | nil | Arbitrary data you want to include with the `cruft_tracker_methods` record. For example, a note about why the method is being tracked or a hash with keys indicating who is tracking the method and and why. |
|
376
604
|
|
377
605
|
## Developing
|
378
606
|
|
@@ -1,4 +1,57 @@
|
|
1
1
|
module CruftTracker
|
2
2
|
module ApplicationHelper
|
3
|
+
def record_cruft_tracker_view_render(metadata = nil)
|
4
|
+
CruftTracker::RecordViewRender.run!(
|
5
|
+
view: cruft_tracker_view,
|
6
|
+
controller: controller.class.to_s,
|
7
|
+
endpoint: action_name,
|
8
|
+
route: route_path,
|
9
|
+
http_method: request.method,
|
10
|
+
render_stack: render_stack,
|
11
|
+
metadata: metadata
|
12
|
+
)
|
13
|
+
rescue StandardError
|
14
|
+
# Swallow errors
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def cruft_tracker_view
|
20
|
+
path = render_stack.first[:path].gsub(%r{#{Rails.root}/}, '')
|
21
|
+
view = CruftTracker::View.find_by(view: path)
|
22
|
+
|
23
|
+
return view if view.present?
|
24
|
+
|
25
|
+
CruftTracker::TrackView.run!(view: path)
|
26
|
+
end
|
27
|
+
|
28
|
+
def route_path
|
29
|
+
_routes
|
30
|
+
.router
|
31
|
+
.recognize(request) { |route, _| return route.path.spec.to_s }
|
32
|
+
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def paths_to_views
|
37
|
+
@paths_to_views ||= view_paths.map { |view_path| view_path.to_path }
|
38
|
+
end
|
39
|
+
|
40
|
+
def render_stack
|
41
|
+
caller_locations
|
42
|
+
.select do |caller_location|
|
43
|
+
paths_to_views.any? do |path_for_view|
|
44
|
+
caller_location.path.match?(%r{^#{path_for_view}/})
|
45
|
+
end
|
46
|
+
end
|
47
|
+
.map do |location|
|
48
|
+
{
|
49
|
+
path: location.path,
|
50
|
+
label: location.label,
|
51
|
+
base_label: location.base_label,
|
52
|
+
lineno: location.lineno
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
3
56
|
end
|
4
57
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CruftTracker
|
4
|
+
class View < ActiveRecord::Base
|
5
|
+
has_many :backtraces, class_name: 'CruftTracker::Backtrace', as: :traceable
|
6
|
+
has_many :view_renders, class_name: 'CruftTracker::ViewRender'
|
7
|
+
|
8
|
+
def still_exists?
|
9
|
+
File.exist?(absolute_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def still_tracked?
|
13
|
+
return true if CruftTracker::Registry.include?(self)
|
14
|
+
if File.read(absolute_path).match?(/record_cruft_tracker_view_render/)
|
15
|
+
return true
|
16
|
+
end
|
17
|
+
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def absolute_path
|
24
|
+
"#{Rails.root}/#{view}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CruftTracker
|
4
|
+
class CleanupUntrackedViews < CruftTracker::ApplicationService
|
5
|
+
private
|
6
|
+
|
7
|
+
def execute
|
8
|
+
CruftTracker::LogSuppressor.suppress_logging do
|
9
|
+
CruftTracker::View
|
10
|
+
.where(deleted_at: nil)
|
11
|
+
.each do |view|
|
12
|
+
unless view.still_exists? && view.still_tracked?
|
13
|
+
view.update(deleted_at: Time.current)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
rescue StandardError
|
18
|
+
# I'm actively ignoring all errors. Chances are, these are due to something like running rake
|
19
|
+
# tasks in CI when the DB doesn't already exist.
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CruftTracker
|
4
|
+
class IncrementViewRenders < CruftTracker::ApplicationService
|
5
|
+
record :view, class: CruftTracker::View
|
6
|
+
|
7
|
+
def execute
|
8
|
+
CruftTracker::LogSuppressor.suppress_logging { increment_renders }
|
9
|
+
end
|
10
|
+
|
11
|
+
def increment_renders
|
12
|
+
view.update(renders: view.reload.renders + 1)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -9,6 +9,8 @@ module CruftTracker
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def execute
|
12
|
+
return unless arguments_record.present?
|
13
|
+
|
12
14
|
CruftTracker::LogSuppressor.suppress_logging do
|
13
15
|
arguments_record.with_lock do
|
14
16
|
arguments_record.reload
|
@@ -22,16 +24,22 @@ module CruftTracker
|
|
22
24
|
def arguments_record
|
23
25
|
@arguments_record ||=
|
24
26
|
begin
|
27
|
+
return find_existing_arguments_record if max_records_reached?
|
28
|
+
|
25
29
|
CruftTracker::Argument.create(
|
26
30
|
method: method,
|
27
31
|
arguments_hash: arguments_hash,
|
28
32
|
arguments: transformed_arguments
|
29
33
|
)
|
30
34
|
rescue ActiveRecord::RecordNotUnique
|
31
|
-
|
35
|
+
find_existing_arguments_record
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
39
|
+
def find_existing_arguments_record
|
40
|
+
CruftTracker::Argument.find_by(arguments_hash: arguments_hash)
|
41
|
+
end
|
42
|
+
|
35
43
|
def arguments_hash
|
36
44
|
Digest::MD5.hexdigest(transformed_arguments.to_json)
|
37
45
|
end
|
@@ -39,5 +47,9 @@ module CruftTracker
|
|
39
47
|
def transformed_arguments
|
40
48
|
@transformed_arguments ||= transformer.call(arguments)
|
41
49
|
end
|
50
|
+
|
51
|
+
def max_records_reached?
|
52
|
+
CruftTracker::Argument.where(method: method).count >= CruftTracker.config.max_argument_variations_per_tracked_method
|
53
|
+
end
|
42
54
|
end
|
43
55
|
end
|
@@ -7,6 +7,8 @@ module CruftTracker
|
|
7
7
|
private
|
8
8
|
|
9
9
|
def execute
|
10
|
+
return unless backtrace_record.present?
|
11
|
+
|
10
12
|
CruftTracker::LogSuppressor.suppress_logging do
|
11
13
|
backtrace_record.with_lock do
|
12
14
|
backtrace_record.reload
|
@@ -20,16 +22,22 @@ module CruftTracker
|
|
20
22
|
def backtrace_record
|
21
23
|
@backtrace_record ||=
|
22
24
|
begin
|
25
|
+
return find_existing_backtrace_record if max_records_reached?
|
26
|
+
|
23
27
|
CruftTracker::Backtrace.create(
|
24
28
|
traceable: method,
|
25
29
|
trace_hash: backtrace_hash,
|
26
30
|
trace: filtered_backtrace
|
27
31
|
)
|
28
32
|
rescue ActiveRecord::RecordNotUnique
|
29
|
-
|
33
|
+
find_existing_backtrace_record
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
37
|
+
def find_existing_backtrace_record
|
38
|
+
CruftTracker::Backtrace.find_by(trace_hash: backtrace_hash)
|
39
|
+
end
|
40
|
+
|
33
41
|
def backtrace_hash
|
34
42
|
Digest::MD5.hexdigest(filtered_backtrace.to_json)
|
35
43
|
end
|
@@ -51,5 +59,9 @@ module CruftTracker
|
|
51
59
|
}
|
52
60
|
end
|
53
61
|
end
|
62
|
+
|
63
|
+
def max_records_reached?
|
64
|
+
CruftTracker::Backtrace.where(traceable: method).count >= CruftTracker.config.max_backtrace_variations_per_tracked_method
|
65
|
+
end
|
54
66
|
end
|
55
67
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CruftTracker
|
4
|
+
# Records provided metadata associated with a given render
|
5
|
+
class RecordRenderMetadata < CruftTracker::ApplicationService
|
6
|
+
record :view_render, class: CruftTracker::ViewRender
|
7
|
+
interface :metadata, methods: %i[to_json], default: nil
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def execute
|
12
|
+
return unless metadata.present?
|
13
|
+
return unless render_metadata_record.present?
|
14
|
+
|
15
|
+
CruftTracker::LogSuppressor.suppress_logging do
|
16
|
+
render_metadata_record.with_lock do
|
17
|
+
render_metadata_record.reload
|
18
|
+
render_metadata_record.update(
|
19
|
+
occurrences: render_metadata_record.occurrences + 1
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def render_metadata_record
|
26
|
+
@render_metadata_record ||=
|
27
|
+
begin
|
28
|
+
return find_existing_render_metadata_record if max_records_reached?
|
29
|
+
|
30
|
+
CruftTracker::RenderMetadata.create(
|
31
|
+
view_render: view_render,
|
32
|
+
metadata_hash: metadata_hash,
|
33
|
+
metadata: metadata
|
34
|
+
)
|
35
|
+
rescue ActiveRecord::RecordNotUnique
|
36
|
+
find_existing_render_metadata_record
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def find_existing_render_metadata_record
|
41
|
+
CruftTracker::RenderMetadata.find_by(metadata_hash: metadata_hash)
|
42
|
+
end
|
43
|
+
|
44
|
+
def metadata_hash
|
45
|
+
Digest::MD5.hexdigest([view_render.render_hash, metadata].to_json)
|
46
|
+
end
|
47
|
+
|
48
|
+
def max_records_reached?
|
49
|
+
CruftTracker::RenderMetadata.where(view_render: view_render).count >= CruftTracker.config.max_render_metadata_variations_per_view_render
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CruftTracker
|
4
|
+
class RecordViewRender < CruftTracker::ApplicationService
|
5
|
+
record :view, class: CruftTracker::View
|
6
|
+
string :controller
|
7
|
+
string :endpoint
|
8
|
+
string :route
|
9
|
+
string :http_method
|
10
|
+
array :render_stack do
|
11
|
+
hash do
|
12
|
+
string :path
|
13
|
+
string :label
|
14
|
+
string :base_label
|
15
|
+
integer :lineno
|
16
|
+
end
|
17
|
+
end
|
18
|
+
interface :metadata, methods: %i[to_json], default: nil
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def execute
|
23
|
+
return unless view_render_record.present?
|
24
|
+
|
25
|
+
CruftTracker::LogSuppressor.suppress_logging do
|
26
|
+
view.with_lock do
|
27
|
+
view.reload
|
28
|
+
view.update(renders: view.renders + 1)
|
29
|
+
end
|
30
|
+
|
31
|
+
view_render_record.with_lock do
|
32
|
+
view_render_record.reload
|
33
|
+
view_render_record.update(
|
34
|
+
occurrences: view_render_record.occurrences + 1
|
35
|
+
)
|
36
|
+
|
37
|
+
record_render_metadata(view_render_record)
|
38
|
+
|
39
|
+
view_render_record
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def record_render_metadata(view_render_record)
|
45
|
+
compose(
|
46
|
+
CruftTracker::RecordRenderMetadata,
|
47
|
+
view_render: view_render_record,
|
48
|
+
metadata: metadata
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def view_render_record
|
53
|
+
@view_render_record ||=
|
54
|
+
begin
|
55
|
+
return find_existing_view_render_record if max_records_reached?
|
56
|
+
|
57
|
+
CruftTracker::ViewRender.create(
|
58
|
+
view: view,
|
59
|
+
render_hash: render_hash,
|
60
|
+
controller: controller,
|
61
|
+
endpoint: endpoint,
|
62
|
+
route: route,
|
63
|
+
http_method: http_method,
|
64
|
+
render_stack: render_stack
|
65
|
+
)
|
66
|
+
rescue ActiveRecord::RecordNotUnique
|
67
|
+
find_existing_view_render_record
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_existing_view_render_record
|
72
|
+
CruftTracker::ViewRender.find_by(render_hash: render_hash)
|
73
|
+
end
|
74
|
+
|
75
|
+
def render_hash
|
76
|
+
Digest::MD5.hexdigest(
|
77
|
+
{
|
78
|
+
controller: controller,
|
79
|
+
endpoint: endpoint,
|
80
|
+
route: route,
|
81
|
+
http_method: http_method,
|
82
|
+
render_stack: render_stack.to_json
|
83
|
+
}.to_json
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
def max_records_reached?
|
88
|
+
CruftTracker::ViewRender.where(view: view).count >= CruftTracker.config.max_view_renders_per_view
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CruftTracker
|
4
|
+
# creates or updates a CruftTracker:View record and configures subscriptions for render events
|
5
|
+
class TrackView < CruftTracker::ApplicationService
|
6
|
+
private
|
7
|
+
|
8
|
+
string :view
|
9
|
+
interface :comment, methods: %i[to_json], default: nil
|
10
|
+
|
11
|
+
def execute
|
12
|
+
view_record =
|
13
|
+
CruftTracker::LogSuppressor.suppress_logging do
|
14
|
+
view_record = create_or_find_view_record
|
15
|
+
view_record.deleted_at = nil
|
16
|
+
view_record.comment = comment if comment != view_record.comment
|
17
|
+
view_record.save
|
18
|
+
view_record
|
19
|
+
end
|
20
|
+
|
21
|
+
listen_for_render(view_record)
|
22
|
+
|
23
|
+
CruftTracker::Registry << view_record
|
24
|
+
|
25
|
+
view_record
|
26
|
+
rescue ActiveRecord::StatementInvalid => e
|
27
|
+
raise unless e.cause.present? && e.cause.instance_of?(Mysql2::Error)
|
28
|
+
|
29
|
+
Rails.logger.warn(
|
30
|
+
'CruftTracker was unable to record a view. Does the cruft_tracker_views table exist? Have migrations been run?'
|
31
|
+
)
|
32
|
+
rescue NoMethodError
|
33
|
+
Rails.logger.warn(
|
34
|
+
'CruftTracker was unable to record a view. Have migrations been run?'
|
35
|
+
)
|
36
|
+
rescue Mysql2::Error::ConnectionError,
|
37
|
+
ActiveRecord::ConnectionNotEstablished
|
38
|
+
Rails.logger.warn(
|
39
|
+
'CruftTracker was unable to record a view due to being unable to connect to the database. This may be a non-issue in cases where the database is intentionally not available.'
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def listen_for_render(view_record)
|
44
|
+
ActiveSupport::Notifications.subscribe /!render_.*\.action_view/ do |*args|
|
45
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
46
|
+
if event.payload[:identifier] == "#{Rails.root}/#{view}"
|
47
|
+
CruftTracker::IncrementViewRenders.run!(view: view_record.id)
|
48
|
+
end
|
49
|
+
rescue StandardError
|
50
|
+
# suppress errors
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_or_find_view_record
|
55
|
+
CruftTracker::View.create(view: view, comment: comment)
|
56
|
+
rescue ActiveRecord::RecordNotUnique
|
57
|
+
CruftTracker::View.find_by(view: view)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateCruftTrackerViews < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
create_table :cruft_tracker_views do |t|
|
4
|
+
t.string :view, null: false
|
5
|
+
t.integer :renders, null: false, default: 0
|
6
|
+
t.json :comment, null: true
|
7
|
+
t.datetime :deleted_at
|
8
|
+
t.timestamps
|
9
|
+
|
10
|
+
t.index :view, unique: true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateCruftTrackerViewRenders < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
create_table :cruft_tracker_view_renders do |t|
|
4
|
+
t.references :view, null: false
|
5
|
+
t.string :render_hash, null: false, index: true, unique: true
|
6
|
+
t.string :controller, null: false, index: true
|
7
|
+
t.string :endpoint, null: false, index: true
|
8
|
+
t.string :route, null: false, index: true
|
9
|
+
t.string :http_method, null: false, index: true
|
10
|
+
t.json :render_stack, null: false
|
11
|
+
t.integer :occurrences, null: false, index: true, default: 0
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
|
15
|
+
t.index %i[view_id render_hash], unique: true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateRenderMetadata < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
create_table :cruft_tracker_render_metadata do |t|
|
4
|
+
t.references :view_render, null: false
|
5
|
+
t.string :metadata_hash, null: false
|
6
|
+
t.json :metadata, null: false
|
7
|
+
t.integer :occurrences, null: false, index: true, default: 0
|
8
|
+
t.timestamps
|
9
|
+
|
10
|
+
t.index :metadata_hash, unique: true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/cruft_tracker/engine.rb
CHANGED
@@ -3,15 +3,13 @@ module CruftTracker
|
|
3
3
|
isolate_namespace CruftTracker
|
4
4
|
|
5
5
|
config.after_initialize do
|
6
|
+
ActionController::Base.helper CruftTracker::ApplicationHelper
|
6
7
|
CruftTracker::CleanupUntrackedMethods.run!
|
8
|
+
CruftTracker::CleanupUntrackedViews.run!
|
7
9
|
rescue StandardError
|
8
10
|
# Swallow all errors to prevent initialization failures.
|
9
11
|
end
|
10
12
|
|
11
|
-
|
12
|
-
# ActiveSupport.on_load(:action_controller) do
|
13
|
-
# ::ActionController::Base.helper(CruftTracker::ApplicationHelper)
|
14
|
-
# end
|
15
|
-
# end
|
13
|
+
|
16
14
|
end
|
17
15
|
end
|
data/lib/cruft_tracker.rb
CHANGED
@@ -4,10 +4,18 @@ require 'cruft_tracker/registry'
|
|
4
4
|
require 'cruft_tracker/log_suppressor'
|
5
5
|
|
6
6
|
module CruftTracker
|
7
|
-
|
7
|
+
class << self
|
8
|
+
attr_accessor :config
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.init(&block)
|
12
|
+
self.config = Config.instance
|
8
13
|
|
9
|
-
|
10
|
-
|
14
|
+
self.instance_eval(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.is_this_view_used?(view, comment: nil)
|
18
|
+
CruftTracker::TrackView.run!(view: view, comment: comment)
|
11
19
|
end
|
12
20
|
|
13
21
|
def self.is_this_method_used?(
|
@@ -29,4 +37,28 @@ module CruftTracker
|
|
29
37
|
def self.are_any_of_these_methods_being_used?(owner, comment: nil)
|
30
38
|
CruftTracker::TrackAllMethods.run!(owner: owner, comment: comment)
|
31
39
|
end
|
40
|
+
|
41
|
+
class Config
|
42
|
+
include Singleton
|
43
|
+
|
44
|
+
DEFAULT_MAX_ARGUMENTS_VARIATIONS_PER_TRACKED_METHOD = 50
|
45
|
+
DEFAULT_MAX_BACKTRACE_VARIATIONS_PER_TRACKED_METHOD = 50
|
46
|
+
DEFAULT_MAX_VIEW_RENDERS_PER_VIEW = 50
|
47
|
+
DEFAULT_MAX_RENDER_METADATA_VARIATIONS_PER_VIEW_RENDER = 50
|
48
|
+
|
49
|
+
attr_accessor :max_argument_variations_per_tracked_method,
|
50
|
+
:max_backtrace_variations_per_tracked_method,
|
51
|
+
:max_view_renders_per_view,
|
52
|
+
:max_render_metadata_variations_per_view_render
|
53
|
+
|
54
|
+
def initialize
|
55
|
+
@max_argument_variations_per_tracked_method =
|
56
|
+
DEFAULT_MAX_ARGUMENTS_VARIATIONS_PER_TRACKED_METHOD
|
57
|
+
@max_backtrace_variations_per_tracked_method =
|
58
|
+
DEFAULT_MAX_BACKTRACE_VARIATIONS_PER_TRACKED_METHOD
|
59
|
+
@max_view_renders_per_view = DEFAULT_MAX_VIEW_RENDERS_PER_VIEW
|
60
|
+
@max_render_metadata_variations_per_view_render =
|
61
|
+
DEFAULT_MAX_RENDER_METADATA_VARIATIONS_PER_VIEW_RENDER
|
62
|
+
end
|
63
|
+
end
|
32
64
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cruft_tracker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adwerx Inc.
|
8
8
|
- Doug Hughes
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-
|
12
|
+
date: 2022-07-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: active_interaction
|
@@ -235,6 +235,20 @@ dependencies:
|
|
235
235
|
- - "~>"
|
236
236
|
- !ruby/object:Gem::Version
|
237
237
|
version: 2.5.0
|
238
|
+
- !ruby/object:Gem::Dependency
|
239
|
+
name: prettier
|
240
|
+
requirement: !ruby/object:Gem::Requirement
|
241
|
+
requirements:
|
242
|
+
- - ">="
|
243
|
+
- !ruby/object:Gem::Version
|
244
|
+
version: '0'
|
245
|
+
type: :development
|
246
|
+
prerelease: false
|
247
|
+
version_requirements: !ruby/object:Gem::Requirement
|
248
|
+
requirements:
|
249
|
+
- - ">="
|
250
|
+
- !ruby/object:Gem::Version
|
251
|
+
version: '0'
|
238
252
|
description: |
|
239
253
|
Have you ever asked yourself, "Is this method even being used?!" Or, "What the heck is this method receiving?" Does your application use Rails? If the answers these questions are yes, this gem may be of use to you!
|
240
254
|
|
@@ -262,13 +276,21 @@ files:
|
|
262
276
|
- app/models/cruft_tracker/argument.rb
|
263
277
|
- app/models/cruft_tracker/backtrace.rb
|
264
278
|
- app/models/cruft_tracker/method.rb
|
279
|
+
- app/models/cruft_tracker/render_metadata.rb
|
280
|
+
- app/models/cruft_tracker/view.rb
|
281
|
+
- app/models/cruft_tracker/view_render.rb
|
265
282
|
- app/services/cruft_tracker/application_service.rb
|
266
283
|
- app/services/cruft_tracker/cleanup_untracked_methods.rb
|
284
|
+
- app/services/cruft_tracker/cleanup_untracked_views.rb
|
285
|
+
- app/services/cruft_tracker/increment_view_renders.rb
|
267
286
|
- app/services/cruft_tracker/record_arguments.rb
|
268
287
|
- app/services/cruft_tracker/record_backtrace.rb
|
269
288
|
- app/services/cruft_tracker/record_invocation.rb
|
289
|
+
- app/services/cruft_tracker/record_render_metadata.rb
|
290
|
+
- app/services/cruft_tracker/record_view_render.rb
|
270
291
|
- app/services/cruft_tracker/track_all_methods.rb
|
271
292
|
- app/services/cruft_tracker/track_method.rb
|
293
|
+
- app/services/cruft_tracker/track_view.rb
|
272
294
|
- app/views/cruft_tracker/methods/index.html.erb
|
273
295
|
- app/views/layouts/cruft_tracker/application.html.erb
|
274
296
|
- config/routes.rb
|
@@ -276,6 +298,9 @@ files:
|
|
276
298
|
- db/migrate/20220418133030_create_cruft_tracker_backtraces.rb
|
277
299
|
- db/migrate/20220419171326_add_comment_to_cruft_tracker_methods.rb
|
278
300
|
- db/migrate/20220419174055_create_cruft_tracker_arguments.rb
|
301
|
+
- db/migrate/20220628175222_create_cruft_tracker_views.rb
|
302
|
+
- db/migrate/20220701125925_create_cruft_tracker_view_renders.rb
|
303
|
+
- db/migrate/20220705152409_create_render_metadata.rb
|
279
304
|
- lib/cruft_tracker.rb
|
280
305
|
- lib/cruft_tracker/engine.rb
|
281
306
|
- lib/cruft_tracker/log_suppressor.rb
|
@@ -288,7 +313,7 @@ licenses:
|
|
288
313
|
metadata:
|
289
314
|
homepage_uri: https://github.com/AdWerx/cruft-tracker
|
290
315
|
source_code_uri: https://github.com/AdWerx/cruft-tracker
|
291
|
-
post_install_message:
|
316
|
+
post_install_message:
|
292
317
|
rdoc_options: []
|
293
318
|
require_paths:
|
294
319
|
- lib
|
@@ -303,8 +328,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
303
328
|
- !ruby/object:Gem::Version
|
304
329
|
version: '0'
|
305
330
|
requirements: []
|
306
|
-
rubygems_version: 3.
|
307
|
-
signing_key:
|
331
|
+
rubygems_version: 3.1.6
|
332
|
+
signing_key:
|
308
333
|
specification_version: 4
|
309
334
|
summary: Provides a system to track Ruby method usage somewhat unobtrusively.
|
310
335
|
test_files: []
|