union_station_hooks_core 2.1.1 → 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dfc9815e53e9b9fdd1ec5ec8406c75dbe63cfad1
4
- data.tar.gz: 9ff6e5d34e4c703e4a1a3d98272dea5e49b07cfc
3
+ metadata.gz: d2c7222363bb2d98083dbcf04c0c3a575ab9b405
4
+ data.tar.gz: 61b97992862e5bc29763daa99aaf3be502c8fc22
5
5
  SHA512:
6
- metadata.gz: 95656628e3239ee71c71b21bf5d093150934f68dcd3cee2642d224c90f1b670304248b173b9b1d60503cd5df6ea75316a7c6a36118ccdb18870aa3624f92050c
7
- data.tar.gz: a3fa7113d2d569c3c1c3a23dcb1efd2853bfaee3434f116b3c128a9b8e143a7f667a6018d90cdd38bcd4fba685587f8f6a4c6f641a6a416e6b4337b3cc1bad52
6
+ metadata.gz: fa91aa10d298de35a1758d070b97f636eccf2cf7f12336a71be780d73884c37c5b2274bd0f5c20235439140f1fb42e8680026158a411a484189f1c71840ae6dc
7
+ data.tar.gz: 7e0b6d7f8833218eecafdf833e80119cf4d9948c32a31a030448bc23f79f46096116a3f10fb0eb388515cbb59acb56e360b580f42be808ce304c8a5f13b4d2b3
@@ -1,5 +1,5 @@
1
1
  # Union Station - https://www.unionstationapp.com/
2
- # Copyright (c) 2015 Phusion Holding B.V.
2
+ # Copyright (c) 2015-2016 Phusion Holding B.V.
3
3
  #
4
4
  # "Union Station" and "Passenger" are trademarks of Phusion Holding B.V.
5
5
  #
@@ -189,7 +189,7 @@ module UnionStationHooks
189
189
  if defined?(PhusionPassenger)
190
190
  PhusionPassenger::App.options['analytics']
191
191
  else
192
- true
192
+ false
193
193
  end
194
194
  end
195
195
 
@@ -330,6 +330,12 @@ module UnionStationHooks
330
330
  nil
331
331
  end
332
332
 
333
+ def get_delta_monotonic
334
+ # When `initialize!` is called, the definition in
335
+ # `api.rb` will override this implementation.
336
+ nil
337
+ end
338
+
333
339
  private
334
340
 
335
341
  def finalize_and_validate_config
@@ -70,12 +70,10 @@ module UnionStationHooks
70
70
 
71
71
  # Workaround for Ruby < 2.1 support where there is no function for querying
72
72
  # the monotonic time.
73
- delta_monotonic = rack_env['PASSENGER_DELTA_MONOTONIC']
74
- if delta_monotonic
75
- delta_monotonic = delta_monotonic.to_i
76
- end
73
+ delta_monotonic_env = rack_env['PASSENGER_DELTA_MONOTONIC']
74
+ set_delta_monotonic(delta_monotonic_env.to_i) if delta_monotonic_env
77
75
 
78
- reporter = RequestReporter.new(context, txn_id, app_group_name, key, delta_monotonic)
76
+ reporter = RequestReporter.new(context, txn_id, app_group_name, key)
79
77
  return if reporter.null?
80
78
 
81
79
  rack_env['union_station_hooks'] = reporter
@@ -122,7 +120,7 @@ module UnionStationHooks
122
120
  #
123
121
  # This method should be used for logging exceptions outside the
124
122
  # request-response cycle, e.g. exceptions in threads. If you want to
125
- # log a request that occurred during a request, use
123
+ # log an exception that occurred during a request, use
126
124
  # {RequestReporter#log_exception} instead. That method will also log
127
125
  # any related request-specific information, while this method does not.
128
126
  #
@@ -149,14 +147,15 @@ module UnionStationHooks
149
147
  # Returns an opaque object (a {TimePoint}) that represents a collection
150
148
  # of metrics about the current time.
151
149
  #
152
- # Various API methods expect you to provide timing information. They
153
- # accept standard Ruby `Time` objects, but it is generally better to
154
- # pass `TimePoint` objects. Unlike the standard Ruby `Time` object,
155
- # which only contains the wall clock time (the real time), `TimePoint`
156
- # may contain additional timing information such as CPU time, time
157
- # spent in userspace and kernel space, time spent context switching,
158
- # etc. The exact information contained in the object is operating
159
- # system specific, hence why the object is meant to be opaque.
150
+ # This TimePoint samples monotonic time (with a fallback to wall clock
151
+ # time) as well as CPU time, time spent in userspace and kernel space,
152
+ # time spent context switching, etc. The exact information contained
153
+ # in the object is operating system specific, hence the object is opaque.
154
+ #
155
+ # You should use it for the various API methods that require timing
156
+ # information. Those methods also accept standard Ruby `Time` objects,
157
+ # but we strongly recommended against doing this, because wall clock
158
+ # time can jump forwards and backwards, which may create issues.
160
159
  #
161
160
  # See {RequestReporter#log_controller_action} for an example of
162
161
  # an API method which expects timing information.
@@ -165,19 +164,28 @@ module UnionStationHooks
165
164
  # information is supposed to be obtained by calling
166
165
  # `UnionStationHooks.now`.
167
166
  #
168
- # In all API methods that expect a `TimePoint`, you can also pass a
169
- # normal Ruby `Time` object instead. But if you do that, the logged
170
- # timing information will be less detailed. Only do this if you cannot
171
- # obtain a `TimePoint` object for some reason.
172
- #
173
167
  # @return [TimePoint]
174
168
  def now
169
+ monotime_usec = Utils.monotime_usec_now
175
170
  pt = Utils.process_times
176
- TimePoint.new(Time.now, pt.utime, pt.stime)
171
+ TimePoint.new(monotime_usec, pt.utime, pt.stime)
172
+ end
173
+
174
+ # Returns a best-estimate delta (usec) between the wallclock and
175
+ # the monotonic clock (updated every request), such that:
176
+ # time_monotic_usec = time_wallclock_usec - delta
177
+ def get_delta_monotonic
178
+ @mono_mutex.synchronize { @delta_monotonic }
177
179
  end
178
180
 
179
181
  private
180
182
 
183
+ # Although the de-facto state seems to be that reading/writing instance variables
184
+ # is MT-safe, it's not guaranteed so better safe than sorry here.
185
+ def set_delta_monotonic(val)
186
+ @mono_mutex.synchronize { @delta_monotonic = val }
187
+ end
188
+
181
189
  def create_context
182
190
  require_lib('context')
183
191
  @@context = Context.new(config[:ust_router_address],
@@ -222,6 +230,8 @@ module UnionStationHooks
222
230
  UnionStationHooks::Log.debugging = true
223
231
  end
224
232
  require_simple_json
233
+ @mono_mutex = Mutex.new
234
+ @delta_monotonic = 0
225
235
  @@initialized = true
226
236
  end
227
237
  end
@@ -173,7 +173,7 @@ module UnionStationHooks
173
173
  end
174
174
  end
175
175
 
176
- def continue_transaction(txn_id, group_name, category, key, delta_monotonic = 0)
176
+ def continue_transaction(txn_id, group_name, category, key)
177
177
  if !@server_address
178
178
  return Transaction.new(nil, nil)
179
179
  elsif !txn_id || txn_id.empty?
@@ -209,7 +209,7 @@ module UnionStationHooks
209
209
  Utils.encoded_timestamp,
210
210
  key,
211
211
  true)
212
- return Transaction.new(@connection, txn_id, delta_monotonic)
212
+ return Transaction.new(@connection, txn_id)
213
213
  rescue SystemCallError, IOError
214
214
  @connection.disconnect
215
215
  UnionStationHooks::Log.warn(
@@ -102,7 +102,7 @@ module UnionStationHooks
102
102
  # in the {RequestReporter class description}.
103
103
  #
104
104
  # @api private
105
- def initialize(context, txn_id, app_group_name, key, delta_monotonic)
105
+ def initialize(context, txn_id, app_group_name, key)
106
106
  raise ArgumentError, 'Transaction ID must be given' if txn_id.nil?
107
107
  raise ArgumentError, 'App group name must be given' if app_group_name.nil?
108
108
  raise ArgumentError, 'Union Station key must be given' if key.nil?
@@ -110,7 +110,6 @@ module UnionStationHooks
110
110
  @txn_id = txn_id
111
111
  @app_group_name = app_group_name
112
112
  @key = key
113
- @delta_monotonic = delta_monotonic
114
113
  @transaction = continue_transaction
115
114
  @next_view_rendering_number = 1
116
115
  @next_user_activity_number = 1
@@ -139,7 +138,7 @@ module UnionStationHooks
139
138
 
140
139
  def continue_transaction
141
140
  @context.continue_transaction(@txn_id, @app_group_name,
142
- :requests, @key, @delta_monotonic)
141
+ :requests, @key)
143
142
  end
144
143
 
145
144
  # Called when one of the methods return early upon detecting null
@@ -29,6 +29,8 @@ require 'strscan'
29
29
  require 'forwardable'
30
30
 
31
31
  module UnionStationHooks
32
+
33
+ # @private
32
34
  module SimpleJSON
33
35
 
34
36
  # Usage:
@@ -38,7 +40,6 @@ module SimpleJSON
38
40
  #
39
41
  # Run tests by executing this file directly. Pipe standard input to the script to have it
40
42
  # parsed as JSON and to display the result in Ruby.
41
- #
42
43
  class JSON
43
44
  def self.parse(data) new(data).parse end
44
45
 
@@ -116,6 +116,8 @@ module UnionStationHooks
116
116
 
117
117
  def initialize_ush_api
118
118
  UnionStationHooks.require_lib('api')
119
+ UnionStationHooks.instance_variable_set(:@mono_mutex, Mutex.new)
120
+ UnionStationHooks.instance_variable_set(:@delta_monotonic, 0)
119
121
  end
120
122
 
121
123
  def initialize_debugging
@@ -26,28 +26,14 @@ module UnionStationHooks
26
26
  # See {UnionStationHooks.now} for more information.
27
27
  class TimePoint
28
28
  # @api private
29
- attr_reader :time, :utime, :stime
29
+ attr_reader :monotime, :utime, :stime
30
30
 
31
31
  # @api private
32
- def initialize(time, utime, stime)
33
- @time = time
32
+ def initialize(monotime, utime, stime)
33
+ @monotime = monotime
34
34
  @utime = utime
35
35
  @stime = stime
36
36
  end
37
37
 
38
- # @api private
39
- def usec_timestamp
40
- @time.to_i * 1_000_000 + @time.usec
41
- end
42
-
43
- # @api private
44
- def usec
45
- @time.usec
46
- end
47
-
48
- # @api private
49
- def to_i
50
- @time.to_i
51
- end
52
38
  end
53
39
  end
@@ -31,10 +31,9 @@ module UnionStationHooks
31
31
  class Transaction
32
32
  attr_reader :txn_id
33
33
 
34
- def initialize(connection, txn_id, delta_monotonic = 0)
34
+ def initialize(connection, txn_id)
35
35
  @connection = connection
36
36
  @txn_id = txn_id
37
- @delta_monotonic = delta_monotonic
38
37
  if connection
39
38
  raise ArgumentError, 'Transaction ID required' if txn_id.nil?
40
39
  connection.ref
@@ -84,37 +83,35 @@ module UnionStationHooks
84
83
  end
85
84
 
86
85
  def log_activity_begin(name, time = UnionStationHooks.now, extra_info = nil)
87
- monotime = Utils.encoded_monotime_now(@delta_monotonic)
88
86
  if extra_info
89
87
  extra_info_base64 = Utils.base64(extra_info)
90
88
  else
91
89
  extra_info_base64 = nil
92
90
  end
93
91
  if time.is_a?(TimePoint)
94
- message "BEGIN: #{name} (#{monotime}," \
92
+ message "BEGIN: #{name} (#{time.monotime.to_s(36)}," \
95
93
  "#{time.utime.to_s(36)},#{time.stime.to_s(36)}) " \
96
94
  "#{extra_info_base64}"
97
95
  else
98
- message "BEGIN: #{name} (#{monotime})" \
96
+ message "BEGIN: #{name} (#{Utils.monotime_usec_from_time(time).to_s(36)})" \
99
97
  " #{extra_info_base64}"
100
98
  end
101
99
  end
102
100
 
103
101
  def log_activity_end(name, time = UnionStationHooks.now, has_error = false)
104
- monotime = Utils.encoded_monotime_now(@delta_monotonic)
105
102
  if time.is_a?(TimePoint)
106
103
  if has_error
107
- message "FAIL: #{name} (#{monotime}," \
104
+ message "FAIL: #{name} (#{time.monotime.to_s(36)}," \
108
105
  "#{time.utime.to_s(36)},#{time.stime.to_s(36)})"
109
106
  else
110
- message "END: #{name} (#{monotime}," \
107
+ message "END: #{name} (#{time.monotime.to_s(36)}," \
111
108
  "#{time.utime.to_s(36)},#{time.stime.to_s(36)})"
112
109
  end
113
110
  else
114
111
  if has_error
115
- message "FAIL: #{name} (#{monotime})"
112
+ message "FAIL: #{name} (#{Utils.monotime_usec_from_time(time).to_s(36)})"
116
113
  else
117
- message "END: #{name} (#{monotime})"
114
+ message "END: #{name} (#{Utils.monotime_usec_from_time(time).to_s(36)})"
118
115
  end
119
116
  end
120
117
  end
@@ -90,20 +90,22 @@ module UnionStationHooks
90
90
  end
91
91
 
92
92
  if Process.const_defined?(:CLOCK_MONOTONIC)
93
- def encoded_monotime_now(delta_monotonic)
94
- time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
95
- timestamp = (time * 1_000_000).to_i
96
- timestamp.to_s(36)
93
+ def monotime_usec_now
94
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, :microsecond)
97
95
  end
98
96
  else
99
- def encoded_monotime_now(delta_monotonic)
100
- time = Time.now
101
- timestamp = time.to_i * 1_000_000 + time.usec - delta_monotonic
102
- timestamp.to_s(36)
97
+ # Workaround for approximating the monotonic clock
98
+ def monotime_usec_now
99
+ monotime_usec_from_time
103
100
  end
104
101
  end
105
102
 
106
- def encoded_timestamp(time = Time.now)
103
+ def monotime_usec_from_time(time = Time.now)
104
+ timestamp = time.to_i * 1_000_000 + time.usec - UnionStationHooks.get_delta_monotonic
105
+ end
106
+
107
+ def encoded_timestamp
108
+ time = Time.now
107
109
  timestamp = time.to_i * 1_000_000 + time.usec
108
110
  timestamp.to_s(36)
109
111
  end
@@ -39,6 +39,6 @@
39
39
  {
40
40
  :major => 2,
41
41
  :minor => 1,
42
- :tiny => 1,
43
- :string => '2.1.1'
42
+ :tiny => 2,
43
+ :string => '2.1.2'
44
44
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: union_station_hooks_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hongli Lai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-15 00:00:00.000000000 Z
11
+ date: 2016-08-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Union Station Ruby hooks core code.
14
14
  email: info@phusion.nl