stenotype 0.1.1 → 0.1.7

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
  SHA256:
3
- metadata.gz: cad5a62bd56d635becd56bf9bae4d6421879d29952473fd507ae60885ea4723e
4
- data.tar.gz: 0b2d65ef6e1f9a84bd369d908f4133f3787156fcc5a6b46a194b4193fa735411
3
+ metadata.gz: 5f58226124306beb915f76259d055c013e197d24dee87513d751764486ce8033
4
+ data.tar.gz: eee031ad3b4f4b9d5b8ed8645e5d7f676f0490f1f9351cec516ffc72ef5b298a
5
5
  SHA512:
6
- metadata.gz: c025894e106d650dcfe1bab82cf878b89a561eaae8a7eb23246a8d01a34800460a17734f55da518602d504a554b41648f6039d3174b2747d093dba8fbfbb0f26
7
- data.tar.gz: 790e1a50a3fabff8db4c62017a556532b8acf3f1df6a330b91dfafba0e1af1701335f8463688fb8d201b75420542fd6cbba054939d33cd80e400e87b07100ed3
6
+ metadata.gz: fe129ae49b3b255a02f1cadcc6920820348846d0b10dba93ab554322b545401a63c8bce7becd239502e9ff433b127e738ff612d4b1cc9903a0f32212ce68eda1
7
+ data.tar.gz: 275de1f70c2c0f4e9d608e79d93e773d75538b18a47c1f2848a7753bb6151b5f96a8ef7c74b36b3a462360de7be196a247d3be3429cfd7f1b00364691ae01a5e
data/.gitignore CHANGED
@@ -11,3 +11,6 @@
11
11
  .rspec_status
12
12
  /.rakeTasks
13
13
  /.idea
14
+
15
+ # rbenv
16
+ .ruby-version
data/CHANGELOG.md CHANGED
@@ -1,6 +1,31 @@
1
1
  # Changelog
2
2
 
3
- *Release Date*: 2019/11/21
3
+ *Release Date*: 2020/01/13
4
+
5
+ ### 0.1.7 2020/01/20
6
+ * Adds a config option to allow explicit adapter setup.
7
+ * Adds an `after_initialize` rails hook to setup adapters.
8
+ * Remove topic from the list of Google Cloud adapter arguments.
9
+
10
+ ### 0.1.6 2020/01/17
11
+ * Allow topic to be explicitly set upon Google Cloud adapter initialization
12
+
13
+ ### 0.1.5 2020/01/13
14
+ * In case `graceful_error_handling` is set to off raise a generic `Stenotype::Error` on any exception in order to intercept a single error type in the client code.
15
+ * Adds an `at_exit` hook to flush the async message queue when using the library in async mode.
16
+
17
+ ### 0.1.4 2020/01/10
18
+ * Adds a new configuration option `graceful_error_handling` to suppress errors raised from the gem's internals yet logging the error to specified `config.logger`
19
+
20
+ ### 0.1.3: 2020/01/10
21
+ * Adds a new configuration option `logger` to use during error handling
22
+ * Adds a new config option `Stenotype.config.enabled`. If the option is set to false then event is not going to be published. The option is `true` by default.
23
+
24
+ ### 0.1.2: 2019/12/10
25
+
26
+ * Changes the interface of how event is emitted. Now you must pass `event_name`, `attributes` and optional `eval_context`. Note that `additional_options` are eliminated
27
+ * Makes StdoutAdapter more informative by adding a special line for every entry in the log.
28
+ * Fixes Rails initializer not working after switching to Configurable from Spicerack.
4
29
 
5
30
  ### 0.1.1: 2019/11/25
6
31
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stenotype (0.1.1)
4
+ stenotype (0.1.6)
5
5
  activesupport (>= 5.0.0)
6
6
  google-cloud-pubsub (~> 1.0.0)
7
7
  spicery (>= 0.19.0, < 1.0)
@@ -147,7 +147,7 @@ GEM
147
147
  coderay (~> 1.1.0)
148
148
  method_source (~> 0.9.0)
149
149
  public_suffix (4.0.1)
150
- rack (2.0.7)
150
+ rack (2.0.8)
151
151
  rack-test (1.1.0)
152
152
  rack (>= 1.0, < 3)
153
153
  rails (5.2.4)
data/README.md CHANGED
@@ -25,24 +25,48 @@ Or install it yourself as:
25
25
  Configuring the library is as simple as:
26
26
  ```ruby
27
27
  Stenotype.configure do |config|
28
+ config.enabled = true
28
29
  config.targets = [ # Supported targets
29
30
  Stenotype::Adapters::StdoutAdapter.new,
30
31
  Stenotype::Adapters::GoogleCloud.new
31
32
  ]
32
33
 
33
- config.uuid_generator = SecureRandom
34
- config.dispatcher = Stenotype::Dispatcher.new
35
- config.gc_project_id = "google_cloud_project_id"
36
- config.gc_credentials = "path_to_key_json"
37
- config.gc_topic = "google_cloud_topic"
38
- config.gc_mode = :async # either :sync or :async
34
+ config.uuid_generator = SecureRandom
35
+ config.dispatcher = Stenotype::Dispatcher.new
36
+ config.logger = Logger.new(STDOUT)
37
+ config.graceful_error_handling = true
38
+ config.auto_adapter_initialization = true
39
+
40
+ config.google_cloud do |gc_config|
41
+ gc_config.project_id = "google_cloud_project_id"
42
+ gc_config.credentials = "path_to_key_json"
43
+ gc_config.topic = "google_cloud_topic"
44
+ gc_config.async = true # either true or false
45
+ end
46
+
47
+ config.rails do |rails_config|
48
+ rails_config.enable_action_controller_ext = true
49
+ rails_config.enable_active_job_ext = true
50
+ end
39
51
  end
40
52
  ```
41
53
 
54
+ #### config.enabled
55
+
56
+ A flag checked upon emission of an event. Will prevent event emission if set to false. An event is emitted if set to true.
57
+
42
58
  #### config.targets
43
59
 
44
60
  Contain an array of targets for the events to be published to. Targets must implement method `#publish(event_data, **additional_arguments)`.
45
61
 
62
+ #### config.logger
63
+
64
+ Specifies a logger for messages and exceptions to be output to. If not set defaults to `Logger.new(STDOUT)`, otherwise a manually set logger is used.
65
+
66
+ #### config.graceful_error_handling
67
+
68
+ This flag if set to `true` is going to suppress all `StandardError`'s raised within a gem. Raises the error to the caller if set to `false`
69
+
46
70
  #### config.uuid_generator
47
71
 
48
72
  An object that must implement method `#uuid`. Used when an event is emitted to generate a unique id for each event.
@@ -51,21 +75,33 @@ An object that must implement method `#uuid`. Used when an event is emitted to g
51
75
 
52
76
  Dispatcher used to dispatch the event. A dispatcher must implement method `#publish(even, serializer: Stenotype::EventSerializer)`. By default `Stenotype::EventSerializer` is used, which is responsible for collecting the data from the event and evaluation context.
53
77
 
54
- #### config.gc_project_id
78
+ #### config.google_cloud.project_id
55
79
 
56
80
  Google cloud project ID. Please refer to Google Cloud management console to get one.
57
81
 
58
- #### config.gc_credentials
82
+ #### config.google_cloud.credentials
59
83
 
60
84
  Google cloud credentials. Might be obtained from Google Cloud management console.
61
85
 
62
- #### config.gc_topic
86
+ #### config.google_cloud.topic
63
87
 
64
88
  Google Cloud topic used for publishing the events.
65
89
 
66
- #### config.gc_mode
90
+ #### config.google_cloud.async
91
+
92
+ Google Cloud publish mode. The mode is either sync or async. When in `sync` mode the event will be published in the same thread (which might influence performance). For `async` mode the event will be put into a pull which is going to be flushed after a threshold is met.
67
93
 
68
- Google Cloud publish mode. Two options are available: `:sync, :async`. When in `sync` mode the event will be published in the same thread (which might influence performance). For `async` mode the event will be put into a pull which is going to be flushed after a threshold is met.
94
+ #### config.rails.enable_action_controller_ext
95
+
96
+ Allows to enable/disable Rails ActionController extension
97
+
98
+ #### config.rails.enable_active_job_ext
99
+
100
+ Allows to enable/disable Rails ActiveJob extension
101
+
102
+ #### config.rails.auto_adapter_initialization
103
+
104
+ Controls whether the hook `auto_initialize!` is run for each adapter. If set to true `auto_initialize!` is invoked for every adapter. If false `auto_initialize!` is not run. For example for google cloud adapter this will instantiate `client` and `topic` objects before first publish. If set to false `client` and `topic` are lazy initialized.
69
105
 
70
106
  #### Configuring context handlers
71
107
 
@@ -76,8 +112,8 @@ Each event is emitted in a context which might be an ActionController instance o
76
112
  Emitting an event is as simple as:
77
113
  ```ruby
78
114
  Stenotype::Event.emit!(
79
- data,
80
- options: additional_options,
115
+ "Event Name",
116
+ { attr1: :value1, attr2: :value2 },
81
117
  eval_context: { name_of_registered_context_handler: context_object }
82
118
  )
83
119
  ```
@@ -172,9 +208,9 @@ Stenotype::ContextHandlers.register CustomHandler
172
208
  class PlainRubyClass < BaseClass
173
209
  def some_method(data)
174
210
  event_data = collect_some_data_as_a_hash
175
- emit_event(event_data) # method name will be `some_method`, eval_context: { klass: self }
211
+ emit_event("event_name", event_data) # method name will be `some_method`, eval_context: { klass: self }
176
212
  other_event_data = do_something_else
177
- emit_event(other_event_data, method: :custom_method_name, eval_context: { overriden_handler: self })
213
+ emit_event("other_event_name", other_event_data, method: :custom_method_name, eval_context: { overriden_handler: self })
178
214
  end
179
215
  end
180
216
  ```
@@ -197,6 +233,14 @@ class CustomAdapter < Stenotype::Adapters::Base
197
233
  def publish(event_data, **additional_arguments)
198
234
  # custom publishing logic
199
235
  end
236
+
237
+ def flush!
238
+ # actions to be taken to flush the messages
239
+ end
240
+
241
+ def auto_initialize!
242
+ # actions to be taken to setup internal adapter state (client, endpoint, whatsoever)
243
+ end
200
244
  end
201
245
  ```
202
246
 
@@ -1,65 +1,82 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Rails.application.configure do
4
- #
5
- # Stenotype allows you to emit events which are then being published to a list of
6
- # targets. Currently two targets are provided by default: Google Cloud Pub Sub and
7
- # STDOUT for debug purposes.
8
- #
9
- # There is also a rails integration module which defines a handy DSL
10
- # for triggering events in various Rails components. ActionController and
11
- # ActiveJob are supported at the time of writing.
12
- #
13
- # Both extensions for Rails are enabled by default, but there are config options
14
- # to control their presence.
15
- # config.stenotype.rails do |rails_modules|
16
- # rails_modules.enable_action_controller_ext = true
17
- # rails_modules.enable_active_job_ext = true
18
- # end
19
- #
20
- #
21
- # To make publishing possible one must specify a list of targets. You could use
22
- # StdoutAdapter for debug purposes before switching to a production publisher.
23
- # By default the list of targets is empty and you'll get an error saying
24
- # that no targets are specified.
25
- #
26
- # A config option is available for setting up the targets:
27
- #
28
- # config.stenotype.targets = [Stenotype::Adapters::StdoutAdapter.new]
29
- #
30
- # Or using Google Cloud:
31
- #
32
- # config.stenotype.targets = [Stenotype::Adapters::GoogleCloud.new]
33
- #
34
- # Or both:
35
- #
36
- # config.stenotype.targets = [
37
- # Stenotype::Adapters::StdoutAdapter.new,
38
- # Stenotype::Adapters::GoogleCloud.new
39
- # ]
40
- #
41
- # To be able to use Google Cloud one has to specify Google Cloud credentials:
42
- #
43
- # config.stenotype.google_cloud do |gc_config|
44
- # gc_config.credentials = "SPECIFY YOUR CREDENTIALS" # path/to/key.json
45
- # gc_config.project_id = "SPECIFY YOUR PROJECT ID"
46
- # gc_config.topic = "SPECIFY YOUR TOPIC"
47
- # gc_config.mode = :async
48
- # end
49
- #
50
- # Each event is shipped with a UUID generated with SecureRandom by default.
51
- # This might be changed by using a corresponding config option. Note that
52
- # uuid_generator expects method #uuid to be implemented
53
- #
54
- # config.stenotype.uuid_generator = SecureRandom
55
- #
56
- # In rare cases you might want to get control over how the event is being dispatched.
57
- # Dispatcher must implement instance method #publish.
58
- # Which dispatcher to use is controlled by the following config option:
59
- #
60
- # config.stenotype.dispatcher = Stenotype::Dispatcher
61
- #
4
+ Stenotype.configure do |config|
5
+ #
6
+ # Stenotype allows you to emit events which are then being published to a list of
7
+ # targets. Currently two targets are provided by default: Google Cloud Pub Sub and
8
+ # STDOUT for debug purposes.
9
+ #
10
+ # There is also a rails integration module which defines a handy DSL
11
+ # for triggering events in various Rails components. ActionController and
12
+ # ActiveJob are supported at the time of writing.
13
+ #
14
+ # Both extensions for Rails are enabled by default, but there are config options
15
+ # to control their presence.
16
+ # config.rails do |rails_modules|
17
+ # rails_modules.enable_action_controller_ext = true
18
+ # rails_modules.enable_active_job_ext = true
19
+ # end
20
+ #
21
+ # To enable or disable the library use the following config option:
22
+ #
23
+ # config.enabled = true # or false
24
+ #
25
+ # To make publishing possible one must specify a list of targets. You could use
26
+ # StdoutAdapter for debug purposes before switching to a production publisher.
27
+ # By default the list of targets is empty and you'll get an error saying
28
+ # that no targets are specified.
29
+ #
30
+ # A config option is available for setting up the targets:
31
+ #
32
+ # config.targets = [Stenotype::Adapters::StdoutAdapter.new]
33
+ #
34
+ # Or using Google Cloud:
35
+ #
36
+ # config.targets = [Stenotype::Adapters::GoogleCloud.new]
37
+ #
38
+ # Or both:
39
+ #
40
+ # config.targets = [
41
+ # Stenotype::Adapters::StdoutAdapter.new,
42
+ # Stenotype::Adapters::GoogleCloud.new
43
+ # ]
44
+ #
45
+ # To be able to use Google Cloud one has to specify Google Cloud credentials:
46
+ #
47
+ # config.google_cloud do |gc_config|
48
+ # gc_config.credentials = "SPECIFY YOUR CREDENTIALS" # path/to/key.json
49
+ # gc_config.project_id = "SPECIFY YOUR PROJECT ID"
50
+ # gc_config.topic = "SPECIFY YOUR TOPIC"
51
+ # gc_config.async = true
52
+ # end
53
+ #
54
+ # Each event is shipped with a UUID generated with SecureRandom by default.
55
+ # This might be changed by using a corresponding config option. Note that
56
+ # uuid_generator expects method #uuid to be implemented
57
+ #
58
+ # config.uuid_generator = SecureRandom
59
+ #
60
+ # In rare cases you might want to get control over how the event is being dispatched.
61
+ # Dispatcher must implement instance method #publish.
62
+ # Which dispatcher to use is controlled by the following config option:
63
+ #
64
+ # config.dispatcher = Stenotype::Dispatcher
65
+ #
66
+ # An option to suppress exception within a gem is available:
67
+ #
68
+ # config.graceful_error_handling = true
69
+ #
70
+ # To log errors a logger config option is available. Logger.new(STDOUT) is used by default.
71
+ #
72
+ # config.logger = Logger.new(STDOUT)
73
+ #
74
+ # Add your own context handlers
75
+ #
76
+ # Stenotype::ContextHandlers.register Your::Custom::HandlerClass
77
+ #
78
+ end
62
79
  end
63
80
 
64
81
  # For more usage instructions please refer to either README.md or yard documentation
65
- # in gem repository https://github.com/Freshly/stenotype
82
+ # in gem repository https://github.com/Freshly/stenotype
@@ -35,12 +35,33 @@ module Stenotype
35
35
  #
36
36
  # This method is expected to be implemented by subclasses
37
37
  # @abstract
38
- # @raise [NotImplementedError] unless implemented in a subclass
38
+ # @raise {NotImplementedError} unless implemented in a subclass
39
39
  #
40
- def publish(_event_data, **_additional_arguments)
40
+ def publish(_event_data, **_additional_attrs)
41
41
  raise NotImplementedError,
42
42
  "#{self.class.name} must implement method #publish"
43
43
  end
44
+
45
+ #
46
+ # Allows custom setup of the adapter. Noop by default
47
+ # @abstract
48
+ #
49
+ def auto_initialize!
50
+ # noop by default
51
+ end
52
+
53
+ #
54
+ # This method is expected to be implemented by subclasses. In case async
55
+ # publisher is used the process might end before the async queue of
56
+ # messages is processed, so this method is going to be used in a
57
+ # `at_exit` hook to flush the queue.
58
+ # @abstract
59
+ # @raise {NotImplementedError} unless implemented in a subclass
60
+ #
61
+ def flush!
62
+ raise NotImplementedError,
63
+ "#{self.class.name} must implement method #flush"
64
+ end
44
65
  end
45
66
  end
46
67
  end
@@ -48,22 +48,42 @@ module Stenotype
48
48
  # # publishes to default CustomGCClient
49
49
  # google_cloud_adapter.publish({ event: :data }, { additional: :data })
50
50
  #
51
- def publish(event_data, **additional_arguments)
51
+ def publish(event_data, **additional_attrs)
52
52
  if config.async
53
- publish_async(event_data, **additional_arguments)
53
+ publish_async(event_data, **additional_attrs)
54
54
  else
55
- publish_sync(event_data, **additional_arguments)
55
+ publish_sync(event_data, **additional_attrs)
56
56
  end
57
57
  end
58
58
 
59
+ #
60
+ # Flushes the topic's async queue
61
+ #
62
+ def flush!
63
+ # a publisher might be uninitialized until the first event is published
64
+ return unless topic.async_publisher
65
+
66
+ topic.async_publisher.stop.wait!
67
+ end
68
+
69
+ #
70
+ # If not called both client and topic are lazy initialized on first call (if not
71
+ # passed to #initialize). #auto_initialize! is going to explicitly initialize
72
+ # both client and topic.
73
+ #
74
+ def auto_initialize!
75
+ client
76
+ topic
77
+ end
78
+
59
79
  private
60
80
 
61
- def publish_sync(event_data, **additional_arguments)
62
- topic.publish(event_data, additional_arguments)
81
+ def publish_sync(event_data, **additional_attrs)
82
+ topic.publish(event_data, additional_attrs)
63
83
  end
64
84
 
65
- def publish_async(event_data, **additional_arguments)
66
- topic.publish_async(event_data, additional_arguments) do |result|
85
+ def publish_async(event_data, **additional_attrs)
86
+ topic.publish_async(event_data, additional_attrs) do |result|
67
87
  raise Stenotype::MessageNotPublishedError unless result.succeeded?
68
88
  end
69
89
  end
@@ -31,8 +31,20 @@ module Stenotype
31
31
  # adapter = Stenotype::Adapters::StdoutAdapter.new(client: STDERR)
32
32
  # adapter.publish({ event: :data }, { additional: :data })
33
33
  #
34
- def publish(event_data, **additional_arguments)
35
- client.info(**event_data, **additional_arguments)
34
+ def publish(event_data, **additional_attrs)
35
+ client.info("[Stenotype::Event] emitted with the following attributes") do
36
+ {
37
+ **event_data,
38
+ **additional_attrs,
39
+ }
40
+ end
41
+ end
42
+
43
+ #
44
+ # Does nothing
45
+ #
46
+ def flush!
47
+ # noop
36
48
  end
37
49
 
38
50
  private
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+ require "stenotype"
5
+
6
+ at_exit do
7
+ targets = Stenotype.config.targets
8
+ targets.each(&:flush!)
9
+ end
10
+ # :nocov:
@@ -6,6 +6,7 @@ module Stenotype
6
6
  #
7
7
  # @example Configuring the library
8
8
  # Stenotype.configure do |config|
9
+ # config.enabled = true
9
10
  # config.targets = [Target1.new, Target2.new]
10
11
  # config.uuid_generator = SecureRandom
11
12
  #
@@ -25,6 +26,18 @@ module Stenotype
25
26
  module Configuration
26
27
  extend Spicerack::Configurable
27
28
 
29
+ # @!attribute graceful_error_handling
30
+ # @return {true, false} a flag for suppressing error raised withing the gem
31
+
32
+ # @!attribute logger
33
+ # @return {Logger} a logger with default severity methods to output gem level messages
34
+
35
+ # @!attribute enabled
36
+ # @return {true, false} a flag indicating whether event emission is enabled
37
+
38
+ # @!attribute auto_adapter_initialization
39
+ # @return {true, false} enables/disables lazy initialization of adapters' clients
40
+
28
41
  # @!attribute targets
29
42
  # @return {Array<#publish>} a list of targets responding to method [#publish]
30
43
 
@@ -49,7 +62,6 @@ module Stenotype
49
62
  # @!attribute [rw] google_cloud.async
50
63
  # @return [true, false] GC publish mode, either async if true, sync if false
51
64
 
52
-
53
65
  # @!attribute [rw] rails
54
66
  # @return [NestedConfiguration] Rails configuration.
55
67
 
@@ -60,9 +72,12 @@ module Stenotype
60
72
  # @return [true, false] A flag of whether ActiveJob ext is enabled
61
73
 
62
74
  configuration_options do
75
+ option :graceful_error_handling, default: true
76
+ option :enabled, default: true
63
77
  option :targets, default: []
64
78
  option :dispatcher, default: Stenotype::Dispatcher
65
79
  option :uuid_generator, default: SecureRandom
80
+ option :logger
66
81
 
67
82
  nested :google_cloud do
68
83
  option :credentials, default: nil
@@ -74,11 +89,34 @@ module Stenotype
74
89
  nested :rails do
75
90
  option :enable_action_controller_ext, default: true
76
91
  option :enable_active_job_ext, default: true
92
+ option :auto_adapter_initialization, default: true
77
93
  end
78
94
  end
79
95
 
80
96
  module_function
81
97
 
98
+ #
99
+ # @example With default logger
100
+ # Stenotype.configure do |config|
101
+ # # config.logger = nil # logger not set manually
102
+ # end
103
+ # Stenotype.config.logger #=> `Logger.new(STDOUT)` instance
104
+ #
105
+ # @example With custom logger
106
+ # Stenotype.configure do |config|
107
+ # config.logger = custom_logger_instance
108
+ # end
109
+ # Stenotype.config.logger #=> custom_logger_instance
110
+ #
111
+ # @return [{Logger, CustomLogger}] a logger object. Logger.new(STDOUT) by
112
+ # default if another is not set during configuration
113
+ #
114
+ def logger
115
+ return config.logger if config.logger
116
+
117
+ config.logger || Logger.new(STDOUT)
118
+ end
119
+
82
120
  #
83
121
  # @example When at least one target is present
84
122
  # Stenotype.configure do |config|
@@ -93,6 +131,8 @@ module Stenotype
93
131
  # @raise {Stenotype::NoTargetsSpecifiedError} in case no targets are configured
94
132
  # @return {Array<#publish>} An array of targets implementing method [#publish]
95
133
  #
134
+ # @todo THIS NEVER GETS CALLED, needs a fix
135
+ #
96
136
  def targets
97
137
  return config.targets unless config.targets.empty?
98
138
 
@@ -33,11 +33,12 @@ module Stenotype
33
33
  end
34
34
 
35
35
  #
36
- # @!method emit_event(data = {}, method: caller_locations.first.label, eval_context: nil)
36
+ # @!method emit_event(name, attributes = {}, method: caller_locations.first.label, eval_context: nil)
37
37
  # A method injected into target class to manually track events
38
38
  # @!scope instance
39
- # @param data {Hash} Data to be sent to the targets
40
- # @param method {String} An optional method name
39
+ # @param name {[String, Symbol]} Event name.
40
+ # @param attributes {Hash} Data to be sent to the targets.
41
+ # @param method {String} An optional method name.
41
42
  # @param eval_context {Hash} A hash linking object to context handler
42
43
  # @return {Stenotype::Event} An instance of emitted event
43
44
  # @example Usage of emit_event
@@ -91,15 +92,14 @@ module Stenotype
91
92
  #
92
93
  def self.build_instance_methods(instance_mod)
93
94
  instance_mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
94
- def emit_event(data = {}, method: caller_locations.first.label, eval_context: nil)
95
+ def emit_event(event_name, attributes = {}, method: caller_locations.first.label, eval_context: nil)
95
96
  Stenotype::Event.emit!(
97
+ event_name,
96
98
  {
97
- type: "class_instance",
98
- **data,
99
- },
100
- options: {
99
+ type: "instance_method",
101
100
  class: self.class.name,
102
- method: method.to_sym
101
+ method: method.to_sym,
102
+ **attributes,
103
103
  },
104
104
  eval_context: (eval_context || { klass: self })
105
105
  )
@@ -120,12 +120,14 @@ module Stenotype
120
120
  proxy.module_eval do
121
121
  define_method(method) do |*args, **rest_args, &block|
122
122
  Stenotype::Event.emit!(
123
- { type: "class_instance" },
124
- options: {
123
+ # @todo How do we name such events?
124
+ "instance_method",
125
+ {
126
+ type: "instance_method",
125
127
  class: self.class.name,
126
- method: __method__
128
+ method: __method__,
127
129
  },
128
- eval_context: { klass: self }
130
+ eval_context: { klass: self },
129
131
  )
130
132
  super(*args, **rest_args, &block)
131
133
  end
@@ -142,12 +144,14 @@ module Stenotype
142
144
  proxy.module_eval do
143
145
  define_method(method) do |*args, **rest_args, &block|
144
146
  Stenotype::Event.emit!(
145
- { type: "class" },
146
- options: {
147
+ # @todo How do we name such events?
148
+ "class_method",
149
+ {
150
+ type: "class_method",
147
151
  class: self.name,
148
- method: __method__
152
+ method: __method__,
149
153
  },
150
- eval_context: { klass: self }
154
+ eval_context: { klass: self },
151
155
  )
152
156
  super(*args, **rest_args, &block)
153
157
  end
@@ -11,19 +11,31 @@ module Stenotype
11
11
  # @example Emit an event using class method
12
12
  # Stenotype::Event.emit!(data, options, eval_context)
13
13
  #
14
- # @param data {Hash} Data to be published to the targets.
15
- # @param options {Hash} A hash of additional options to be tracked.
16
- # @param eval_context {Hash} A context having handler defined in {Stenotype::ContextHandlers}.
17
- # @param dispatcher {#publish} A dispatcher object responding to [#publish]
14
+ # @param {[String, Symbol]} name Event name.
15
+ # @param {Hash} attributes Data to be published to the targets.
16
+ # @param {Hash} eval_context A context having handler defined in {Stenotype::ContextHandlers}.
17
+ # @param dispatcher {#publish} A dispatcher object responding to [#publish].
18
18
  # @return {Stenotype::Event} An instance of {Stenotype::Event}
19
19
  #
20
- def self.emit!(data, options: {}, eval_context: {}, dispatcher: Stenotype.config.dispatcher)
21
- event = new(data, options: options, eval_context: eval_context, dispatcher: dispatcher)
22
- event.emit!
23
- event
20
+ def self.emit!(name, attributes = {}, eval_context: {}, dispatcher: Stenotype.config.dispatcher)
21
+ return unless Stenotype.config.enabled
22
+
23
+ begin
24
+ event = new(name, attributes, eval_context: eval_context, dispatcher: dispatcher)
25
+ event.emit!
26
+ event
27
+ rescue StandardError => exception
28
+ #
29
+ # @todo This is a temporary solution to enable conditional logger fetching
30
+ # needs a fix to use default Spicerack::Configuration functionality
31
+ #
32
+ Stenotype::Configuration.logger.error(exception)
33
+
34
+ raise Stenotype::Error unless Stenotype.config.graceful_error_handling
35
+ end
24
36
  end
25
37
 
26
- attr_reader :data, :options, :eval_context, :dispatcher
38
+ attr_reader :name, :attributes, :eval_context, :dispatcher
27
39
 
28
40
  #
29
41
  # @example Create an event
@@ -31,15 +43,15 @@ module Stenotype
31
43
  # @example Create an event with custom dispatcher
32
44
  # event = Stenotype::Event.new(data, options, eval_context, dispatcher: MyDispatcher.new)
33
45
  #
34
- # @param {Hash} data Data to be published to the targets.
35
- # @param {Hash} options A hash of additional options to be tracked.
46
+ # @param {[String, Symbol]} name Event name.
47
+ # @param {Hash} attributes Data to be published to the targets.
36
48
  # @param {Hash} eval_context A context having handler defined in {Stenotype::ContextHandlers}.
37
49
  # @param dispatcher {#publish} A dispatcher object responding to [#publish].
38
50
  # @return {Stenotype::Event} An instance of event
39
51
  #
40
- def initialize(data, options: {}, eval_context: {}, dispatcher: Stenotype.config.dispatcher)
41
- @data = data
42
- @options = options
52
+ def initialize(name, attributes = {}, eval_context: {}, dispatcher: Stenotype.config.dispatcher)
53
+ @name = name
54
+ @attributes = attributes
43
55
  @eval_context = eval_context
44
56
  @dispatcher = dispatcher.new
45
57
  end
@@ -48,11 +60,23 @@ module Stenotype
48
60
  # Emits a {Stenotype::Event}.
49
61
  #
50
62
  # @example Emit an instance of event
51
- # event = Stenotype::Event.new(data, options, eval_context)
63
+ # event = Stenotype::Event.new('events_name', { key: :value }, eval_context: { controller: ctrl })
52
64
  # event.emit! #=> Publishes the event to targets
53
65
  #
54
66
  def emit!
55
- dispatcher.publish(self)
67
+ return unless Stenotype.config.enabled
68
+
69
+ begin
70
+ dispatcher.publish(self)
71
+ rescue StandardError => exception
72
+ #
73
+ # @todo This is a temporary solution to enable conditional logger fetching
74
+ # needs a fix to use default Spicerack::Configuration functionality
75
+ #
76
+ Stenotype::Configuration.logger.error(exception)
77
+
78
+ raise Stenotype::Error unless Stenotype.config.graceful_error_handling
79
+ end
56
80
  end
57
81
  end
58
82
  end
@@ -42,8 +42,8 @@ module Stenotype
42
42
  #
43
43
  def serialize
44
44
  {
45
- **event_data,
46
- **event_options,
45
+ name: event_name,
46
+ **event_attributes,
47
47
  **default_options,
48
48
  **eval_context_options,
49
49
  }
@@ -51,12 +51,12 @@ module Stenotype
51
51
 
52
52
  private
53
53
 
54
- def event_data
55
- event.data
54
+ def event_name
55
+ event.name
56
56
  end
57
57
 
58
- def event_options
59
- event.options
58
+ def event_attributes
59
+ event.attributes
60
60
  end
61
61
 
62
62
  def eval_context
@@ -20,10 +20,11 @@ module Stenotype
20
20
 
21
21
  #
22
22
  # Emits and event with given data
23
- # @param data {Hash} Data to be sent to targets
23
+ # @param name {[String, Symbol]} Event name
24
+ # @todo What is really the name here?
24
25
  #
25
- def _record_freshly_event(data)
26
- Stenotype::Event.emit!(data, options: {}, eval_context: { controller: self })
26
+ def _record_freshly_event(name)
27
+ Stenotype::Event.emit!(name, { type: "controller_action" }, { eval_context: { controller: self }})
27
28
  end
28
29
 
29
30
  #
@@ -72,7 +73,7 @@ module Stenotype
72
73
  return if delta.empty?
73
74
 
74
75
  before_action only: delta do
75
- _record_freshly_event(type: "view")
76
+ _record_freshly_event("view")
76
77
  end
77
78
 
78
79
  _tracked_actions.merge(delta)
@@ -110,7 +111,7 @@ module Stenotype
110
111
  return if delta.empty?
111
112
 
112
113
  before_action only: delta.to_a do
113
- _record_freshly_event(type: "view")
114
+ _record_freshly_event("view")
114
115
  end
115
116
 
116
117
  # merge is a mutating op
@@ -35,9 +35,9 @@ module Stenotype
35
35
  proxy.module_eval do
36
36
  define_method(:perform) do |*args, **rest_args, &block|
37
37
  Stenotype::Event.emit!(
38
+ "active_job_#{self.class.name}",
38
39
  { type: "active_job" },
39
- { options: {},
40
- eval_context: { active_job: self }},
40
+ { eval_context: { active_job: self }},
41
41
  )
42
42
  super(*args, **rest_args, &block)
43
43
  end
@@ -18,6 +18,8 @@ module Stenotype
18
18
 
19
19
  config.stenotype = Stenotype.config
20
20
 
21
+ config.after_initialize { config.stenotype.targets.each(&:auto_initialize!) } if config.stenotype.rails.auto_adapter_initialization
22
+
21
23
  if config.stenotype.rails.enable_action_controller_ext
22
24
  ActiveSupport.on_load(:action_controller) do
23
25
  Stenotype::ContextHandlers.register Stenotype::ContextHandlers::Rails::Controller
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Stenotype
4
4
  # :nodoc:
5
- VERSION = "0.1.1"
5
+ VERSION = "0.1.7"
6
6
  # :nodoc:
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stenotype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Kapitonov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-09 00:00:00.000000000 Z
11
+ date: 2020-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -267,6 +267,7 @@ files:
267
267
  - lib/stenotype/adapters/base.rb
268
268
  - lib/stenotype/adapters/google_cloud.rb
269
269
  - lib/stenotype/adapters/stdout_adapter.rb
270
+ - lib/stenotype/at_exit.rb
270
271
  - lib/stenotype/configuration.rb
271
272
  - lib/stenotype/context_handlers.rb
272
273
  - lib/stenotype/context_handlers/base.rb