nexus_semantic_logger 1.17.0 → 1.34.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +0 -2
- data/.gitlab-ci.yml +36 -0
- data/Gemfile +0 -1
- data/README.md +0 -14
- data/lib/nexus_semantic_logger/application.rb +0 -25
- data/lib/nexus_semantic_logger/datadog_formatter.rb +1 -0
- data/lib/nexus_semantic_logger/datadog_tracer.rb +3 -1
- data/lib/nexus_semantic_logger/extensions/action_dispatch/debug_exceptions.rb +2 -13
- data/lib/nexus_semantic_logger/version.rb +2 -2
- data/lib/nexus_semantic_logger.rb +0 -6
- data/nexus_semantic_logger.gemspec +5 -8
- metadata +18 -38
- data/.github/workflows/ci.yml +0 -52
- data/.rspec +0 -2
- data/Appraisals +0 -20
- data/gemfiles/rails_7_1.gemfile +0 -11
- data/gemfiles/rails_7_2.gemfile +0 -11
- data/gemfiles/rails_8_0.gemfile +0 -11
- data/gemfiles/rails_8_1.gemfile +0 -12
- data/lib/nexus_semantic_logger/traced_shell.rb +0 -163
- data/renovate.json +0 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2fec2fab7ed4208841df5e24feb89f5492dcf7e7da927a66c213ba320f10d70c
|
|
4
|
+
data.tar.gz: 560a758d31cf9bf3d773f85f588c977ba74b5acfd18a417dc2ce7fbd50c3762f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 00c2dc1aa81205934c9ddc44e8a9c1135bc75f8a3191cb2d0b23c38af98ac2da1c311f034d54eb0f865a7b7237da1ec056658a4031300ed67e4e79e0700fd2c4
|
|
7
|
+
data.tar.gz: 54421ea76eb1c16ad584b4a547452bfa0ecb430ef37ccbcd15ada51f63a30c89f8e800bb6404a3c94fc830dcfe22277540a8fbf557c4a8d28c0d5038456c6d27
|
data/.gitignore
CHANGED
data/.gitlab-ci.yml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
image: "ruby:3.2.2"
|
|
2
|
+
|
|
3
|
+
stages:
|
|
4
|
+
- release
|
|
5
|
+
- test
|
|
6
|
+
|
|
7
|
+
before_script:
|
|
8
|
+
- gem install bundler --no-document
|
|
9
|
+
- bundle install --jobs $(nproc) "${FLAGS[@]}"
|
|
10
|
+
|
|
11
|
+
rspec:
|
|
12
|
+
script:
|
|
13
|
+
- bundle exec rspec
|
|
14
|
+
|
|
15
|
+
rubocop:
|
|
16
|
+
script:
|
|
17
|
+
- bundle exec rubocop
|
|
18
|
+
|
|
19
|
+
release:
|
|
20
|
+
stage: release
|
|
21
|
+
rules:
|
|
22
|
+
- if: '$CI_COMMIT_TAG'
|
|
23
|
+
script:
|
|
24
|
+
- mkdir -p ~/.gem
|
|
25
|
+
- cp $RUBYGEMS_CREDENTIALS ~/.gem/credentials
|
|
26
|
+
- chmod 0600 ~/.gem/credentials
|
|
27
|
+
- gem update --system
|
|
28
|
+
- ruby --version
|
|
29
|
+
- gem env version
|
|
30
|
+
- sed -i "s/0.0.0/$CI_COMMIT_TAG/g" lib/nexus_semantic_logger/version.rb
|
|
31
|
+
- gem build nexus_semantic_logger.gemspec
|
|
32
|
+
- gem push nexus_semantic_logger*.gem
|
|
33
|
+
artifacts:
|
|
34
|
+
paths:
|
|
35
|
+
- nexus_semantic_logger*.gem
|
|
36
|
+
expire_in: 30 days
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -60,20 +60,6 @@ For example, to increment a count:
|
|
|
60
60
|
NexusSemanticLogger.metrics.increment('nexus.users.registration.complete')
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
### Running shell commands
|
|
64
|
-
|
|
65
|
-
Use `NexusSemanticLogger.shell.capture3` as a drop-in replacement for `Open3.capture3`:
|
|
66
|
-
|
|
67
|
-
```
|
|
68
|
-
stdout, stderr, status = NexusSemanticLogger.shell.capture3('7z', 'x', archive_path)
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Each call is wrapped in a Datadog APM span (`shell.exec`) and emits `nexus.shell.duration_ms`,
|
|
72
|
-
`nexus.shell.peak_rss_mb` (the child's peak RSS, sampled from procfs) and `nexus.shell.executions`
|
|
73
|
-
metrics tagged with `command:<binary>` and `outcome:<success|failure|signaled|exception>`, plus an
|
|
74
|
-
info log line. A child killed by the kernel OOM killer shows up as `outcome:signaled` with
|
|
75
|
-
`termsig: 9` and its last-observed peak RSS.
|
|
76
|
-
|
|
77
63
|
# Local gem development
|
|
78
64
|
|
|
79
65
|
Steps to run this gem from local sources in one the nexus 'staged build' rails components:
|
|
@@ -46,7 +46,6 @@ module NexusSemanticLogger
|
|
|
46
46
|
config.after_initialize do
|
|
47
47
|
require("nexus_semantic_logger/extensions/action_dispatch/debug_exceptions") if defined?(
|
|
48
48
|
::ActionDispatch::DebugExceptions)
|
|
49
|
-
warn_on_incompatible_rails_semantic_logger
|
|
50
49
|
end
|
|
51
50
|
end
|
|
52
51
|
|
|
@@ -86,29 +85,5 @@ module NexusSemanticLogger
|
|
|
86
85
|
# Ensure logging is immediately flushed.
|
|
87
86
|
$stdout.sync = true
|
|
88
87
|
end
|
|
89
|
-
|
|
90
|
-
# Rails 8.1 needs rails_semantic_logger 5.x and no gemspec can express that, so detect the
|
|
91
|
-
# broken pairing at boot.
|
|
92
|
-
def self.warn_on_incompatible_rails_semantic_logger
|
|
93
|
-
return unless incompatible_rails_semantic_logger?
|
|
94
|
-
|
|
95
|
-
logger.warn(
|
|
96
|
-
'rails_semantic_logger 4.x cannot log ActiveRecord events on this Rails version, every ' \
|
|
97
|
-
'sql.active_record event will log a NoMethodError instead of the query. Add ' \
|
|
98
|
-
'`gem "rails_semantic_logger", ">= 5.1"` to your Gemfile so bundler refuses this ' \
|
|
99
|
-
'pairing, then `bundle update rails_semantic_logger semantic_logger`.'
|
|
100
|
-
)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Rails 8.1 moved ActiveRecord::RuntimeRegistry.sql_runtime onto a stats object, which
|
|
104
|
-
# rails_semantic_logger only handles from 5.0. Apps carrying their own shim restore
|
|
105
|
-
# sql_runtime and so read as compatible here.
|
|
106
|
-
def self.incompatible_rails_semantic_logger?
|
|
107
|
-
defined?(::ActiveRecord::RuntimeRegistry) &&
|
|
108
|
-
!::ActiveRecord::RuntimeRegistry.respond_to?(:sql_runtime) &&
|
|
109
|
-
Gem::Version.new(RailsSemanticLogger::VERSION) < Gem::Version.new('5.0')
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
private_class_method :warn_on_incompatible_rails_semantic_logger, :incompatible_rails_semantic_logger?
|
|
113
88
|
end
|
|
114
89
|
end
|
|
@@ -18,6 +18,7 @@ module NexusSemanticLogger
|
|
|
18
18
|
# Note that 'env' is NOT sent- that is set as the default on the agent e.g. staging, canary, production.
|
|
19
19
|
# It does not necessarily align with the Rails env, and we do not want to double tag the env.
|
|
20
20
|
global_tags = [
|
|
21
|
+
"railsenv:#{Rails.env}",
|
|
21
22
|
"service:#{service}",
|
|
22
23
|
"container_name:#{container_name}",
|
|
23
24
|
"pod_name:#{pod_name}",
|
|
@@ -41,6 +42,7 @@ module NexusSemanticLogger
|
|
|
41
42
|
# Trace tags API is Hash<String,String>, see https://www.rubydoc.info/gems/ddtrace/Datadog/Tracing
|
|
42
43
|
# Should match the global tags, but as a Hash.
|
|
43
44
|
c.tags = {
|
|
45
|
+
railsenv: Rails.env,
|
|
44
46
|
service: service,
|
|
45
47
|
container_name: container_name,
|
|
46
48
|
pod_name: pod_name,
|
|
@@ -56,7 +58,7 @@ module NexusSemanticLogger
|
|
|
56
58
|
c.profiling.enabled = dd_tracer_enabled
|
|
57
59
|
end
|
|
58
60
|
|
|
59
|
-
c.tracing.instrument(:rails, service_name: service
|
|
61
|
+
c.tracing.instrument(:rails, service_name: service)
|
|
60
62
|
|
|
61
63
|
c.logger.level = Logger::WARN # datadog info logging is too verbose.
|
|
62
64
|
end
|
|
@@ -14,19 +14,8 @@ module ActionDispatch
|
|
|
14
14
|
# log_rescued_responses? is a rails7 feature, but this gem is also used on rails6. Check for its existence.
|
|
15
15
|
return if respond_to?('log_rescued_responses?') && !log_rescued_responses?(request) && wrapper.rescue_response?
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# replaced by Rails.application.deprecators. Calling the removed singleton on >= 7.2 raises NoMethodError
|
|
20
|
-
# inside render_exception (before the exception is logged), which swallowed all exception logging and
|
|
21
|
-
# produced empty 500s. Use whichever API the Rails version provides, mirroring rails_semantic_logger.
|
|
22
|
-
if (Rails::VERSION::MAJOR == 7 && Rails::VERSION::MINOR >= 1) || Rails::VERSION::MAJOR > 7
|
|
23
|
-
Rails.application.deprecators.silence do
|
|
24
|
-
ActionController::Base.logger.fatal(wrapper.exception)
|
|
25
|
-
end
|
|
26
|
-
else
|
|
27
|
-
ActiveSupport::Deprecation.silence do
|
|
28
|
-
ActionController::Base.logger.fatal(wrapper.exception)
|
|
29
|
-
end
|
|
17
|
+
ActiveSupport::Deprecation.silence do
|
|
18
|
+
ActionController::Base.logger.fatal(wrapper.exception)
|
|
30
19
|
end
|
|
31
20
|
end
|
|
32
21
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module NexusSemanticLogger
|
|
3
|
-
# Leave this as 1.
|
|
4
|
-
VERSION = '1.
|
|
3
|
+
# Leave this as 1.34.4 in order for CI process to replace with the tagged version.
|
|
4
|
+
VERSION = '1.34.4'
|
|
5
5
|
end
|
|
@@ -5,18 +5,12 @@ require 'nexus_semantic_logger/datadog_formatter'
|
|
|
5
5
|
require 'nexus_semantic_logger/datadog_singleton'
|
|
6
6
|
require 'nexus_semantic_logger/datadog_tracer'
|
|
7
7
|
require 'nexus_semantic_logger/logger_metrics_subscriber'
|
|
8
|
-
require 'nexus_semantic_logger/traced_shell'
|
|
9
8
|
|
|
10
9
|
module NexusSemanticLogger
|
|
11
10
|
# Get application wide object for sending metrics.
|
|
12
11
|
def self.metrics
|
|
13
12
|
DatadogSingleton.instance
|
|
14
13
|
end
|
|
15
|
-
|
|
16
|
-
# Get application wide object for running instrumented shell commands.
|
|
17
|
-
def self.shell
|
|
18
|
-
@shell ||= TracedShell.new
|
|
19
|
-
end
|
|
20
14
|
end
|
|
21
15
|
|
|
22
16
|
# Patch access to LEVELS array.
|
|
@@ -14,14 +14,11 @@ Gem::Specification.new do |spec|
|
|
|
14
14
|
end
|
|
15
15
|
spec.require_paths = ['lib']
|
|
16
16
|
spec.add_dependency('amazing_print', '~> 1.4.0')
|
|
17
|
-
spec.add_dependency('datadog', '~> 2.
|
|
18
|
-
spec.add_dependency('dogstatsd-ruby', '~> 5.
|
|
19
|
-
spec.add_dependency('google-protobuf', '
|
|
17
|
+
spec.add_dependency('datadog', '~> 2.7.0') # For datadog tracing/profiling.
|
|
18
|
+
spec.add_dependency('dogstatsd-ruby', '~> 5.6.1') # For custom application metrics.
|
|
19
|
+
spec.add_dependency('google-protobuf', '~> 3.25.5')
|
|
20
20
|
spec.add_dependency('net_tcp_client', '~> 2.2.0') # For TCP logging.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# Rails 7.1 still resolve 4.x and newer apps take 5.x.
|
|
24
|
-
spec.add_dependency('rails_semantic_logger', '>= 4.17', '< 6')
|
|
25
|
-
spec.add_dependency('semantic_logger', '>= 4.16.1', '< 6')
|
|
21
|
+
spec.add_dependency('rails_semantic_logger', '~> 4.17.0')
|
|
22
|
+
spec.add_dependency('semantic_logger', '<= 4.16.0')
|
|
26
23
|
spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
|
|
27
24
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nexus_semantic_logger
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.34.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Johnathon Harris
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-12-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: amazing_print
|
|
@@ -30,40 +30,40 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
33
|
+
version: 2.7.0
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
40
|
+
version: 2.7.0
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: dogstatsd-ruby
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version:
|
|
47
|
+
version: 5.6.1
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version:
|
|
54
|
+
version: 5.6.1
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: google-protobuf
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
|
-
- - "
|
|
59
|
+
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
61
|
version: 3.25.5
|
|
62
62
|
type: :runtime
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
|
-
- - "
|
|
66
|
+
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: 3.25.5
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
@@ -84,59 +84,41 @@ dependencies:
|
|
|
84
84
|
name: rails_semantic_logger
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
|
-
- - "
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: '4.17'
|
|
90
|
-
- - "<"
|
|
87
|
+
- - "~>"
|
|
91
88
|
- !ruby/object:Gem::Version
|
|
92
|
-
version:
|
|
89
|
+
version: 4.17.0
|
|
93
90
|
type: :runtime
|
|
94
91
|
prerelease: false
|
|
95
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
96
93
|
requirements:
|
|
97
|
-
- - "
|
|
98
|
-
- !ruby/object:Gem::Version
|
|
99
|
-
version: '4.17'
|
|
100
|
-
- - "<"
|
|
94
|
+
- - "~>"
|
|
101
95
|
- !ruby/object:Gem::Version
|
|
102
|
-
version:
|
|
96
|
+
version: 4.17.0
|
|
103
97
|
- !ruby/object:Gem::Dependency
|
|
104
98
|
name: semantic_logger
|
|
105
99
|
requirement: !ruby/object:Gem::Requirement
|
|
106
100
|
requirements:
|
|
107
|
-
- - "
|
|
101
|
+
- - "<="
|
|
108
102
|
- !ruby/object:Gem::Version
|
|
109
|
-
version: 4.16.
|
|
110
|
-
- - "<"
|
|
111
|
-
- !ruby/object:Gem::Version
|
|
112
|
-
version: '6'
|
|
103
|
+
version: 4.16.0
|
|
113
104
|
type: :runtime
|
|
114
105
|
prerelease: false
|
|
115
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
116
107
|
requirements:
|
|
117
|
-
- - "
|
|
118
|
-
- !ruby/object:Gem::Version
|
|
119
|
-
version: 4.16.1
|
|
120
|
-
- - "<"
|
|
108
|
+
- - "<="
|
|
121
109
|
- !ruby/object:Gem::Version
|
|
122
|
-
version:
|
|
110
|
+
version: 4.16.0
|
|
123
111
|
description:
|
|
124
112
|
email: john.harris@nexusmods.com
|
|
125
113
|
executables: []
|
|
126
114
|
extensions: []
|
|
127
115
|
extra_rdoc_files: []
|
|
128
116
|
files:
|
|
129
|
-
- ".github/workflows/ci.yml"
|
|
130
117
|
- ".gitignore"
|
|
131
|
-
- ".
|
|
118
|
+
- ".gitlab-ci.yml"
|
|
132
119
|
- ".rubocop.yml"
|
|
133
|
-
- Appraisals
|
|
134
120
|
- Gemfile
|
|
135
121
|
- README.md
|
|
136
|
-
- gemfiles/rails_7_1.gemfile
|
|
137
|
-
- gemfiles/rails_7_2.gemfile
|
|
138
|
-
- gemfiles/rails_8_0.gemfile
|
|
139
|
-
- gemfiles/rails_8_1.gemfile
|
|
140
122
|
- lib/nexus_semantic_logger.rb
|
|
141
123
|
- lib/nexus_semantic_logger/appender_filter.rb
|
|
142
124
|
- lib/nexus_semantic_logger/application.rb
|
|
@@ -146,12 +128,10 @@ files:
|
|
|
146
128
|
- lib/nexus_semantic_logger/extensions/action_dispatch/debug_exceptions.rb
|
|
147
129
|
- lib/nexus_semantic_logger/logger_metrics_subscriber.rb
|
|
148
130
|
- lib/nexus_semantic_logger/sneakers_metrics.rb
|
|
149
|
-
- lib/nexus_semantic_logger/traced_shell.rb
|
|
150
131
|
- lib/nexus_semantic_logger/version.rb
|
|
151
132
|
- lib/puma/plugin/README.md
|
|
152
133
|
- lib/puma/plugin/nexus_puma_statsd.rb
|
|
153
134
|
- nexus_semantic_logger.gemspec
|
|
154
|
-
- renovate.json
|
|
155
135
|
homepage:
|
|
156
136
|
licenses: []
|
|
157
137
|
metadata: {}
|
|
@@ -170,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
170
150
|
- !ruby/object:Gem::Version
|
|
171
151
|
version: '0'
|
|
172
152
|
requirements: []
|
|
173
|
-
rubygems_version: 3.
|
|
153
|
+
rubygems_version: 3.5.23
|
|
174
154
|
signing_key:
|
|
175
155
|
specification_version: 4
|
|
176
156
|
summary: semantic_logger usage for nexus
|
data/.github/workflows/ci.yml
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main]
|
|
6
|
-
tags: ["*"]
|
|
7
|
-
pull_request:
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
rspec:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
strategy:
|
|
13
|
-
fail-fast: false
|
|
14
|
-
matrix:
|
|
15
|
-
gemfile: [rails_7_1, rails_7_2, rails_8_0, rails_8_1]
|
|
16
|
-
env:
|
|
17
|
-
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
|
|
18
|
-
steps:
|
|
19
|
-
- uses: actions/checkout@v4
|
|
20
|
-
- uses: ruby/setup-ruby@v1
|
|
21
|
-
with:
|
|
22
|
-
ruby-version: "3.2.2"
|
|
23
|
-
- run: bundle install --jobs 4
|
|
24
|
-
- run: bundle exec rspec
|
|
25
|
-
|
|
26
|
-
rubocop:
|
|
27
|
-
runs-on: ubuntu-latest
|
|
28
|
-
steps:
|
|
29
|
-
- uses: actions/checkout@v4
|
|
30
|
-
- uses: ruby/setup-ruby@v1
|
|
31
|
-
with:
|
|
32
|
-
ruby-version: "3.2.2"
|
|
33
|
-
- run: bundle install --jobs 4
|
|
34
|
-
- run: bundle exec rubocop
|
|
35
|
-
|
|
36
|
-
release:
|
|
37
|
-
needs: [rspec, rubocop]
|
|
38
|
-
if: startsWith(github.ref, 'refs/tags/')
|
|
39
|
-
runs-on: ubuntu-latest
|
|
40
|
-
steps:
|
|
41
|
-
- uses: actions/checkout@v4
|
|
42
|
-
- uses: ruby/setup-ruby@v1
|
|
43
|
-
with:
|
|
44
|
-
ruby-version: "3.2.2"
|
|
45
|
-
- run: bundle install --jobs 4
|
|
46
|
-
- name: Build and push gem to RubyGems
|
|
47
|
-
env:
|
|
48
|
-
GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
|
|
49
|
-
run: |
|
|
50
|
-
sed -i "s/0.0.0/${GITHUB_REF_NAME}/g" lib/nexus_semantic_logger/version.rb
|
|
51
|
-
gem build nexus_semantic_logger.gemspec
|
|
52
|
-
gem push nexus_semantic_logger-*.gem
|
data/.rspec
DELETED
data/Appraisals
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
appraise "rails-7-1" do
|
|
4
|
-
gem "railties", "~> 7.1.0"
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
appraise "rails-7-2" do
|
|
8
|
-
gem "railties", "~> 7.2.0"
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
appraise "rails-8-0" do
|
|
12
|
-
gem "railties", "~> 8.0.0"
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
appraise "rails-8-1" do
|
|
16
|
-
gem "railties", "~> 8.1.0"
|
|
17
|
-
# No 4.x release of rails_semantic_logger works on Rails 8.1, and bundler will not upgrade past
|
|
18
|
-
# 4.x on its own when an older lockfile exists.
|
|
19
|
-
gem "rails_semantic_logger", "~> 5.1"
|
|
20
|
-
end
|
data/gemfiles/rails_7_1.gemfile
DELETED
data/gemfiles/rails_7_2.gemfile
DELETED
data/gemfiles/rails_8_0.gemfile
DELETED
data/gemfiles/rails_8_1.gemfile
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# This file was generated by Appraisal
|
|
2
|
-
|
|
3
|
-
source "https://rubygems.org"
|
|
4
|
-
|
|
5
|
-
gem "appraisal"
|
|
6
|
-
gem "rubocop"
|
|
7
|
-
gem "rubocop-shopify", "~> 1.0.4", require: false
|
|
8
|
-
gem "rspec"
|
|
9
|
-
gem "railties", "~> 8.1.0"
|
|
10
|
-
gem "rails_semantic_logger", "~> 5.1"
|
|
11
|
-
|
|
12
|
-
gemspec path: "../"
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
require 'open3'
|
|
3
|
-
require 'semantic_logger'
|
|
4
|
-
|
|
5
|
-
module NexusSemanticLogger
|
|
6
|
-
# Instrumented replacement for Open3.capture3, so child processes (7z, unrar, yara, ...) are
|
|
7
|
-
# observable. Each call produces:
|
|
8
|
-
# - a Datadog APM span ('shell.exec', resource = binary basename) tagged with the command line,
|
|
9
|
-
# exit status, terminating signal and peak RSS
|
|
10
|
-
# - statsd metrics: nexus.shell.duration_ms (timing), nexus.shell.peak_rss_mb (distribution)
|
|
11
|
-
# and nexus.shell.executions (count), tagged with command:<binary> and
|
|
12
|
-
# outcome:<success|failure|signaled|exception>
|
|
13
|
-
# - an info log line with the same payload
|
|
14
|
-
#
|
|
15
|
-
# Peak RSS is the child's kernel-maintained high-water mark (VmHWM in /proc/<pid>/status),
|
|
16
|
-
# sampled while the child runs. Linux only; nil elsewhere. Direct child only - grandchildren
|
|
17
|
-
# are not measured. A process killed by the kernel OOM killer reports outcome:signaled with
|
|
18
|
-
# termsig 9 and the last-sampled peak RSS, which is exactly the evidence an OOM postmortem needs.
|
|
19
|
-
class TracedShell
|
|
20
|
-
include SemanticLogger::Loggable
|
|
21
|
-
|
|
22
|
-
SPAN_NAME = 'shell.exec'
|
|
23
|
-
METRIC_PREFIX = 'nexus.shell'
|
|
24
|
-
RSS_POLL_INTERVAL_SECONDS = 0.05
|
|
25
|
-
COMMAND_LOG_MAX_CHARS = 500
|
|
26
|
-
|
|
27
|
-
# Drop-in replacement for Open3.capture3.
|
|
28
|
-
# A leading env Hash and trailing spawn options are supported as with Open3; the env Hash is
|
|
29
|
-
# excluded from spans/logs since it may hold secrets.
|
|
30
|
-
# @return [Array(String, String, Process::Status)] stdout, stderr, status.
|
|
31
|
-
def capture3(*cmd, stdin_data: '', binmode: false, **opts)
|
|
32
|
-
binary = command_basename(cmd)
|
|
33
|
-
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
34
|
-
outcome = 'exception'
|
|
35
|
-
status = nil
|
|
36
|
-
peak_rss_kb = nil
|
|
37
|
-
trace(binary, cmd) do |span|
|
|
38
|
-
stdout, stderr, status, peak_rss_kb = run_capture3(cmd, stdin_data, binmode, opts)
|
|
39
|
-
outcome = outcome_for(status)
|
|
40
|
-
annotate_span(span, status, peak_rss_kb)
|
|
41
|
-
[stdout, stderr, status]
|
|
42
|
-
end
|
|
43
|
-
ensure
|
|
44
|
-
duration_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - started_at) * 1000).round
|
|
45
|
-
record(cmd, outcome, duration_ms, status, peak_rss_kb)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
def trace(binary, cmd, &block)
|
|
51
|
-
return yield(nil) unless defined?(Datadog::Tracing)
|
|
52
|
-
|
|
53
|
-
Datadog::Tracing.trace(SPAN_NAME, resource: binary, type: 'system') do |span|
|
|
54
|
-
span.set_tag('shell.command', command_string(cmd))
|
|
55
|
-
block.call(span)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Open3.capture3 semantics, reimplemented over popen3 so the child pid is available to the
|
|
60
|
-
# RSS poller while it runs.
|
|
61
|
-
def run_capture3(cmd, stdin_data, binmode, opts)
|
|
62
|
-
Open3.popen3(*cmd, **opts) do |stdin, stdout, stderr, wait_thr|
|
|
63
|
-
if binmode
|
|
64
|
-
stdin.binmode
|
|
65
|
-
stdout.binmode
|
|
66
|
-
stderr.binmode
|
|
67
|
-
end
|
|
68
|
-
poller = start_rss_poller(wait_thr)
|
|
69
|
-
out_reader = Thread.new { stdout.read }
|
|
70
|
-
err_reader = Thread.new { stderr.read }
|
|
71
|
-
begin
|
|
72
|
-
stdin.write(stdin_data) if stdin_data && !stdin_data.empty?
|
|
73
|
-
rescue Errno::EPIPE
|
|
74
|
-
# Child exited without consuming stdin; Open3.capture3 ignores this too.
|
|
75
|
-
end
|
|
76
|
-
stdin.close
|
|
77
|
-
status = wait_thr.value
|
|
78
|
-
[out_reader.value, err_reader.value, status, poller&.value]
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def start_rss_poller(wait_thr)
|
|
83
|
-
return nil unless procfs?
|
|
84
|
-
|
|
85
|
-
pid = wait_thr.pid
|
|
86
|
-
Thread.new do
|
|
87
|
-
peak_kb = nil
|
|
88
|
-
while wait_thr.alive?
|
|
89
|
-
sample = read_vm_hwm_kb(pid)
|
|
90
|
-
peak_kb = sample if sample && (peak_kb.nil? || sample > peak_kb)
|
|
91
|
-
sleep(RSS_POLL_INTERVAL_SECONDS)
|
|
92
|
-
end
|
|
93
|
-
peak_kb
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# VmHWM is the process's peak RSS as maintained by the kernel, so each sample is itself a
|
|
98
|
-
# high-water mark; the true peak can only be missed by the process exiting within one poll.
|
|
99
|
-
def read_vm_hwm_kb(pid)
|
|
100
|
-
File.read("/proc/#{pid}/status")[/^VmHWM:\s*(\d+)\s*kB/, 1]&.to_i
|
|
101
|
-
rescue SystemCallError, IOError
|
|
102
|
-
nil
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def procfs?
|
|
106
|
-
return @procfs if defined?(@procfs)
|
|
107
|
-
|
|
108
|
-
@procfs = File.exist?('/proc/self/status')
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def outcome_for(status)
|
|
112
|
-
return 'success' if status.success?
|
|
113
|
-
return 'signaled' if status.signaled?
|
|
114
|
-
|
|
115
|
-
'failure'
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def annotate_span(span, status, peak_rss_kb)
|
|
119
|
-
return unless span
|
|
120
|
-
|
|
121
|
-
span.set_tag('shell.exit_status', status.exitstatus) if status.exitstatus
|
|
122
|
-
span.set_tag('shell.termsig', status.termsig) if status.signaled?
|
|
123
|
-
span.set_tag('shell.peak_rss_mb', to_mb(peak_rss_kb)) if peak_rss_kb
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def record(cmd, outcome, duration_ms, status, peak_rss_kb)
|
|
127
|
-
tags = ["command:#{command_basename(cmd)}", "outcome:#{outcome}"]
|
|
128
|
-
metrics = NexusSemanticLogger.metrics
|
|
129
|
-
metrics.timing("#{METRIC_PREFIX}.duration_ms", duration_ms, tags: tags)
|
|
130
|
-
metrics.increment("#{METRIC_PREFIX}.executions", tags: tags)
|
|
131
|
-
peak_rss_mb = peak_rss_kb && to_mb(peak_rss_kb)
|
|
132
|
-
metrics.distribution("#{METRIC_PREFIX}.peak_rss_mb", peak_rss_mb, tags: tags) if peak_rss_mb
|
|
133
|
-
|
|
134
|
-
payload = {
|
|
135
|
-
command: command_string(cmd),
|
|
136
|
-
outcome: outcome,
|
|
137
|
-
duration_ms: duration_ms,
|
|
138
|
-
exit_status: status&.exitstatus,
|
|
139
|
-
termsig: status&.signaled? ? status.termsig : nil,
|
|
140
|
-
peak_rss_mb: peak_rss_mb,
|
|
141
|
-
}.compact
|
|
142
|
-
logger.info('Shell command finished.', payload)
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
# Binary basename for span resource and metric tags; deliberately low cardinality.
|
|
146
|
-
def command_basename(cmd)
|
|
147
|
-
first = cmd.first.is_a?(Hash) ? cmd[1] : cmd.first
|
|
148
|
-
first = first.first if first.is_a?(Array) # [binary, argv0] form
|
|
149
|
-
return 'unknown' unless first.is_a?(String)
|
|
150
|
-
|
|
151
|
-
File.basename(first.split(' ').first.to_s)
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
def command_string(cmd)
|
|
155
|
-
parts = cmd.reject { |part| part.is_a?(Hash) }
|
|
156
|
-
parts.flatten.join(' ').slice(0, COMMAND_LOG_MAX_CHARS)
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
def to_mb(kb)
|
|
160
|
-
kb.fdiv(1024).round(1)
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
end
|
data/renovate.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
-
"extends": [
|
|
4
|
-
"config:recommended"
|
|
5
|
-
],
|
|
6
|
-
"vulnerabilityAlerts": {
|
|
7
|
-
"dependencyDashboardApproval": false,
|
|
8
|
-
"labels": ["security"]
|
|
9
|
-
},
|
|
10
|
-
"osvVulnerabilityAlerts": true,
|
|
11
|
-
"reviewers": ["team:platform-engineering"],
|
|
12
|
-
"assignees": ["team:platform-engineering"],
|
|
13
|
-
"packageRules": [
|
|
14
|
-
{
|
|
15
|
-
"matchManagers": ["github-actions"],
|
|
16
|
-
"groupName": "GitHub Actions",
|
|
17
|
-
"dependencyDashboardApproval": false
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
}
|