event_meter 0.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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +1081 -0
  4. data/exe/event_meter +5 -0
  5. data/lib/event_meter/auto_cleanup.rb +93 -0
  6. data/lib/event_meter/cli.rb +124 -0
  7. data/lib/event_meter/configuration.rb +244 -0
  8. data/lib/event_meter/errors.rb +9 -0
  9. data/lib/event_meter/event.rb +180 -0
  10. data/lib/event_meter/event_payload.rb +103 -0
  11. data/lib/event_meter/hash_input.rb +20 -0
  12. data/lib/event_meter/index_key.rb +19 -0
  13. data/lib/event_meter/keys.rb +63 -0
  14. data/lib/event_meter/path_name.rb +37 -0
  15. data/lib/event_meter/processor.rb +305 -0
  16. data/lib/event_meter/rails.rb +79 -0
  17. data/lib/event_meter/report_definition.rb +184 -0
  18. data/lib/event_meter/reports.rb +143 -0
  19. data/lib/event_meter/rollup.rb +148 -0
  20. data/lib/event_meter/stores/cleanup_helpers.rb +76 -0
  21. data/lib/event_meter/stores/file_helpers.rb +47 -0
  22. data/lib/event_meter/stores/lock_refresher.rb +75 -0
  23. data/lib/event_meter/stores/namespace.rb +14 -0
  24. data/lib/event_meter/stores/redis_lock.rb +77 -0
  25. data/lib/event_meter/stores/rollup/active_record_postgres.rb +135 -0
  26. data/lib/event_meter/stores/rollup/file.rb +736 -0
  27. data/lib/event_meter/stores/rollup/postgres.rb +813 -0
  28. data/lib/event_meter/stores/rollup/redis.rb +349 -0
  29. data/lib/event_meter/stores/stream/file.rb +98 -0
  30. data/lib/event_meter/stores/stream/redis.rb +79 -0
  31. data/lib/event_meter/time_buckets.rb +56 -0
  32. data/lib/event_meter/version.rb +3 -0
  33. data/lib/event_meter/write_result.rb +26 -0
  34. data/lib/event_meter.rb +150 -0
  35. data/lib/generators/event_meter/install_generator.rb +57 -0
  36. data/lib/generators/event_meter/templates/create_event_meter_tables.rb.erb +12 -0
  37. data/lib/generators/event_meter/templates/event_meter.rb.erb +12 -0
  38. metadata +156 -0
@@ -0,0 +1,150 @@
1
+ require "time"
2
+
3
+ require_relative "event_meter/version"
4
+ require_relative "event_meter/errors"
5
+ require_relative "event_meter/hash_input"
6
+ require_relative "event_meter/configuration"
7
+ require_relative "event_meter/write_result"
8
+ require_relative "event_meter/event"
9
+ require_relative "event_meter/event_payload"
10
+ require_relative "event_meter/index_key"
11
+ require_relative "event_meter/path_name"
12
+ require_relative "event_meter/report_definition"
13
+ require_relative "event_meter/rollup"
14
+ require_relative "event_meter/time_buckets"
15
+ require_relative "event_meter/keys"
16
+ require_relative "event_meter/reports"
17
+ require_relative "event_meter/processor"
18
+ require_relative "event_meter/auto_cleanup"
19
+ require_relative "event_meter/stores/namespace"
20
+ require_relative "event_meter/stores/cleanup_helpers"
21
+ require_relative "event_meter/stores/file_helpers"
22
+ require_relative "event_meter/stores/redis_lock"
23
+ require_relative "event_meter/stores/stream/file"
24
+ require_relative "event_meter/stores/stream/redis"
25
+ require_relative "event_meter/stores/rollup/file"
26
+ require_relative "event_meter/stores/rollup/postgres"
27
+ require_relative "event_meter/stores/rollup/active_record_postgres"
28
+ require_relative "event_meter/stores/rollup/redis"
29
+
30
+ module EventMeter
31
+ class << self
32
+ def start(name, attributes = nil, **keyword_attributes)
33
+ Event.start(name, attributes, keyword_attributes, started_at: Time.now.utc)
34
+ rescue StandardError => error
35
+ Event.failed(error)
36
+ end
37
+
38
+ def configure
39
+ yield configuration if block_given?
40
+ configuration
41
+ end
42
+
43
+ def configuration
44
+ @configuration ||= Configuration.new
45
+ end
46
+
47
+ def reset
48
+ @configuration = Configuration.new
49
+ end
50
+
51
+ def process_pending(name, version:, &block)
52
+ definition = build_report_definition(name, version: version, &block)
53
+
54
+ result = Processor.new(
55
+ configuration: configuration,
56
+ report_definition: definition,
57
+ stream_storage: stream_storage,
58
+ rollup_storage: rollup_storage_for(definition)
59
+ ).process
60
+
61
+ auto_cleanup_history unless result.locked
62
+ result
63
+ end
64
+
65
+ def cleanup_history(before:, events: nil, interval_state: true)
66
+ namespaced_rollup_storage.cleanup_history(
67
+ before: time_value(before),
68
+ events: Array(events).compact.map(&:to_s),
69
+ interval_state: interval_state
70
+ )
71
+ end
72
+
73
+ def summary(name, version:, from: nil, to: nil, by: {})
74
+ reports(name, version: version).summary(name, version: version, from: from, to: to, by: by)
75
+ end
76
+
77
+ def series(name, version:, from: nil, to: nil, every: :minute, by: {})
78
+ reports(name, version: version).series(name, version: version, from: from, to: to, every: every, by: by)
79
+ end
80
+
81
+ def compare(name, version:, before:, after:, by: {})
82
+ reports(name, version: version).compare(name, version: version, before: before, after: after, by: by)
83
+ end
84
+
85
+ def report_definition(name, version:)
86
+ storage = rollup_storage_for_name(name, version: version)
87
+ stored = storage.report_definition(name: name, version: version)
88
+ raise DefinitionNotFoundError, "no definition stored for #{name} v#{version}" unless stored
89
+
90
+ ReportDefinition.from_h(stored).to_h
91
+ end
92
+
93
+ def stream_storage
94
+ configuration.stream_storage
95
+ end
96
+
97
+ def rollup_storage
98
+ configuration.rollup_storage
99
+ end
100
+
101
+ private
102
+
103
+ def auto_cleanup_history
104
+ AutoCleanup.new(
105
+ configuration: configuration,
106
+ rollup_storage: namespaced_rollup_storage
107
+ ).run
108
+ end
109
+
110
+ def time_value(value)
111
+ return value.utc if value.respond_to?(:utc)
112
+ raise ArgumentError unless value.respond_to?(:to_str)
113
+
114
+ Time.parse(value.to_str).utc
115
+ rescue ArgumentError, TypeError, RangeError
116
+ raise ArgumentError, "time must be a Time or parseable time string"
117
+ end
118
+
119
+ def reports(name, version:)
120
+ Reports.new(
121
+ configuration: configuration,
122
+ rollup_storage: rollup_storage_for_name(name, version: version)
123
+ )
124
+ end
125
+
126
+ def build_report_definition(name, version:, &block)
127
+ ReportDefinition.build(name, version: version) do |definition|
128
+ block.call(definition) if block
129
+ end
130
+ end
131
+
132
+ def rollup_storage_for(definition)
133
+ rollup_storage_for_name(definition.name, version: definition.version)
134
+ end
135
+
136
+ def rollup_storage_for_name(name, version:)
137
+ storage = namespaced_rollup_storage
138
+ return storage.for_report(name: name, version: version) if storage.respond_to?(:for_report)
139
+
140
+ storage
141
+ end
142
+
143
+ def namespaced_rollup_storage
144
+ storage = rollup_storage
145
+ return storage.for_namespace(configuration.namespace) if storage.respond_to?(:for_namespace)
146
+
147
+ storage
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,57 @@
1
+ require "rails/generators"
2
+ require "rails/generators/active_record"
3
+
4
+ require_relative "../../event_meter/rails"
5
+
6
+ module EventMeter
7
+ module Generators
8
+ class InstallGenerator < ::Rails::Generators::Base
9
+ include ::Rails::Generators::Migration
10
+
11
+ source_root File.expand_path("templates", __dir__)
12
+
13
+ class_option :table_prefix,
14
+ type: :string,
15
+ default: "event_meter",
16
+ desc: "PostgreSQL table prefix"
17
+
18
+ class_option :namespace,
19
+ type: :string,
20
+ default: "event_meter:v1",
21
+ desc: "EventMeter namespace"
22
+
23
+ def copy_migration
24
+ migration_template(
25
+ "create_event_meter_tables.rb.erb",
26
+ "db/migrate/create_event_meter_tables.rb"
27
+ )
28
+ end
29
+
30
+ def create_initializer
31
+ template "event_meter.rb.erb", "config/initializers/event_meter.rb"
32
+ end
33
+
34
+ def self.next_migration_number(dirname)
35
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
36
+ end
37
+
38
+ private
39
+
40
+ def table_prefix
41
+ options.fetch(:table_prefix)
42
+ end
43
+
44
+ def namespace
45
+ options.fetch(:namespace)
46
+ end
47
+
48
+ def migration_sql
49
+ EventMeter::Rails.migration_sql(table_prefix: table_prefix)
50
+ end
51
+
52
+ def indented_migration_sql
53
+ migration_sql.lines.map { |line| " #{line}" }.join
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,12 @@
1
+ class CreateEventMeterTables < ActiveRecord::Migration[7.0]
2
+ def up
3
+ execute <<~SQL
4
+ <%= indented_migration_sql %> SQL
5
+ end
6
+
7
+ def down
8
+ drop_table :<%= table_prefix %>_processed_entries, if_exists: true
9
+ drop_table :<%= table_prefix %>_strings, if_exists: true
10
+ drop_table :<%= table_prefix %>_rollups, if_exists: true
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require "event_meter/rails"
2
+
3
+ EventMeter::Rails.configure(
4
+ namespace: "<%= namespace %>",
5
+ stream_storage: :file,
6
+ stream_path: Rails.root.join("tmp/event_meter/<%= namespace.tr(':', '-') %>").to_s,
7
+ rollup_storage: :postgres,
8
+ table_prefix: "<%= table_prefix %>",
9
+ stream_sync: :flush,
10
+ auto_cleanup_history: true,
11
+ logger: Rails.logger
12
+ )
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: event_meter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Lim
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: time_bucket_stream
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '0.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '0.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: minitest
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '5.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: pg
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.5'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.5'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rake
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '13.0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '13.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: redis
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '5.0'
75
+ - - "<"
76
+ - !ruby/object:Gem::Version
77
+ version: '6.0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '5.0'
85
+ - - "<"
86
+ - !ruby/object:Gem::Version
87
+ version: '6.0'
88
+ description: EventMeter records application events and turns them into storage-backed
89
+ metrics for counts, speed, duration, and intervals.
90
+ email:
91
+ - aaron.lim.yu.kwang@gmail.com
92
+ executables:
93
+ - event_meter
94
+ extensions: []
95
+ extra_rdoc_files: []
96
+ files:
97
+ - LICENSE.txt
98
+ - README.md
99
+ - exe/event_meter
100
+ - lib/event_meter.rb
101
+ - lib/event_meter/auto_cleanup.rb
102
+ - lib/event_meter/cli.rb
103
+ - lib/event_meter/configuration.rb
104
+ - lib/event_meter/errors.rb
105
+ - lib/event_meter/event.rb
106
+ - lib/event_meter/event_payload.rb
107
+ - lib/event_meter/hash_input.rb
108
+ - lib/event_meter/index_key.rb
109
+ - lib/event_meter/keys.rb
110
+ - lib/event_meter/path_name.rb
111
+ - lib/event_meter/processor.rb
112
+ - lib/event_meter/rails.rb
113
+ - lib/event_meter/report_definition.rb
114
+ - lib/event_meter/reports.rb
115
+ - lib/event_meter/rollup.rb
116
+ - lib/event_meter/stores/cleanup_helpers.rb
117
+ - lib/event_meter/stores/file_helpers.rb
118
+ - lib/event_meter/stores/lock_refresher.rb
119
+ - lib/event_meter/stores/namespace.rb
120
+ - lib/event_meter/stores/redis_lock.rb
121
+ - lib/event_meter/stores/rollup/active_record_postgres.rb
122
+ - lib/event_meter/stores/rollup/file.rb
123
+ - lib/event_meter/stores/rollup/postgres.rb
124
+ - lib/event_meter/stores/rollup/redis.rb
125
+ - lib/event_meter/stores/stream/file.rb
126
+ - lib/event_meter/stores/stream/redis.rb
127
+ - lib/event_meter/time_buckets.rb
128
+ - lib/event_meter/version.rb
129
+ - lib/event_meter/write_result.rb
130
+ - lib/generators/event_meter/install_generator.rb
131
+ - lib/generators/event_meter/templates/create_event_meter_tables.rb.erb
132
+ - lib/generators/event_meter/templates/event_meter.rb.erb
133
+ homepage: https://github.com/aaron-lim/event_meter
134
+ licenses:
135
+ - MIT
136
+ metadata:
137
+ source_code_uri: https://github.com/aaron-lim/event_meter
138
+ rubygems_mfa_required: 'true'
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: 3.1.0
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ requirements: []
153
+ rubygems_version: 3.6.9
154
+ specification_version: 4
155
+ summary: Small event-based runtime metrics for Ruby applications.
156
+ test_files: []