scout_apm 3.0.0.pre0 → 3.0.0.pre1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: afa1d7b25baf3d94a547899966b95419ac560d07
4
- data.tar.gz: d6201d2acc85f2e94c92315b8193d110a4febd0a
3
+ metadata.gz: d4de385d6ffca53d6dd6e5de87fdc5e89fba54a3
4
+ data.tar.gz: 5147b662a5b8c7454b8fdf50d6e82cc24c6cbbf7
5
5
  SHA512:
6
- metadata.gz: 9a125da761d39c62094fc48ca66163bac787c0de62e9b6a3f38e984ae2ab8f41dcc7d271519764694c6b9a194e084c626bbf7b042a364ee56afe524c912fd83a
7
- data.tar.gz: cce9304bd70490eb711c92a6df03d656710c01eb0343f809e58d0bb49c02ec152a99f668b21f7e51424aec34e432286c0ec83f7cdc74cdc994300ae6aa0b4ed6
6
+ metadata.gz: 790273c395b6b7f96bc0ca6a260a3372ca931362991553a9d7fb544d30959c769552532e1873bd0b2d4e9e6e0f86e5567964a75f8b75cb66c8d67f411a1a2384
7
+ data.tar.gz: 37ab78f6e6f001ae3c82729daf9b1a008c61d5e70d9139795d4b80ae172de5100a82efe57ba3890301172902aa486a8404e8779914448c8b146584c246e8d0c4
data/CHANGELOG.markdown CHANGED
@@ -1,11 +1,19 @@
1
- # 2.2.0
1
+ # 3.0.0
2
2
 
3
3
  * ScoutProf BETA
4
4
 
5
+ # 2.1.8
6
+
7
+ * Adds Git revision detection, which is reported on app load and associated with transaction traces
8
+
9
+ # 2.1.7
10
+
11
+ * Fix allocations extension compilation on Ruby 1.8.7
12
+ >>>>>>> master
13
+
5
14
  # 2.1.6
6
15
 
7
16
  * Support older versions of Grape (0.10 onward)
8
- * Fix issue with complex AR queries
9
17
  * Vendor rusage library
10
18
  * Fix double-exit that caused error messages when running under Passenger
11
19
 
data/Rakefile CHANGED
@@ -23,4 +23,3 @@ require 'rake/extensiontask'
23
23
  Rake::ExtensionTask.new('allocations')
24
24
  Rake::ExtensionTask.new('stacks')
25
25
  Rake::ExtensionTask.new('rusage')
26
-
@@ -1,4 +1,8 @@
1
+ #ifdef HAVE_RUBY_RUBY_H
1
2
  #include <ruby/ruby.h>
3
+ #else // Ruby <= 1.8.7
4
+ #include <ruby.h>
5
+ #endif
2
6
 
3
7
  VALUE mScoutApm;
4
8
  VALUE mInstruments;
@@ -1,3 +1,4 @@
1
1
  require 'mkmf'
2
2
 
3
+ have_header("ruby/ruby.h") # Needed to check for Ruby <= 1.8.7
3
4
  create_makefile('allocations')
@@ -121,11 +121,6 @@ module ScoutApm
121
121
 
122
122
  @ignored_uris = ScoutApm::IgnoredUris.new(config.value('ignore'))
123
123
 
124
- if environment.deploy_integration
125
- logger.info "Starting monitoring for [#{environment.deploy_integration.name}]]."
126
- return environment.deploy_integration.install
127
- end
128
-
129
124
  load_instruments if should_load_instruments?(options)
130
125
 
131
126
  return false unless preconditions_met?(options)
@@ -330,10 +325,6 @@ module ScoutApm
330
325
  instance.install
331
326
  end
332
327
 
333
- def deploy_integration
334
- environment.deploy_integration
335
- end
336
-
337
328
  def app_server_missing?(options = {})
338
329
  !environment.app_server_integration(true).found? && !options[:skip_app_server_check]
339
330
  end
@@ -38,7 +38,8 @@ module ScoutApm
38
38
  :database_adapter => ScoutApm::Environment.instance.raw_database_adapter, # Raw
39
39
  :application_name => ScoutApm::Environment.instance.application_name,
40
40
  :libraries => ScoutApm::Utils::InstalledGems.new.run,
41
- :paas => ScoutApm::Environment.instance.platform_integration.name
41
+ :paas => ScoutApm::Environment.instance.platform_integration.name,
42
+ :git_sha => ScoutApm::Environment.instance.git_revision.sha
42
43
  }
43
44
  end
44
45
  end
@@ -41,13 +41,8 @@ module ScoutApm
41
41
  ScoutApm::PlatformIntegrations::Server.new,
42
42
  ]
43
43
 
44
- DEPLOY_INTEGRATIONS = [
45
- ScoutApm::DeployIntegrations::Capistrano3.new(STDOUT_LOGGER),
46
- # ScoutApm::DeployIntegrations::Capistrano2.new(STDOUT_LOGGER),
47
- ]
48
-
49
44
  def env
50
- @env ||= deploy_integration? ? deploy_integration.env : framework_integration.env
45
+ @env ||= framework_integration.env
51
46
  end
52
47
 
53
48
  def framework
@@ -88,7 +83,7 @@ module ScoutApm
88
83
  end
89
84
 
90
85
  def root
91
- @root ||= deploy_integration? ? deploy_integration.root : framework_root
86
+ @root ||= framework_root
92
87
  end
93
88
 
94
89
  def framework_root
@@ -110,6 +105,10 @@ module ScoutApm
110
105
  @hostname ||= Agent.instance.config.value("hostname") || platform_integration.hostname
111
106
  end
112
107
 
108
+ def git_revision
109
+ @git_revision ||= ScoutApm::GitRevision.new
110
+ end
111
+
113
112
  # Returns the whole integration object
114
113
  # This needs to be improved. Frequently, multiple app servers gem are present and which
115
114
  # ever is checked first becomes the designated app server.
@@ -143,14 +142,6 @@ module ScoutApm
143
142
  background_job_integration && background_job_integration.name
144
143
  end
145
144
 
146
- def deploy_integration
147
- @deploy_integration ||= DEPLOY_INTEGRATIONS.detect{ |integration| integration.present? }
148
- end
149
-
150
- def deploy_integration?
151
- !@deploy_integration.nil?
152
- end
153
-
154
145
  ### ruby checks
155
146
 
156
147
  def rubinius?
@@ -0,0 +1,51 @@
1
+ module ScoutApm
2
+ class GitRevision
3
+
4
+ attr_accessor :sha
5
+
6
+ def initialize
7
+ @sha = detect
8
+ ScoutApm::Agent.instance.logger.debug "Detected Git Revision [#{@sha}]"
9
+ end
10
+
11
+ private
12
+
13
+ def detect
14
+ detect_from_env_var ||
15
+ detect_from_heroku ||
16
+ detect_from_capistrano ||
17
+ detect_from_git
18
+ end
19
+
20
+ def detect_from_heroku
21
+ ENV['HEROKU_SLUG_COMMIT']
22
+ end
23
+
24
+ def detect_from_env_var
25
+ ENV['SCOUT_REVISION_SHA']
26
+ end
27
+
28
+ def detect_from_capistrano
29
+ version = File.read(File.join(app_root, 'REVISION')).strip
30
+ # Capistrano 3.0 - 3.1.x
31
+ version || File.open(File.join(app_root, '..', 'revisions.log')).to_a.last.strip.sub(/.*as release ([0-9]+).*/, '\1')
32
+ rescue
33
+ ScoutApm::Agent.instance.logger.debug "Unable to detect Git Revision from Capistrano: #{$!.message}"
34
+ nil
35
+ end
36
+
37
+ def detect_from_git
38
+ if File.directory?(".git")
39
+ `git rev-parse --short HEAD`.strip
40
+ end
41
+ rescue
42
+ ScoutApm::Agent.instance.logger.debug "Unable to detect Git Revision from Git: #{$!.message}"
43
+ nil
44
+ end
45
+
46
+ def app_root
47
+ ScoutApm::Environment.instance.root
48
+ end
49
+
50
+ end
51
+ end
@@ -21,6 +21,7 @@ module ScoutApm
21
21
  "allocations" => job.allocations,
22
22
  "seconds_since_startup" => job.seconds_since_startup,
23
23
  "hostname" => job.hostname,
24
+ "git_sha" => job.git_sha,
24
25
  "metrics" => MetricsToJsonSerializer.new(job.metrics).as_json, # New style of metrics
25
26
  "allocation_metrics" => MetricsToJsonSerializer.new(job.allocation_metrics).as_json, # New style of metrics
26
27
  "context" => job.context.to_hash,
@@ -20,6 +20,7 @@ module ScoutApm
20
20
  attr_reader :hostname
21
21
  attr_reader :seconds_since_startup
22
22
  attr_reader :score
23
+ attr_reader :git_sha
23
24
 
24
25
  def initialize(queue_name, job_name, time, total_time, exclusive_time, context, metrics, allocation_metrics, mem_delta, allocations, score)
25
26
  @queue_name = queue_name
@@ -34,6 +35,7 @@ module ScoutApm
34
35
  @allocations = allocations
35
36
  @seconds_since_startup = (Time.now - ScoutApm::Agent.instance.process_start_time)
36
37
  @hostname = ScoutApm::Environment.instance.hostname
38
+ @git_sha = ScoutApm::Environment.instance.git_revision.sha
37
39
  @score = score
38
40
  ScoutApm::Agent.instance.logger.debug { "Slow Job [#{metric_name}] - Call Time: #{total_call_time} Mem Delta: #{mem_delta}"}
39
41
  end
@@ -15,6 +15,7 @@ module ScoutApm
15
15
  attr_reader :allocations
16
16
  attr_accessor :hostname # hack - we need to reset these server side.
17
17
  attr_accessor :seconds_since_startup # hack - we need to reset these server side.
18
+ attr_accessor :git_sha # hack - we need to reset these server side.
18
19
 
19
20
  def initialize(uri, metric_name, total_call_time, metrics, allocation_metrics, context, time, raw_stackprof, mem_delta, allocations, score)
20
21
  @uri = uri
@@ -30,6 +31,7 @@ module ScoutApm
30
31
  @seconds_since_startup = (Time.now - ScoutApm::Agent.instance.process_start_time)
31
32
  @hostname = ScoutApm::Environment.instance.hostname
32
33
  @score = score
34
+ @git_sha = ScoutApm::Environment.instance.git_revision.sha
33
35
  ScoutApm::Agent.instance.logger.debug { "Slow Request [#{uri}] - Call Time: #{total_call_time} Mem Delta: #{mem_delta} Score: #{score}"}
34
36
  end
35
37
 
@@ -44,7 +46,7 @@ module ScoutApm
44
46
  end
45
47
 
46
48
  def as_json
47
- json_attributes = [:key, :time, :total_call_time, :uri, [:context, :context_hash], :score, :prof, :mem_delta, :allocations, :seconds_since_startup, :hostname]
49
+ json_attributes = [:key, :time, :total_call_time, :uri, [:context, :context_hash], :score, :prof, :mem_delta, :allocations, :seconds_since_startup, :hostname, :git_sha]
48
50
  ScoutApm::AttributeArranger.call(self, json_attributes)
49
51
  end
50
52
 
@@ -1,4 +1,3 @@
1
1
  module ScoutApm
2
- VERSION = "3.0.0.pre0"
3
- end
4
-
2
+ VERSION = "3.0.0.pre1"
3
+ end
data/lib/scout_apm.rb CHANGED
@@ -63,9 +63,6 @@ require 'scout_apm/platform_integrations/server'
63
63
 
64
64
  require 'scout_apm/histogram'
65
65
 
66
- require 'scout_apm/deploy_integrations/capistrano_3'
67
- # require 'scout_apm/deploy_integrations/capistrano_2'
68
-
69
66
  require 'scout_apm/instruments/net_http'
70
67
  require 'scout_apm/instruments/http_client'
71
68
  require 'scout_apm/instruments/moped'
@@ -136,6 +133,7 @@ require 'scout_apm/request_histograms'
136
133
 
137
134
  require 'scout_apm/capacity'
138
135
  require 'scout_apm/attribute_arranger'
136
+ require 'scout_apm/git_revision'
139
137
 
140
138
  require 'scout_apm/serializers/payload_serializer'
141
139
  require 'scout_apm/serializers/payload_serializer_to_json'
@@ -144,7 +142,6 @@ require 'scout_apm/serializers/slow_jobs_serializer_to_json'
144
142
  require 'scout_apm/serializers/metrics_to_json_serializer'
145
143
  require 'scout_apm/serializers/directive_serializer'
146
144
  require 'scout_apm/serializers/app_server_load_serializer'
147
- require 'scout_apm/serializers/deploy_serializer'
148
145
 
149
146
  require 'scout_apm/middleware'
150
147
 
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ require 'scout_apm/git_revision'
4
+
5
+ class GitRevisionTest < Minitest::Test
6
+ # TODO - other tests that would be nice:
7
+ # * ensure we only detect once, on initialize.
8
+ # * tests for reading cap files
9
+
10
+ def test_sha_from_heroku
11
+ ENV['HEROKU_SLUG_COMMIT'] = 'heroku_slug'
12
+ revision = ScoutApm::GitRevision.new
13
+ assert_equal 'heroku_slug', revision.sha
14
+ end
15
+ end
@@ -78,6 +78,7 @@ class PayloadSerializerTest < Minitest::Test
78
78
  "min_call_time" => 0.000613518,
79
79
  "total_call_time" => 0.033245704,
80
80
  "total_exclusive_time" => 0.033245704,
81
+ "traces" => []
81
82
  },
82
83
  {
83
84
  "key" => {
@@ -92,6 +93,7 @@ class PayloadSerializerTest < Minitest::Test
92
93
  "min_call_time" => 0.034881757,
93
94
  "total_call_time" => 0.113403176,
94
95
  "total_exclusive_time" => 0.07813208899999999,
96
+ "traces" => []
95
97
  }
96
98
  ]
97
99
  assert_equal formatted_metrics, JSON.parse(payload)["metrics"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scout_apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.pre0
4
+ version: 3.0.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derek Haynes
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-08-29 00:00:00.000000000 Z
12
+ date: 2016-09-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -135,16 +135,13 @@ files:
135
135
  - lib/scout_apm/capacity.rb
136
136
  - lib/scout_apm/config.rb
137
137
  - lib/scout_apm/context.rb
138
- - lib/scout_apm/deploy_integrations/capistrano_2.cap
139
- - lib/scout_apm/deploy_integrations/capistrano_2.rb
140
- - lib/scout_apm/deploy_integrations/capistrano_3.cap
141
- - lib/scout_apm/deploy_integrations/capistrano_3.rb
142
138
  - lib/scout_apm/environment.rb
143
139
  - lib/scout_apm/fake_store.rb
144
140
  - lib/scout_apm/framework_integrations/rails_2.rb
145
141
  - lib/scout_apm/framework_integrations/rails_3_or_4.rb
146
142
  - lib/scout_apm/framework_integrations/ruby.rb
147
143
  - lib/scout_apm/framework_integrations/sinatra.rb
144
+ - lib/scout_apm/git_revision.rb
148
145
  - lib/scout_apm/histogram.rb
149
146
  - lib/scout_apm/ignored_uris.rb
150
147
  - lib/scout_apm/instant/assets/xmlhttp_instrumentation.html
@@ -195,7 +192,6 @@ files:
195
192
  - lib/scout_apm/request_manager.rb
196
193
  - lib/scout_apm/scored_item_set.rb
197
194
  - lib/scout_apm/serializers/app_server_load_serializer.rb
198
- - lib/scout_apm/serializers/deploy_serializer.rb
199
195
  - lib/scout_apm/serializers/directive_serializer.rb
200
196
  - lib/scout_apm/serializers/jobs_serializer_to_json.rb
201
197
  - lib/scout_apm/serializers/metrics_to_json_serializer.rb
@@ -238,6 +234,7 @@ files:
238
234
  - test/unit/config_test.rb
239
235
  - test/unit/context_test.rb
240
236
  - test/unit/environment_test.rb
237
+ - test/unit/git_revision_test.rb
241
238
  - test/unit/histogram_test.rb
242
239
  - test/unit/ignored_uris_test.rb
243
240
  - test/unit/instruments/active_record_instruments_test.rb
@@ -273,8 +270,30 @@ required_rubygems_version: !ruby/object:Gem::Requirement
273
270
  version: 1.3.1
274
271
  requirements: []
275
272
  rubyforge_project: scout_apm
276
- rubygems_version: 2.2.2
273
+ rubygems_version: 2.4.6
277
274
  signing_key:
278
275
  specification_version: 4
279
276
  summary: Ruby application performance monitoring
280
- test_files: []
277
+ test_files:
278
+ - test/data/config_test_1.yml
279
+ - test/test_helper.rb
280
+ - test/unit/agent_test.rb
281
+ - test/unit/background_job_integrations/sidekiq_test.rb
282
+ - test/unit/config_test.rb
283
+ - test/unit/context_test.rb
284
+ - test/unit/environment_test.rb
285
+ - test/unit/git_revision_test.rb
286
+ - test/unit/histogram_test.rb
287
+ - test/unit/ignored_uris_test.rb
288
+ - test/unit/instruments/active_record_instruments_test.rb
289
+ - test/unit/layaway_test.rb
290
+ - test/unit/metric_set_test.rb
291
+ - test/unit/scored_item_set_test.rb
292
+ - test/unit/serializers/payload_serializer_test.rb
293
+ - test/unit/slow_job_policy_test.rb
294
+ - test/unit/slow_request_policy_test.rb
295
+ - test/unit/sql_sanitizer_test.rb
296
+ - test/unit/store_test.rb
297
+ - test/unit/utils/active_record_metric_name_test.rb
298
+ - test/unit/utils/backtrace_parser_test.rb
299
+ has_rdoc:
@@ -1,12 +0,0 @@
1
- namespace :scout_apm do
2
- namespace :deploy do
3
- task :starting do
4
- # Warn if missing scout apm deploy creds?
5
- end
6
- task :finished do
7
- ScoutApm::Agent.instance.deploy_integration.report
8
- end
9
- end
10
- end
11
-
12
- after 'deploy:finished', 'scout_apm:deploy:finished'
@@ -1,83 +0,0 @@
1
- require 'scout_apm'
2
-
3
- module ScoutApm
4
- module DeployIntegrations
5
- class Capistrano2
6
- attr_reader :logger
7
-
8
- def initialize(logger)
9
- @logger = logger
10
- @cap = defined?(Capistrano::Configuration) ? ObjectSpace.each_object(Capistrano::Configuration).map.first : nil rescue nil
11
- end
12
-
13
- def name
14
- :capistrano_2
15
- end
16
-
17
- def version
18
- present? ? Capistrano::VERSION : nil
19
- end
20
-
21
- def present?
22
- if !@cap.nil? && @cap.is_a?(Capistrano::Configuration)
23
- require 'capistrano/version'
24
- defined?(Capistrano::VERSION) && Gem::Dependency.new('', '~> 2.0').match?('', Capistrano::VERSION.to_s)
25
- else
26
- return false
27
- end
28
- return true
29
- rescue
30
- return false
31
- end
32
-
33
- def install
34
- logger.debug "Initializing Capistrano2 Deploy Integration."
35
- @cap.load File.expand_path("../capistrano_2.cap", __FILE__)
36
- end
37
-
38
- def root
39
- '.'
40
- end
41
-
42
- def env
43
- @cap.fetch(:stage)
44
- end
45
-
46
- def found?
47
- true
48
- end
49
-
50
- def report
51
- if reporter.can_report?
52
- data = deploy_data
53
- logger.debug "Sending deploy hook data: #{data}"
54
- payload = ScoutApm::Serializers::DeploySerializer.serialize(data)
55
- reporter.report(payload, ScoutApm::Serializers::DeploySerializer::HTTP_HEADERS)
56
- else
57
- logger.warn "Unable to post deploy hook data"
58
- end
59
- end
60
-
61
- def reporter
62
- @reporter ||= ScoutApm::Reporter.new(:deploy_hook, ScoutApm::Agent.instance.config, @logger)
63
- end
64
-
65
- def deploy_data
66
- {:revision => current_revision, :branch => branch, :deployed_by => deployed_by}
67
- end
68
-
69
- def branch
70
- @cap.fetch(:branch)
71
- end
72
-
73
- def current_revision
74
- @cap.fetch(:current_revision) || `git rev-list --max-count=1 --abbrev-commit --abbrev=12 #{branch}`.chomp
75
- end
76
-
77
- def deployed_by
78
- ScoutApm::Agent.instance.config.value('deployed_by')
79
- end
80
-
81
- end
82
- end
83
- end
@@ -1,12 +0,0 @@
1
- namespace :scout_apm do
2
- namespace :deploy do
3
- task :starting do
4
- # Warn if missing scout apm deploy creds?
5
- end
6
- task :finished do
7
- ScoutApm::Agent.instance.deploy_integration.report
8
- end
9
- end
10
- end
11
-
12
- after 'deploy:finished', 'scout_apm:deploy:finished'
@@ -1,88 +0,0 @@
1
- require 'scout_apm'
2
-
3
- module ScoutApm
4
- module DeployIntegrations
5
- class Capistrano3
6
- attr_reader :logger
7
-
8
- def initialize(logger)
9
- @logger = logger
10
- @cap = Rake.application rescue nil
11
- end
12
-
13
- def name
14
- :capistrano_3
15
- end
16
-
17
- def version
18
- present? ? Capistrano::VERSION : nil
19
- end
20
-
21
- def present?
22
- if !@cap.nil? && @cap.is_a?(Capistrano::Application)
23
- require 'capistrano/version'
24
- defined?(Capistrano::VERSION) && Gem::Dependency.new('', '~> 3.0').match?('', Capistrano::VERSION.to_s)
25
- else
26
- return false
27
- end
28
- rescue
29
- return false
30
- end
31
-
32
- def install
33
- logger.debug "Initializing Capistrano3 Deploy Integration."
34
- load File.expand_path("../capistrano_3.cap", __FILE__)
35
- end
36
-
37
- def root
38
- '.'
39
- end
40
-
41
- def env
42
- @cap.fetch(:stage).to_s
43
- end
44
-
45
- def found?
46
- true
47
- end
48
-
49
- def report
50
- if reporter.can_report?
51
- data = deploy_data
52
- logger.debug "Sending deploy hook data: #{data}"
53
- payload = ScoutApm::Serializers::DeploySerializer.serialize(data)
54
- reporter.report(payload, ScoutApm::Serializers::DeploySerializer::HTTP_HEADERS)
55
- else
56
- logger.warn "Unable to post deploy hook data"
57
- end
58
- end
59
-
60
- def reporter
61
- config = if env == ''
62
- ScoutApm::Agent.instance.config
63
- else
64
- ScoutApm::Config.with_file(nil, {:file => { :environment => env }}) # instantiate our own config, with an overridden environment for the deploy-to app name instead of deploy-from app name)
65
- end
66
-
67
- @reporter ||= ScoutApm::Reporter.new(:deploy_hook, config, @logger)
68
- end
69
-
70
- def deploy_data
71
- {:revision => current_revision, :branch => branch, :deployed_by => deployed_by}
72
- end
73
-
74
- def branch
75
- @cap.fetch(:branch)
76
- end
77
-
78
- def current_revision
79
- @cap.fetch(:current_revision) || `git rev-list --max-count=1 --abbrev-commit --abbrev=12 #{branch}`.chomp
80
- end
81
-
82
- def deployed_by
83
- ScoutApm::Agent.instance.config.value('deployed_by')
84
- end
85
-
86
- end
87
- end
88
- end
@@ -1,16 +0,0 @@
1
- # Serialize & deserialize deploy data up to the APM server
2
- module ScoutApm
3
- module Serializers
4
- class DeploySerializer
5
- HTTP_HEADERS = {'Content-Type' => 'application/x-www-form-urlencoded'}
6
-
7
- def self.serialize(data)
8
- URI.encode_www_form(data)
9
- end
10
-
11
- def self.deserialize(data)
12
- Marshal.load(data)
13
- end
14
- end
15
- end
16
- end