image_vise 0.6.1 → 0.7.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 +5 -5
- data/examples/error_handling_appsignal.rb +1 -1
- data/image_vise.gemspec +2 -1
- data/lib/image_vise.rb +6 -3
- data/lib/image_vise/image_request.rb +2 -2
- data/lib/image_vise/pipeline.rb +1 -1
- data/lib/image_vise/render_engine.rb +4 -4
- data/lib/image_vise/version.rb +1 -1
- metadata +19 -7
- data/lib/measurometer.rb +0 -92
- data/spec/measurometer_spec.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b23604cb3ebdd9901fdde805b567a785d9ae1cd81f08575ef960ee14abc2681c
|
4
|
+
data.tar.gz: b7a76ca5ffcd26c3ce574f95cf58cd9b2ed5e5b08779658f0ec58841ea5bcc94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4cb5afb69d834571cfcd36e418e22860f2fc24c530c167281a9fde0c6e7ebee8968255db682ecb21e410bfdce2e68e1bdce8f659f929d0f4481b99737c1cba25
|
7
|
+
data.tar.gz: 873b414d64a5091565f9693215e54f877811c4c3035fcf56a3998bdc654b54e1ef215f2b7c37bb789eb22b1ac992523cea34762153a47573acff738572615f18
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Anywhere in your app code
|
2
2
|
module ImageViseAppsignal
|
3
3
|
ImageVise::RenderEngine.prepend self
|
4
|
-
|
4
|
+
Measurometer.drivers << Appsignal # to obtain ImageVise instrumentation
|
5
5
|
def setup_error_handling(rack_env)
|
6
6
|
txn = Appsignal::Transaction.current
|
7
7
|
txn.set_action('%s#%s' % [self.class, 'call'])
|
data/image_vise.gemspec
CHANGED
@@ -31,7 +31,8 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_dependency 'rmagick', '~> 2.15'
|
32
32
|
spec.add_dependency 'ks'
|
33
33
|
spec.add_dependency 'rack', '>= 1', '< 3'
|
34
|
-
spec.add_dependency 'format_parser', '>= 0.
|
34
|
+
spec.add_dependency 'format_parser', '>= 0.14.0', '< 1.0'
|
35
|
+
spec.add_dependency 'measurometer', '~> 1'
|
35
36
|
|
36
37
|
spec.add_development_dependency 'magic_bytes', '~> 1'
|
37
38
|
spec.add_development_dependency "bundler", "~> 1.7"
|
data/lib/image_vise.rb
CHANGED
@@ -5,6 +5,7 @@ require 'rmagick'
|
|
5
5
|
require 'thread'
|
6
6
|
require 'base64'
|
7
7
|
require 'rack'
|
8
|
+
require 'measurometer'
|
8
9
|
require 'format_parser'
|
9
10
|
|
10
11
|
class ImageVise
|
@@ -26,7 +27,9 @@ class ImageVise
|
|
26
27
|
@allowed_glob_patterns = Set.new
|
27
28
|
@fetchers = {}
|
28
29
|
@cache_lifetime = DEFAULT_CACHE_LIFETIME
|
29
|
-
|
30
|
+
|
31
|
+
const_set(:Measurometer, ::Measurometer)
|
32
|
+
|
30
33
|
class << self
|
31
34
|
# Resets all allowed hosts
|
32
35
|
def reset_allowed_hosts!
|
@@ -164,7 +167,7 @@ class ImageVise
|
|
164
167
|
return unless maybe_image
|
165
168
|
return unless maybe_image.respond_to?(:destroy!)
|
166
169
|
return if maybe_image.destroyed?
|
167
|
-
|
170
|
+
Measurometer.instrument('image_vise.image_destroy_dealloc') do
|
168
171
|
maybe_image.destroy!
|
169
172
|
end
|
170
173
|
end
|
@@ -174,7 +177,7 @@ class ImageVise
|
|
174
177
|
# in scope but not yet set to an image) we take the possibility of nils into account.
|
175
178
|
def self.close_and_unlink(maybe_tempfile)
|
176
179
|
return unless maybe_tempfile
|
177
|
-
|
180
|
+
Measurometer.instrument('image_vise.tempfile_unlink') do
|
178
181
|
maybe_tempfile.close unless maybe_tempfile.closed?
|
179
182
|
maybe_tempfile.unlink if maybe_tempfile.respond_to?(:unlink)
|
180
183
|
end
|
@@ -14,11 +14,11 @@ class ImageVise::ImageRequest < Ks.strict(:src_url, :pipeline)
|
|
14
14
|
|
15
15
|
# Check the signature before decoding JSON (since we will be creating symbols)
|
16
16
|
unless valid_signature?(base64_encoded_params, given_signature, secrets)
|
17
|
-
|
17
|
+
Measurometer.increment_counter('image_vise.params.invalid_signatures', 1)
|
18
18
|
raise SignatureError, "Invalid or missing signature"
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
Measurometer.increment_counter('image_vise.params.valid_signatures', 1)
|
22
22
|
|
23
23
|
# Decode the JSON - only AFTER the signature has been validated,
|
24
24
|
# so we can use symbol keys
|
data/lib/image_vise/pipeline.rb
CHANGED
@@ -47,7 +47,7 @@ class ImageVise::Pipeline
|
|
47
47
|
def apply!(magick_image, image_metadata)
|
48
48
|
@ops.each do |operator|
|
49
49
|
operator_short_classname = operator.class.to_s.split('::').pop
|
50
|
-
|
50
|
+
Measurometer.instrument('image_vise.op.%s' % operator_short_classname) do
|
51
51
|
apply_operator_passing_metadata(magick_image, operator, image_metadata)
|
52
52
|
end
|
53
53
|
end
|
@@ -152,7 +152,7 @@
|
|
152
152
|
|
153
153
|
# Download/copy the original into a Tempfile
|
154
154
|
fetcher = ImageVise.fetcher_for(source_image_uri.scheme)
|
155
|
-
source_file =
|
155
|
+
source_file = Measurometer.instrument('image_vise.fetch') do
|
156
156
|
fetcher.fetch_uri_to_tempfile(source_image_uri)
|
157
157
|
end
|
158
158
|
file_format = FormatParser.parse(source_file, natures: [:image]).tap { source_file.rewind }
|
@@ -162,7 +162,7 @@
|
|
162
162
|
render_destination_file = Tempfile.new('imagevise-render').tap{|f| f.binmode }
|
163
163
|
|
164
164
|
# Do the actual imaging stuff
|
165
|
-
expire_after =
|
165
|
+
expire_after = Measurometer.instrument('image_vise.render_engine.apply_pipeline') do
|
166
166
|
apply_pipeline(source_file.path, pipeline, file_format, render_destination_file.path)
|
167
167
|
end
|
168
168
|
|
@@ -295,7 +295,7 @@
|
|
295
295
|
def apply_pipeline(source_file_path, pipeline, source_format_parser_result, render_to_path)
|
296
296
|
|
297
297
|
# Load the first frame of the animated GIF _or_ the blended compatibility layer from Photoshop
|
298
|
-
image_list =
|
298
|
+
image_list = Measurometer.instrument('image_vise.load_pixbuf') do
|
299
299
|
Magick::Image.read(source_file_path)
|
300
300
|
end
|
301
301
|
|
@@ -312,7 +312,7 @@
|
|
312
312
|
# it so that we get a KeyError if some operator has deleted it without providing a replacement.
|
313
313
|
# If no operators touched the writer we are going to use the automatic format selection
|
314
314
|
writer = metadata.fetch(:writer, ImageVise::AutoWriter.new)
|
315
|
-
|
315
|
+
Measurometer.instrument('image_vise.write_image') do
|
316
316
|
writer.write_image!(magick_image, metadata, render_to_path)
|
317
317
|
end
|
318
318
|
|
data/lib/image_vise/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image_vise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: patron
|
@@ -78,7 +78,7 @@ dependencies:
|
|
78
78
|
requirements:
|
79
79
|
- - ">="
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version: 0.
|
81
|
+
version: 0.14.0
|
82
82
|
- - "<"
|
83
83
|
- !ruby/object:Gem::Version
|
84
84
|
version: '1.0'
|
@@ -88,10 +88,24 @@ dependencies:
|
|
88
88
|
requirements:
|
89
89
|
- - ">="
|
90
90
|
- !ruby/object:Gem::Version
|
91
|
-
version: 0.
|
91
|
+
version: 0.14.0
|
92
92
|
- - "<"
|
93
93
|
- !ruby/object:Gem::Version
|
94
94
|
version: '1.0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: measurometer
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '1'
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '1'
|
95
109
|
- !ruby/object:Gem::Dependency
|
96
110
|
name: magic_bytes
|
97
111
|
requirement: !ruby/object:Gem::Requirement
|
@@ -260,7 +274,6 @@ files:
|
|
260
274
|
- lib/image_vise/version.rb
|
261
275
|
- lib/image_vise/writers/auto_writer.rb
|
262
276
|
- lib/image_vise/writers/jpeg_writer.rb
|
263
|
-
- lib/measurometer.rb
|
264
277
|
- spec/image_vise/auto_orient_spec.rb
|
265
278
|
- spec/image_vise/background_fill_spec.rb
|
266
279
|
- spec/image_vise/crop_spec.rb
|
@@ -282,7 +295,6 @@ files:
|
|
282
295
|
- spec/image_vise/writers/jpeg_writer_spec.rb
|
283
296
|
- spec/image_vise_spec.rb
|
284
297
|
- spec/layers-with-blending.psd
|
285
|
-
- spec/measurometer_spec.rb
|
286
298
|
- spec/spec_helper.rb
|
287
299
|
- spec/test_server.rb
|
288
300
|
- spec/waterside_magic_hour.jpg
|
@@ -312,7 +324,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
312
324
|
version: '0'
|
313
325
|
requirements: []
|
314
326
|
rubyforge_project:
|
315
|
-
rubygems_version: 2.
|
327
|
+
rubygems_version: 2.7.3
|
316
328
|
signing_key:
|
317
329
|
specification_version: 4
|
318
330
|
summary: Runtime thumbnailing proxy
|
data/lib/measurometer.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
# Measurometer is 1-1 API compatible with Appsignal,
|
2
|
-
# which we use a lot
|
3
|
-
class ImageVise::Measurometer
|
4
|
-
class << self
|
5
|
-
# Permits adding instrumentation drivers. To magically
|
6
|
-
# obtain all Appsignal instrumentation, add the Appsignal module
|
7
|
-
# as a driver.
|
8
|
-
#
|
9
|
-
# Measurometer.drivers << Appsignal
|
10
|
-
#
|
11
|
-
# A driver must be reentrant and thread-safe - it should be possible
|
12
|
-
# to have multiple `instrument` calls open from different threads at the
|
13
|
-
# same time.
|
14
|
-
#
|
15
|
-
# The driver must support the same interface as the Measurometer class
|
16
|
-
# itself, minus the `drivers` and `instrument_instance_method` methods.
|
17
|
-
#
|
18
|
-
# @return Array
|
19
|
-
def drivers
|
20
|
-
@drivers ||= []
|
21
|
-
@drivers
|
22
|
-
end
|
23
|
-
|
24
|
-
# Runs a given block within a cascade of `instrument` blocks of all the
|
25
|
-
# added drivers.
|
26
|
-
#
|
27
|
-
# Measurometer.instrument('do_foo') { compute! }
|
28
|
-
#
|
29
|
-
# unfolds to
|
30
|
-
#
|
31
|
-
# Appsignal.instrument('do_foo') do
|
32
|
-
# Statsd.timing('do_foo') do
|
33
|
-
# compute!
|
34
|
-
# end
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
# Note that it is _imperative_ that the block return value is preserved
|
38
|
-
# by the drivers and passed as the result of the block.
|
39
|
-
#
|
40
|
-
# @param block_name[String] under which path to push the metric
|
41
|
-
# @param blk[#call] the block to instrument
|
42
|
-
# @return [Object] the return value of &blk
|
43
|
-
def instrument(block_name, &blk)
|
44
|
-
return yield unless @drivers && @drivers.any? # The block wrapping business is not free
|
45
|
-
@drivers.inject(blk) { |outer_block, driver|
|
46
|
-
-> {
|
47
|
-
driver.instrument(block_name, &outer_block)
|
48
|
-
}
|
49
|
-
}.call
|
50
|
-
end
|
51
|
-
|
52
|
-
# Adds a distribution value (sample) under a given path
|
53
|
-
#
|
54
|
-
# @param value_path[String] under which path to push the metric
|
55
|
-
# @param value[Numeric] distribution value
|
56
|
-
# @return nil
|
57
|
-
def add_distribution_value(value_path, value)
|
58
|
-
(@drivers || []).each { |d| d.add_distribution_value(value_path, value) }
|
59
|
-
nil
|
60
|
-
end
|
61
|
-
|
62
|
-
# Increment a named counter under a given path
|
63
|
-
#
|
64
|
-
# @param counter_path[String] under which path to push the metric
|
65
|
-
# @param by[Integer] the counter increment to apply
|
66
|
-
# @return nil
|
67
|
-
def increment_counter(counter_path, by)
|
68
|
-
(@drivers || []).each { |d| d.increment_counter(counter_path, by) }
|
69
|
-
nil
|
70
|
-
end
|
71
|
-
|
72
|
-
# Wrap an anonymous module around an instance method in the given class to have
|
73
|
-
# it instrumented automatically. The name of the measurement will be interpolated as:
|
74
|
-
#
|
75
|
-
# "#{prefix}.#{rightmost_class_constant_name}.#{instance_method_name}"
|
76
|
-
#
|
77
|
-
# @param target_class[Class] the class to instrument
|
78
|
-
# @param instance_method_name_to_instrument[Symbol] the method name to instrument
|
79
|
-
# @param path_prefix[String] under which path to push the instrumented metric
|
80
|
-
# @return void
|
81
|
-
def instrument_instance_method(target_class, instance_method_name_to_instrument, path_prefix)
|
82
|
-
short_class_name = target_class.to_s.split('::').last
|
83
|
-
instrumentation_name = [path_prefix, short_class_name, instance_method_name_to_instrument].join('.')
|
84
|
-
instrumenter_module = Module.new do
|
85
|
-
define_method(instance_method_name_to_instrument) do |*any|
|
86
|
-
::ImageVise::Measurometer.instrument(instrumentation_name) { super(*any) }
|
87
|
-
end
|
88
|
-
end
|
89
|
-
target_class.prepend(instrumenter_module)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
data/spec/measurometer_spec.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ImageVise::Measurometer do
|
4
|
-
RSpec::Matchers.define :include_counter_or_measurement_named do |named|
|
5
|
-
match do |actual|
|
6
|
-
actual.any? do |e|
|
7
|
-
e[0] == named && e[1] > 0
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'instruments a full cycle FormatParser.parse' do
|
13
|
-
driver_class = Class.new do
|
14
|
-
attr_accessor :timings, :counters, :distributions
|
15
|
-
def initialize
|
16
|
-
@timings = []
|
17
|
-
@distributions = []
|
18
|
-
@counters = []
|
19
|
-
end
|
20
|
-
|
21
|
-
def instrument(block_name)
|
22
|
-
s = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
23
|
-
yield.tap do
|
24
|
-
delta = Process.clock_gettime(Process::CLOCK_MONOTONIC) - s
|
25
|
-
@timings << [block_name, delta * 1000]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def add_distribution_value(value_path, value)
|
30
|
-
@distributions << [value_path, value]
|
31
|
-
end
|
32
|
-
|
33
|
-
def increment_counter(value_path, value)
|
34
|
-
@counters << [value_path, value]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
instrumenter = driver_class.new
|
39
|
-
described_class.drivers << instrumenter
|
40
|
-
|
41
|
-
builder = ImageVise::Pipeline.new
|
42
|
-
pipeline = builder.
|
43
|
-
auto_orient.
|
44
|
-
fit_crop(width: 48, height: 48, gravity: 'c').
|
45
|
-
sharpen(radius: 2, sigma: 0.5).
|
46
|
-
ellipse_stencil.
|
47
|
-
strip_metadata
|
48
|
-
|
49
|
-
image = Magick::Image.read(test_image_path)[0]
|
50
|
-
pipeline.apply! image, {}
|
51
|
-
|
52
|
-
described_class.drivers.delete(instrumenter)
|
53
|
-
expect(described_class.drivers).not_to include(instrumenter)
|
54
|
-
|
55
|
-
expect(instrumenter.timings).to include_counter_or_measurement_named('image_vise.op.AutoOrient')
|
56
|
-
expect(instrumenter.timings).to include_counter_or_measurement_named('image_vise.op.StripMetadata')
|
57
|
-
end
|
58
|
-
end
|