atatus 1.0.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 +7 -0
- data/.gitignore +16 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +57 -0
- data/LICENSE +65 -0
- data/LICENSE-THIRD-PARTY +205 -0
- data/README.md +13 -0
- data/Rakefile +19 -0
- data/atatus.gemspec +36 -0
- data/atatus.yml +2 -0
- data/bench/.gitignore +2 -0
- data/bench/app.rb +53 -0
- data/bench/benchmark.rb +36 -0
- data/bench/report.rb +55 -0
- data/bench/rubyprof.rb +39 -0
- data/bench/stackprof.rb +23 -0
- data/bin/build_docs +5 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/bin/with_framework +7 -0
- data/lib/atatus.rb +325 -0
- data/lib/atatus/agent.rb +260 -0
- data/lib/atatus/central_config.rb +141 -0
- data/lib/atatus/central_config/cache_control.rb +34 -0
- data/lib/atatus/collector/base.rb +329 -0
- data/lib/atatus/collector/builder.rb +317 -0
- data/lib/atatus/collector/transport.rb +72 -0
- data/lib/atatus/config.rb +248 -0
- data/lib/atatus/config/bytes.rb +25 -0
- data/lib/atatus/config/duration.rb +23 -0
- data/lib/atatus/config/options.rb +134 -0
- data/lib/atatus/config/regexp_list.rb +13 -0
- data/lib/atatus/context.rb +33 -0
- data/lib/atatus/context/request.rb +11 -0
- data/lib/atatus/context/request/socket.rb +19 -0
- data/lib/atatus/context/request/url.rb +42 -0
- data/lib/atatus/context/response.rb +22 -0
- data/lib/atatus/context/user.rb +42 -0
- data/lib/atatus/context_builder.rb +97 -0
- data/lib/atatus/deprecations.rb +22 -0
- data/lib/atatus/error.rb +22 -0
- data/lib/atatus/error/exception.rb +46 -0
- data/lib/atatus/error/log.rb +24 -0
- data/lib/atatus/error_builder.rb +76 -0
- data/lib/atatus/instrumenter.rb +224 -0
- data/lib/atatus/internal_error.rb +6 -0
- data/lib/atatus/logging.rb +55 -0
- data/lib/atatus/metadata.rb +19 -0
- data/lib/atatus/metadata/process_info.rb +18 -0
- data/lib/atatus/metadata/service_info.rb +61 -0
- data/lib/atatus/metadata/system_info.rb +35 -0
- data/lib/atatus/metadata/system_info/container_info.rb +121 -0
- data/lib/atatus/metadata/system_info/hw_info.rb +118 -0
- data/lib/atatus/metadata/system_info/os_info.rb +31 -0
- data/lib/atatus/metrics.rb +98 -0
- data/lib/atatus/metrics/cpu_mem.rb +240 -0
- data/lib/atatus/metrics/vm.rb +60 -0
- data/lib/atatus/metricset.rb +19 -0
- data/lib/atatus/middleware.rb +76 -0
- data/lib/atatus/naively_hashable.rb +21 -0
- data/lib/atatus/normalizers.rb +68 -0
- data/lib/atatus/normalizers/action_controller.rb +27 -0
- data/lib/atatus/normalizers/action_mailer.rb +26 -0
- data/lib/atatus/normalizers/action_view.rb +77 -0
- data/lib/atatus/normalizers/active_record.rb +45 -0
- data/lib/atatus/opentracing.rb +346 -0
- data/lib/atatus/rails.rb +61 -0
- data/lib/atatus/railtie.rb +30 -0
- data/lib/atatus/span.rb +125 -0
- data/lib/atatus/span/context.rb +40 -0
- data/lib/atatus/span_helpers.rb +44 -0
- data/lib/atatus/spies.rb +86 -0
- data/lib/atatus/spies/action_dispatch.rb +28 -0
- data/lib/atatus/spies/delayed_job.rb +68 -0
- data/lib/atatus/spies/elasticsearch.rb +36 -0
- data/lib/atatus/spies/faraday.rb +70 -0
- data/lib/atatus/spies/http.rb +44 -0
- data/lib/atatus/spies/json.rb +22 -0
- data/lib/atatus/spies/mongo.rb +87 -0
- data/lib/atatus/spies/net_http.rb +70 -0
- data/lib/atatus/spies/rake.rb +45 -0
- data/lib/atatus/spies/redis.rb +27 -0
- data/lib/atatus/spies/sequel.rb +47 -0
- data/lib/atatus/spies/sidekiq.rb +89 -0
- data/lib/atatus/spies/sinatra.rb +41 -0
- data/lib/atatus/spies/tilt.rb +27 -0
- data/lib/atatus/sql_summarizer.rb +35 -0
- data/lib/atatus/stacktrace.rb +16 -0
- data/lib/atatus/stacktrace/frame.rb +52 -0
- data/lib/atatus/stacktrace_builder.rb +104 -0
- data/lib/atatus/subscriber.rb +77 -0
- data/lib/atatus/trace_context.rb +85 -0
- data/lib/atatus/transaction.rb +100 -0
- data/lib/atatus/transport/base.rb +174 -0
- data/lib/atatus/transport/connection.rb +156 -0
- data/lib/atatus/transport/connection/http.rb +116 -0
- data/lib/atatus/transport/connection/proxy_pipe.rb +75 -0
- data/lib/atatus/transport/filters.rb +43 -0
- data/lib/atatus/transport/filters/secrets_filter.rb +74 -0
- data/lib/atatus/transport/serializers.rb +93 -0
- data/lib/atatus/transport/serializers/context_serializer.rb +85 -0
- data/lib/atatus/transport/serializers/error_serializer.rb +77 -0
- data/lib/atatus/transport/serializers/metadata_serializer.rb +70 -0
- data/lib/atatus/transport/serializers/metricset_serializer.rb +28 -0
- data/lib/atatus/transport/serializers/span_serializer.rb +80 -0
- data/lib/atatus/transport/serializers/transaction_serializer.rb +37 -0
- data/lib/atatus/transport/worker.rb +73 -0
- data/lib/atatus/util.rb +42 -0
- data/lib/atatus/util/inflector.rb +93 -0
- data/lib/atatus/util/lru_cache.rb +48 -0
- data/lib/atatus/util/prefixed_logger.rb +18 -0
- data/lib/atatus/util/throttle.rb +35 -0
- data/lib/atatus/version.rb +5 -0
- data/vendor/.gitkeep +0 -0
- metadata +190 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
# @api private
|
|
5
|
+
class Metadata
|
|
6
|
+
def initialize(config)
|
|
7
|
+
@service = ServiceInfo.new(config)
|
|
8
|
+
@process = ProcessInfo.new(config)
|
|
9
|
+
@system = SystemInfo.new(config)
|
|
10
|
+
@labels = config.global_labels
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :service, :process, :system, :labels
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require 'atatus/metadata/service_info'
|
|
18
|
+
require 'atatus/metadata/system_info'
|
|
19
|
+
require 'atatus/metadata/process_info'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
class Metadata
|
|
5
|
+
# @api private
|
|
6
|
+
class ProcessInfo
|
|
7
|
+
def initialize(config)
|
|
8
|
+
@config = config
|
|
9
|
+
|
|
10
|
+
@argv = ARGV
|
|
11
|
+
@pid = $PID || Process.pid
|
|
12
|
+
@title = $PROGRAM_NAME
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :argv, :pid, :title
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
class Metadata
|
|
5
|
+
# @api private
|
|
6
|
+
class ServiceInfo
|
|
7
|
+
# @api private
|
|
8
|
+
class Versioned
|
|
9
|
+
def initialize(name: nil, version: nil)
|
|
10
|
+
@name = name
|
|
11
|
+
@version = version
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
attr_reader :name, :version
|
|
15
|
+
end
|
|
16
|
+
class Agent < Versioned; end
|
|
17
|
+
class Framework < Versioned; end
|
|
18
|
+
class Language < Versioned; end
|
|
19
|
+
class Runtime < Versioned; end
|
|
20
|
+
|
|
21
|
+
# rubocop:disable Metrics/MethodLength
|
|
22
|
+
def initialize(config)
|
|
23
|
+
@config = config
|
|
24
|
+
|
|
25
|
+
@name = @config.service_name
|
|
26
|
+
@environment = @config.environment
|
|
27
|
+
@agent = Agent.new(name: 'ruby', version: VERSION)
|
|
28
|
+
@framework = Framework.new(
|
|
29
|
+
name: @config.framework_name,
|
|
30
|
+
version: @config.framework_version
|
|
31
|
+
)
|
|
32
|
+
@language = Language.new(name: 'ruby', version: RUBY_VERSION)
|
|
33
|
+
@runtime = lookup_runtime
|
|
34
|
+
@version = @config.service_version || Util.git_sha
|
|
35
|
+
end
|
|
36
|
+
# rubocop:enable Metrics/MethodLength
|
|
37
|
+
|
|
38
|
+
attr_reader :name, :environment, :agent, :framework, :language, :runtime,
|
|
39
|
+
:version
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
# rubocop:disable Metrics/MethodLength
|
|
44
|
+
def lookup_runtime
|
|
45
|
+
case RUBY_ENGINE
|
|
46
|
+
when 'ruby'
|
|
47
|
+
Runtime.new(
|
|
48
|
+
name: RUBY_ENGINE,
|
|
49
|
+
version: RUBY_VERSION || RUBY_ENGINE_VERSION
|
|
50
|
+
)
|
|
51
|
+
when 'jruby'
|
|
52
|
+
Runtime.new(
|
|
53
|
+
name: RUBY_ENGINE,
|
|
54
|
+
version: JRUBY_VERSION || RUBY_ENGINE_VERSION
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
# rubocop:enable Metrics/MethodLength
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
class Metadata
|
|
5
|
+
# @api private
|
|
6
|
+
class SystemInfo
|
|
7
|
+
def initialize(config)
|
|
8
|
+
@config = config
|
|
9
|
+
|
|
10
|
+
@hostname = @config.hostname || `hostname`.chomp
|
|
11
|
+
@architecture = gem_platform.cpu
|
|
12
|
+
@platform = gem_platform.os
|
|
13
|
+
|
|
14
|
+
container_info = ContainerInfo.read!
|
|
15
|
+
@container = container_info.container
|
|
16
|
+
@kubernetes = container_info.kubernetes
|
|
17
|
+
|
|
18
|
+
@hwinfo = HWInfo.read!
|
|
19
|
+
@osinfo = OSInfo.read!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
attr_reader :hostname, :architecture, :platform, :container, :kubernetes, :hwinfo, :osinfo
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def gem_platform
|
|
27
|
+
@gem_platform ||= Gem::Platform.local
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
require 'atatus/metadata/system_info/container_info'
|
|
34
|
+
require 'atatus/metadata/system_info/hw_info'
|
|
35
|
+
require 'atatus/metadata/system_info/os_info'
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
class Metadata
|
|
5
|
+
class SystemInfo
|
|
6
|
+
# @api private
|
|
7
|
+
class ContainerInfo
|
|
8
|
+
CGROUP_PATH = '/proc/self/cgroup'
|
|
9
|
+
|
|
10
|
+
attr_accessor :container_id, :kubernetes_namespace,
|
|
11
|
+
:kubernetes_node_name, :kubernetes_pod_name, :kubernetes_pod_uid
|
|
12
|
+
|
|
13
|
+
def initialize(cgroup_path: CGROUP_PATH)
|
|
14
|
+
@cgroup_path = cgroup_path
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attr_reader :cgroup_path
|
|
18
|
+
|
|
19
|
+
def read!
|
|
20
|
+
read_from_cgroup!
|
|
21
|
+
read_from_env!
|
|
22
|
+
self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.read!
|
|
26
|
+
new.read!
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def container
|
|
30
|
+
@container ||=
|
|
31
|
+
begin
|
|
32
|
+
return unless container_id
|
|
33
|
+
{ id: container_id }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# rubocop:disable Metrics/MethodLength
|
|
38
|
+
def kubernetes
|
|
39
|
+
@kubernetes =
|
|
40
|
+
begin
|
|
41
|
+
kubernetes = {
|
|
42
|
+
namespace: kubernetes_namespace,
|
|
43
|
+
node: { name: kubernetes_node_name },
|
|
44
|
+
pod: {
|
|
45
|
+
name: kubernetes_pod_name,
|
|
46
|
+
uid: kubernetes_pod_uid
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return nil if kubernetes.values.all?(&:nil?)
|
|
50
|
+
|
|
51
|
+
kubernetes
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
# rubocop:enable Metrics/MethodLength
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def read_from_env!
|
|
59
|
+
self.kubernetes_namespace =
|
|
60
|
+
ENV.fetch('KUBERNETES_NAMESPACE', kubernetes_namespace)
|
|
61
|
+
self.kubernetes_node_name =
|
|
62
|
+
ENV.fetch('KUBERNETES_NODE_NAME', kubernetes_node_name)
|
|
63
|
+
self.kubernetes_pod_name =
|
|
64
|
+
ENV.fetch('KUBERNETES_POD_NAME', kubernetes_pod_name)
|
|
65
|
+
self.kubernetes_pod_uid =
|
|
66
|
+
ENV.fetch('KUBERNETES_POD_UID', kubernetes_pod_uid)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
CONTAINER_ID_REGEX = /^[0-9A-Fa-f]{64}$/.freeze
|
|
70
|
+
KUBEPODS_REGEX = %r{(?:^/kubepods/[^/]+/pod([^/]+)$)|(?:^/kubepods\.slice/kubepods-[^/]+\.slice/kubepods-[^/]+-pod([^/]+)\.slice$)}.freeze # rubocop:disable Metrics/LineLength
|
|
71
|
+
SYSTEMD_SCOPE_SUFFIX = '.scope'
|
|
72
|
+
|
|
73
|
+
# rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
74
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
|
75
|
+
def read_from_cgroup!
|
|
76
|
+
return unless File.exist?(cgroup_path)
|
|
77
|
+
IO.readlines(cgroup_path).each do |line|
|
|
78
|
+
parts = line.strip.split(':')
|
|
79
|
+
next if parts.length != 3
|
|
80
|
+
|
|
81
|
+
cgroup_path = parts[2]
|
|
82
|
+
|
|
83
|
+
# Depending on the filesystem driver used for cgroup
|
|
84
|
+
# management, the paths in /proc/pid/cgroup will have
|
|
85
|
+
# one of the following formats in a Docker container:
|
|
86
|
+
#
|
|
87
|
+
# systemd: /system.slice/docker-<container-ID>.scope
|
|
88
|
+
# cgroupfs: /docker/<container-ID>
|
|
89
|
+
#
|
|
90
|
+
# In a Kubernetes pod, the cgroup path will look like:
|
|
91
|
+
#
|
|
92
|
+
# systemd:
|
|
93
|
+
# /kubepods.slice/kubepods-<QoS-class>.slice/kubepods-\
|
|
94
|
+
# <QoS-class>-pod<pod-UID>.slice/<container-iD>.scope
|
|
95
|
+
# cgroupfs:
|
|
96
|
+
# /kubepods/<QoS-class>/pod<pod-UID>/<container-iD>
|
|
97
|
+
directory, container_id = File.split(cgroup_path)
|
|
98
|
+
|
|
99
|
+
if container_id.end_with?(SYSTEMD_SCOPE_SUFFIX)
|
|
100
|
+
container_id = container_id[0...-SYSTEMD_SCOPE_SUFFIX.length]
|
|
101
|
+
if container_id.include?('-')
|
|
102
|
+
container_id = container_id.split('-', 2)[1]
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
if (kubepods_match = KUBEPODS_REGEX.match(directory))
|
|
107
|
+
pod_id = kubepods_match[1] || kubepods_match[2]
|
|
108
|
+
|
|
109
|
+
self.container_id = container_id
|
|
110
|
+
self.kubernetes_pod_uid = pod_id
|
|
111
|
+
elsif CONTAINER_ID_REGEX.match(container_id)
|
|
112
|
+
self.container_id = container_id
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
# rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
117
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'rbconfig'
|
|
3
|
+
require 'socket'
|
|
4
|
+
|
|
5
|
+
module Atatus
|
|
6
|
+
class Metadata
|
|
7
|
+
class SystemInfo
|
|
8
|
+
# @api private
|
|
9
|
+
class HWInfo
|
|
10
|
+
attr_accessor :cpuinfo_cores, :cpuinfo_model, :cpuinfo_mhz,
|
|
11
|
+
:meminfo_total, :host_bootid
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@os = RbConfig::CONFIG['target_os']
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def read!
|
|
18
|
+
if @os =~ /(linux)/i
|
|
19
|
+
read_from_cpuinfo!
|
|
20
|
+
read_from_meminfo!
|
|
21
|
+
read_from_bootid!
|
|
22
|
+
elsif @os =~ /(darwin)/i
|
|
23
|
+
read_cpuinfo_from_sysctl!
|
|
24
|
+
read_meminfo_from_sysctl!
|
|
25
|
+
end
|
|
26
|
+
self
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.read!
|
|
30
|
+
new.read!
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# rubocop:disable Metrics/MethodLength
|
|
34
|
+
def cpuinfo
|
|
35
|
+
@cpuinfo ||=
|
|
36
|
+
begin
|
|
37
|
+
cpuinfo = {
|
|
38
|
+
cores: @cpuinfo_cores,
|
|
39
|
+
model: @cpuinfo_model
|
|
40
|
+
}
|
|
41
|
+
cpuinfo[:mhz] = @cpuinfo_mhz unless @cpuinfo_mhz.nil?
|
|
42
|
+
|
|
43
|
+
cpuinfo
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
# rubocop:enable Metrics/MethodLength
|
|
47
|
+
|
|
48
|
+
def meminfo
|
|
49
|
+
@meminfo ||= @meminfo_total
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# rubocop:disable Metrics/MethodLength
|
|
53
|
+
def hostid
|
|
54
|
+
@hostid ||=
|
|
55
|
+
begin
|
|
56
|
+
return Socket.gethostname if @host_bootid.nil?
|
|
57
|
+
@host_bootid
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
# rubocop:enable Metrics/MethodLength
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def get_sysctl_value(key)
|
|
65
|
+
`sysctl -n #{key} 2>/dev/null`
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
LINUX_CPUINFO_PATH = '/proc/cpuinfo'.freeze
|
|
69
|
+
PROCESSOR_COUNT_REGEX = /^processor\s*:/.freeze
|
|
70
|
+
MODEL_NAME_REGEX = /model name.+:(.+)/.freeze
|
|
71
|
+
CPU_MHZ_REGEX = /cpu MHz\s+:\s+([0-9.]+)/.freeze
|
|
72
|
+
|
|
73
|
+
LINUX_MEMINFO_PATH = '/proc/meminfo'.freeze
|
|
74
|
+
TOTAL_MEMORY_REGEX = /^MemTotal:\s+(\d+)\skB$/.freeze
|
|
75
|
+
|
|
76
|
+
LINUX_BOOTID_PATH = '/proc/sys/kernel/random/boot_id'.freeze
|
|
77
|
+
|
|
78
|
+
# rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
79
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
|
80
|
+
def read_from_cpuinfo!
|
|
81
|
+
return unless File.exist?(LINUX_CPUINFO_PATH)
|
|
82
|
+
cpuinfo = File.read(LINUX_CPUINFO_PATH)
|
|
83
|
+
self.cpuinfo_cores = cpuinfo.scan(PROCESSOR_COUNT_REGEX).size
|
|
84
|
+
self.cpuinfo_model = cpuinfo.scan(MODEL_NAME_REGEX).flatten.first.strip
|
|
85
|
+
self.cpuinfo_mhz = cpuinfo.scan(CPU_MHZ_REGEX).flatten.first
|
|
86
|
+
end
|
|
87
|
+
# rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
88
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
|
89
|
+
|
|
90
|
+
# rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
91
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
|
92
|
+
def read_from_meminfo!
|
|
93
|
+
return unless File.exist?(LINUX_MEMINFO_PATH)
|
|
94
|
+
meminfo = File.read(LINUX_MEMINFO_PATH)
|
|
95
|
+
self.meminfo_total = meminfo.scan(TOTAL_MEMORY_REGEX).flatten.first.to_i
|
|
96
|
+
end
|
|
97
|
+
# rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
98
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
|
99
|
+
|
|
100
|
+
def read_from_bootid!
|
|
101
|
+
return unless File.exist?(LINUX_BOOTID_PATH)
|
|
102
|
+
self.host_bootid = File.read(LINUX_BOOTID_PATH)
|
|
103
|
+
self.host_bootid.strip!
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def read_cpuinfo_from_sysctl!
|
|
107
|
+
self.cpuinfo_cores = get_sysctl_value('hw.logicalcpu_max').to_i
|
|
108
|
+
self.cpuinfo_model = get_sysctl_value('machdep.cpu.brand_string').strip
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def read_meminfo_from_sysctl!
|
|
112
|
+
self.meminfo_total = get_sysctl_value('hw.memsize').to_i
|
|
113
|
+
self.meminfo_total
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
class Metadata
|
|
5
|
+
class SystemInfo
|
|
6
|
+
# @api private
|
|
7
|
+
class OSInfo
|
|
8
|
+
attr_accessor :os, :kernel
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def read!
|
|
14
|
+
read_from_uname!
|
|
15
|
+
self
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.read!
|
|
19
|
+
new.read!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def read_from_uname!
|
|
25
|
+
self.os = `uname -s`.strip.downcase!
|
|
26
|
+
self.kernel = `uname -r`.strip
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'atatus/metricset'
|
|
4
|
+
|
|
5
|
+
module Atatus
|
|
6
|
+
# @api private
|
|
7
|
+
module Metrics
|
|
8
|
+
MUTEX = Mutex.new
|
|
9
|
+
|
|
10
|
+
def self.new(config, &block)
|
|
11
|
+
Collector.new(config, &block)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.platform
|
|
15
|
+
@platform ||= Gem::Platform.local.os.to_sym
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @api private
|
|
19
|
+
class Collector
|
|
20
|
+
include Logging
|
|
21
|
+
|
|
22
|
+
TIMEOUT_INTERVAL = 5 # seconds
|
|
23
|
+
|
|
24
|
+
def initialize(config, labels: nil, &block)
|
|
25
|
+
@config = config
|
|
26
|
+
@labels = labels
|
|
27
|
+
@samplers = [CpuMem, VM].map do |kls|
|
|
28
|
+
debug "Adding metrics collector '#{kls}'"
|
|
29
|
+
kls.new(config)
|
|
30
|
+
end
|
|
31
|
+
@callback = block
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
attr_reader :config, :samplers, :callback, :labels
|
|
35
|
+
|
|
36
|
+
# rubocop:disable Metrics/MethodLength
|
|
37
|
+
def start
|
|
38
|
+
unless config.collect_metrics?
|
|
39
|
+
debug 'Skipping metrics'
|
|
40
|
+
return
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
debug 'Starting metrics'
|
|
44
|
+
|
|
45
|
+
@timer_task = Concurrent::TimerTask.execute(
|
|
46
|
+
run_now: true,
|
|
47
|
+
execution_interval: config.metrics_interval,
|
|
48
|
+
timeout_interval: TIMEOUT_INTERVAL
|
|
49
|
+
) do
|
|
50
|
+
begin
|
|
51
|
+
debug 'Collecting metrics'
|
|
52
|
+
collect_and_send
|
|
53
|
+
true
|
|
54
|
+
rescue StandardError => e
|
|
55
|
+
error 'Error while collecting metrics: %e', e.inspect
|
|
56
|
+
debug { e.backtrace.join("\n") }
|
|
57
|
+
false
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
@running = true
|
|
62
|
+
end
|
|
63
|
+
# rubocop:enable Metrics/MethodLength
|
|
64
|
+
|
|
65
|
+
def stop
|
|
66
|
+
return unless running?
|
|
67
|
+
|
|
68
|
+
debug 'Stopping metrics'
|
|
69
|
+
|
|
70
|
+
@timer_task.shutdown
|
|
71
|
+
@running = false
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def running?
|
|
75
|
+
!!@running
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def collect_and_send
|
|
79
|
+
metricset = Metricset.new(labels: labels, **collect)
|
|
80
|
+
return if metricset.empty?
|
|
81
|
+
|
|
82
|
+
callback.call(metricset)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def collect
|
|
86
|
+
MUTEX.synchronize do
|
|
87
|
+
samplers.each_with_object({}) do |sampler, samples|
|
|
88
|
+
next unless (sample = sampler.collect)
|
|
89
|
+
samples.merge!(sample)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
require 'atatus/metrics/cpu_mem'
|
|
98
|
+
require 'atatus/metrics/vm'
|