jekyll-minify 1.0.7 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/jekyll-minify/instrumentation.rb +291 -0
- data/lib/jekyll-minify/version.rb +12 -0
- data/lib/jekyll-minify.rb +7 -1
- metadata +19 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f3cca42f128bfb722359fbe7cad0782cdde8192bc1dbadc889ab09de710e0fba
|
|
4
|
+
data.tar.gz: bba9d326f421608eb24d4d4613947b1ca4427d5a7ef3a599c66c193722d52fe6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8f0826508130a2f2c2ddb1c8a26799412c82752b49066282ceb279526a505f86d91209b88230362bfdc02e53f0b9835df33f6843d49ad797c14591b56f88e013
|
|
7
|
+
data.tar.gz: d3caa8d83001eafc4ada3ab56e6c9210e415af5478892fc255a5d8a6589e4ff0b7f978e82dcd991288b88197519be1f7325a9ad57be34df57ba8e4a69bee7ca9
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module Minify
|
|
5
|
+
# OpenTelemetry instrumentation facade for jekyll-minify.
|
|
6
|
+
#
|
|
7
|
+
# All tracing is configured centrally in TRACED_METHODS — no span code lives
|
|
8
|
+
# in business logic classes. To add a span: append one entry. To rename a
|
|
9
|
+
# method: update the one entry. When a method is removed from its class the
|
|
10
|
+
# stale entry raises NoMethodError in tests, signalling the entry to delete.
|
|
11
|
+
#
|
|
12
|
+
# Requires opentelemetry-api at runtime; falls back to a no-op if absent.
|
|
13
|
+
# Users opt in to real tracing by adding opentelemetry-sdk and
|
|
14
|
+
# opentelemetry-exporter-otlp to their site Gemfile and exporting:
|
|
15
|
+
#
|
|
16
|
+
# OTEL_SERVICE_NAME=jekyll-minify
|
|
17
|
+
# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
18
|
+
module Instrumentation
|
|
19
|
+
# Name reported to the OTel tracer provider for spans created by this gem.
|
|
20
|
+
#
|
|
21
|
+
# @return [String]
|
|
22
|
+
TRACER_NAME = 'jekyll-minify'
|
|
23
|
+
|
|
24
|
+
# Central instrumentation registry.
|
|
25
|
+
#
|
|
26
|
+
# Each row: [class_name, method_type, method_name, span_name, attribute_proc]
|
|
27
|
+
#
|
|
28
|
+
# method_type:
|
|
29
|
+
# :instance — public instance method
|
|
30
|
+
# :private — private instance method (visibility is preserved on the wrapper)
|
|
31
|
+
# :class — class / module method (prepended on the singleton class)
|
|
32
|
+
#
|
|
33
|
+
# attribute_proc: ->(span, this, args, result) or nil
|
|
34
|
+
# span — OTel span (or NoopSpan); call span.set_attribute after super returns
|
|
35
|
+
# this — receiver object (instance or nil for class methods)
|
|
36
|
+
# args — positional args array as passed to the method
|
|
37
|
+
# result — return value of the original method
|
|
38
|
+
#
|
|
39
|
+
# @return [Array<Array>]
|
|
40
|
+
# :nocov: — attribute procs are configuration data; coverage comes from integration tests
|
|
41
|
+
TRACED_METHODS = [
|
|
42
|
+
['Jekyll::Minify::Minifier', :class, :minify_site, 'minify.site_minify',
|
|
43
|
+
lambda { |span, _this, args, result|
|
|
44
|
+
span.set_attribute('minify.dest_path', args[0].dest.to_s)
|
|
45
|
+
next unless result
|
|
46
|
+
|
|
47
|
+
types = result.values_at(:html, :css, :js)
|
|
48
|
+
span.set_attribute('minify.total_file_count', types.sum { |t| t[:count] })
|
|
49
|
+
span.set_attribute('minify.total_original_size_bytes', types.sum { |t| t[:original_bytes] })
|
|
50
|
+
span.set_attribute('minify.total_minified_size_bytes', types.sum { |t| t[:minified_bytes] })
|
|
51
|
+
span.set_attribute('minify.error_count', result[:errors].length)
|
|
52
|
+
}],
|
|
53
|
+
|
|
54
|
+
['Jekyll::Minify::Minifier', :private, :minify_each_file, 'minify.file_discovery',
|
|
55
|
+
lambda { |span, _this, args, _result|
|
|
56
|
+
span.set_attribute('minify.dest_path', args[0].to_s)
|
|
57
|
+
}],
|
|
58
|
+
|
|
59
|
+
['Jekyll::Minify::Minifier', :private, :minify_with_fallback, 'minify.file_process',
|
|
60
|
+
lambda { |span, _this, args, _result|
|
|
61
|
+
span.set_attribute('minify.file_path', args[0].to_s)
|
|
62
|
+
span.set_attribute('minify.asset_type', args[1].to_s)
|
|
63
|
+
}],
|
|
64
|
+
|
|
65
|
+
['Jekyll::Minify::Minifier', :private, :minify_html, 'minify.html_minify',
|
|
66
|
+
lambda { |span, _this, args, result|
|
|
67
|
+
span.set_attribute('minify.input_size_bytes', args[0].bytesize)
|
|
68
|
+
span.set_attribute('minify.output_size_bytes', result.to_s.bytesize)
|
|
69
|
+
}],
|
|
70
|
+
|
|
71
|
+
['Jekyll::Minify::Minifier', :private, :minify_css, 'minify.css_minify',
|
|
72
|
+
lambda { |span, _this, args, result|
|
|
73
|
+
span.set_attribute('minify.input_size_bytes', args[0].bytesize)
|
|
74
|
+
span.set_attribute('minify.output_size_bytes', result.to_s.bytesize)
|
|
75
|
+
}],
|
|
76
|
+
|
|
77
|
+
['Jekyll::Minify::Minifier', :private, :minify_js, 'minify.js_minify',
|
|
78
|
+
lambda { |span, _this, args, result|
|
|
79
|
+
span.set_attribute('minify.input_size_bytes', args[0].bytesize)
|
|
80
|
+
span.set_attribute('minify.output_size_bytes', result.to_s.bytesize)
|
|
81
|
+
}]
|
|
82
|
+
].freeze
|
|
83
|
+
# :nocov:
|
|
84
|
+
|
|
85
|
+
# Returns the active OTel tracer, or a no-op tracer if opentelemetry-api is absent.
|
|
86
|
+
#
|
|
87
|
+
# @return [OpenTelemetry::Trace::Tracer, NoopTracer]
|
|
88
|
+
def self.tracer
|
|
89
|
+
@tracer ||=
|
|
90
|
+
if defined?(OpenTelemetry)
|
|
91
|
+
# :nocov:
|
|
92
|
+
OpenTelemetry.tracer_provider.tracer(TRACER_NAME, Jekyll::Minify::VERSION)
|
|
93
|
+
# :nocov:
|
|
94
|
+
else
|
|
95
|
+
NoopTracer.new
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Wraps a block in an OTel span.
|
|
100
|
+
#
|
|
101
|
+
# @param span_name [String] Dot-separated span name (e.g. 'minify.html_minify')
|
|
102
|
+
# @param attributes [Hash] Initial span attributes
|
|
103
|
+
# @yieldparam span [OpenTelemetry::Trace::Span, NoopSpan] Active span
|
|
104
|
+
# @return [Object] The return value of the block
|
|
105
|
+
def self.instrument(span_name, attributes: {}, &block)
|
|
106
|
+
tracer.in_span(span_name, attributes: attributes, &block)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Resets the cached tracer and installation flag. Call in tests after changing OTel configuration.
|
|
110
|
+
#
|
|
111
|
+
# @return [void]
|
|
112
|
+
def self.reset!
|
|
113
|
+
@tracer = nil
|
|
114
|
+
@installed = false
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Returns true when OTel is requested via standard environment variables.
|
|
118
|
+
#
|
|
119
|
+
# install! guards on this so the prepend wrappers are only applied when
|
|
120
|
+
# a real exporter is configured. In CI and local tests (no OTel env vars)
|
|
121
|
+
# business logic classes are untouched, keeping allow_any_instance_of stubs
|
|
122
|
+
# and other RSpec mechanics fully functional.
|
|
123
|
+
#
|
|
124
|
+
# @return [Boolean]
|
|
125
|
+
def self.enabled?
|
|
126
|
+
ENV.key?('OTEL_EXPORTER_OTLP_ENDPOINT') || ENV.key?('OTEL_SERVICE_NAME')
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Installs wrappers on all classes listed in TRACED_METHODS using Module#prepend.
|
|
130
|
+
#
|
|
131
|
+
# Called once at plugin load time (end of jekyll-minify.rb, after all requires),
|
|
132
|
+
# but only when enabled? returns true. Use OTEL_EXPORTER_OTLP_ENDPOINT or
|
|
133
|
+
# OTEL_SERVICE_NAME to activate tracing.
|
|
134
|
+
#
|
|
135
|
+
# @return [void]
|
|
136
|
+
def self.install!
|
|
137
|
+
return if @installed
|
|
138
|
+
|
|
139
|
+
@installed = true
|
|
140
|
+
setup_sdk!
|
|
141
|
+
TRACED_METHODS.group_by { |e| e[0] }.each do |class_name, entries|
|
|
142
|
+
prepend_wrappers(resolve_class(class_name), entries)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Configures the OTel SDK from standard env vars if the SDK gem is available.
|
|
147
|
+
# Silently no-ops when opentelemetry-sdk or opentelemetry-exporter-otlp is
|
|
148
|
+
# not installed. Uses SimpleSpanProcessor (not the SDK default
|
|
149
|
+
# BatchSpanProcessor) since Jekyll is a short-lived CLI process that could
|
|
150
|
+
# exit before a batch timer fires, dropping spans.
|
|
151
|
+
#
|
|
152
|
+
# jekyll-theme-centos loads several instrumented plugins in one process;
|
|
153
|
+
# OpenTelemetry::SDK.configure overwrites the global tracer_provider on
|
|
154
|
+
# every call, so only the first plugin to reach here (see
|
|
155
|
+
# sdk_already_configured?) configures the SDK — later callers reuse that
|
|
156
|
+
# provider. The at_exit/post_write hooks are registered once, by whichever
|
|
157
|
+
# plugin wins, and flush every plugin's spans, not just this one's.
|
|
158
|
+
#
|
|
159
|
+
# @return [void]
|
|
160
|
+
def self.setup_sdk!
|
|
161
|
+
return if sdk_already_configured?
|
|
162
|
+
|
|
163
|
+
# :nocov:
|
|
164
|
+
require 'opentelemetry/sdk'
|
|
165
|
+
require 'opentelemetry/exporter/otlp'
|
|
166
|
+
exporter = OpenTelemetry::Exporter::OTLP::Exporter.new
|
|
167
|
+
processor = OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(exporter)
|
|
168
|
+
OpenTelemetry::SDK.configure { |c| c.add_span_processor(processor) }
|
|
169
|
+
|
|
170
|
+
at_exit { OpenTelemetry.tracer_provider&.shutdown }
|
|
171
|
+
Jekyll::Hooks.register(:site, :post_write, priority: 0) { OpenTelemetry.tracer_provider&.force_flush }
|
|
172
|
+
rescue LoadError
|
|
173
|
+
nil
|
|
174
|
+
# :nocov:
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# True when some plugin (this one or another) already installed a real
|
|
178
|
+
# SDK-backed tracer_provider, in which case setup_sdk! must not run again.
|
|
179
|
+
#
|
|
180
|
+
# @return [Boolean]
|
|
181
|
+
def self.sdk_already_configured?
|
|
182
|
+
defined?(OpenTelemetry::SDK::Trace::TracerProvider) &&
|
|
183
|
+
OpenTelemetry.tracer_provider.is_a?(OpenTelemetry::SDK::Trace::TracerProvider)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Resolves a dot-separated class name to a constant; returns nil on NameError.
|
|
187
|
+
#
|
|
188
|
+
# @param name [String] fully-qualified class name, e.g. 'Jekyll::Minify::Minifier'
|
|
189
|
+
# @return [Class, nil]
|
|
190
|
+
def self.resolve_class(name)
|
|
191
|
+
name.split('::').reduce(Object) { |m, c| m.const_get(c) }
|
|
192
|
+
rescue NameError
|
|
193
|
+
nil
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Applies instance and class-method wrappers to klass; skips if klass is nil.
|
|
197
|
+
#
|
|
198
|
+
# @param klass [Class, nil] the class to wrap
|
|
199
|
+
# @param entries [Array<Array>] TRACED_METHODS rows scoped to klass
|
|
200
|
+
# @return [void]
|
|
201
|
+
def self.prepend_wrappers(klass, entries)
|
|
202
|
+
return unless klass
|
|
203
|
+
|
|
204
|
+
class_entries, instance_entries = entries.partition { |e| e[1] == :class }
|
|
205
|
+
klass.prepend(build_wrapper_module(instance_entries)) unless instance_entries.empty?
|
|
206
|
+
klass.singleton_class.prepend(build_wrapper_module(class_entries)) unless class_entries.empty?
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Builds an anonymous module that wraps each listed method in a span.
|
|
210
|
+
#
|
|
211
|
+
# @param entries [Array<Array>] TRACED_METHODS rows to wrap
|
|
212
|
+
# @return [Module] anonymous module ready to be prepended
|
|
213
|
+
def self.build_wrapper_module(entries)
|
|
214
|
+
Module.new do
|
|
215
|
+
entries.each { |entry| Instrumentation.send(:define_traced_method, self, entry) }
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Defines a single span-wrapped method on mod for one TRACED_METHODS entry.
|
|
220
|
+
#
|
|
221
|
+
# @param mod [Module] the wrapper module being built
|
|
222
|
+
# @param entry [Array] one TRACED_METHODS row: [class_name, method_type, method_name, span_name, attr_proc]
|
|
223
|
+
# @return [void]
|
|
224
|
+
def self.define_traced_method(mod, entry)
|
|
225
|
+
_class_name, method_type, method_name, span_name, attr_proc = entry
|
|
226
|
+
mod.define_method(method_name) do |*args, **kwargs, &blk|
|
|
227
|
+
Instrumentation.send(:run_traced, span_name, attr_proc, self, args) { super(*args, **kwargs, &blk) }
|
|
228
|
+
end
|
|
229
|
+
mod.send(:private, method_name) if method_type == :private
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Runs the original method inside a span, applying attr_proc on success and
|
|
233
|
+
# recording exceptions on the span before re-raising them.
|
|
234
|
+
#
|
|
235
|
+
# @param span_name [String] span name
|
|
236
|
+
# @param attr_proc [Proc, nil] attribute callback: ->(span, receiver, args, result)
|
|
237
|
+
# @param receiver [Object] the wrapped method's receiver (self)
|
|
238
|
+
# @param args [Array] positional arguments passed to the wrapped method
|
|
239
|
+
# @yieldreturn [Object] the original (unwrapped) method's return value
|
|
240
|
+
# @return [Object] the wrapped method's return value
|
|
241
|
+
def self.run_traced(span_name, attr_proc, receiver, args)
|
|
242
|
+
instrument(span_name) do |span|
|
|
243
|
+
result = yield
|
|
244
|
+
attr_proc&.call(span, receiver, args, result)
|
|
245
|
+
result
|
|
246
|
+
rescue StandardError => e
|
|
247
|
+
span.record_exception(e)
|
|
248
|
+
raise
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
private_class_method :build_wrapper_module, :define_traced_method, :run_traced, :prepend_wrappers, :setup_sdk!,
|
|
253
|
+
:sdk_already_configured?
|
|
254
|
+
|
|
255
|
+
# No-op tracer used when opentelemetry-api is not loaded.
|
|
256
|
+
class NoopTracer
|
|
257
|
+
# Yields a NoopSpan and returns the block's value.
|
|
258
|
+
#
|
|
259
|
+
# @param _name [String] span name (ignored)
|
|
260
|
+
# @param _opts [Hash] span options (ignored)
|
|
261
|
+
# @yieldparam span [NoopSpan]
|
|
262
|
+
# @return [Object] the block's return value
|
|
263
|
+
def in_span(_name, **_opts)
|
|
264
|
+
yield NoopSpan.new
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# No-op span that silently accepts all attribute and event calls.
|
|
269
|
+
class NoopSpan
|
|
270
|
+
# No-op attribute setter. Accepts and ignores any arguments.
|
|
271
|
+
#
|
|
272
|
+
# @return [NoopSpan] self
|
|
273
|
+
def set_attribute(*)
|
|
274
|
+
self
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# No-op exception recorder. Accepts and ignores any arguments.
|
|
278
|
+
#
|
|
279
|
+
# @return [NoopSpan] self
|
|
280
|
+
def record_exception(*)
|
|
281
|
+
self
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# No-op status setter. Accepts and ignores any arguments.
|
|
285
|
+
#
|
|
286
|
+
# @return [void]
|
|
287
|
+
def status=(*); end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module Minify
|
|
5
|
+
# The version of the jekyll-minify gem.
|
|
6
|
+
#
|
|
7
|
+
# Updated with each release to reflect the current version. Independent of the
|
|
8
|
+
# gemspec's CI-generated version; used to identify this library's version to
|
|
9
|
+
# the OpenTelemetry tracer provider.
|
|
10
|
+
VERSION = '1.0.6'
|
|
11
|
+
end
|
|
12
|
+
end
|
data/lib/jekyll-minify.rb
CHANGED
|
@@ -76,6 +76,9 @@ rescue LoadError
|
|
|
76
76
|
'Install with: gem install minify_html'
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
+
require_relative 'jekyll-minify/version'
|
|
80
|
+
require_relative 'jekyll-minify/instrumentation'
|
|
81
|
+
|
|
79
82
|
module Jekyll
|
|
80
83
|
# Jekyll plugin for automatic minification of HTML, CSS, and JavaScript.
|
|
81
84
|
module Minify
|
|
@@ -146,7 +149,7 @@ module Jekyll
|
|
|
146
149
|
# Returns immediately if with_minify is false or the destination directory does not exist.
|
|
147
150
|
#
|
|
148
151
|
# @param site [Jekyll::Site] the Jekyll site object providing dest and config
|
|
149
|
-
# @return [
|
|
152
|
+
# @return [Hash, nil] the run's @stats, or nil if minification was skipped
|
|
150
153
|
def run(site)
|
|
151
154
|
unless plugin_enabled?(site.config)
|
|
152
155
|
Jekyll.logger.info 'jekyll-minify:', 'Minification disabled (with_minify: false).'
|
|
@@ -162,6 +165,7 @@ module Jekyll
|
|
|
162
165
|
|
|
163
166
|
minify_each_file(dest)
|
|
164
167
|
log_statistics
|
|
168
|
+
@stats
|
|
165
169
|
end
|
|
166
170
|
|
|
167
171
|
private
|
|
@@ -486,3 +490,5 @@ end
|
|
|
486
490
|
Jekyll::Hooks.register :site, :post_write, priority: :low do |site|
|
|
487
491
|
Jekyll::Minify::Minifier.minify_site(site)
|
|
488
492
|
end
|
|
493
|
+
|
|
494
|
+
Jekyll::Minify::Instrumentation.install! if Jekyll::Minify::Instrumentation.enabled?
|
metadata
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-minify
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- Alain Reguera Delgado
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
@@ -43,6 +43,20 @@ dependencies:
|
|
|
43
43
|
- - "~>"
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
45
|
version: '0.15'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: opentelemetry-api
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - "~>"
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '1.4'
|
|
53
|
+
type: :runtime
|
|
54
|
+
prerelease: false
|
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - "~>"
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '1.4'
|
|
46
60
|
- !ruby/object:Gem::Dependency
|
|
47
61
|
name: rake
|
|
48
62
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -171,7 +185,7 @@ dependencies:
|
|
|
171
185
|
version: '0.9'
|
|
172
186
|
description: Jekyll plugin to minify HTML, CSS, and JavaScript files.
|
|
173
187
|
email:
|
|
174
|
-
-
|
|
188
|
+
- alain.reguera@gmail.com
|
|
175
189
|
executables: []
|
|
176
190
|
extensions: []
|
|
177
191
|
extra_rdoc_files: []
|
|
@@ -179,6 +193,8 @@ files:
|
|
|
179
193
|
- LICENSE
|
|
180
194
|
- README.md
|
|
181
195
|
- lib/jekyll-minify.rb
|
|
196
|
+
- lib/jekyll-minify/instrumentation.rb
|
|
197
|
+
- lib/jekyll-minify/version.rb
|
|
182
198
|
homepage: https://gitlab.com/CentOS/artwork/centos-web/jekyll-minify
|
|
183
199
|
licenses:
|
|
184
200
|
- MIT
|