metrics-capacitor 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2ba1e0c3121bf7c479cd51c71a5928f5d1cceb52
4
+ data.tar.gz: 65a6d6e97f87fb96d52e5f1e061a82fb28f70f18
5
+ SHA512:
6
+ metadata.gz: 3c033eb3cd61172b26aebc36f54c6248621128e63864e10e6396caec1f52eb75b358694fc75bb0271eca5b78769ad725dc55cb97ace644b376caf7b850fb66c3
7
+ data.tar.gz: 376e4a97aa8714174c5a4f2ad80409c44253643f7aee37a5da04d9b1037c9167f8ed3ad950330d73ca850baf5734538735dfde6a464d8ace55825acf6d63c369
@@ -0,0 +1,3 @@
1
+ #!/bin/env/ruby
2
+ require 'metrics-capacitor/cli'
3
+ MetricsCapacitor::CLI.start ARGV
@@ -0,0 +1,3 @@
1
+ module MetricsCapacitor; end
2
+ require_relative 'metrics-capacitor/model'
3
+ require_relative 'metrics-capacitor/config'
@@ -0,0 +1,69 @@
1
+ require 'thor'
2
+
3
+ module MetricsCapacitor
4
+ class CLI < Thor
5
+ package_name 'Metrics Capacitor'
6
+
7
+ desc 'engine', 'Start the engine :-)'
8
+ long_desc <<-LONGDESC
9
+ Usage: metrics-capacitor engine
10
+
11
+ all options are defined in /etc/metrics-capacitor.yaml
12
+ LONGDESC
13
+ def engine
14
+ require 'metrics-capacitor/engine'
15
+ Engine.new.run!
16
+ end
17
+
18
+ desc 'graphite', 'Send Graphite data'
19
+ long_desc <<-LONGDESC
20
+ This triggers Graphite metrics transformer. The data is awaited on STDIN.
21
+ AVOID EMPTY LINES AT THE END OF OUTPUT AT ALL COSTS
22
+
23
+ TAG_MAP option is mandatory and controls the behavior of graphite path
24
+ transformation into Elasticsearch fields, we call @tags and @name. Tag map must
25
+ correspond to the graphite data path.
26
+
27
+ There are 3 acceptable values: Integer (any sane positive whole number),
28
+ String (anything that Ruby parser can't convert to Integer) and special string `_`,
29
+ Integers are used as an array field indexes that are joined by `:` into @name field.
30
+ Strings are used as as @tags subfield names. And finally `_` is used if you want to
31
+ ignore the value on the position.
32
+
33
+ EXAMPLE:
34
+
35
+ Graphite path `server.node10.redis.hz` and TAG_MAP (-m) `_.host.0.1`
36
+ result metric with @name: `redis:hz` and @tags: `{ host: node10 }`
37
+
38
+ LONGDESC
39
+ option :tag_map, type: :string, required: true, aliases: '-m'
40
+ option :add_tag, type: :hash, aliases: '-t'
41
+ option :debug, type: :boolean, aliases: '-d'
42
+ option :counter_match, type: :string
43
+ def graphite
44
+ require 'metrics-capacitor/utils/graphite'
45
+ Utils::Graphite.new(options).run!
46
+ end
47
+
48
+ desc 'status', 'Report the state (TODO)'
49
+ def status
50
+ # TODO ...
51
+ end
52
+
53
+ desc 'aggregate', 'Manually trigger aggregator run (TODO)'
54
+ def aggregate
55
+ # TODO ...
56
+ end
57
+
58
+ desc 'expunge', 'Expunge old data (TODO)'
59
+ def expunge
60
+ # TODO ...
61
+ end
62
+
63
+ desc 'optimize', 'Optimize ElasticSearch indices (TODO)'
64
+ def optimize
65
+ # TODO ...
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,61 @@
1
+ require 'yaml'
2
+ class ::Hash
3
+ def deep_merge(second)
4
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
5
+ self.merge(second, &merger)
6
+ end
7
+ end
8
+
9
+ module MetricsCapacitor
10
+ module Config
11
+
12
+ extend self
13
+ attr_reader :_cfg
14
+
15
+ def load!
16
+ @_cfg = {
17
+ syslog: false,
18
+ debug: false,
19
+ redis: {
20
+ url: 'redis://127.0.0.1:6379/0',
21
+ timeout: 5,
22
+ },
23
+ elasticsearch: {
24
+ urls: ['http://localhost:9200/'],
25
+ index: 'metrics',
26
+ timeout: 10,
27
+ connections: 2,
28
+ },
29
+ scrubber: {
30
+ threads: 4,
31
+ processes: 2,
32
+ retry: 3,
33
+ tags: {}
34
+ },
35
+ writer: {
36
+ processes: 2,
37
+ doc_type: 'actual',
38
+ bulk_max: 5000,
39
+ bulk_wait: 10,
40
+ ttl: '1w'
41
+ },
42
+ aggregator: {
43
+ doc_type: 'aggregated',
44
+ aggregate_by: 600, # seconds
45
+ optimize_indices: true,
46
+ }
47
+ }
48
+ @_cfg = @_cfg.deep_merge YAML.load_file('/etc/metrics-capacitor.yaml') if File.exists? '/etc/metrics-capacitor.yaml'
49
+ end
50
+
51
+ def method_missing (name, *args, &block)
52
+ return @_cfg[name.to_sym] if @_cfg[name.to_sym] != nil
53
+ fail(NoMethodError, "Unknown configuration section Config.#{name}", caller)
54
+ rescue NoMethodError => e
55
+ $stderr.puts "ERROR config: #{e.class}: #{e.message}"
56
+ $stderr.puts e.backtrace.map { |l| "ERROR config: #{l}\n" }.join
57
+ exit! 1
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,6 @@
1
+ require 'msgpack'
2
+ require 'json'
3
+ require 'forwardable'
4
+ require_relative 'model/metric'
5
+ require_relative 'model/metrics'
6
+ require_relative 'model/index_template'
@@ -0,0 +1,59 @@
1
+ module MetricsCapacitor
2
+ module Model
3
+ INDEX_TEMPLATE = {
4
+ template: "metrics*",
5
+ settings: {
6
+ number_of_shards: 2
7
+ },
8
+ mappings: {
9
+ '_default_' => {
10
+ '_source' => { 'enabled' => true },
11
+ 'dynamic_templates' => [
12
+ {
13
+ 'values' => {
14
+ 'mapping' => {
15
+ 'index' => 'not_analyzed',
16
+ 'type' => 'float'
17
+ },
18
+ 'path_match' => '@values.*'
19
+ }
20
+ },
21
+ {
22
+ 'tags' => {
23
+ 'mapping' => {
24
+ 'index' => 'not_analyzed',
25
+ 'type' => 'string',
26
+ 'copy_to' => '@uniq'
27
+ },
28
+ 'path_match' => '@tags.*',
29
+ 'path_unmatch' => '@tags._counter'
30
+ }
31
+ }
32
+ ],
33
+ 'properties' => {
34
+ '@uniq' => {
35
+ 'type' => 'string',
36
+ 'index' => 'not_analyzed'
37
+ },
38
+ '@name' => {
39
+ 'type' => 'string',
40
+ 'index' => 'not_analyzed',
41
+ 'copy_to' => '@uniq'
42
+ },
43
+ '@timestamp' => {
44
+ 'type' => 'date'
45
+ },
46
+ '@tags' => {
47
+ 'properties' => {
48
+ '_counter' => {
49
+ 'type' => 'boolean',
50
+ 'index' => 'not_analyzed'
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ end
59
+ end
@@ -0,0 +1,67 @@
1
+ module MetricsCapacitor
2
+ module Model
3
+ class Metric
4
+ extend Forwardable
5
+
6
+ def_delegators :@metric, :[], :[]=, :merge, :map
7
+
8
+ def initialize(data = {})
9
+ @metric = data if data.class == Hash
10
+ @metric ||= JSON.parse(data, symbolize_names: true)
11
+ end
12
+
13
+ def to_elastic
14
+ { index: {
15
+ data: {
16
+ :@name => name,
17
+ :@timestamp => timestamp(:ms),
18
+ :@tags => tags,
19
+ :@values => values
20
+ }
21
+ }
22
+ }
23
+ end
24
+
25
+ def to_redis
26
+ @metric.to_json
27
+ end
28
+
29
+ def name
30
+ @metric[:name].to_s
31
+ end
32
+
33
+ def tags
34
+ return @metric[:tags] if ( @metric[:tags] || @metric[:tags].empty? )
35
+ { capacitor: 'untagged' }
36
+ end
37
+
38
+ def values
39
+ case @metric[:values]
40
+ when Hash
41
+ return @metric[:values]
42
+ when Integer
43
+ return { value: @metric[:values].to_f }
44
+ when Float
45
+ return { value: @metric[:values] }
46
+ else
47
+ return { value: 0.0 }
48
+ end
49
+ end
50
+
51
+ def timestamp(scale = :ms)
52
+ m = case scale
53
+ when :ms
54
+ 1000.0
55
+ when :us
56
+ 1_000_000.0
57
+ when :ns
58
+ 1_000_000_000.0
59
+ else
60
+ 1.0
61
+ end
62
+ return (Time.now.to_f * m).to_i.to_s unless @metric[:timestamp]
63
+ (Time.at(@metric[:timestamp]).to_f * m).to_i.to_s
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,25 @@
1
+ module MetricsCapacitor
2
+ module Model
3
+ class Metrics
4
+ extend Forwardable
5
+
6
+ def_delegators :@metrics, :slice, :slice!, :map, :each, :empty?, :length, :<<
7
+
8
+ def initialize(data = [])
9
+ @metrics = data.map { |m| Metric.new(m) }
10
+ end
11
+
12
+ def proc_by_slices!(n)
13
+ @metrics.each_slice(n) { |s| yield Metrics.new(s) }
14
+ end
15
+
16
+ def to_elastic
17
+ @metrics.map(&:to_elastic)
18
+ end
19
+
20
+ def to_redis
21
+ @metrics.map(&:to_redis)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module MetricsCapacitor
2
+ class Status; end
3
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metrics-capacitor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Radek 'blufor' Slavicinsky
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.19'
20
+ - - '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.19.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.19'
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.19.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: msgpack
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: '0.7'
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: 0.7.6
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ version: '0.7'
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: 0.7.6
53
+ description: Metrics igenstion service with ElasticSearch as storage
54
+ email: radek@blufor.cz
55
+ executables:
56
+ - metrics-capacitor
57
+ extensions: []
58
+ extra_rdoc_files: []
59
+ files:
60
+ - bin/metrics-capacitor
61
+ - lib/metrics-capacitor.rb
62
+ - lib/metrics-capacitor/cli.rb
63
+ - lib/metrics-capacitor/config.rb
64
+ - lib/metrics-capacitor/model.rb
65
+ - lib/metrics-capacitor/model/index_template.rb
66
+ - lib/metrics-capacitor/model/metric.rb
67
+ - lib/metrics-capacitor/model/metrics.rb
68
+ - lib/metrics-capacitor/status.rb
69
+ homepage: https://github.com/metrics-capacitor/metrics-capacitor
70
+ licenses:
71
+ - GPLv3
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '>='
80
+ - !ruby/object:Gem::Version
81
+ version: 2.0.0
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 2.4.8
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Metrics Capacitor
93
+ test_files: []