protor 0.0.11 → 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.
- checksums.yaml +4 -4
- data/README.md +14 -11
- data/lib/protor.rb +48 -25
- data/lib/protor/entry.rb +66 -0
- data/lib/protor/entry_family.rb +25 -0
- data/lib/protor/logger_client.rb +16 -0
- data/lib/protor/registry.rb +53 -39
- data/lib/protor/udp_client.rb +31 -0
- data/lib/protor/udp_formatter.rb +50 -0
- data/lib/protor/version.rb +2 -2
- metadata +7 -8
- data/lib/protor/accumulator.rb +0 -38
- data/lib/protor/client.rb +0 -50
- data/lib/protor/configuration.rb +0 -23
- data/lib/protor/error.rb +0 -3
- data/lib/protor/observer.rb +0 -47
- data/lib/protor/payload.rb +0 -106
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 792b0db1c9b32cc19645c2c08afc39a5446b5834
|
4
|
+
data.tar.gz: f2cdf2b5eba5ec663611a0718f4c6c7fc5d7732c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d551325d26dc6e8f62bd6670feb85ac1f66ef49a3a917113d014612da99770197da1f5bf6d5a6890ba046f7ec675771d3c38da50408c8d4822e6fadb769a8190
|
7
|
+
data.tar.gz: fd9e321c2650a27e2b8b343972157a9f1e5dabdac4f3c32e4d04f9db3dd80c9830e9c7bdf12289d4de1643ea59191d4fd9920cacba98b7dfcf149b7dce4f08f1
|
data/README.md
CHANGED
@@ -16,36 +16,39 @@ bundle install
|
|
16
16
|
It automatically aggregate value
|
17
17
|
|
18
18
|
````ruby
|
19
|
-
|
20
|
-
|
19
|
+
protor.counter(:counter, 1, {label1: 1}) # value => 1
|
20
|
+
protor.counter(:counter, 1, {label1: 1}) # value => 2
|
21
21
|
````
|
22
22
|
### Gauge
|
23
23
|
It automatically replace value
|
24
24
|
````ruby
|
25
|
-
|
26
|
-
|
25
|
+
protor.gauge(:gauge, 50) # value 50
|
26
|
+
protor.gauge(:gauge, 20) # value 20
|
27
27
|
````
|
28
28
|
|
29
29
|
### Histogram
|
30
30
|
It save all observed values
|
31
31
|
````ruby
|
32
|
-
|
33
|
-
|
32
|
+
protor.histogram(:histogram, 10, {label1: 1}, [1,2,3,4]) # observed value [10]
|
33
|
+
protor.histogram(:histogram, 2, {label1: 1}, [1,2,3,4]( # observed value [10,2]
|
34
34
|
````
|
35
35
|
|
36
36
|
### Publish
|
37
37
|
To publish all saved metrics to aggregator
|
38
38
|
````ruby
|
39
|
-
|
39
|
+
protor.publish
|
40
40
|
````
|
41
41
|
|
42
42
|
## Configuration
|
43
43
|
To configure protor:
|
44
44
|
````ruby
|
45
|
-
Protor.
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
$protor = Protor.new do |conf|
|
46
|
+
conf[:client] = :udp # valid option :udp and :logger, use :logger to print into a Logger
|
47
|
+
conf[:host] = 'localhost' # prometheus_aggregator host
|
48
|
+
conf[:port] = 10601 # prometheus_aggregator port
|
49
|
+
conf[:logger] = Rails.logger # logger to be used by protor
|
50
|
+
conf[:packet_size] = 56_607 # max udp packet buffer
|
51
|
+
conf[:formatter] = :udp # valid option only :udp, format to send
|
49
52
|
end
|
50
53
|
````
|
51
54
|
|
data/lib/protor.rb
CHANGED
@@ -1,50 +1,73 @@
|
|
1
1
|
require 'monitor'
|
2
2
|
|
3
|
-
require_relative 'protor/
|
4
|
-
require_relative 'protor/
|
5
|
-
require_relative 'protor/
|
3
|
+
require_relative 'protor/udp_formatter'
|
4
|
+
require_relative 'protor/udp_client'
|
5
|
+
require_relative 'protor/logger_client'
|
6
6
|
require_relative 'protor/registry'
|
7
7
|
require_relative 'protor/version'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
end
|
9
|
+
class Protor
|
10
|
+
include MonitorMixin
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
DEFAULT_CONFIG = {
|
13
|
+
client: :udp,
|
14
|
+
formatter: :udp,
|
15
|
+
host: 'localhost',
|
16
|
+
port: 10601,
|
17
|
+
packet_size: 56_607
|
18
|
+
}
|
19
|
+
|
20
|
+
attr_reader :config, :registry
|
17
21
|
|
18
|
-
def
|
19
|
-
|
22
|
+
def initialize(&block)
|
23
|
+
super(&block)
|
24
|
+
|
25
|
+
@config = DEFAULT_CONFIG.dup
|
26
|
+
@registry = Registry.new
|
27
|
+
yield(config) if block_given?
|
20
28
|
end
|
21
29
|
|
22
30
|
def publish
|
23
|
-
|
24
|
-
|
25
|
-
client.publish(registry)
|
26
|
-
reset
|
27
|
-
end
|
28
|
-
end
|
31
|
+
safely{ client.publish(registry) }
|
32
|
+
logger.debug("publish") if logger
|
29
33
|
end
|
30
34
|
|
31
35
|
[:counter, :gauge, :histogram].each do |method|
|
32
|
-
define_method method do |*args
|
33
|
-
|
36
|
+
define_method method do |*args|
|
37
|
+
safely{ registry.public_send(method, *args) }
|
38
|
+
logger.debug("#{method} #{args}") if logger
|
34
39
|
end
|
35
40
|
end
|
36
41
|
|
37
42
|
private
|
38
43
|
|
44
|
+
def safely(&block)
|
45
|
+
synchronize(&block)
|
46
|
+
rescue StandardError => err
|
47
|
+
logger.error(err) if logger
|
48
|
+
raise err unless silent
|
49
|
+
end
|
50
|
+
|
39
51
|
def client
|
40
|
-
@client ||=
|
52
|
+
@client ||=
|
53
|
+
case config[:client]
|
54
|
+
when :udp; UDPClient.new(config[:host], config[:port], formatter)
|
55
|
+
when :logger; LoggerClient.new(logger, formatter)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def formatter
|
60
|
+
@formatter ||=
|
61
|
+
case config[:formatter]
|
62
|
+
when :udp; UDPFormatter.new(config[:packet_size])
|
63
|
+
end
|
41
64
|
end
|
42
65
|
|
43
|
-
def
|
44
|
-
|
66
|
+
def logger
|
67
|
+
config[:logger]
|
45
68
|
end
|
46
69
|
|
47
|
-
def
|
48
|
-
|
70
|
+
def silent
|
71
|
+
config[:silent]
|
49
72
|
end
|
50
73
|
end
|
data/lib/protor/entry.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
class Protor
|
2
|
+
class Entry
|
3
|
+
attr_reader :name, :type, :value, :labels, :additional
|
4
|
+
attr_writer :value
|
5
|
+
|
6
|
+
VALID_NAME = /^[a-zA-Z_:][a-zA-Z0-9_:]+$/
|
7
|
+
VALID_TYPE = [:c, :g, :h]
|
8
|
+
VALID_LABEL_NAME = /^[a-zA-Z_][a-zA-Z0-9_]*$/
|
9
|
+
VALID_LABEL_VALUE = /^[^;|=]+$/
|
10
|
+
|
11
|
+
def initialize(name, type, value, labels = nil, additional = nil)
|
12
|
+
@name = name.to_s
|
13
|
+
@type = type
|
14
|
+
@value = value
|
15
|
+
@labels = labels || {}
|
16
|
+
@additional = additional || []
|
17
|
+
|
18
|
+
verify
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def verify
|
24
|
+
raise InvalidNameError, name unless name =~ VALID_NAME
|
25
|
+
raise InvalidTypeError, type unless VALID_TYPE.include?(type)
|
26
|
+
labels.each do |k, v|
|
27
|
+
raise InvalidLabelNameError, labels unless k =~ VALID_LABEL_NAME
|
28
|
+
raise InvalidLabelValueError, labels unless v =~ VALID_LABEL_VALUE
|
29
|
+
end
|
30
|
+
additional.each do |a|
|
31
|
+
raise InvalidAdditionalError, additional unless a.is_a?(Numeric)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
class InvalidNameError < StandardError
|
38
|
+
def initialize(message)
|
39
|
+
super("Invalid name #{message}, please satisfy /^[a-zA-Z_:][a-zA-Z0-9_:]+$/")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class InvalidTypeError < StandardError
|
44
|
+
def initialize(message)
|
45
|
+
super("Invalid type #{message}, allowed types are [c, g, h]")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class InvalidLabelNameError < StandardError
|
50
|
+
def initialize(message)
|
51
|
+
super("Invalid label name #{message}, please satisfy /^[a-zA-Z_][a-zA-Z0-9_]*$/")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class InvalidLabelValueError < StandardError
|
56
|
+
def initialize(message)
|
57
|
+
super("Invalid label value #{message}, please satisfy /^[^;|=\s]+$/")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class InvalidAdditionalError < StandardError
|
62
|
+
def initialize(message)
|
63
|
+
super("Invalid additional {message}, additional must be numbers")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Protor
|
2
|
+
class EntryFamily
|
3
|
+
attr_reader :name, :type, :data
|
4
|
+
|
5
|
+
def initialize(name, type)
|
6
|
+
@name = name
|
7
|
+
@type = type
|
8
|
+
@data = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def []=(label, value)
|
12
|
+
data[label] = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](label)
|
16
|
+
data[label]
|
17
|
+
end
|
18
|
+
|
19
|
+
def each
|
20
|
+
return unless block_given?
|
21
|
+
|
22
|
+
data.each_value{ |d| yield(d) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Protor
|
2
|
+
class LoggerClient
|
3
|
+
attr_reader :logger, :formatter
|
4
|
+
|
5
|
+
def initialize(logger, formatter)
|
6
|
+
@logger = logger
|
7
|
+
@formatter = formatter
|
8
|
+
end
|
9
|
+
|
10
|
+
def publish(payload)
|
11
|
+
formatter.format(payload) do |msg|
|
12
|
+
logger.info(msg)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/protor/registry.rb
CHANGED
@@ -1,70 +1,84 @@
|
|
1
|
-
require_relative '
|
2
|
-
require_relative '
|
3
|
-
require_relative 'observer'
|
1
|
+
require_relative 'entry'
|
2
|
+
require_relative 'entry_family'
|
4
3
|
|
5
|
-
|
4
|
+
class Protor
|
6
5
|
class Registry
|
7
|
-
|
6
|
+
attr_reader :families
|
8
7
|
|
9
|
-
|
10
|
-
|
8
|
+
DEFAULT_BUCKET = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10].freeze
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@families = {}
|
11
12
|
end
|
12
13
|
|
13
14
|
def counter(metric_name, value, labels = {})
|
14
|
-
|
15
|
-
|
15
|
+
labels = stringify(labels)
|
16
|
+
fam = family(metric_name, :counter)
|
17
|
+
|
18
|
+
if (entry = fam[labels])
|
19
|
+
entry.value += value
|
20
|
+
else
|
21
|
+
fam[labels] = Entry.new(metric_name, :c, value, labels)
|
22
|
+
end
|
16
23
|
end
|
17
24
|
|
18
25
|
def gauge(metric_name, value, labels = {})
|
19
|
-
|
20
|
-
|
26
|
+
labels = stringify(labels)
|
27
|
+
fam = family(metric_name, :gauge)
|
28
|
+
|
29
|
+
if (entry = fam[labels])
|
30
|
+
entry.value = value
|
31
|
+
else
|
32
|
+
fam[labels] = Entry.new(metric_name, :g, value, labels)
|
33
|
+
end
|
21
34
|
end
|
22
35
|
|
23
|
-
def histogram(metric_name, value, labels = {}, buckets =
|
24
|
-
|
25
|
-
|
36
|
+
def histogram(metric_name, value, labels = {}, buckets = DEFAULT_BUCKET)
|
37
|
+
labels = stringify(labels)
|
38
|
+
fam = family(metric_name, :histogram)
|
39
|
+
|
40
|
+
entry = Entry.new(metric_name, :h, value, labels, buckets)
|
41
|
+
if (array = fam[labels])
|
42
|
+
array << entry
|
43
|
+
else
|
44
|
+
fam[labels] = [ entry ]
|
45
|
+
end
|
26
46
|
end
|
27
47
|
|
28
48
|
def each
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
payload = Payload.new options.max_packet_size
|
35
|
-
payload.add(data)
|
49
|
+
families.each_value do |family|
|
50
|
+
if family.type == :histogram
|
51
|
+
family.each{ |arr| arr.each{ |e| yield(e) }}
|
52
|
+
else
|
53
|
+
family.each{ |e| yield(e) }
|
36
54
|
end
|
37
55
|
end
|
38
|
-
|
39
|
-
yield payload.to_s
|
40
56
|
end
|
41
57
|
|
42
58
|
def empty?
|
43
|
-
|
59
|
+
families.empty?
|
44
60
|
end
|
45
61
|
|
46
62
|
private
|
47
63
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
def counter_data
|
55
|
-
@counter ||= Accumulator.new(:counter)
|
64
|
+
def stringify(labels)
|
65
|
+
{}.tap do |h|
|
66
|
+
labels.each{ |k, v| h[k.to_s] = v.to_s }
|
67
|
+
end
|
56
68
|
end
|
57
69
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
70
|
+
def family(name, type)
|
71
|
+
families[name] ||= EntryFamily.new(name, type)
|
72
|
+
family = families[name]
|
73
|
+
raise IncompatibleTypeError.new(name, family.type, type) if family.type != type
|
61
74
|
|
62
|
-
|
63
|
-
@histogram ||= Observer.new(:histogram)
|
75
|
+
return family
|
64
76
|
end
|
77
|
+
end
|
65
78
|
|
66
|
-
|
67
|
-
|
79
|
+
class IncompatibleTypeError < StandardError
|
80
|
+
def initialize(name, previous, now)
|
81
|
+
super("Incompatible type for metric #{name}, previously it was a #{previous}, now it is a #{now}")
|
68
82
|
end
|
69
83
|
end
|
70
84
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
class Protor
|
4
|
+
class UDPClient
|
5
|
+
attr_reader :host, :port, :formatter, :connection
|
6
|
+
|
7
|
+
def initialize(host, port, formatter)
|
8
|
+
@port = port
|
9
|
+
@host = host
|
10
|
+
@formatter = formatter
|
11
|
+
end
|
12
|
+
|
13
|
+
def publish(payload)
|
14
|
+
connect do |conn|
|
15
|
+
formatter.format(payload) do |msg|
|
16
|
+
conn.send(msg, 0)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def connect
|
24
|
+
connection = UDPSocket.new
|
25
|
+
connection.connect(host, port)
|
26
|
+
yield(connection)
|
27
|
+
ensure
|
28
|
+
connection.close unless connection.closed?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Protor
|
2
|
+
class UDPFormatter
|
3
|
+
attr_reader :max_packet_size
|
4
|
+
|
5
|
+
LF = "\n".freeze
|
6
|
+
|
7
|
+
def initialize(max_packet_size)
|
8
|
+
@max_packet_size = max_packet_size
|
9
|
+
end
|
10
|
+
|
11
|
+
def format(registry)
|
12
|
+
return unless block_given?
|
13
|
+
|
14
|
+
str = ""
|
15
|
+
size = 0
|
16
|
+
registry.each do |entry|
|
17
|
+
line = stringify(entry)
|
18
|
+
|
19
|
+
if size + line.size > max_packet_size
|
20
|
+
yield(str)
|
21
|
+
str = line
|
22
|
+
size = line.size
|
23
|
+
else
|
24
|
+
str << line
|
25
|
+
size += line.size
|
26
|
+
end
|
27
|
+
end
|
28
|
+
yield(str)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def stringify(entry)
|
34
|
+
"#{ entry.name }|#{ entry.type }|".tap do |str|
|
35
|
+
str << "#{ additional_string(entry.additional) }|" unless entry.additional.empty?
|
36
|
+
str << "#{ labels_string(entry.labels) }|" unless entry.labels.empty?
|
37
|
+
str << "#{ entry.value }#{LF}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def labels_string(labels)
|
42
|
+
labels.map{ |k, v| "#{k}=#{v}" }.join(';')
|
43
|
+
end
|
44
|
+
|
45
|
+
def additional_string(additional)
|
46
|
+
additional.join(';')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
data/lib/protor/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = '0.0
|
1
|
+
class Protor
|
2
|
+
VERSION = '0.1.0'
|
3
3
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roland Rinfandi Utama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -19,13 +19,12 @@ extra_rdoc_files: []
|
|
19
19
|
files:
|
20
20
|
- README.md
|
21
21
|
- lib/protor.rb
|
22
|
-
- lib/protor/
|
23
|
-
- lib/protor/
|
24
|
-
- lib/protor/
|
25
|
-
- lib/protor/error.rb
|
26
|
-
- lib/protor/observer.rb
|
27
|
-
- lib/protor/payload.rb
|
22
|
+
- lib/protor/entry.rb
|
23
|
+
- lib/protor/entry_family.rb
|
24
|
+
- lib/protor/logger_client.rb
|
28
25
|
- lib/protor/registry.rb
|
26
|
+
- lib/protor/udp_client.rb
|
27
|
+
- lib/protor/udp_formatter.rb
|
29
28
|
- lib/protor/version.rb
|
30
29
|
homepage: https://github.com/rolandhawk/protor-ruby
|
31
30
|
licenses:
|
data/lib/protor/accumulator.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
module Protor
|
2
|
-
class Accumulator
|
3
|
-
def initialize(type)
|
4
|
-
@data = {}
|
5
|
-
@type = type
|
6
|
-
end
|
7
|
-
|
8
|
-
def inc(metric_name, value, labels = {})
|
9
|
-
data[metric_name] ||= Hash.new(0)
|
10
|
-
data[metric_name][labels] += value
|
11
|
-
end
|
12
|
-
|
13
|
-
def set(metric_name, value, labels = {})
|
14
|
-
data[metric_name] ||= Hash.new(0)
|
15
|
-
data[metric_name][labels] = value
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_a
|
19
|
-
array = []
|
20
|
-
|
21
|
-
data.each do |metric_name, values|
|
22
|
-
values.each do |labels, value|
|
23
|
-
array << { metric_name: metric_name, labels: labels, value: value, type: type }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
return array
|
28
|
-
end
|
29
|
-
|
30
|
-
def empty?
|
31
|
-
data.empty?
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
attr_reader :type, :data
|
37
|
-
end
|
38
|
-
end
|
data/lib/protor/client.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
|
3
|
-
module Protor
|
4
|
-
class Client
|
5
|
-
def initialize(configuration)
|
6
|
-
@options = configuration
|
7
|
-
@retries = 0
|
8
|
-
end
|
9
|
-
|
10
|
-
def publish(payload)
|
11
|
-
connect
|
12
|
-
payload.each do |message|
|
13
|
-
send(message)
|
14
|
-
end
|
15
|
-
rescue Errno::EPERM, Errno::ECONNREFUSED => e
|
16
|
-
options.logger.error(e)
|
17
|
-
ensure
|
18
|
-
close
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
attr_reader :options, :connection, :retries
|
24
|
-
|
25
|
-
def send(message)
|
26
|
-
connection.send(message, 0)
|
27
|
-
rescue Errno::EPERM => exception
|
28
|
-
retries += 1
|
29
|
-
if retries <= 3
|
30
|
-
refresh && retry
|
31
|
-
else
|
32
|
-
raise exception
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def connect
|
37
|
-
@connection = UDPSocket.new
|
38
|
-
@connection.connect(options.host, options.port)
|
39
|
-
end
|
40
|
-
|
41
|
-
def refresh
|
42
|
-
close
|
43
|
-
connect
|
44
|
-
end
|
45
|
-
|
46
|
-
def close
|
47
|
-
connection.close unless connection.closed?
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
data/lib/protor/configuration.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'logger'
|
2
|
-
|
3
|
-
module Protor
|
4
|
-
class Configuration
|
5
|
-
attr_writer :host, :port, :max_packet_size, :logger
|
6
|
-
|
7
|
-
def host
|
8
|
-
@host ||= 'localhost'
|
9
|
-
end
|
10
|
-
|
11
|
-
def port
|
12
|
-
@port ||= 10601
|
13
|
-
end
|
14
|
-
|
15
|
-
def max_packet_size
|
16
|
-
@max_packet_size ||= 56_607
|
17
|
-
end
|
18
|
-
|
19
|
-
def logger
|
20
|
-
@logger ||= Logger.new(STDOUT)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/protor/error.rb
DELETED
data/lib/protor/observer.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module Protor
|
2
|
-
class Observer
|
3
|
-
def initialize(type)
|
4
|
-
@data = {}
|
5
|
-
@type = type
|
6
|
-
end
|
7
|
-
|
8
|
-
def observe(metric_name, value, labels = {}, additional = [])
|
9
|
-
data[metric_name] ||= { values: {} }
|
10
|
-
data[metric_name][:values][labels] ||= []
|
11
|
-
|
12
|
-
data[metric_name][:additional] = additional
|
13
|
-
data[metric_name][:values][labels] << value
|
14
|
-
end
|
15
|
-
|
16
|
-
def to_a
|
17
|
-
array = []
|
18
|
-
|
19
|
-
data.each do |metric_name, values|
|
20
|
-
first = true
|
21
|
-
values[:values].each do |labels, value|
|
22
|
-
value.each do |val|
|
23
|
-
array << {
|
24
|
-
metric_name: metric_name,
|
25
|
-
labels: labels,
|
26
|
-
value: val,
|
27
|
-
additional: values[:additional],
|
28
|
-
first: first,
|
29
|
-
type: type
|
30
|
-
}
|
31
|
-
first = false
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
return array
|
37
|
-
end
|
38
|
-
|
39
|
-
def empty?
|
40
|
-
data.empty?
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
attr_reader :data, :type
|
46
|
-
end
|
47
|
-
end
|
data/lib/protor/payload.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
module Protor
|
2
|
-
class Payload
|
3
|
-
|
4
|
-
Lf = "\n".freeze
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(max_packet_size)
|
8
|
-
@max_packet_size = max_packet_size
|
9
|
-
@lines = []
|
10
|
-
@total_size = 0
|
11
|
-
end
|
12
|
-
|
13
|
-
def add(data)
|
14
|
-
data = data.dup
|
15
|
-
data[:first] = true if lines.empty?
|
16
|
-
|
17
|
-
if data[:labels]
|
18
|
-
data[:labels].delete_if{ |k, v| v.to_s.empty? }
|
19
|
-
else
|
20
|
-
data[:labels] = {}
|
21
|
-
end
|
22
|
-
|
23
|
-
return false if packet_overflow?(data)
|
24
|
-
|
25
|
-
self.common_labels = data[:labels]
|
26
|
-
@total_size += data_size(data)
|
27
|
-
@lines << data
|
28
|
-
end
|
29
|
-
|
30
|
-
def to_s
|
31
|
-
str = first_line
|
32
|
-
lines.each do |data|
|
33
|
-
line = template(data)
|
34
|
-
str << "#{line}#{Lf}"
|
35
|
-
end
|
36
|
-
|
37
|
-
return str
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
attr_reader :common_labels, :lines, :total_size, :max_packet_size
|
43
|
-
|
44
|
-
def data_size(data)
|
45
|
-
size = 3
|
46
|
-
[:metric_name, :value].each do |key|
|
47
|
-
size += data[key].to_s.size
|
48
|
-
end
|
49
|
-
|
50
|
-
size += labels_string(data[:labels]).size + 1 if data[:labels]
|
51
|
-
|
52
|
-
size += additional_string(data[:additional]).size + 1 if data[:first] && data[:additional]
|
53
|
-
|
54
|
-
return size
|
55
|
-
end
|
56
|
-
|
57
|
-
def common_labels=(labels = {})
|
58
|
-
@common_labels ||= labels.dup
|
59
|
-
intersect(common_labels, labels)
|
60
|
-
@common_labels.keep_if{ |k, v| labels.key?(k) }
|
61
|
-
end
|
62
|
-
|
63
|
-
def first_line
|
64
|
-
if !common_labels || common_labels.empty?
|
65
|
-
""
|
66
|
-
else
|
67
|
-
"#{labels_string(common_labels)}#{Lf}"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def template(data)
|
72
|
-
labels = exclude_common(data[:labels])
|
73
|
-
|
74
|
-
"#{ data[:metric_name] }|#{ data[:type][0] }|".tap do |str|
|
75
|
-
str << "#{ additional_string(data[:additional]) }|" if data[:first] && data[:additional]
|
76
|
-
str << "#{ labels_string(labels) }|" unless labels.empty?
|
77
|
-
str << "#{ data[:value] }"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def labels_string(labels)
|
82
|
-
labels.map{ |k, v| "#{k}=#{v}" }.join(';')
|
83
|
-
end
|
84
|
-
|
85
|
-
def additional_string(additional)
|
86
|
-
additional.join(';')
|
87
|
-
end
|
88
|
-
|
89
|
-
def intersect(a, b)
|
90
|
-
a.keep_if{ |k, v| b[k] == v }
|
91
|
-
end
|
92
|
-
|
93
|
-
def exclude_common(labels)
|
94
|
-
labels.keep_if{ |k, v| !common_labels[k] }
|
95
|
-
end
|
96
|
-
|
97
|
-
def packet_overflow?(data)
|
98
|
-
backup = common_labels && common_labels.dup || data[:labels]
|
99
|
-
intersect(backup, data[:labels])
|
100
|
-
size = data_size(data)
|
101
|
-
|
102
|
-
total_size + size - (labels_string(backup).size * lines.size) > max_packet_size
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|