hoss-agent 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/Bug_report.md +40 -0
  3. data/.github/ISSUE_TEMPLATE/Feature_request.md +17 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +60 -0
  5. data/.gitignore +27 -0
  6. data/.rspec +2 -0
  7. data/Dockerfile +43 -0
  8. data/Gemfile +105 -0
  9. data/LICENSE +201 -0
  10. data/hoss-agent.gemspec +42 -0
  11. data/lib/hoss/agent.rb +231 -0
  12. data/lib/hoss/central_config/cache_control.rb +51 -0
  13. data/lib/hoss/central_config.rb +184 -0
  14. data/lib/hoss/child_durations.rb +64 -0
  15. data/lib/hoss/config/bytes.rb +42 -0
  16. data/lib/hoss/config/duration.rb +40 -0
  17. data/lib/hoss/config/options.rb +154 -0
  18. data/lib/hoss/config/regexp_list.rb +30 -0
  19. data/lib/hoss/config/wildcard_pattern_list.rb +54 -0
  20. data/lib/hoss/config.rb +304 -0
  21. data/lib/hoss/context/request/socket.rb +36 -0
  22. data/lib/hoss/context/request/url.rb +59 -0
  23. data/lib/hoss/context/request.rb +28 -0
  24. data/lib/hoss/context/response.rb +47 -0
  25. data/lib/hoss/context/user.rb +59 -0
  26. data/lib/hoss/context.rb +64 -0
  27. data/lib/hoss/context_builder.rb +112 -0
  28. data/lib/hoss/deprecations.rb +39 -0
  29. data/lib/hoss/error/exception.rb +70 -0
  30. data/lib/hoss/error/log.rb +41 -0
  31. data/lib/hoss/error.rb +49 -0
  32. data/lib/hoss/error_builder.rb +90 -0
  33. data/lib/hoss/event.rb +131 -0
  34. data/lib/hoss/instrumenter.rb +107 -0
  35. data/lib/hoss/internal_error.rb +23 -0
  36. data/lib/hoss/logging.rb +70 -0
  37. data/lib/hoss/metadata/process_info.rb +35 -0
  38. data/lib/hoss/metadata/service_info.rb +76 -0
  39. data/lib/hoss/metadata/system_info/container_info.rb +136 -0
  40. data/lib/hoss/metadata/system_info.rb +47 -0
  41. data/lib/hoss/metadata.rb +36 -0
  42. data/lib/hoss/naively_hashable.rb +38 -0
  43. data/lib/hoss/rails.rb +68 -0
  44. data/lib/hoss/railtie.rb +42 -0
  45. data/lib/hoss/report.rb +9 -0
  46. data/lib/hoss/sinatra.rb +53 -0
  47. data/lib/hoss/spies/faraday.rb +102 -0
  48. data/lib/hoss/spies/http.rb +81 -0
  49. data/lib/hoss/spies/net_http.rb +97 -0
  50. data/lib/hoss/spies.rb +104 -0
  51. data/lib/hoss/stacktrace/frame.rb +66 -0
  52. data/lib/hoss/stacktrace.rb +33 -0
  53. data/lib/hoss/stacktrace_builder.rb +124 -0
  54. data/lib/hoss/transport/base.rb +191 -0
  55. data/lib/hoss/transport/connection/http.rb +139 -0
  56. data/lib/hoss/transport/connection/proxy_pipe.rb +94 -0
  57. data/lib/hoss/transport/connection.rb +55 -0
  58. data/lib/hoss/transport/filters/hash_sanitizer.rb +77 -0
  59. data/lib/hoss/transport/filters/secrets_filter.rb +48 -0
  60. data/lib/hoss/transport/filters.rb +60 -0
  61. data/lib/hoss/transport/headers.rb +74 -0
  62. data/lib/hoss/transport/serializers/context_serializer.rb +112 -0
  63. data/lib/hoss/transport/serializers/error_serializer.rb +92 -0
  64. data/lib/hoss/transport/serializers/event_serializer.rb +73 -0
  65. data/lib/hoss/transport/serializers/metadata_serializer.rb +92 -0
  66. data/lib/hoss/transport/serializers/report_serializer.rb +33 -0
  67. data/lib/hoss/transport/serializers.rb +113 -0
  68. data/lib/hoss/transport/user_agent.rb +48 -0
  69. data/lib/hoss/transport/worker.rb +319 -0
  70. data/lib/hoss/util/inflector.rb +110 -0
  71. data/lib/hoss/util/lru_cache.rb +65 -0
  72. data/lib/hoss/util/throttle.rb +52 -0
  73. data/lib/hoss/util.rb +54 -0
  74. data/lib/hoss/version.rb +22 -0
  75. data/lib/hoss-agent.rb +210 -0
  76. data/lib/hoss.rb +21 -0
  77. metadata +147 -0
@@ -0,0 +1,107 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ require 'hoss/child_durations'
21
+ require 'hoss/event'
22
+
23
+ module Hoss
24
+ # @api private
25
+ class Instrumenter
26
+ EVENT_KEY = :__elastic_instrumenter_events_key
27
+
28
+ include Logging
29
+
30
+ # @api private
31
+ class Current
32
+ def initialize
33
+ self.events = []
34
+ end
35
+
36
+ def events
37
+ Thread.current[EVENT_KEY] ||= []
38
+ end
39
+
40
+ def events=(events)
41
+ Thread.current[EVENT_KEY] ||= []
42
+ Thread.current[EVENT_KEY] = events
43
+ end
44
+ end
45
+
46
+ def initialize(config, metrics:, stacktrace_builder:, &enqueue)
47
+ @config = config
48
+ @stacktrace_builder = stacktrace_builder
49
+ @enqueue = enqueue
50
+ @metrics = metrics
51
+
52
+ @current = Current.new
53
+ end
54
+
55
+ attr_reader :stacktrace_builder, :enqueue
56
+
57
+ def start
58
+ debug 'Starting instrumenter'
59
+ # We call register! on @subscriber in case the
60
+ # instrumenter was stopped and started again
61
+ @subscriber&.register!
62
+ end
63
+
64
+ def stop
65
+ debug 'Stopping instrumenter'
66
+
67
+ current_events.pop until current_events.empty?
68
+
69
+ @subscriber&.unregister!
70
+ end
71
+
72
+ def handle_forking!
73
+ stop
74
+ start
75
+ end
76
+
77
+ def subscriber=(subscriber)
78
+ debug 'Registering subscriber'
79
+ @subscriber = subscriber
80
+ @subscriber.register!
81
+ end
82
+
83
+
84
+ # events
85
+
86
+ def current_events
87
+ @current.events
88
+ end
89
+
90
+ def current_event
91
+ current_events.last
92
+ end
93
+
94
+ def start_event
95
+ event = Event.new
96
+ current_events.push event
97
+ event.start
98
+ end
99
+
100
+ def end_event
101
+ return unless (event = current_events.pop)
102
+ event.done
103
+ enqueue.call event
104
+ event
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,23 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ module Hoss
21
+ class InternalError < StandardError; end
22
+ class ExistingTransactionError < InternalError; end
23
+ end
@@ -0,0 +1,70 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ module Hoss
21
+ # @api private
22
+ module Logging
23
+ PREFIX = '[Hoss] '
24
+
25
+ LEVELS = {
26
+ debug: Logger::DEBUG,
27
+ info: Logger::INFO,
28
+ warn: Logger::WARN,
29
+ error: Logger::ERROR,
30
+ fatal: Logger::FATAL
31
+ }.freeze
32
+
33
+ def debug(msg, *args, &block)
34
+ log(:debug, msg, *args, &block)
35
+ end
36
+
37
+ def info(msg, *args, &block)
38
+ log(:info, msg, *args, &block)
39
+ end
40
+
41
+ def warn(msg, *args, &block)
42
+ log(:warn, msg, *args, &block)
43
+ end
44
+
45
+ def error(msg, *args, &block)
46
+ log(:error, msg, *args, &block)
47
+ end
48
+
49
+ def fatal(msg, *args, &block)
50
+ log(:fatal, msg, *args, &block)
51
+ end
52
+
53
+ private
54
+
55
+ def log(lvl, msg, *args)
56
+ return unless (logger = @config&.logger)
57
+ return unless LEVELS[lvl] >= (@config&.log_level || 0)
58
+
59
+ formatted_msg = prepend_prefix(format(msg.to_s, *args))
60
+
61
+ return logger.send(lvl, formatted_msg) unless block_given?
62
+
63
+ logger.send(lvl, "#{formatted_msg}\n#{yield}")
64
+ end
65
+
66
+ def prepend_prefix(str)
67
+ "#{PREFIX}#{str}"
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,35 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ module Hoss
21
+ class Metadata
22
+ # @api private
23
+ class ProcessInfo
24
+ def initialize(config)
25
+ @config = config
26
+
27
+ @argv = ARGV
28
+ @pid = $PID || Process.pid
29
+ @title = $PROGRAM_NAME
30
+ end
31
+
32
+ attr_reader :argv, :pid, :title
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,76 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ module Hoss
21
+ class Metadata
22
+ # @api private
23
+ class ServiceInfo
24
+ # @api private
25
+ class Versioned
26
+ def initialize(name: nil, version: nil)
27
+ @name = name
28
+ @version = version
29
+ end
30
+
31
+ attr_reader :name, :version
32
+ end
33
+
34
+ class Agent < Versioned; end
35
+ class Framework < Versioned; end
36
+ class Language < Versioned; end
37
+ class Runtime < Versioned; end
38
+
39
+ def initialize(config)
40
+ @config = config
41
+
42
+ @name = @config.service_name
43
+ @node_name = @config.service_node_name
44
+ @environment = @config.environment
45
+ @agent = Agent.new(name: 'ruby', version: VERSION)
46
+ @framework = Framework.new(
47
+ name: @config.framework_name,
48
+ version: @config.framework_version
49
+ )
50
+ @language = Language.new(name: 'ruby', version: RUBY_VERSION)
51
+ @runtime = lookup_runtime
52
+ @version = @config.service_version || Util.git_sha
53
+ end
54
+
55
+ attr_reader :name, :node_name, :environment, :agent, :framework, :language,
56
+ :runtime, :version
57
+
58
+ private
59
+
60
+ def lookup_runtime
61
+ case RUBY_ENGINE
62
+ when 'ruby'
63
+ Runtime.new(
64
+ name: RUBY_ENGINE,
65
+ version: RUBY_VERSION || RUBY_ENGINE_VERSION
66
+ )
67
+ when 'jruby'
68
+ Runtime.new(
69
+ name: RUBY_ENGINE,
70
+ version: JRUBY_VERSION || RUBY_ENGINE_VERSION
71
+ )
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,136 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ module Hoss
21
+ class Metadata
22
+ class SystemInfo
23
+ # @api private
24
+ class ContainerInfo
25
+ CGROUP_PATH = '/proc/self/cgroup'
26
+
27
+ attr_accessor :container_id, :kubernetes_namespace,
28
+ :kubernetes_node_name, :kubernetes_pod_name, :kubernetes_pod_uid
29
+
30
+ def initialize(cgroup_path: CGROUP_PATH)
31
+ @cgroup_path = cgroup_path
32
+ end
33
+
34
+ attr_reader :cgroup_path
35
+
36
+ def read!
37
+ read_from_cgroup!
38
+ read_from_env!
39
+ self
40
+ end
41
+
42
+ def self.read!
43
+ new.read!
44
+ end
45
+
46
+ def container
47
+ @container ||=
48
+ begin
49
+ return unless container_id
50
+ { id: container_id }
51
+ end
52
+ end
53
+
54
+ def kubernetes
55
+ @kubernetes =
56
+ begin
57
+ kubernetes = {
58
+ namespace: kubernetes_namespace,
59
+ node: { name: kubernetes_node_name },
60
+ pod: {
61
+ name: kubernetes_pod_name,
62
+ uid: kubernetes_pod_uid
63
+ }
64
+ }
65
+ return nil if kubernetes.values.all?(&:nil?)
66
+
67
+ kubernetes
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def read_from_env!
74
+ self.kubernetes_namespace =
75
+ ENV.fetch('KUBERNETES_NAMESPACE', kubernetes_namespace)
76
+ self.kubernetes_node_name =
77
+ ENV.fetch('KUBERNETES_NODE_NAME', kubernetes_node_name)
78
+ self.kubernetes_pod_name =
79
+ ENV.fetch('KUBERNETES_POD_NAME', kubernetes_pod_name)
80
+ self.kubernetes_pod_uid =
81
+ ENV.fetch('KUBERNETES_POD_UID', kubernetes_pod_uid)
82
+ end
83
+
84
+ CONTAINER_ID_REGEX = /^[0-9A-Fa-f]{64}$/.freeze
85
+ KUBEPODS_REGEX = %r{(?:^/kubepods/[^/]+/pod([^/]+)$)|(?:^/kubepods\.slice/kubepods-[^/]+\.slice/kubepods-[^/]+-pod([^/]+)\.slice$)}.freeze # rubocop:disable Metrics/LineLength
86
+ SYSTEMD_SCOPE_SUFFIX = '.scope'
87
+
88
+ # rubocop:disable Metrics/PerceivedComplexity
89
+ # rubocop:disable Metrics/CyclomaticComplexity
90
+ def read_from_cgroup!
91
+ return unless File.exist?(cgroup_path)
92
+ IO.readlines(cgroup_path).each do |line|
93
+ parts = line.strip.split(':')
94
+ next if parts.length != 3
95
+
96
+ cgroup_path = parts[2]
97
+
98
+ # Depending on the filesystem driver used for cgroup
99
+ # management, the paths in /proc/pid/cgroup will have
100
+ # one of the following formats in a Docker container:
101
+ #
102
+ # systemd: /system.slice/docker-<container-ID>.scope
103
+ # cgroupfs: /docker/<container-ID>
104
+ #
105
+ # In a Kubernetes pod, the cgroup path will look like:
106
+ #
107
+ # systemd:
108
+ # /kubepods.slice/kubepods-<QoS-class>.slice/kubepods-\
109
+ # <QoS-class>-pod<pod-UID>.slice/<container-iD>.scope
110
+ # cgroupfs:
111
+ # /kubepods/<QoS-class>/pod<pod-UID>/<container-iD>
112
+ directory, container_id = File.split(cgroup_path)
113
+
114
+ if container_id.end_with?(SYSTEMD_SCOPE_SUFFIX)
115
+ container_id = container_id[0...-SYSTEMD_SCOPE_SUFFIX.length]
116
+ if container_id.include?('-')
117
+ container_id = container_id.split('-', 2)[1]
118
+ end
119
+ end
120
+
121
+ if (kubepods_match = KUBEPODS_REGEX.match(directory))
122
+ pod_id = kubepods_match[1] || kubepods_match[2]
123
+
124
+ self.container_id = container_id
125
+ self.kubernetes_pod_uid = pod_id
126
+ elsif CONTAINER_ID_REGEX.match(container_id)
127
+ self.container_id = container_id
128
+ end
129
+ end
130
+ end
131
+ # rubocop:enable Metrics/PerceivedComplexity
132
+ # rubocop:enable Metrics/CyclomaticComplexity
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,47 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ module Hoss
21
+ class Metadata
22
+ # @api private
23
+ class SystemInfo
24
+ def initialize(config)
25
+ @config = config
26
+
27
+ @hostname = @config.hostname || `hostname`.chomp
28
+ @architecture = gem_platform.cpu
29
+ @platform = gem_platform.os
30
+
31
+ container_info = ContainerInfo.read!
32
+ @container = container_info.container
33
+ @kubernetes = container_info.kubernetes
34
+ end
35
+
36
+ attr_reader :hostname, :architecture, :platform, :container, :kubernetes
37
+
38
+ private
39
+
40
+ def gem_platform
41
+ @gem_platform ||= Gem::Platform.local
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ require 'hoss/metadata/system_info/container_info'
@@ -0,0 +1,36 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ module Hoss
21
+ # @api private
22
+ class Metadata
23
+ def initialize(config)
24
+ @service = ServiceInfo.new(config)
25
+ @process = ProcessInfo.new(config)
26
+ @system = SystemInfo.new(config)
27
+ @labels = config.global_labels
28
+ end
29
+
30
+ attr_reader :service, :process, :system, :labels
31
+ end
32
+ end
33
+
34
+ require 'hoss/metadata/service_info'
35
+ require 'hoss/metadata/system_info'
36
+ require 'hoss/metadata/process_info'
@@ -0,0 +1,38 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ module Hoss
21
+ # @api private
22
+ module NaivelyHashable
23
+ def naively_hashable?
24
+ true
25
+ end
26
+
27
+ def to_h
28
+ instance_variables.each_with_object({}) do |name, h|
29
+ key = name.to_s.delete('@').to_sym
30
+ value = instance_variable_get(name)
31
+ is_hashable =
32
+ value.respond_to?(:naively_hashable?) && value.naively_hashable?
33
+
34
+ h[key] = is_hashable ? value.to_h : value
35
+ end
36
+ end
37
+ end
38
+ end
data/lib/hoss/rails.rb ADDED
@@ -0,0 +1,68 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ require 'hoss/railtie'
21
+
22
+ module Hoss
23
+ # Module for explicitly starting the Hoss agent and hooking into Rails.
24
+ # It is recommended to use the Railtie instead.
25
+ module Rails
26
+ extend self
27
+ # Start the Hoss agent and hook into Rails.
28
+ # Note that the agent won't be started if the Rails console is being used.
29
+ #
30
+ # @param config [Config, Hash] An instance of Config or a Hash config.
31
+ # @return [true, nil] true if the agent was started, nil otherwise.
32
+ def start(config)
33
+ config = Config.new(config) unless config.is_a?(Config)
34
+
35
+ if (reason = should_skip?(config))
36
+ unless config.disable_start_message?
37
+ config.logger.info "Skipping because: #{reason}. " \
38
+ "Start manually with `Hoss.start'"
39
+ end
40
+
41
+ return
42
+ end
43
+
44
+ Hoss.start(config).tap do |agent|
45
+ end
46
+
47
+ Hoss.running?
48
+ rescue StandardError => e
49
+ if config.disable_start_message?
50
+ config.logger.error format('Failed to start: %s', e.message)
51
+ config.logger.debug "Backtrace:\n" + e.backtrace.join("\n")
52
+ else
53
+ puts format('Failed to start: %s', e.message)
54
+ puts "Backtrace:\n" + e.backtrace.join("\n")
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def should_skip?(_config)
61
+ if ::Rails.const_defined?('Console', false)
62
+ return 'Rails console'
63
+ end
64
+
65
+ nil
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,42 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ module Hoss
21
+ # @api private
22
+ class Railtie < ::Rails::Railtie
23
+ config.hoss = ActiveSupport::OrderedOptions.new
24
+
25
+ Config.schema.each do |key, args|
26
+ next unless args.length > 1
27
+ config.hoss[key] = args[:default]
28
+ end
29
+
30
+ initializer 'hoss.initialize' do |app|
31
+ config = Config.new(app.config.hoss.merge(app: app)).tap do |c|
32
+ # Prepend Rails.root to log_path if present
33
+ if c.log_path && !c.log_path.start_with?('/')
34
+ c.log_path = ::Rails.root.join(c.log_path)
35
+ end
36
+ end
37
+
38
+ if Rails.start(config)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ module Hoss
2
+ # @api private
3
+ class Report
4
+ extend Forwardable
5
+ attr_accessor(
6
+ :events
7
+ )
8
+ end
9
+ end