metric_system 0.1.2 → 0.1.3

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: d1483853542b6eb79dc9c7a0e349591d2ee14d52
4
- data.tar.gz: 9f50ee6bc48e72b83002aaf165576ce586414873
3
+ metadata.gz: 3c313b1e1c7d585f73c1210c3fb3bc610268d804
4
+ data.tar.gz: 26cf80941ed294412d5afb60e79b883ae13e2fa8
5
5
  SHA512:
6
- metadata.gz: 422740c79d19c46fce188e3b33d6cdbf45fc34c79ab37cda1560dfeae0aed607411b6678d0a6085ba6e0569249ec50ac91967fa8bb5bce38bdb048195cfa60b4
7
- data.tar.gz: 03deb35f0a2baa9a5842de40355cd8118120a49ec371e900491d458455bab093acbac6bfecc2dd1a34829bbb5122ce47294593ff7c40e3d120959d732bd34475
6
+ metadata.gz: 1c2b87a70402f5f6090c33f39228c0762777abedbd9f0d27caee1092442a6943a782576a45a48e84b6aec0ce54b4db7080abb9dbbf1a0759575274f0262f847c
7
+ data.tar.gz: a8e41c77e9810bed3d53e7bbd6c3e30c167d1ffac75c09d41d7955e6b737534cf2f1d0e618d667e5fd979d0398002caf80fc9730c3a94fa6249cb504aa3ec317
@@ -23,7 +23,7 @@ module MetricSystem
23
23
  end
24
24
 
25
25
  extend Forwardable
26
- delegate [:aggregate, :select, :print, :run, :ask, :register] => :"@target"
26
+ delegate [:aggregate, :select, :print, :run, :ask] => :"@target"
27
27
  delegate [:transaction] => :"@target"
28
28
  delegate [:add_event] => :"@target"
29
29
  delegate [:quit_server!] => :"@target"
@@ -1,12 +1,15 @@
1
1
  class MetricSystem::Database
2
- def initialize(path)
2
+ def initialize(path, readonly = false)
3
3
  require_relative "./sqlite3_extensions"
4
4
  open path
5
+
6
+ exec "PRAGMA query_only = 1" if readonly # This might or might not work.
7
+ @db.readonly = !!readonly
5
8
  end
6
9
 
7
10
  extend Forwardable
8
11
 
9
- delegate [:exec, :select, :transaction, :rollback, :print, :run, :ask, :register] => :"@db"
12
+ delegate [:exec, :select, :transaction, :rollback, :print, :run, :ask, :register, :readonly?] => :"@db"
10
13
 
11
14
  PERIODS = [
12
15
  [ :year, 31536000, "strftime('%Y-01-01', starts_at, 'unixepoch')" ],
@@ -103,7 +106,7 @@ class MetricSystem::Database
103
106
  aggregate_for_period :period => period, :source => :counters, :dest => :aggregated_counters, :aggregate => "sum"
104
107
  end
105
108
 
106
- @db.exec "DELETE FROM counters"
109
+ exec "DELETE FROM counters"
107
110
  end
108
111
 
109
112
  transaction do
@@ -111,7 +114,7 @@ class MetricSystem::Database
111
114
  aggregate_for_period :period => period, :source => :gauges, :dest => :aggregated_gauges, :aggregate => "CAST(sum AS FLOAT) / count"
112
115
  end
113
116
 
114
- @db.exec "DELETE FROM gauges"
117
+ exec "DELETE FROM gauges"
115
118
  end
116
119
  end
117
120
 
@@ -128,7 +131,7 @@ class MetricSystem::Database
128
131
  # sql expression to calculate value from sum and count of event values
129
132
  aggregate = source == :gauges ? "CAST(sum AS FLOAT) / count" : "sum"
130
133
 
131
- @db.exec <<-SQL
134
+ exec <<-SQL
132
135
  CREATE TEMPORARY TABLE batch AS
133
136
  SELECT name, starts_at, SUM(sum) AS sum, SUM(count) AS count FROM
134
137
  (
@@ -157,7 +160,7 @@ class MetricSystem::Database
157
160
  FROM batch;
158
161
  SQL
159
162
 
160
- @db.exec <<-SQL
163
+ exec <<-SQL
161
164
  DROP TABLE batch;
162
165
  SQL
163
166
  end
@@ -1,3 +1,3 @@
1
1
  module MetricSystem
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -1,27 +1,43 @@
1
1
  require 'sinatra/base'
2
2
  require 'to_js'
3
-
4
- module GoogleCharts
5
- extend self
6
-
7
- def convert(results)
8
- results.description.to_js
9
- end
10
-
11
- private
12
-
13
- end
3
+ require 'metric_system/database'
14
4
 
15
5
  class MetricSystem::Web < Sinatra::Base
16
6
  set :environment, :development
17
7
  set :raise_errors, true
18
8
  set :views, "#{File.dirname(__FILE__)}/web"
19
9
  set :dump_errors, true
10
+ set :database, nil
11
+
12
+ def self.register_query(name, query)
13
+ registry[name] = query
14
+ end
15
+
16
+ def self.registry
17
+ @registry ||= {}
18
+ end
19
+
20
+ # return a database for the current thread
21
+ def self.connection
22
+ Thread.current[:"MetricSystem::Web.database"] ||= MetricSystem::Database.new(self.database, :readonly)
23
+ end
24
+
25
+ def self.select(query, *args)
26
+ expect! query => [ String, Symbol ]
27
+
28
+ if query.is_a?(Symbol)
29
+ expect! query => registry.keys
30
+ query = registry.fetch(query)
31
+ end
32
+
33
+ result = connection.select query, *args #period: "month"
34
+ result.data_table.to_js
35
+ end
20
36
 
21
37
  helpers do
22
38
  def select(query, *args)
23
39
  @result_cache ||= {}
24
- @result_cache[query] ||= MetricSystem.database.select(query, *args).data_table.to_js
40
+ @result_cache[[query, args]] ||= self.class.select(query, *args, params)
25
41
  end
26
42
  end
27
43
 
@@ -116,22 +116,18 @@
116
116
  <div>
117
117
  <h3>Table</h3>
118
118
  <div class="google-visualization">
119
- <%=
120
- select "SELECT date(starts_at), value FROM aggregates WHERE period='day'"
121
- %>
119
+ <%= select "SELECT date(starts_at), value FROM aggregates WHERE period=:period" %>
122
120
  </div>
123
121
  </div>
124
122
  <div>
125
123
  <h3>Pie Chart</h3>
126
- <div class="google-visualization" data-src="/value_by_day_name.js" data-chart="pie">
124
+ <div class="google-visualization" data-src="/value_by_day_name.js?period=month" data-chart="pie">
127
125
  </div>
128
126
  </div>
129
127
  <div>
130
128
  <h3>Area Chart</h3>
131
129
  <div class="google-visualization" data-chart="area">
132
- <%=
133
- select "SELECT date(starts_at), value FROM aggregates WHERE period='day'"
134
- %>
130
+ <%= select "SELECT date(starts_at), value FROM aggregates WHERE period=:period" %>
135
131
  </div>
136
132
  </div>
137
133
  <div>
@@ -1,6 +1,16 @@
1
1
  class SQLite3::Database
2
+ def readonly?
3
+ @readonly
4
+ end
5
+
6
+ def readonly=(readonly)
7
+ @readonly = readonly
8
+ end
9
+
2
10
  # execute multiple SQL statements at once.
3
11
  def exec(sql, *args)
12
+ raise "Cannot run nondestructive query: #{sql}" if readonly?
13
+
4
14
  args = prepare_arguments(args)
5
15
 
6
16
  while sql =~ /\S/ do
@@ -22,15 +32,14 @@ class SQLite3::Database
22
32
  private
23
33
 
24
34
  def query(sql)
25
- expect! sql => [ String, Symbol ]
26
-
27
- if sql.is_a?(Symbol)
28
- expect! sql => registry.keys
29
- sql = registry.fetch(sql)
30
- end
35
+ expect! sql => String
31
36
 
32
37
  @queries ||= {}
33
- @queries[sql] ||= SQLite3::Query.new sql, prepare(sql)
38
+ query = @queries[sql] ||= begin
39
+ query = SQLite3::Query.new sql, prepare(sql)
40
+ raise "Cannot run nondestructive query: #{sql}" if readonly? && query.destructive?
41
+ query
42
+ end
34
43
  end
35
44
 
36
45
  def prepare_arguments(args)
@@ -72,14 +81,4 @@ class SQLite3::Database
72
81
  end
73
82
  puts "=" * log_sql.length
74
83
  end
75
-
76
- # -- query registry
77
-
78
- def registry
79
- @registry ||= {}
80
- end
81
-
82
- def register(name, query)
83
- registry[name] = query
84
- end
85
84
  end
@@ -1,12 +1,43 @@
1
+ class SQLite3::MissingParameters < RuntimeError
2
+ end
3
+
1
4
  class SQLite3::Query
5
+
6
+ # all parameters in the query, as Symbols.
7
+ attr :parameters
8
+
2
9
  def initialize(sql, statement)
3
10
  expect! statement => SQLite3::Statement
4
11
 
5
12
  @sql, @statement = sql, statement
13
+ @parameters = @sql.scan(/:([a-z]+)/).map(&:first).map(&:to_sym)
14
+ end
15
+
16
+ def destructive?
17
+ @sql !~ /\A\S*SELECT/i
6
18
  end
7
19
 
8
20
  def run(*args)
9
- # STDERR.puts "Q: #{@sql} #{args.map(&:inspect).join(", ")}"
21
+ if parameters.length > 0
22
+ named_args = {}
23
+
24
+ if args.last.is_a?(Hash)
25
+ args.pop.each do |name, value|
26
+ named_args[name.to_sym] = value
27
+ end
28
+ end
29
+
30
+ missing = parameters - named_args.keys
31
+ unless missing.empty?
32
+ raise SQLite3::MissingParameters, "Missing parameter(s): #{missing.inspect}"
33
+ end
34
+
35
+ named_args = named_args.select do |name, value|
36
+ parameters.include?(name)
37
+ end
38
+ args << named_args
39
+ end
40
+
10
41
  @statement.execute *args
11
42
  end
12
43
 
@@ -44,6 +75,8 @@ class SQLite3::Query
44
75
  { cols: cols, rows: rows }
45
76
  end
46
77
 
78
+ private
79
+
47
80
  def convert_record(record, cols)
48
81
  values = cols.map do |col|
49
82
  id, type = col.values_at(:id, :type)
@@ -30,7 +30,7 @@ benchmark "Building metric_system" do
30
30
  MetricSystem.transaction do
31
31
  1.upto(TICKS_PER_DAY) do |step|
32
32
  time = midnight + distance * step
33
- STDERR.print "."
33
+ # STDERR.print "."
34
34
  MetricSystem.count "clicks", 1, time
35
35
  end
36
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metric_system
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - radiospiel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-12 00:00:00.000000000 Z
11
+ date: 2014-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: expectation