tsd_metrics 0.2.0 → 0.2.8
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 +15 -0
- data/.gitignore +23 -0
- data/.travis.yml +13 -0
- data/CONTRIBUTORS.md +10 -0
- data/DEPENDENCIES.md +15 -0
- data/Gemfile +22 -0
- data/LICENSE +158 -0
- data/README.md +182 -0
- data/Rakefile +5 -0
- data/demo.rb +27 -0
- data/doc/QUERY_LOG_FORMAT.md +59 -0
- data/doc/query-log-schema-2c.json +55 -0
- data/doc/query-log-schema-2d.json +69 -0
- data/doc/query-log-schema-2e.json +103 -0
- data/lib/tsd_metrics/async_queue_writer.rb +40 -0
- data/lib/tsd_metrics/counter.rb +43 -0
- data/lib/tsd_metrics/counter_sample.rb +37 -0
- data/lib/tsd_metrics/exceptions.rb +22 -0
- data/lib/tsd_metrics/json_formatting_sink.rb +63 -0
- data/lib/tsd_metrics/metric_builder_for_single_struct_receiver.rb +24 -0
- data/lib/tsd_metrics/queue_writer.rb +24 -0
- data/lib/tsd_metrics/timer.rb +48 -0
- data/lib/tsd_metrics/timer_sample.rb +69 -0
- data/lib/tsd_metrics/tsd_metric.rb +200 -0
- data/lib/tsd_metrics/units.rb +22 -0
- data/lib/tsd_metrics.rb +63 -15
- data/resources/LICENSE +158 -0
- data/spec/integration_spec.rb +84 -0
- data/spec/json_formatter_spec.rb +99 -0
- data/spec/tsd_metric_spec.rb +289 -0
- data/spec/tsd_metrics_spec.rb +22 -0
- data/spec/units_utils_spec.rb +29 -0
- data/tsd_metrics.gemspec +35 -0
- metadata +124 -82
@@ -0,0 +1,103 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
3
|
+
"definitions": {
|
4
|
+
"sampleObject" : {
|
5
|
+
"type": "object",
|
6
|
+
"properties" : {
|
7
|
+
"unit": {
|
8
|
+
"type": "string",
|
9
|
+
"enum": ["nanosecond","microsecond", "millisecond", "second", "minute", "hour", "day", "week", "bit", "byte", "kilobit", "kilobyte", "megabit", "megabyte", "gigabit", "gigabyte", "terabyte", "petabyte"]
|
10
|
+
},
|
11
|
+
"value": {
|
12
|
+
"type": "number"
|
13
|
+
}
|
14
|
+
},
|
15
|
+
"required": ["value"]
|
16
|
+
},
|
17
|
+
"dataElement": {
|
18
|
+
"type": "object",
|
19
|
+
"properties": {
|
20
|
+
"values": {
|
21
|
+
"type": "array",
|
22
|
+
"items": {
|
23
|
+
"$ref": "#/definitions/sampleObject"
|
24
|
+
}
|
25
|
+
}
|
26
|
+
},
|
27
|
+
"required": ["values"]
|
28
|
+
},
|
29
|
+
"metricsList": {
|
30
|
+
"type": "object",
|
31
|
+
"additionalProperties": {
|
32
|
+
"$ref": "#/definitions/dataElement"
|
33
|
+
}
|
34
|
+
},
|
35
|
+
"data": {
|
36
|
+
"type": "object",
|
37
|
+
"properties":{
|
38
|
+
"annotations": {
|
39
|
+
"type":"object",
|
40
|
+
"properties": {
|
41
|
+
"finalTimestamp": {
|
42
|
+
"type":"string",
|
43
|
+
"format": "date-time"
|
44
|
+
},
|
45
|
+
"initTimestamp": {
|
46
|
+
"type":"string",
|
47
|
+
"format": "date-time"
|
48
|
+
}
|
49
|
+
},
|
50
|
+
"required": ["initTimestamp", "finalTimestamp"],
|
51
|
+
"additionalProperties": {
|
52
|
+
"type": "string"
|
53
|
+
}
|
54
|
+
},
|
55
|
+
"counters": {
|
56
|
+
"$ref": "#/definitions/metricsList"
|
57
|
+
},
|
58
|
+
"gauges": {
|
59
|
+
"$ref": "#/definitions/metricsList"
|
60
|
+
},
|
61
|
+
"timers": {
|
62
|
+
"$ref": "#/definitions/metricsList"
|
63
|
+
},
|
64
|
+
"version": {
|
65
|
+
"type":"string",
|
66
|
+
"pattern": "^2e$"
|
67
|
+
}
|
68
|
+
},
|
69
|
+
"required": ["annotations", "version"]
|
70
|
+
}
|
71
|
+
},
|
72
|
+
|
73
|
+
"title": "Query Log",
|
74
|
+
"description": "log file entry for ingestion by tsd aggregator",
|
75
|
+
"type":"object",
|
76
|
+
|
77
|
+
"properties":{
|
78
|
+
"time": {
|
79
|
+
"type":"string",
|
80
|
+
"format": "date-time"
|
81
|
+
},
|
82
|
+
"name": {
|
83
|
+
"type":"string",
|
84
|
+
"pattern": "^aint.metrics$"
|
85
|
+
},
|
86
|
+
"level": {
|
87
|
+
"type":"string",
|
88
|
+
"pattern": "^info$"
|
89
|
+
},
|
90
|
+
"data": {
|
91
|
+
"$ref": "#/definitions/data"
|
92
|
+
},
|
93
|
+
"id": {
|
94
|
+
"type":"string"
|
95
|
+
},
|
96
|
+
"context": {
|
97
|
+
"type":"object",
|
98
|
+
"properties": {
|
99
|
+
}
|
100
|
+
}
|
101
|
+
},
|
102
|
+
"required": ["time", "name", "level", "data"]
|
103
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Copyright 2014 Groupon.com
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module TsdMetrics
|
16
|
+
# Not threadsafe
|
17
|
+
class AsyncQueueWriter
|
18
|
+
def initialize(queue, logger)
|
19
|
+
@queue = queue
|
20
|
+
@logger = logger
|
21
|
+
end
|
22
|
+
|
23
|
+
def start
|
24
|
+
Thread.new do
|
25
|
+
while true
|
26
|
+
tryPopQueueToFile
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def tryPopQueueToFile
|
34
|
+
line = @queue.pop
|
35
|
+
return if line == nil
|
36
|
+
@logger << line
|
37
|
+
@logger << "\n"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Copyright 2014 Groupon.com
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative 'counter_sample'
|
16
|
+
|
17
|
+
module TsdMetrics
|
18
|
+
class Counter
|
19
|
+
|
20
|
+
def initialize(parentMetric)
|
21
|
+
@parentMetric = parentMetric
|
22
|
+
@samples = []
|
23
|
+
@staticSample = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def createNewSample
|
27
|
+
newSample = CounterSample.new(@parentMetric)
|
28
|
+
@samples.push(newSample)
|
29
|
+
return newSample
|
30
|
+
end
|
31
|
+
|
32
|
+
def values
|
33
|
+
@samples.map do |s|
|
34
|
+
s.sampleRepresentation
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def getFirstOrNewStaticSample
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copyright 2014 Groupon.com
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module TsdMetrics
|
16
|
+
class CounterSample
|
17
|
+
attr_reader :value
|
18
|
+
def initialize(metricStatusSupplier)
|
19
|
+
@metricStatusSupplier = metricStatusSupplier
|
20
|
+
@value = 0
|
21
|
+
end
|
22
|
+
def increment(magnitude = 1)
|
23
|
+
if @metricStatusSupplier.metricIsClosed
|
24
|
+
TsdMetrics.errorLogger.warn("Increment or decrement called on Counter after metric has been closed")
|
25
|
+
return
|
26
|
+
end
|
27
|
+
@value += magnitude
|
28
|
+
end
|
29
|
+
def decrement(magnitude = 1)
|
30
|
+
increment(-1*magnitude)
|
31
|
+
end
|
32
|
+
def sampleRepresentation
|
33
|
+
# Always unitless
|
34
|
+
{value: @value}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Copyright 2014 Groupon.com
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module TsdMetrics
|
16
|
+
class Error < RuntimeError
|
17
|
+
end
|
18
|
+
class MetricClosedError < Error
|
19
|
+
end
|
20
|
+
class OutputThreadError < Error
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Copyright 2014 Groupon.com
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'json'
|
16
|
+
require 'time'
|
17
|
+
|
18
|
+
module TsdMetrics
|
19
|
+
class JsonFormattingSink # Implements metricSink
|
20
|
+
def initialize(outputStream)
|
21
|
+
@outputStream = outputStream
|
22
|
+
end
|
23
|
+
def receive(tsdMetricEvent)
|
24
|
+
hash = {
|
25
|
+
time: Time.now.utc.iso8601(3),
|
26
|
+
name: "aint.metrics",
|
27
|
+
level: "info",
|
28
|
+
data: {
|
29
|
+
version: "2e",
|
30
|
+
gauges: proxyValuesProperty(tsdMetricEvent.gauges),
|
31
|
+
timers: proxyValuesProperty(tsdMetricEvent.timers),
|
32
|
+
counters: proxyValuesProperty(tsdMetricEvent.counters),
|
33
|
+
annotations: tsdMetricEvent.annotations
|
34
|
+
}
|
35
|
+
}
|
36
|
+
haveMetrics = [:gauges, :timers, :counters].any? do |metricType|
|
37
|
+
hash[:data][metricType].length > 0
|
38
|
+
end
|
39
|
+
# The timestamp annotations are always present, but we're looking for
|
40
|
+
# any further annotations.
|
41
|
+
haveMetrics = true if hash[:data][:annotations].length > 2
|
42
|
+
|
43
|
+
return unless haveMetrics
|
44
|
+
|
45
|
+
hash[:data][:annotations][:initTimestamp] = hash[:data][:annotations][:initTimestamp].utc.iso8601(3)
|
46
|
+
hash[:data][:annotations][:finalTimestamp] = hash[:data][:annotations][:finalTimestamp].utc.iso8601(3)
|
47
|
+
@outputStream.write(hash.to_json)
|
48
|
+
end
|
49
|
+
|
50
|
+
def record(tsdMetricEvent)
|
51
|
+
receive(tsdMetricEvent)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def proxyValuesProperty(hash)
|
57
|
+
hash.merge(hash) do |key, val, _|
|
58
|
+
{values: val}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright 2014 Groupon.com
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module TsdMetrics
|
16
|
+
class MetricBuilderForSingleStructReceiver
|
17
|
+
def initialize(structReceiver)
|
18
|
+
@structReceiver = structReceiver
|
19
|
+
end
|
20
|
+
def build
|
21
|
+
TsdMetric.new(Time.now, @structReceiver, Mutex.new)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright 2014 Groupon.com
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module TsdMetrics
|
16
|
+
class QueueWriter
|
17
|
+
def initialize(queue)
|
18
|
+
@queue = queue
|
19
|
+
end
|
20
|
+
def write(s)
|
21
|
+
@queue << s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Copyright 2014 Groupon.com
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative 'timer_sample'
|
16
|
+
|
17
|
+
module TsdMetrics
|
18
|
+
class Timer
|
19
|
+
def initialize(parentMetric)
|
20
|
+
@parentMetric = parentMetric
|
21
|
+
@samples = []
|
22
|
+
end
|
23
|
+
|
24
|
+
def createNewSample
|
25
|
+
sample = TimerSample.new(@parentMetric)
|
26
|
+
@samples.push sample
|
27
|
+
sample
|
28
|
+
end
|
29
|
+
|
30
|
+
def addDuration(duration)
|
31
|
+
sample = TimerSample.new(@parentMetric)
|
32
|
+
sample.duration = duration
|
33
|
+
@samples.push sample
|
34
|
+
end
|
35
|
+
|
36
|
+
def samples
|
37
|
+
durations = []
|
38
|
+
@samples.each do |s|
|
39
|
+
if s.stopped?
|
40
|
+
durations.push s.sampleRepresentation
|
41
|
+
else
|
42
|
+
TsdMetrics.errorLogger.warn("Unstopped timer dropped from log")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
durations
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Copyright 2014 Groupon.com
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module TsdMetrics
|
16
|
+
class TimerSample
|
17
|
+
attr_reader :duration, :unit
|
18
|
+
|
19
|
+
def initialize(metricStatusSupplier)
|
20
|
+
@metricStatusSupplier = metricStatusSupplier
|
21
|
+
@startTime = Time.now
|
22
|
+
@duration = nil
|
23
|
+
@unit = :nanosecond
|
24
|
+
end
|
25
|
+
|
26
|
+
def stop
|
27
|
+
if @startTime == nil
|
28
|
+
TsdMetrics.errorLogger.warn("Stop called on already-stopped Timer sample")
|
29
|
+
return
|
30
|
+
end
|
31
|
+
if @metricStatusSupplier.metricIsClosed
|
32
|
+
TsdMetrics.errorLogger.warn("Stop called on Timer after metric has been closed")
|
33
|
+
return
|
34
|
+
end
|
35
|
+
now = Time.now
|
36
|
+
diffSecs = now.tv_sec - @startTime.tv_sec
|
37
|
+
diffNanoSecs = now.tv_nsec - @startTime.tv_nsec
|
38
|
+
diff = ((10**9) * diffSecs) + diffNanoSecs
|
39
|
+
@duration = diff
|
40
|
+
@startTime = nil
|
41
|
+
end
|
42
|
+
|
43
|
+
# Deprecated: Instead use the more ruby-esque #running?
|
44
|
+
def isRunning
|
45
|
+
return running?
|
46
|
+
end
|
47
|
+
|
48
|
+
def running?
|
49
|
+
return @startTime != nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def stopped?
|
53
|
+
return ! running?
|
54
|
+
end
|
55
|
+
|
56
|
+
def set(duration, unit)
|
57
|
+
@duration = duration
|
58
|
+
@unit = unit
|
59
|
+
end
|
60
|
+
|
61
|
+
def sampleRepresentation
|
62
|
+
if @unit == :noUnit
|
63
|
+
{value: @duration}
|
64
|
+
else
|
65
|
+
{value: @duration, unit: @unit}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
# Copyright 2014 Groupon.com
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative 'timer_sample'
|
16
|
+
require_relative 'timer'
|
17
|
+
require_relative 'counter'
|
18
|
+
require_relative 'exceptions'
|
19
|
+
require_relative 'units'
|
20
|
+
|
21
|
+
module TsdMetrics
|
22
|
+
class TsdMetric
|
23
|
+
# Implements TsdMetricEvent interface
|
24
|
+
attr_reader :annotations, :gauges
|
25
|
+
|
26
|
+
def initialize(startTime, metricSink, mutexStrategy)
|
27
|
+
@metricSink = metricSink
|
28
|
+
@annotations = {initTimestamp: startTime}
|
29
|
+
@mutexStrategy = mutexStrategy
|
30
|
+
@gauges = {}
|
31
|
+
@metrics = {timers: {}, counters: {}}
|
32
|
+
@metricClasses = {timers: Timer, counters: Counter}
|
33
|
+
@staticSamples = {timers: {}, counters: {}}
|
34
|
+
@closed = false
|
35
|
+
end
|
36
|
+
|
37
|
+
def open?
|
38
|
+
@mutexStrategy.synchronize do
|
39
|
+
not @closed
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def setGauge(name, value, unit = :noUnit)
|
44
|
+
@mutexStrategy.synchronize do
|
45
|
+
assertNotClosed
|
46
|
+
assertValidUnit(unit)
|
47
|
+
@gauges[name] ||= []
|
48
|
+
@gauges[name].push({value: value, unit: unit}.select{|k, v| v != :noUnit})
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def startTimer(name)
|
53
|
+
@mutexStrategy.synchronize do
|
54
|
+
assertNotClosed
|
55
|
+
# Timer sample is started on creation
|
56
|
+
pushNewStaticSample(:timers, name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def stopTimer(name)
|
61
|
+
@mutexStrategy.synchronize do
|
62
|
+
assertNotClosed
|
63
|
+
sample = getStaticSample(:timers, name)
|
64
|
+
sample.stop
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def setTimer(name, duration, unit = :noUnit)
|
69
|
+
@mutexStrategy.synchronize do
|
70
|
+
assertNotClosed
|
71
|
+
assertValidUnit(unit)
|
72
|
+
pushNewStaticSample(:timers, name)
|
73
|
+
sample = getStaticSample(:timers, name)
|
74
|
+
sample.stop()
|
75
|
+
sample.set(duration, unit)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def createTimer(name)
|
80
|
+
@mutexStrategy.synchronize do
|
81
|
+
assertNotClosed
|
82
|
+
ensureMetricExists(:timers, name)
|
83
|
+
sample = getMetric(:timers, name).createNewSample
|
84
|
+
sample
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def resetCounter(name)
|
89
|
+
@mutexStrategy.synchronize do
|
90
|
+
assertNotClosed
|
91
|
+
ensureCounterExists(name)
|
92
|
+
@staticSamples[:counters][name] = getMetric(:counters, name).createNewSample
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def incrementCounter(name, magnitude=1)
|
97
|
+
@mutexStrategy.synchronize do
|
98
|
+
assertNotClosed
|
99
|
+
ensureStaticCounterSampleExists(name)
|
100
|
+
getStaticSample(:counters, name).increment(magnitude)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def decrementCounter(name, magnitude=1)
|
105
|
+
@mutexStrategy.synchronize do
|
106
|
+
assertNotClosed
|
107
|
+
incrementCounter(name, -1*magnitude)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def createCounter(name)
|
112
|
+
@mutexStrategy.synchronize do
|
113
|
+
assertNotClosed
|
114
|
+
ensureMetricExists(:counters, name)
|
115
|
+
getMetric(:counters, name).createNewSample
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def annotate(name, value)
|
120
|
+
@mutexStrategy.synchronize do
|
121
|
+
assertNotClosed
|
122
|
+
@annotations[name] = value
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def close
|
127
|
+
@mutexStrategy.synchronize do
|
128
|
+
assertNotClosed
|
129
|
+
@closed = true
|
130
|
+
@annotations[:finalTimestamp] = Time.now()
|
131
|
+
@metricSink.record(self)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def timers
|
136
|
+
samplesHash = {}
|
137
|
+
getMetricsOfType(:timers).each do |timerName,timer|
|
138
|
+
samplesHash[timerName] = timer.samples
|
139
|
+
end
|
140
|
+
samplesHash
|
141
|
+
end
|
142
|
+
|
143
|
+
def counters
|
144
|
+
countersHash = {}
|
145
|
+
getMetricsOfType(:counters).each do |k,v|
|
146
|
+
countersHash[k] = v.values
|
147
|
+
end
|
148
|
+
countersHash
|
149
|
+
end
|
150
|
+
|
151
|
+
# "Implements" metricStatusSupplier
|
152
|
+
def metricIsClosed
|
153
|
+
return @closed
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def ensureCounterExists(name)
|
159
|
+
ensureMetricExists(:counters, name)
|
160
|
+
end
|
161
|
+
|
162
|
+
def ensureMetricExists(metricType, name)
|
163
|
+
@metrics[metricType][name] ||= @metricClasses[metricType].new(self)
|
164
|
+
end
|
165
|
+
|
166
|
+
def ensureStaticSampleExists(sampleType, name)
|
167
|
+
ensureMetricExists(sampleType, name)
|
168
|
+
@staticSamples[sampleType][name] ||= getMetric(sampleType, name).createNewSample
|
169
|
+
end
|
170
|
+
|
171
|
+
def ensureStaticCounterSampleExists(name)
|
172
|
+
ensureStaticSampleExists(:counters, name)
|
173
|
+
end
|
174
|
+
|
175
|
+
def pushNewStaticSample(metricType, name)
|
176
|
+
ensureMetricExists(metricType, name)
|
177
|
+
@staticSamples[metricType][name] = getMetric(metricType, name).createNewSample
|
178
|
+
end
|
179
|
+
|
180
|
+
def getMetric(metricType, name)
|
181
|
+
@metrics[metricType][name]
|
182
|
+
end
|
183
|
+
|
184
|
+
def getMetricsOfType(metricType)
|
185
|
+
@metrics[metricType]
|
186
|
+
end
|
187
|
+
|
188
|
+
def getStaticSample(sampleType, name)
|
189
|
+
@staticSamples[sampleType][name]
|
190
|
+
end
|
191
|
+
|
192
|
+
def assertNotClosed
|
193
|
+
raise MetricClosedError if @closed
|
194
|
+
end
|
195
|
+
|
196
|
+
def assertValidUnit(unit)
|
197
|
+
raise MetricClosedError unless UnitsUtils.isValidUnitValue?(unit)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|