aho 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +34 -7
- data/.ruby-version +1 -1
- data/README.md +2 -2
- data/Rakefile +3 -3
- data/aho.gemspec +41 -0
- data/app/controllers/dsp/api/v1/agent_controller.rb +17 -0
- data/app/controllers/dsp/api/v1/base_controller.rb +32 -0
- data/app/controllers/dsp/api/v1/config_controller.rb +20 -0
- data/app/controllers/dsp/api/v1/healthcheck_controller.rb +29 -0
- data/app/controllers/dsp/api/v1/metrics_controller.rb +13 -0
- data/config/default.aho.yml +36 -0
- data/config/puma.rb +5 -0
- data/config/routes.rb +10 -0
- data/config.ru +5 -0
- data/exe/aho +6 -3
- data/lib/aho/configuration.rb +43 -0
- data/lib/aho/errors.rb +19 -0
- data/lib/aho/metrics/active.rb +58 -0
- data/lib/aho/metrics/ignore.rb +23 -0
- data/lib/aho/metrics_aggregator.rb +29 -0
- data/lib/aho/metrics_builder.rb +14 -0
- data/lib/aho/metrics_formatter.rb +7 -0
- data/lib/aho/metrics_log_device.rb +10 -0
- data/lib/aho/metrics_logger/period.rb +27 -0
- data/lib/aho/metrics_logger.rb +24 -0
- data/lib/aho/schema/parser.rb +45 -0
- data/lib/aho/schema/validator.rb +55 -0
- data/lib/aho/version.rb +1 -1
- data/lib/aho/web_server/application.rb +44 -0
- data/lib/aho/web_server/router.rb +34 -0
- data/lib/aho.rb +49 -7
- data/lib/extensions/dot_hash.rb +29 -0
- data/lib/extensions/hash/deep_mergeable.rb +24 -0
- data/lib/extensions/hash.rb +43 -0
- data/openapi.yml +386 -0
- metadata +100 -15
- data/.idea/.gitignore +0 -8
- data/.idea/aho.iml +0 -77
- data/.idea/misc.xml +0 -4
- data/.idea/modules.xml +0 -8
- data/.idea/vcs.xml +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8c2812dff97476d7b3067cef5d3d083dd4c01914d3d2aa13b5ef0d51bdc6268
|
4
|
+
data.tar.gz: d6c0a70dd6833fd1c22bc3c3070cab05d159507dfa1b83bb19d3b16f63b01faf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ecdae714f1c0b98f736c7dc90cfe7c10ea7b4540a8b6f45973dd227109a533f5d61863eff5e4f4ea172441429a779d0a21e5884475dd3e09584f6e39a7dfffed
|
7
|
+
data.tar.gz: 014c55ce1ce59493da340c7b880f019b990f11cbe883c21a8a519deb8a9366f9799663ca58841953a48d0a7c6a83c86d4bebc7e2ba5a22870e9e48bea216c498
|
data/.rubocop.yml
CHANGED
@@ -1,13 +1,40 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rspec
|
3
|
+
- rubocop-performance
|
4
|
+
- rubocop-rake
|
5
|
+
|
1
6
|
AllCops:
|
2
|
-
TargetRubyVersion: 3.0
|
7
|
+
TargetRubyVersion: 3.3.0
|
8
|
+
NewCops: enable
|
9
|
+
|
10
|
+
Metrics/MethodLength:
|
11
|
+
Max: 15
|
3
12
|
|
4
|
-
|
5
|
-
|
6
|
-
EnforcedStyle: double_quotes
|
13
|
+
Metrics/CyclomaticComplexity:
|
14
|
+
Max: 21
|
7
15
|
|
8
|
-
|
9
|
-
|
10
|
-
|
16
|
+
Metrics/PerceivedComplexity:
|
17
|
+
Max: 21
|
18
|
+
|
19
|
+
Metrics/AbcSize:
|
20
|
+
Max: 100
|
11
21
|
|
12
22
|
Layout/LineLength:
|
13
23
|
Max: 120
|
24
|
+
|
25
|
+
Style/Documentation:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
RSpec/MultipleExpectations:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
RSpec/ExampleLength:
|
32
|
+
Exclude:
|
33
|
+
- 'spec/requests/**/*'
|
34
|
+
|
35
|
+
RSpec/MultipleMemoizedHelpers:
|
36
|
+
Exclude:
|
37
|
+
- 'spec/requests/**/*'
|
38
|
+
|
39
|
+
Naming/VariableNumber:
|
40
|
+
EnforcedStyle: snake_case
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.3.0
|
data/README.md
CHANGED
@@ -4,12 +4,12 @@ Aho — агент для сбора данных с ресурсов для б
|
|
4
4
|
|
5
5
|
## Установка
|
6
6
|
|
7
|
-
|
7
|
+
Установите агента командой:
|
8
8
|
|
9
9
|
$ gem install aho
|
10
10
|
|
11
11
|
## Использование
|
12
12
|
|
13
|
-
Для
|
13
|
+
Для запуска выполните `aho`, в ответ запустится Puma сервер:
|
14
14
|
|
15
15
|
$ aho
|
data/Rakefile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
5
|
|
6
6
|
RSpec::Core::RakeTask.new(:spec)
|
7
7
|
|
8
|
-
require
|
8
|
+
require 'rubocop/rake_task'
|
9
9
|
|
10
10
|
RuboCop::RakeTask.new
|
11
11
|
|
data/aho.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/aho/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'aho'
|
7
|
+
spec.version = Aho::VERSION
|
8
|
+
spec.authors = ['Panasenkov A.']
|
9
|
+
spec.email = ['aapanasenkov@gmail.com']
|
10
|
+
|
11
|
+
spec.summary = 'Aho agent for billing, monitoring and audit data from resources.'
|
12
|
+
spec.description = 'Aho agent is responsible for collecting resource usage data of VM instances on \
|
13
|
+
individual Compute nodes within an Datamart Platform Studio deployment.'
|
14
|
+
spec.homepage = 'https://datamart.ru/aho'
|
15
|
+
spec.required_ruby_version = '>= 3.3.0'
|
16
|
+
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
18
|
+
spec.metadata['source_code_uri'] = 'https://gitlab.datamart.ru/datamart/aho'
|
19
|
+
spec.metadata['changelog_uri'] = 'https://gitlab.datamart.ru/datamart/aho/CHANGELOG.md'
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(__dir__) do
|
24
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
25
|
+
(File.expand_path(f) == __FILE__) ||
|
26
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
spec.bindir = 'exe'
|
30
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ['lib']
|
32
|
+
|
33
|
+
# For more information and examples about making a new gem, check out our
|
34
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
35
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
36
|
+
|
37
|
+
spec.add_dependency 'puma', '~> 6.4', '>= 6.4.3'
|
38
|
+
spec.add_dependency 'rack', '~> 3.1', '>= 3.1.8'
|
39
|
+
spec.add_dependency 'rackup', '~> 2.1'
|
40
|
+
spec.add_dependency 'rake', '~> 13.2', '>= 13.2.1'
|
41
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dsp
|
4
|
+
module Api
|
5
|
+
module V1
|
6
|
+
class BaseController
|
7
|
+
attr_reader :env, :request, :path, :method
|
8
|
+
|
9
|
+
def initialize(env)
|
10
|
+
@env = env
|
11
|
+
@request = Rack::Request.new(env)
|
12
|
+
@path = request.path
|
13
|
+
@method = request.request_method
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def respond(response, status: 200)
|
19
|
+
[status, { 'Content-Type' => 'application/json' }, [response.to_json]]
|
20
|
+
end
|
21
|
+
|
22
|
+
def schema
|
23
|
+
Aho.router.routes.dig(method.downcase.to_sym, path)[:schema]
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate_schema!(...)
|
27
|
+
Aho::Schema::Validator.new(...).validate!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dsp
|
4
|
+
module Api
|
5
|
+
module V1
|
6
|
+
class ConfigController < BaseController
|
7
|
+
def index
|
8
|
+
respond(Aho.config.settings)
|
9
|
+
end
|
10
|
+
|
11
|
+
def create
|
12
|
+
body = JSON.parse(request.body.read)
|
13
|
+
validate_schema!(body, schema)
|
14
|
+
Aho.config.update(body)
|
15
|
+
respond({ status: 'OK', message: 'Configuration applied successfully' })
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dsp
|
4
|
+
module Api
|
5
|
+
module V1
|
6
|
+
class HealthcheckController < BaseController
|
7
|
+
def index
|
8
|
+
render_up
|
9
|
+
rescue StandardError
|
10
|
+
render_down
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def render_up
|
16
|
+
[200, { 'Content-Type' => 'text/html' }, [html_status(color: 'green')]]
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_down
|
20
|
+
[500, { 'Content-Type' => 'text/html' }, [html_status(color: 'red')]]
|
21
|
+
end
|
22
|
+
|
23
|
+
def html_status(color:)
|
24
|
+
%(<!DOCTYPE html><html><body style="background-color: #{color}"></body></html>)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
server_id: STUDIO_SERVER_ID
|
2
|
+
ignore_metrics: -1
|
3
|
+
life_jwt_time: 3600
|
4
|
+
scrape_interval_time: 60
|
5
|
+
enable_agent: -1
|
6
|
+
|
7
|
+
upload:
|
8
|
+
limit_time: 3600
|
9
|
+
limit_lines: 100
|
10
|
+
limit_size: 1
|
11
|
+
|
12
|
+
studio_settings:
|
13
|
+
url: http://localhost:8088/dsp/api/v1/vmagent
|
14
|
+
|
15
|
+
agent_settings:
|
16
|
+
port: 16888
|
17
|
+
|
18
|
+
storage:
|
19
|
+
limit_size: 0
|
20
|
+
limit_time: 86400
|
21
|
+
directory: /opt/dtms-billing-agent/
|
22
|
+
|
23
|
+
file:
|
24
|
+
limit_size: 1
|
25
|
+
limit_time: 86400
|
26
|
+
|
27
|
+
archive:
|
28
|
+
files_on: 0
|
29
|
+
size_on: 0
|
30
|
+
files_limit: 10
|
31
|
+
compression_level: -1
|
32
|
+
|
33
|
+
aggregation:
|
34
|
+
files_on: 0
|
35
|
+
size_on: 0
|
36
|
+
level: 1
|
data/config/puma.rb
ADDED
data/config/routes.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Aho.router.instance_eval do
|
4
|
+
get '/dsp/api/v1/metrics', to: 'dsp/api/v1/metrics#index'
|
5
|
+
get '/dsp/api/v1/config', to: 'dsp/api/v1/config#index'
|
6
|
+
post '/dsp/api/v1/config', to: 'dsp/api/v1/config#create'
|
7
|
+
post '/dsp/api/v1/restart', to: 'dsp/api/v1/agent#restart'
|
8
|
+
delete '/dsp/api/v1/delete', to: 'dsp/api/v1/agent#destroy'
|
9
|
+
get '/dsp/api/v1/healthcheck', to: 'dsp/api/v1/healthcheck#index'
|
10
|
+
end
|
data/config.ru
ADDED
data/exe/aho
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require
|
5
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'aho'
|
6
|
+
require 'rack/handler/puma'
|
7
|
+
require File.join(Aho.root_path, 'config', 'routes')
|
6
8
|
|
7
|
-
|
9
|
+
app = Aho::WebServer::Application.new
|
10
|
+
Rack::Handler::Puma.run(app)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aho
|
4
|
+
class Configuration
|
5
|
+
DEFAULT_CONFIG_FILE_PATH = File.expand_path('../../config/default.aho.yml', __dir__)
|
6
|
+
CONFIG_FILE_PATH = File.expand_path('../../config/aho.yml', __dir__)
|
7
|
+
|
8
|
+
attr_reader :settings
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
reset unless File.exist?(CONFIG_FILE_PATH)
|
12
|
+
raw_settings = YAML.load_file(CONFIG_FILE_PATH)
|
13
|
+
rich_settings = process_env_variables(raw_settings)
|
14
|
+
@settings = DotHash.new(rich_settings)
|
15
|
+
end
|
16
|
+
|
17
|
+
def update(new_settings)
|
18
|
+
@settings.deep_merge!(new_settings.stringify_keys.slice(*default_settings.keys))
|
19
|
+
File.write(CONFIG_FILE_PATH, @settings.to_h.to_yaml)
|
20
|
+
end
|
21
|
+
|
22
|
+
def reset
|
23
|
+
File.write(CONFIG_FILE_PATH, File.read(DEFAULT_CONFIG_FILE_PATH))
|
24
|
+
@settings = DotHash.new(default_settings)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def process_env_variables(settings)
|
30
|
+
settings.deep_transform_values do |value|
|
31
|
+
if value.is_a?(String) && ENV.key?(value)
|
32
|
+
ENV.fetch(value, nil)
|
33
|
+
else
|
34
|
+
value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_settings
|
40
|
+
@default_settings ||= YAML.load_file(DEFAULT_CONFIG_FILE_PATH)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/aho/errors.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aho
|
4
|
+
class Error < StandardError; end
|
5
|
+
|
6
|
+
module Api
|
7
|
+
class MissingFieldError < Error
|
8
|
+
def initialize(field_name)
|
9
|
+
super("Missing required field '#{field_name}'")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class InvalidTypeError < Error
|
14
|
+
def initialize(field_name, expected_type, value)
|
15
|
+
super("Invalid type for '#{field_name}'. Expected #{expected_type}, got #{value.class}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../metrics_builder'
|
4
|
+
|
5
|
+
module Aho
|
6
|
+
module Metrics
|
7
|
+
class Active < MetricsBuilder
|
8
|
+
def metrics
|
9
|
+
{
|
10
|
+
timestamp: run('date'),
|
11
|
+
server_id: 'TODO',
|
12
|
+
event_type: 'TODO',
|
13
|
+
description: 'TODO',
|
14
|
+
crashtime: 'TODO',
|
15
|
+
uptime: run('uptime'),
|
16
|
+
cpu_core: run('nproc'),
|
17
|
+
ram_total: run("awk '/MemTotal/ {print $2}' /proc/meminfo"),
|
18
|
+
disk_total: run("lsblk -b -o SIZE | awk 'NR>1 {total+=$1} END {print total}'"),
|
19
|
+
cpu_seconds_total:,
|
20
|
+
ram_used: run("free | awk '/^Mem/ {print $3}'"),
|
21
|
+
disk_used: run("df --block-size=1 | awk 'NR>1 {used+=$3} END {print used}'"),
|
22
|
+
network_load:
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def cpu_seconds_total
|
29
|
+
File.readlines('/proc/stat').each_with_object([]) do |line, stats|
|
30
|
+
next unless line.start_with?('cpu') && !line.start_with?('cpu ')
|
31
|
+
|
32
|
+
parts = line.split
|
33
|
+
stats << {
|
34
|
+
cpu: parts[0],
|
35
|
+
user: parts[1].to_i,
|
36
|
+
system: parts[3].to_i,
|
37
|
+
idle: parts[4].to_i
|
38
|
+
}
|
39
|
+
end
|
40
|
+
rescue Errno::ENOENT
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def network_load
|
45
|
+
File.readlines('/proc/net/dev').drop(2).each_with_object([]) do |line, stats|
|
46
|
+
parts = line.split
|
47
|
+
stats << {
|
48
|
+
device: parts[0].delete_suffix(':'),
|
49
|
+
received: parts[1].to_i,
|
50
|
+
sent: parts[9].to_i
|
51
|
+
}
|
52
|
+
end
|
53
|
+
rescue Errno::ENOENT
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../metrics_builder'
|
4
|
+
|
5
|
+
module Aho
|
6
|
+
module Metrics
|
7
|
+
class Ignore < MetricsBuilder
|
8
|
+
def metrics
|
9
|
+
{
|
10
|
+
loadaverage_01: run("cat /proc/loadavg | awk '{print $1}'"),
|
11
|
+
loadaverage_05: run("cat /proc/loadavg | awk '{print $2}'"),
|
12
|
+
loadaverage_15: run("cat /proc/loadavg | awk '{print $3}'"),
|
13
|
+
tasks_total: run("top -bn1 | grep Tasks | awk '{print $2}'"),
|
14
|
+
tasks_running: run("top -bn1 | grep Tasks | awk '{print $4}'"),
|
15
|
+
disk_reads_completed_total: run("awk '{sum += $4} END {print sum}' /proc/diskstats"),
|
16
|
+
disk_writes_completed_total: run("awk '{sum += $8} END {print sum}' /proc/diskstats"),
|
17
|
+
swap_total_bytes: run("free --bytes | awk '/^Swap:/ {print $2}'"),
|
18
|
+
swap_used_bytes: run("free --bytes | awk '/^Swap:/ {print $3}'")
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'metrics/active'
|
4
|
+
require_relative 'metrics/ignore'
|
5
|
+
|
6
|
+
module Aho
|
7
|
+
class MetricsAggregator
|
8
|
+
attr_reader :metrics
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@metrics = active_metrics
|
12
|
+
@metrics.merge!(ignore_metrics) if collect_ignore_metrics?
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def active_metrics
|
18
|
+
Aho::Metrics::Active.new.metrics
|
19
|
+
end
|
20
|
+
|
21
|
+
def ignore_metrics
|
22
|
+
Aho::Metrics::Ignore.new.metrics
|
23
|
+
end
|
24
|
+
|
25
|
+
def collect_ignore_metrics?
|
26
|
+
Aho.config.settings.ignore_metrics == -1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Logger
|
4
|
+
module Period
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def next_rotate_time(now, shift_age)
|
8
|
+
now + shift_age.to_i
|
9
|
+
end
|
10
|
+
|
11
|
+
def previous_period_end(now, shift_age)
|
12
|
+
# case shift_age
|
13
|
+
# when 'daily', :daily
|
14
|
+
# t = Time.mktime(now.year, now.month, now.mday) - SiD / 2
|
15
|
+
# when 'weekly', :weekly
|
16
|
+
# t = Time.mktime(now.year, now.month, now.mday) - (SiD * now.wday + SiD / 2)
|
17
|
+
# when 'monthly', :monthly
|
18
|
+
# t = Time.mktime(now.year, now.month, 1) - SiD / 2
|
19
|
+
# when 'now', 'everytime', :now, :everytime
|
20
|
+
# return now
|
21
|
+
# else
|
22
|
+
# raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime"
|
23
|
+
# end
|
24
|
+
# Time.mktime(t.year, t.month, t.mday, 23, 59, 59)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'metrics_log_device'
|
4
|
+
|
5
|
+
module Aho
|
6
|
+
class MetricsLogger < Logger
|
7
|
+
TIMESTAMP_FORMAT = '%Y-%m-%d_%H-%M-%S'
|
8
|
+
|
9
|
+
def initialize(...)
|
10
|
+
super(
|
11
|
+
MetricsLogDevice.new(log_file_path, ...),
|
12
|
+
formatter: MetricsFormatter.new,
|
13
|
+
shift_period_suffix: TIMESTAMP_FORMAT
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def log_file_path
|
20
|
+
timestamp = Time.now.strftime(TIMESTAMP_FORMAT)
|
21
|
+
"#{Aho.logs_path}/#{timestamp}_metrics.jsonl"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aho
|
4
|
+
module Schema
|
5
|
+
class Parser
|
6
|
+
OPENAPI_FILE = 'openapi.yml'
|
7
|
+
|
8
|
+
attr_reader :method, :path, :destination, :openapi_paths
|
9
|
+
|
10
|
+
def initialize(method, path, destination)
|
11
|
+
@method = method
|
12
|
+
@path = path
|
13
|
+
@destination = destination
|
14
|
+
@openapi_paths = YAML.load_file(OPENAPI_FILE)['paths']
|
15
|
+
end
|
16
|
+
|
17
|
+
def controller
|
18
|
+
"#{destination.split('#').first.split('/').map(&:capitalize).join('::')}Controller"
|
19
|
+
end
|
20
|
+
|
21
|
+
def action
|
22
|
+
destination.split('#').last
|
23
|
+
end
|
24
|
+
|
25
|
+
def schema
|
26
|
+
remove_descriptions(openapi_paths.dig(path, method, 'requestBody', 'content', 'application/json', 'schema'))
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def remove_descriptions(hash)
|
32
|
+
return unless hash.is_a?(Hash)
|
33
|
+
|
34
|
+
hash.each_value do |value|
|
35
|
+
if value.is_a?(Hash)
|
36
|
+
value.delete('description')
|
37
|
+
remove_descriptions(value)
|
38
|
+
elsif value.is_a?(Array)
|
39
|
+
value.each { |v| remove_descriptions(v) if v.is_a?(Hash) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|