metric_system 0.1.2 → 0.1.3
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 +4 -4
- data/lib/metric_system.rb +1 -1
- data/lib/metric_system/database.rb +9 -6
- data/lib/metric_system/version.rb +1 -1
- data/lib/metric_system/web.rb +28 -12
- data/lib/metric_system/web/dashboard.erb +3 -7
- data/lib/sqlite3/database_extension.rb +16 -17
- data/lib/sqlite3/query.rb +34 -1
- data/test/benchmark.rb +1 -1
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 3c313b1e1c7d585f73c1210c3fb3bc610268d804
         | 
| 4 | 
            +
              data.tar.gz: 26cf80941ed294412d5afb60e79b883ae13e2fa8
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 1c2b87a70402f5f6090c33f39228c0762777abedbd9f0d27caee1092442a6943a782576a45a48e84b6aec0ce54b4db7080abb9dbbf1a0759575274f0262f847c
         | 
| 7 | 
            +
              data.tar.gz: a8e41c77e9810bed3d53e7bbd6c3e30c167d1ffac75c09d41d7955e6b737534cf2f1d0e618d667e5fd979d0398002caf80fc9730c3a94fa6249cb504aa3ec317
         | 
    
        data/lib/metric_system.rb
    CHANGED
    
    | @@ -23,7 +23,7 @@ module MetricSystem | |
| 23 23 | 
             
              end
         | 
| 24 24 |  | 
| 25 25 | 
             
              extend Forwardable
         | 
| 26 | 
            -
              delegate [:aggregate, :select, :print, :run, :ask | 
| 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 | 
            -
                   | 
| 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 | 
            -
                   | 
| 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 | 
            -
                 | 
| 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 | 
            -
                 | 
| 163 | 
            +
                exec <<-SQL
         | 
| 161 164 | 
             
                  DROP TABLE batch;
         | 
| 162 165 | 
             
                SQL
         | 
| 163 166 | 
             
              end
         | 
    
        data/lib/metric_system/web.rb
    CHANGED
    
    | @@ -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] ||=  | 
| 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 =>  | 
| 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] ||=  | 
| 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
         | 
    
        data/lib/sqlite3/query.rb
    CHANGED
    
    | @@ -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 | 
            -
                 | 
| 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)
         | 
    
        data/test/benchmark.rb
    CHANGED
    
    
    
        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. | 
| 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- | 
| 11 | 
            +
            date: 2014-04-14 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: expectation
         |