cli_application 0.1.9 → 0.1.10
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/lib/cli_application.rb +7 -0
- data/lib/cli_application/app.rb +30 -2
- data/lib/cli_application/config.rb +2 -0
- data/lib/cli_application/locales/ru.yml +20 -0
- data/lib/cli_application/log/README.md +57 -0
- data/lib/cli_application/log/base.rb +27 -0
- data/lib/cli_application/log/config.rb +71 -0
- data/lib/cli_application/log/database.rb +21 -0
- data/lib/cli_application/log/file.rb +96 -0
- data/lib/cli_application/log/none.rb +19 -0
- data/lib/cli_application/stat.rb +70 -46
- data/lib/cli_application/version.rb +1 -1
- data/test/examples/1/stat/app.yml +15 -27
- data/test/log/01_log_section_missing/app.rb +24 -0
- data/test/log/01_log_section_missing/cli_example.rb +14 -0
- data/test/log/02_log_section_type_wrong/app.rb +24 -0
- data/test/log/02_log_section_type_wrong/cli_example.rb +14 -0
- data/test/log/02_log_section_type_wrong/stat/app.yml +21 -0
- data/test/log/03_log_section_type_none_ok/app.rb +24 -0
- data/test/log/03_log_section_type_none_ok/cli_example.rb +14 -0
- data/test/log/03_log_section_type_none_ok/stat/app.yml +26 -0
- data/test/log/04_log_section_type_file_ok/app.rb +25 -0
- data/test/log/04_log_section_type_file_ok/cli_example.rb +14 -0
- data/test/log/04_log_section_type_file_ok/logs/app.log +11 -0
- data/test/log/04_log_section_type_file_ok/stat/app.yml +33 -0
- metadata +29 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97e161aaae872e64c8eb70ae91392d210c789564
|
4
|
+
data.tar.gz: c5d7d088bedf9edb2b02eaa0348d0d2da3a272cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55ae149543d5269befed662bb517dc4caf9137d45f9d0bb9afa345a7093fba129a8cdf9afb6134c499920fe90d92955afe990bf452eb399de8f5315e8b390ea6
|
7
|
+
data.tar.gz: bb55fb421ad8fc54f29db17678b788332151b7a37115c097be66063025b908e518318efab920ed87b363a8f969d87b37a57702972573f2c2df24e0cd8d38c204
|
data/lib/cli_application.rb
CHANGED
@@ -24,6 +24,13 @@ module CliApplication # :nodoc:
|
|
24
24
|
require 'cli_application/mail_lib/sendmail'
|
25
25
|
require 'cli_application/mail_lib/log'
|
26
26
|
|
27
|
+
# Функции записи логов в файл или в базу данных
|
28
|
+
require 'cli_application/log/base'
|
29
|
+
require 'cli_application/log/file'
|
30
|
+
require 'cli_application/log/database'
|
31
|
+
require 'cli_application/log/config'
|
32
|
+
require 'cli_application/log/none'
|
33
|
+
|
27
34
|
require 'cli_application/json_struct'
|
28
35
|
require 'cli_application/config'
|
29
36
|
require 'cli_application/databases'
|
data/lib/cli_application/app.rb
CHANGED
@@ -35,7 +35,13 @@ module CliApplication
|
|
35
35
|
# @param [String] classfolder директория, в которой расположен базовый класс проекта
|
36
36
|
# @param [Sym] lang язык работы приложения (реализовано не полностью)
|
37
37
|
def initialize(argv, appfolder, classfolder, lang = :ru)
|
38
|
+
# ru: Настраиваем локализацию приложения
|
39
|
+
# en: setup a localization
|
38
40
|
StTools.configure { |config| config.locale = lang }
|
41
|
+
I18n.load_path += Dir[File.join(__dir__, 'locales', '*.{rb,yml}')]
|
42
|
+
I18n.available_locales = [:ru]
|
43
|
+
I18n.default_locale = lang
|
44
|
+
I18n.backend.load_translations
|
39
45
|
|
40
46
|
@folders = Hash.new
|
41
47
|
@folders[:app] = appfolder
|
@@ -50,9 +56,23 @@ module CliApplication
|
|
50
56
|
|
51
57
|
@footer = nil
|
52
58
|
|
59
|
+
init_app_log
|
53
60
|
init_app
|
54
61
|
end
|
55
62
|
|
63
|
+
def init_app_log
|
64
|
+
log_config = ::CliApplication::Log::Config.new(@config)
|
65
|
+
case log_config.type
|
66
|
+
when :none
|
67
|
+
@cli_log = ::CliApplication::Log::None.new
|
68
|
+
when :file
|
69
|
+
@cli_log = ::CliApplication::Log::File.new(self, log_config, @folders[:class])
|
70
|
+
else
|
71
|
+
raise I18n.t('error.config.log_unknown', type: log_config.type.to_s.inspect)
|
72
|
+
end
|
73
|
+
@cli_log.save_app_start_information
|
74
|
+
end
|
75
|
+
|
56
76
|
#-------------------------------------------------------------
|
57
77
|
#
|
58
78
|
# Функции для использования внутри функции main
|
@@ -223,8 +243,16 @@ module CliApplication
|
|
223
243
|
|
224
244
|
# При вызове данного метода начнется выполнение кода приложения (будет осуществен вызов функции main)
|
225
245
|
def run
|
226
|
-
|
227
|
-
|
246
|
+
@cli_log.save_app_run_information
|
247
|
+
begin
|
248
|
+
self.exitcode = main || 255
|
249
|
+
rescue Exception => e
|
250
|
+
@cli_log.set_exception(e)
|
251
|
+
raise e
|
252
|
+
ensure
|
253
|
+
self.executed_at = (::Time.now - @started_at).to_f
|
254
|
+
@cli_log.save_app_finish_information
|
255
|
+
end
|
228
256
|
puts_footer
|
229
257
|
@cli_stat_record.save
|
230
258
|
self.exitcode
|
@@ -10,6 +10,7 @@
|
|
10
10
|
module CliApplication
|
11
11
|
class Config < OpenStruct
|
12
12
|
attr_reader :config
|
13
|
+
attr_reader :filename
|
13
14
|
|
14
15
|
# Конструктор. Вызывается при создании класса приложения. Данный класс доступен
|
15
16
|
# в главной функции приложения (main) через переменную config
|
@@ -21,6 +22,7 @@ module CliApplication
|
|
21
22
|
@folders = folders
|
22
23
|
@filenames = Array.new
|
23
24
|
@config_filename = File.join([folders[:class], 'config.yml'])
|
25
|
+
@filename = @config_filename
|
24
26
|
load_config(@config_filename)
|
25
27
|
end
|
26
28
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
ru:
|
2
|
+
error:
|
3
|
+
config:
|
4
|
+
log_section_missing: "В конфигурационном файле %{filename} отсутствует секция \"log\""
|
5
|
+
log_section_type_wrong: "Секция \"log\" конфигурационого файла %{filename} должна принимать одно из следующих значений: none, file, database (указано значение %{type})"
|
6
|
+
log_unknown: "Неизвестный тип логгирования: %{type}"
|
7
|
+
log_section_overwrite: "Необходимо переписать функцию \"%{func}\" в дочернем классе"
|
8
|
+
|
9
|
+
config:
|
10
|
+
log_section:
|
11
|
+
start_header: "-- Запуск приложения ---------------------------"
|
12
|
+
run_header: "-- Пользовательская секция ---------------------"
|
13
|
+
finish_header: "-- Завершение приложения -----------------------"
|
14
|
+
app_name: "Приложение: %{name}"
|
15
|
+
app_started_at: "Приложение запущено: %{time}"
|
16
|
+
app_executed_at: "Приложение завершено: %{time} (время выполнения: %{executed_at} сек.)"
|
17
|
+
app_exitcode: "Результат завершения: %{exitcode} (%{status})"
|
18
|
+
app_memory: "Использование памяти: %{value}"
|
19
|
+
app_script_name: "Имя скрипта: %{name}"
|
20
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# module CliApplication::Log
|
2
|
+
|
3
|
+
В ходе эксплуатации библиотеки мне пришлось столкнуться с некоторыми проблемами, которые не сразу были
|
4
|
+
диагностированы. Например, в ходе выполнения скрипта, через полгода, случайно выяснялось, что скрипт
|
5
|
+
последний месяц работал с ошибкой. Подобных ситуаций может быть две:
|
6
|
+
|
7
|
+
- Cкрипт был отлажен под девелоперским профилем, записаны логи, затем скрипт помещен в cron. После этого,
|
8
|
+
при запуске из под крона, возникала ошибка записи лога (из-под крона другие права), которая не выводилась
|
9
|
+
в консоль. Как следствие - под кроном скрипт не работет, а причина неизвестна.
|
10
|
+
- В ходе исполнения скрипта возникали не предусмотренные на этапе отладки исключительные ситуации, и скрипт
|
11
|
+
прекращал работать. Если не озаботиться выводом диагностических сообщений, например, в почту, то об этой
|
12
|
+
ситуации можно было долго не узнать.
|
13
|
+
|
14
|
+
Поэтому в CliApplication добавляются функции логгирования работы приложения. Практика показывет, что полные
|
15
|
+
логи никто не изучает (трудоемко), поэтому логгирование осуществляется только для последнего запуска скрипта.
|
16
|
+
|
17
|
+
При этом, функции логгирования делают следующее:
|
18
|
+
1. Уже на этапе девелопмента предупреждают о ситуации, если запись лог-файлов будет ограничена по причине прав.
|
19
|
+
Это дает гарантию того, что при запуске из под крона данные будут гарантированно записываться в файл.
|
20
|
+
2. Записывают информацию о старте приложения. Если есть блок старта приложения, и ничего больше - где-то
|
21
|
+
произошел "вылет" приложения.
|
22
|
+
3. Дает возможность записи пользовательских сообщений (например, для отладки или контроля исполнения)
|
23
|
+
4. Пишет финальную часть - время исполнения, результат, занятую память.
|
24
|
+
|
25
|
+
Помимо файла, запись также возможна в базу данных, что дает возможность удаленно мониторить исполнение
|
26
|
+
скриптов
|
27
|
+
|
28
|
+
## Настройка логгирования
|
29
|
+
|
30
|
+
Для настройки логгирования необходимо создать секцию cli/log в конфигурационном файле. Формат секции
|
31
|
+
определяется значением type. Например:
|
32
|
+
|
33
|
+
```yaml
|
34
|
+
cli:
|
35
|
+
log:
|
36
|
+
type: none
|
37
|
+
```
|
38
|
+
|
39
|
+
```yaml
|
40
|
+
cli:
|
41
|
+
log:
|
42
|
+
type: file
|
43
|
+
location: <folder>
|
44
|
+
```
|
45
|
+
|
46
|
+
```yaml
|
47
|
+
cli:
|
48
|
+
log:
|
49
|
+
type: database
|
50
|
+
database: <имя секции cli/database>
|
51
|
+
```
|
52
|
+
|
53
|
+
## Логгирование в файл
|
54
|
+
|
55
|
+
|
56
|
+
## Логгирование в базу данных
|
57
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module CliApplication
|
2
|
+
module Log
|
3
|
+
class Base
|
4
|
+
|
5
|
+
def log(message)
|
6
|
+
raise I18n.t('error.config.log_section_overwrite', func: 'log')
|
7
|
+
end
|
8
|
+
|
9
|
+
def save_app_start_information
|
10
|
+
raise I18n.t('error.config.log_section_overwrite', func: 'save_app_start_information')
|
11
|
+
end
|
12
|
+
|
13
|
+
def save_app_run_information
|
14
|
+
raise I18n.t('error.config.log_section_overwrite', func: 'save_app_run_information')
|
15
|
+
end
|
16
|
+
|
17
|
+
def save_app_finish_information
|
18
|
+
raise I18n.t('error.config.log_section_overwrite', func: 'save_app_finish_information')
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_exception(e)
|
22
|
+
@exception = e
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module CliApplication
|
2
|
+
module Log
|
3
|
+
class Config
|
4
|
+
attr_reader :log_section
|
5
|
+
attr_reader :type
|
6
|
+
|
7
|
+
# Конструктор. Вызывается при создании класса приложения. В Конструктор передается
|
8
|
+
# секция конфигурационного файла, описывающего правила логгирования приложения
|
9
|
+
# Форматы файла:
|
10
|
+
#
|
11
|
+
# Логгирование отключено (не рекомендуется)
|
12
|
+
# cli:
|
13
|
+
# log:
|
14
|
+
# type: none
|
15
|
+
#
|
16
|
+
# Логгирование в файл
|
17
|
+
# cli:
|
18
|
+
# log:
|
19
|
+
# type: file
|
20
|
+
# location: папка для храннения логов
|
21
|
+
#
|
22
|
+
# Логгирование в базу данных
|
23
|
+
# cli:
|
24
|
+
# log:
|
25
|
+
# type: database
|
26
|
+
# database: имя конфигурации базы данных
|
27
|
+
# table_name: имя таблицы. По умолчанию - st_cli_application_log
|
28
|
+
#
|
29
|
+
#
|
30
|
+
# 1. Описание хранения логов в файлах
|
31
|
+
# Если ключ location не указан, то в качестве базовой папки будет использована
|
32
|
+
# папка класса, с добавлением logs. Если папки нет - она будет создана.
|
33
|
+
# Имя файла лога - соответствует имени скрипта, с добавкой '/logs/'
|
34
|
+
# При запуске осуществляется проверка прав на указанные файлы. Если есть риск незапуска
|
35
|
+
# скрипта под другими пользователями - то будет исключение.
|
36
|
+
# Файл создается в два этапа. Первый - создается файл при запуске, с указанием даты старта
|
37
|
+
# В случае ошибки - она пишется в лог. В случае успешного завершения - запись об этом тоже пишется
|
38
|
+
# в лог
|
39
|
+
#
|
40
|
+
# 2. Описание хранения логов в базе данных
|
41
|
+
#
|
42
|
+
def initialize(config)
|
43
|
+
@possible_keys = [:none, :file, :database]
|
44
|
+
|
45
|
+
@log_section = config.cli.log
|
46
|
+
@config = config
|
47
|
+
check_section_exist
|
48
|
+
check_section_type
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
|
55
|
+
def check_section_type
|
56
|
+
@type = @log_section.type.downcase.to_sym rescue :unknown
|
57
|
+
unless @possible_keys.include?(@type)
|
58
|
+
raise I18n.t('error.config.log_section_type_wrong', filename: @config.filename, type: @type.to_s.inspect)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_section_exist
|
63
|
+
if @log_section.nil?
|
64
|
+
raise I18n.t('error.config.log_section_missing', filename: @config.filename)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module CliApplication
|
2
|
+
module Log
|
3
|
+
class File < CliApplication::Log::Base
|
4
|
+
attr_reader :folder
|
5
|
+
attr_reader :filename
|
6
|
+
|
7
|
+
def initialize(app, log, class_folder)
|
8
|
+
@app = app
|
9
|
+
@log = log
|
10
|
+
@class_folder = class_folder
|
11
|
+
init_log
|
12
|
+
end
|
13
|
+
|
14
|
+
def save_app_start_information
|
15
|
+
log(I18n.t('config.log_section.start_header'))
|
16
|
+
log(I18n.t('config.log_section.app_name', name: $PROGRAM_NAME))
|
17
|
+
log(I18n.t('config.log_section.app_script_name', name: ::File.basename($PROGRAM_NAME)))
|
18
|
+
log(I18n.t('config.log_section.app_started_at', time: Time.zone.now))
|
19
|
+
log("")
|
20
|
+
end
|
21
|
+
|
22
|
+
def save_app_run_information
|
23
|
+
log(I18n.t('config.log_section.run_header'))
|
24
|
+
log("")
|
25
|
+
end
|
26
|
+
|
27
|
+
def save_app_finish_information
|
28
|
+
log(I18n.t('config.log_section.finish_header'))
|
29
|
+
unless @exception.nil?
|
30
|
+
log(@exception.message)
|
31
|
+
log(@exception.backtrace.join("\n"))
|
32
|
+
end
|
33
|
+
log(I18n.t('config.log_section.app_executed_at', time: Time.zone.now, executed_at: @app.executed_at.round(3)))
|
34
|
+
log(I18n.t('config.log_section.app_memory', value: StTools::Human.memory))
|
35
|
+
log(I18n.t('config.log_section.app_exitcode', exitcode: @app.exitcode, status: ((@app.exitcode == 0 ? 'SUCCESS' : 'FAIL'))))
|
36
|
+
end
|
37
|
+
|
38
|
+
def log(message)
|
39
|
+
::File.open(@filename, 'a') {|f| f.write message + "\n" }
|
40
|
+
::File.chmod(0777, @filename)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
|
47
|
+
def init_log
|
48
|
+
init_names
|
49
|
+
create_folder
|
50
|
+
check_folder_and_file
|
51
|
+
end
|
52
|
+
|
53
|
+
# Проверка на доступность папки и файла. Если с этим проблема,
|
54
|
+
# то выбрасываем исключение, чтобы уже на этапе отладки было понятно, что
|
55
|
+
# при запуске приложения из под cron будут проблемы
|
56
|
+
def check_folder_and_file
|
57
|
+
if ::File.exists?(@filename)
|
58
|
+
delete_file
|
59
|
+
else
|
60
|
+
check_folder
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Проверка на возможность дописывать в вфайл из под любого пользователя
|
65
|
+
# Если права не XXX, то выбрасываем исключение
|
66
|
+
def delete_file
|
67
|
+
::File.delete(@filename)
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_folder
|
71
|
+
if Dir.exists?(@folder)
|
72
|
+
# s = Dir.stat(@filename)
|
73
|
+
# puts "Dir >>>>>>>>>>>>>>>>>> #{s.mode}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def create_folder
|
78
|
+
unless Dir.exists?(@folder)
|
79
|
+
Dir.mkdir(@folder, 0777)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def init_names
|
84
|
+
if @log.log_section.location.nil?
|
85
|
+
# Локация не задана
|
86
|
+
@folder = ::File.join(@class_folder, 'logs')
|
87
|
+
else
|
88
|
+
# Локация в конфиге задана
|
89
|
+
@folder = @log.log_section.location
|
90
|
+
end
|
91
|
+
@filename = ::File.join(@folder, ::File.basename($PROGRAM_NAME, '.rb')+'.log')
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module CliApplication
|
2
|
+
module Log
|
3
|
+
class None < CliApplication::Log::Base
|
4
|
+
|
5
|
+
def log(message)
|
6
|
+
end
|
7
|
+
|
8
|
+
def save_app_start_information
|
9
|
+
end
|
10
|
+
|
11
|
+
def save_app_run_information
|
12
|
+
end
|
13
|
+
|
14
|
+
def save_app_finish_information
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/cli_application/stat.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
module CliApplication
|
2
|
-
class Stat
|
2
|
+
class Stat # :nodoc:
|
3
3
|
attr_reader :stat
|
4
4
|
|
5
|
+
|
5
6
|
def initialize(folders)
|
6
7
|
@stat_filename = File.join([folders[:class], 'stat', ::StTools::System.exename.gsub(/\.rb$/, '.yml')])
|
7
|
-
@stat_folder
|
8
|
+
@stat_folder = File.join([folders[:class], 'stat'])
|
8
9
|
create_folder
|
9
10
|
|
10
11
|
init_stat
|
11
|
-
folders[:stat]
|
12
|
+
folders[:stat] = @stat_folder
|
12
13
|
@stat[:folders] = folders
|
13
14
|
|
14
15
|
@prev = load_stat
|
15
16
|
end
|
16
17
|
|
18
|
+
|
17
19
|
#-------------------------------------------------------------
|
18
20
|
#
|
19
21
|
# Функции настройки приложения
|
@@ -23,36 +25,38 @@ module CliApplication
|
|
23
25
|
@stat[:last][:exitcode] = code
|
24
26
|
end
|
25
27
|
|
28
|
+
|
26
29
|
def executed_at=(at)
|
27
30
|
@stat[:last][:executed_at] = at
|
28
31
|
end
|
29
32
|
|
33
|
+
|
30
34
|
def last_started_at=(at)
|
31
35
|
@stat[:last][:started_at] = at.to_s
|
32
|
-
@stat[:last_started_at]
|
36
|
+
@stat[:last_started_at] = at.to_s
|
33
37
|
end
|
34
38
|
|
39
|
+
|
35
40
|
def version=(val)
|
36
41
|
@stat[:version] = val
|
37
42
|
end
|
38
43
|
|
44
|
+
|
39
45
|
def description=(val)
|
40
46
|
@stat[:description] = val
|
41
47
|
end
|
42
48
|
|
49
|
+
|
43
50
|
def shortdescription=(val)
|
44
51
|
@stat[:shortdescription] = val
|
45
52
|
end
|
46
53
|
|
54
|
+
|
47
55
|
def releasedate=(val)
|
48
56
|
@stat[:releasedate] = val
|
49
57
|
end
|
50
58
|
|
51
59
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
60
|
def last_started_at_human
|
57
61
|
res = last_started_at
|
58
62
|
if res.nil? || res == ''
|
@@ -62,45 +66,62 @@ module CliApplication
|
|
62
66
|
end
|
63
67
|
end
|
64
68
|
|
69
|
+
|
65
70
|
def startes_human
|
66
71
|
res = @prev[:avg][:starts]
|
67
72
|
"Всего было #{res} запусков"
|
68
73
|
end
|
69
74
|
|
75
|
+
|
70
76
|
def last_started_at
|
71
77
|
@prev[:last][:started_at] || ::Time.zone.now
|
72
78
|
end
|
73
79
|
|
80
|
+
|
74
81
|
def load_stat
|
75
|
-
YAML.load_file(@stat_filename)
|
82
|
+
res = YAML.load_file(@stat_filename, {})
|
83
|
+
res.empty? ? Marshal.load(Marshal.dump(init_stat)) : res
|
76
84
|
rescue
|
77
|
-
Marshal.load(
|
85
|
+
Marshal.load(Marshal.dump(init_stat))
|
78
86
|
end
|
79
87
|
|
88
|
+
|
80
89
|
def save
|
81
90
|
@prev = load_stat
|
82
91
|
update_stat
|
83
|
-
File.open(@stat_filename, 'w') {|f| f.write @prev.to_yaml }
|
92
|
+
File.open(@stat_filename, 'w') { |f| f.write @prev.to_yaml }
|
84
93
|
end
|
85
94
|
|
95
|
+
|
86
96
|
def create_folder
|
87
97
|
unless Dir.exist?(@stat_folder)
|
88
98
|
Dir.mkdir(@stat_folder, 0777)
|
89
99
|
end
|
100
|
+
|
101
|
+
# ToDo убрать в модуль Log
|
102
|
+
# 2018-01-06, добавляем проверку на доступность папки и файла. Если с этим проблема,
|
103
|
+
# то выбрасываем исключение, чтобы уже на этапе отладки было понятно, что
|
104
|
+
# при запуске приложения из под cron будут проблемы
|
105
|
+
if File.exist?(@stat_filename)
|
106
|
+
s = File.stat(@stat_filename)
|
107
|
+
puts ">>>>>>>>>>>>>>>>>> #{s.mode}"
|
108
|
+
end
|
90
109
|
end
|
91
110
|
|
111
|
+
|
92
112
|
def timezone=(val)
|
93
113
|
@stat[:timezone] = val
|
94
114
|
end
|
95
115
|
|
116
|
+
|
96
117
|
def update_stat
|
97
|
-
@prev[:name]
|
118
|
+
@prev[:name] = @stat[:name]
|
98
119
|
@prev[:shortdescription] = @stat[:shortdescription]
|
99
|
-
@prev[:version]
|
100
|
-
@prev[:releasedate]
|
101
|
-
@prev[:timezone]
|
102
|
-
@prev[:last_started_at]
|
103
|
-
@prev[:folders]
|
120
|
+
@prev[:version] = @stat[:version]
|
121
|
+
@prev[:releasedate] = @stat[:releasedate]
|
122
|
+
@prev[:timezone] = ::Time.zone.name
|
123
|
+
@prev[:last_started_at] = @stat[:last_started_at]
|
124
|
+
@prev[:folders] = @stat[:folders]
|
104
125
|
|
105
126
|
make_averages(@prev[:avg])
|
106
127
|
make_last(@prev[:last])
|
@@ -112,58 +133,61 @@ module CliApplication
|
|
112
133
|
tmp << @prev[:last][:memory]
|
113
134
|
|
114
135
|
@prev[:last10].unshift(tmp.join(','))
|
115
|
-
@prev[:last10] = @prev[:last10][0,10]
|
136
|
+
@prev[:last10] = @prev[:last10][0, 10]
|
116
137
|
end
|
117
138
|
|
139
|
+
|
118
140
|
def init_stat
|
119
|
-
@stat
|
120
|
-
@stat[:name]
|
141
|
+
@stat = Hash.new
|
142
|
+
@stat[:name] = ::StTools::System.exename
|
121
143
|
@stat[:shortdescription] = ''
|
122
|
-
@stat[:version]
|
123
|
-
@stat[:releasedate]
|
124
|
-
@stat[:timezone]
|
125
|
-
@stat[:last_started_at]
|
126
|
-
@stat[:folders]
|
127
|
-
|
128
|
-
@stat[:avg]
|
129
|
-
@stat[:avg][:starts]
|
130
|
-
@stat[:avg][:executed_at]
|
144
|
+
@stat[:version] = ''
|
145
|
+
@stat[:releasedate] = ''
|
146
|
+
@stat[:timezone] = ''
|
147
|
+
@stat[:last_started_at] = ''
|
148
|
+
@stat[:folders] = @folders
|
149
|
+
|
150
|
+
@stat[:avg] = Hash.new
|
151
|
+
@stat[:avg][:starts] = 0
|
152
|
+
@stat[:avg][:executed_at] = 0
|
131
153
|
@stat[:avg][:executed_at_human] = ''
|
132
|
-
@stat[:avg][:memory]
|
154
|
+
@stat[:avg][:memory] = 0
|
133
155
|
|
134
|
-
@stat[:last]
|
135
|
-
@stat[:last][:started_at]
|
136
|
-
@stat[:last][:executed_at]
|
156
|
+
@stat[:last] = Hash.new
|
157
|
+
@stat[:last][:started_at] = nil
|
158
|
+
@stat[:last][:executed_at] = 0
|
137
159
|
@stat[:last][:executed_at_human] = ''
|
138
|
-
@stat[:last][:memory]
|
139
|
-
@stat[:last][:exitcode]
|
160
|
+
@stat[:last][:memory] = ''
|
161
|
+
@stat[:last][:exitcode] = 0
|
140
162
|
|
141
163
|
@stat[:last10] = Array.new
|
142
164
|
|
143
165
|
@stat
|
144
166
|
end
|
145
167
|
|
168
|
+
|
146
169
|
def make_averages(avg)
|
147
170
|
if avg[:starts] == 0
|
148
|
-
avg[:starts]
|
149
|
-
avg[:executed_at]
|
171
|
+
avg[:starts] = 1
|
172
|
+
avg[:executed_at] = @stat[:last][:executed_at]
|
150
173
|
avg[:executed_at_human] = ::StTools::Human.ago_in_words_pair(avg[:executed_at].to_i).join(' ')
|
151
|
-
avg[:memory]
|
174
|
+
avg[:memory] = ::StTools::System.memory.to_i
|
152
175
|
else
|
153
|
-
mul
|
154
|
-
avg[:starts]
|
155
|
-
avg[:executed_at]
|
176
|
+
mul = avg[:starts]
|
177
|
+
avg[:starts] += 1
|
178
|
+
avg[:executed_at] = ((avg[:executed_at] * mul + @stat[:last][:executed_at]).to_f / avg[:starts]).round(6)
|
156
179
|
avg[:executed_at_human] = ::StTools::Human.ago_in_words_pair(avg[:executed_at]).join(' ')
|
157
|
-
avg[:memory]
|
180
|
+
avg[:memory] = (avg[:memory] * mul + ::StTools::System.memory).to_i / avg[:starts]
|
158
181
|
end
|
159
182
|
end
|
160
183
|
|
184
|
+
|
161
185
|
def make_last(last)
|
162
|
-
last[:started_at]
|
163
|
-
last[:executed_at]
|
186
|
+
last[:started_at] = @stat[:last_started_at]
|
187
|
+
last[:executed_at] = @stat[:last][:executed_at]
|
164
188
|
last[:executed_at_human] = ::StTools::Human.ago_in_words_pair(last[:executed_at]).join(' ')
|
165
|
-
last[:memory]
|
166
|
-
last[:exitcode]
|
189
|
+
last[:memory] = ::StTools::Human.memory
|
190
|
+
last[:exitcode] = @stat[:last][:exitcode]
|
167
191
|
end
|
168
192
|
|
169
193
|
end
|
@@ -1,33 +1,21 @@
|
|
1
1
|
---
|
2
2
|
:name: app.rb
|
3
|
-
:shortdescription:
|
4
|
-
:version: '
|
5
|
-
:releasedate: '
|
3
|
+
:shortdescription: ''
|
4
|
+
:version: ''
|
5
|
+
:releasedate: ''
|
6
6
|
:timezone: Moscow
|
7
|
-
:last_started_at: '
|
8
|
-
:folders:
|
9
|
-
:app: "/Users/Stan/Documents/Development/RubyMine/cli_application/test/examples/2"
|
10
|
-
:class: "/Users/Stan/Documents/Development/RubyMine/cli_application/test/examples/1"
|
11
|
-
:stat: "/Users/Stan/Documents/Development/RubyMine/cli_application/test/examples/1/stat"
|
7
|
+
:last_started_at: ''
|
8
|
+
:folders:
|
12
9
|
:avg:
|
13
|
-
:starts:
|
14
|
-
:executed_at:
|
15
|
-
:executed_at_human:
|
16
|
-
:memory:
|
10
|
+
:starts: 1
|
11
|
+
:executed_at: 0
|
12
|
+
:executed_at_human: 0 секунд
|
13
|
+
:memory: 44269568
|
17
14
|
:last:
|
18
|
-
:started_at: '
|
19
|
-
:executed_at: 0
|
20
|
-
:executed_at_human: 0
|
21
|
-
:memory:
|
22
|
-
:exitcode:
|
15
|
+
:started_at: ''
|
16
|
+
:executed_at: 0
|
17
|
+
:executed_at_human: 0 секунд
|
18
|
+
:memory: 42.2 Мбайт
|
19
|
+
:exitcode: 0
|
23
20
|
:last10:
|
24
|
-
-
|
25
|
-
- 2017-01-04 12:18:26 +0300,255,0.053526,41.2 Мбайт
|
26
|
-
- 2015-11-12 08:04:04 +0300,10,0.032581,35 кбайт
|
27
|
-
- 2015-10-26 22:16:55 +0300,0,0.029927,36 кбайт
|
28
|
-
- 2015-10-26 22:16:01 +0300,0,0.02892,36 кбайт
|
29
|
-
- 2015-10-26 22:10:40 +0300,0,0.033229,36 кбайт
|
30
|
-
- 2015-10-26 22:10:25 +0300,0,0.036708,36 кбайт
|
31
|
-
- 2015-10-26 22:08:56 +0300,0,0.036485,38 кбайт
|
32
|
-
- 2015-10-26 22:07:56 +0300,0,0.035323,36 кбайт
|
33
|
-
- 2015-10-26 22:04:20 +0300,255,0.053609,35 кбайт
|
21
|
+
- ",0,0,42.2 Мбайт"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: utf-8
|
3
|
+
require './cli_example.rb'
|
4
|
+
|
5
|
+
class TestApp < CliExample
|
6
|
+
|
7
|
+
def main
|
8
|
+
puts "Hello, world!"
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
app = TestApp.new(ARGV, __dir__)
|
14
|
+
|
15
|
+
app.version = '1.0'
|
16
|
+
app.releasedate = '2018-01-06'
|
17
|
+
app.shortdescription = 'Тестовый скрипт демонстрации CliApplication'
|
18
|
+
app.description = "CliApplication gem демо. #{app.shortdescription}"
|
19
|
+
|
20
|
+
app.help
|
21
|
+
|
22
|
+
app.run
|
23
|
+
exit(app.exitcode)
|
24
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: utf-8
|
3
|
+
require './cli_example.rb'
|
4
|
+
|
5
|
+
class TestApp < CliExample
|
6
|
+
|
7
|
+
def main
|
8
|
+
puts "Hello, world!"
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
app = TestApp.new(ARGV, __dir__)
|
14
|
+
|
15
|
+
app.version = '1.0'
|
16
|
+
app.releasedate = '2018-01-06'
|
17
|
+
app.shortdescription = 'Тестовый скрипт демонстрации CliApplication'
|
18
|
+
app.description = "CliApplication gem демо. #{app.shortdescription}"
|
19
|
+
|
20
|
+
app.help
|
21
|
+
|
22
|
+
app.run
|
23
|
+
exit(app.exitcode)
|
24
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
:name: app.rb
|
3
|
+
:shortdescription: ''
|
4
|
+
:version: ''
|
5
|
+
:releasedate: ''
|
6
|
+
:timezone: Moscow
|
7
|
+
:last_started_at: ''
|
8
|
+
:folders:
|
9
|
+
:avg:
|
10
|
+
:starts: 1
|
11
|
+
:executed_at: 0
|
12
|
+
:executed_at_human: 0 секунд
|
13
|
+
:memory: 41975808
|
14
|
+
:last:
|
15
|
+
:started_at: ''
|
16
|
+
:executed_at: 0
|
17
|
+
:executed_at_human: 0 секунд
|
18
|
+
:memory: 40.0 Мбайт
|
19
|
+
:exitcode: 0
|
20
|
+
:last10:
|
21
|
+
- ",0,0,40.0 Мбайт"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: utf-8
|
3
|
+
require './cli_example.rb'
|
4
|
+
|
5
|
+
class TestApp < CliExample
|
6
|
+
|
7
|
+
def main
|
8
|
+
puts "Hello, world!"
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
app = TestApp.new(ARGV, __dir__)
|
14
|
+
|
15
|
+
app.version = '1.0'
|
16
|
+
app.releasedate = '2018-01-06'
|
17
|
+
app.shortdescription = 'Тестовый скрипт демонстрации CliApplication'
|
18
|
+
app.description = "CliApplication gem демо. #{app.shortdescription}"
|
19
|
+
|
20
|
+
app.help
|
21
|
+
|
22
|
+
app.run
|
23
|
+
exit(app.exitcode)
|
24
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
:name: app.rb
|
3
|
+
:shortdescription: "Тестовый скрипт демонстрации CliApplication"
|
4
|
+
:version: '1.0'
|
5
|
+
:releasedate: '2018-01-06'
|
6
|
+
:timezone: Moscow
|
7
|
+
:last_started_at: '2018-01-06 23:26:28 +0300'
|
8
|
+
:folders:
|
9
|
+
:app: "/Users/Stan/Documents/Development/RubyMine/cli_application/test/log/03_log_section_type_none_ok"
|
10
|
+
:class: "/Users/Stan/Documents/Development/RubyMine/cli_application/test/log/03_log_section_type_none_ok"
|
11
|
+
:stat: "/Users/Stan/Documents/Development/RubyMine/cli_application/test/log/03_log_section_type_none_ok/stat"
|
12
|
+
:avg:
|
13
|
+
:starts: 3
|
14
|
+
:executed_at: 0.040108
|
15
|
+
:executed_at_human: 0.040108 секунд
|
16
|
+
:memory: 41891157
|
17
|
+
:last:
|
18
|
+
:started_at: '2018-01-06 23:26:28 +0300'
|
19
|
+
:executed_at: 0.054604
|
20
|
+
:executed_at_human: 0.054604 секунд
|
21
|
+
:memory: 40.1 Мбайт
|
22
|
+
:exitcode: 255
|
23
|
+
:last10:
|
24
|
+
- 2018-01-06 23:26:28 +0300,255,0.054604,40.1 Мбайт
|
25
|
+
- 2018-01-06 20:20:48 +0300,255,0.06572,39.7 Мбайт
|
26
|
+
- ",0,0,40.0 Мбайт"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: utf-8
|
3
|
+
require './cli_example.rb'
|
4
|
+
|
5
|
+
class TestApp < CliExample
|
6
|
+
|
7
|
+
def main
|
8
|
+
puts "Hello, world!"
|
9
|
+
0
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
app = TestApp.new(ARGV, __dir__)
|
15
|
+
|
16
|
+
app.version = '1.0'
|
17
|
+
app.releasedate = '2018-01-06'
|
18
|
+
app.shortdescription = 'Тестовый скрипт демонстрации CliApplication'
|
19
|
+
app.description = "CliApplication gem демо. #{app.shortdescription}"
|
20
|
+
|
21
|
+
app.help
|
22
|
+
|
23
|
+
app.run
|
24
|
+
exit(app.exitcode)
|
25
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
-- Запуск приложения ---------------------------
|
2
|
+
Приложение: /Users/Stan/Documents/Development/RubyMine/cli_application/test/log/04_log_section_type_file_ok/app.rb
|
3
|
+
Имя скрипта: app.rb
|
4
|
+
Приложение запущено: 2018-01-07 16:47:13 +0300
|
5
|
+
|
6
|
+
-- Пользовательская секция ---------------------
|
7
|
+
|
8
|
+
-- Завершение приложения -----------------------
|
9
|
+
Приложение завершено: 2018-01-07 16:47:13 +0300 (время выполнения: 0.045 сек.)
|
10
|
+
Использование памяти: 40.0 Мбайт
|
11
|
+
Результат завершения: 0 (SUCCESS)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
---
|
2
|
+
:name: app.rb
|
3
|
+
:shortdescription: "Тестовый скрипт демонстрации CliApplication"
|
4
|
+
:version: '1.0'
|
5
|
+
:releasedate: '2018-01-06'
|
6
|
+
:timezone: Moscow
|
7
|
+
:last_started_at: '2018-01-07 16:47:13 +0300'
|
8
|
+
:folders:
|
9
|
+
:app: "/Users/Stan/Documents/Development/RubyMine/cli_application/test/log/04_log_section_type_file_ok"
|
10
|
+
:class: "/Users/Stan/Documents/Development/RubyMine/cli_application/test/log/04_log_section_type_file_ok"
|
11
|
+
:stat: "/Users/Stan/Documents/Development/RubyMine/cli_application/test/log/04_log_section_type_file_ok/stat"
|
12
|
+
:avg:
|
13
|
+
:starts: 21
|
14
|
+
:executed_at: 0.062094
|
15
|
+
:executed_at_human: 0.062094 секунд
|
16
|
+
:memory: 41897590
|
17
|
+
:last:
|
18
|
+
:started_at: '2018-01-07 16:47:13 +0300'
|
19
|
+
:executed_at: 0.044499
|
20
|
+
:executed_at_human: 0.044499 секунд
|
21
|
+
:memory: 40.0 Мбайт
|
22
|
+
:exitcode: 0
|
23
|
+
:last10:
|
24
|
+
- 2018-01-07 16:47:13 +0300,0,0.044499,40.0 Мбайт
|
25
|
+
- 2018-01-07 00:00:13 +0300,0,0.066548,40.4 Мбайт
|
26
|
+
- 2018-01-06 23:59:57 +0300,255,0.089557,39.7 Мбайт
|
27
|
+
- 2018-01-06 23:54:52 +0300,255,0.088694,40.0 Мбайт
|
28
|
+
- 2018-01-06 23:51:19 +0300,255,0.085997,39.9 Мбайт
|
29
|
+
- 2018-01-06 23:32:03 +0300,255,0.051075,40.2 Мбайт
|
30
|
+
- 2018-01-06 23:30:44 +0300,255,0.075102,39.7 Мбайт
|
31
|
+
- 2018-01-06 23:27:03 +0300,255,0.079105,40.1 Мбайт
|
32
|
+
- 2018-01-06 23:24:07 +0300,255,0.056074,40.1 Мбайт
|
33
|
+
- 2018-01-06 23:23:17 +0300,255,0.057794,40.2 Мбайт
|
metadata
CHANGED
@@ -1,61 +1,61 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cli_application
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stan Zhuravlev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.9'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.9'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '10.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: st_tools
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0.4'
|
48
|
-
- - "
|
48
|
+
- - ">"
|
49
49
|
- !ruby/object:Gem::Version
|
50
50
|
version: '0.4'
|
51
51
|
type: :development
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
|
-
- - "
|
55
|
+
- - "~>"
|
56
56
|
- !ruby/object:Gem::Version
|
57
57
|
version: '0.4'
|
58
|
-
- - "
|
58
|
+
- - ">"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0.4'
|
61
61
|
- !ruby/object:Gem::Dependency
|
@@ -100,6 +100,13 @@ files:
|
|
100
100
|
- lib/cli_application/databases.rb
|
101
101
|
- lib/cli_application/includes.rb
|
102
102
|
- lib/cli_application/json_struct.rb
|
103
|
+
- lib/cli_application/locales/ru.yml
|
104
|
+
- lib/cli_application/log/README.md
|
105
|
+
- lib/cli_application/log/base.rb
|
106
|
+
- lib/cli_application/log/config.rb
|
107
|
+
- lib/cli_application/log/database.rb
|
108
|
+
- lib/cli_application/log/file.rb
|
109
|
+
- lib/cli_application/log/none.rb
|
103
110
|
- lib/cli_application/mail.rb
|
104
111
|
- lib/cli_application/mail_lib/base.rb
|
105
112
|
- lib/cli_application/mail_lib/error.rb
|
@@ -123,6 +130,18 @@ files:
|
|
123
130
|
- test/examples/7/app.rb
|
124
131
|
- test/examples/7/mail/app-mail-2015-06-10.txt
|
125
132
|
- test/examples/8/app.rb
|
133
|
+
- test/log/01_log_section_missing/app.rb
|
134
|
+
- test/log/01_log_section_missing/cli_example.rb
|
135
|
+
- test/log/02_log_section_type_wrong/app.rb
|
136
|
+
- test/log/02_log_section_type_wrong/cli_example.rb
|
137
|
+
- test/log/02_log_section_type_wrong/stat/app.yml
|
138
|
+
- test/log/03_log_section_type_none_ok/app.rb
|
139
|
+
- test/log/03_log_section_type_none_ok/cli_example.rb
|
140
|
+
- test/log/03_log_section_type_none_ok/stat/app.yml
|
141
|
+
- test/log/04_log_section_type_file_ok/app.rb
|
142
|
+
- test/log/04_log_section_type_file_ok/cli_example.rb
|
143
|
+
- test/log/04_log_section_type_file_ok/logs/app.log
|
144
|
+
- test/log/04_log_section_type_file_ok/stat/app.yml
|
126
145
|
- test/stat/rdebug-ide
|
127
146
|
- test/stat/test_app.yml
|
128
147
|
- test/test_app.rb
|