hoss-agent 1.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.
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