openc3 5.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +18 -0
- data/Guardfile +35 -0
- data/LICENSE.txt +727 -0
- data/README.md +37 -0
- data/Rakefile +131 -0
- data/bin/cstol_converter +1178 -0
- data/bin/openc3cli +531 -0
- data/bin/rubysloc +139 -0
- data/data/config/_array_params.yaml +23 -0
- data/data/config/_id_items.yaml +24 -0
- data/data/config/_id_params.yaml +58 -0
- data/data/config/_interfaces.yaml +214 -0
- data/data/config/_interfaces.yaml.err +1017 -0
- data/data/config/_items.yaml +20 -0
- data/data/config/_params.yaml +60 -0
- data/data/config/cmd_tlm_server.yaml +136 -0
- data/data/config/command.yaml +44 -0
- data/data/config/command_modifiers.yaml +160 -0
- data/data/config/command_telemetry.yaml +3 -0
- data/data/config/interface_modifiers.yaml +104 -0
- data/data/config/item_modifiers.yaml +221 -0
- data/data/config/microservice.yaml +78 -0
- data/data/config/param_item_modifiers.yaml +52 -0
- data/data/config/parameter_modifiers.yaml +200 -0
- data/data/config/plugins.yaml +80 -0
- data/data/config/protocols.yaml +290 -0
- data/data/config/screen.yaml +147 -0
- data/data/config/table_manager.yaml +89 -0
- data/data/config/table_parameter_modifiers.yaml +9 -0
- data/data/config/target.yaml +142 -0
- data/data/config/target_config.yaml +94 -0
- data/data/config/telemetry.yaml +87 -0
- data/data/config/telemetry_modifiers.yaml +159 -0
- data/data/config/tool.yaml +63 -0
- data/data/config/unknown.yaml +3 -0
- data/data/config/widgets.yaml +1505 -0
- data/ext/mkrf_conf.rb +49 -0
- data/ext/openc3/ext/array/array.c +122 -0
- data/ext/openc3/ext/array/extconf.rb +13 -0
- data/ext/openc3/ext/buffered_file/buffered_file.c +198 -0
- data/ext/openc3/ext/buffered_file/extconf.rb +13 -0
- data/ext/openc3/ext/config_parser/config_parser.c +280 -0
- data/ext/openc3/ext/config_parser/extconf.rb +13 -0
- data/ext/openc3/ext/crc/crc.c +351 -0
- data/ext/openc3/ext/crc/extconf.rb +13 -0
- data/ext/openc3/ext/openc3_io/extconf.rb +13 -0
- data/ext/openc3/ext/openc3_io/openc3_io.c +158 -0
- data/ext/openc3/ext/packet/extconf.rb +13 -0
- data/ext/openc3/ext/packet/packet.c +318 -0
- data/ext/openc3/ext/platform/extconf.rb +13 -0
- data/ext/openc3/ext/platform/platform.c +134 -0
- data/ext/openc3/ext/polynomial_conversion/extconf.rb +13 -0
- data/ext/openc3/ext/polynomial_conversion/polynomial_conversion.c +79 -0
- data/ext/openc3/ext/string/extconf.rb +13 -0
- data/ext/openc3/ext/string/string.c +63 -0
- data/ext/openc3/ext/structure/structure.c +1719 -0
- data/ext/openc3/ext/tabbed_plots_config/extconf.rb +13 -0
- data/ext/openc3/ext/tabbed_plots_config/tabbed_plots_config.c +62 -0
- data/ext/openc3/ext/telemetry/extconf.rb +13 -0
- data/ext/openc3/ext/telemetry/telemetry.c +336 -0
- data/lib/cosmos.rb +20 -0
- data/lib/cosmosc2.rb +20 -0
- data/lib/openc3/api/api.rb +39 -0
- data/lib/openc3/api/authorized_api.rb +30 -0
- data/lib/openc3/api/cmd_api.rb +451 -0
- data/lib/openc3/api/config_api.rb +58 -0
- data/lib/openc3/api/interface_api.rb +117 -0
- data/lib/openc3/api/limits_api.rb +375 -0
- data/lib/openc3/api/router_api.rb +117 -0
- data/lib/openc3/api/settings_api.rb +70 -0
- data/lib/openc3/api/target_api.rb +78 -0
- data/lib/openc3/api/tlm_api.rb +455 -0
- data/lib/openc3/bridge/bridge.rb +54 -0
- data/lib/openc3/bridge/bridge_config.rb +167 -0
- data/lib/openc3/bridge/bridge_interface_thread.rb +42 -0
- data/lib/openc3/bridge/bridge_router_thread.rb +42 -0
- data/lib/openc3/ccsds/ccsds_packet.rb +68 -0
- data/lib/openc3/ccsds/ccsds_parser.rb +148 -0
- data/lib/openc3/config/config_parser.rb +549 -0
- data/lib/openc3/config/meta_config_parser.rb +74 -0
- data/lib/openc3/conversions/conversion.rb +70 -0
- data/lib/openc3/conversions/generic_conversion.rb +83 -0
- data/lib/openc3/conversions/packet_time_formatted_conversion.rb +43 -0
- data/lib/openc3/conversions/packet_time_seconds_conversion.rb +43 -0
- data/lib/openc3/conversions/polynomial_conversion.rb +87 -0
- data/lib/openc3/conversions/processor_conversion.rb +70 -0
- data/lib/openc3/conversions/received_count_conversion.rb +38 -0
- data/lib/openc3/conversions/received_time_formatted_conversion.rb +42 -0
- data/lib/openc3/conversions/received_time_seconds_conversion.rb +42 -0
- data/lib/openc3/conversions/segmented_polynomial_conversion.rb +171 -0
- data/lib/openc3/conversions/unix_time_conversion.rb +68 -0
- data/lib/openc3/conversions/unix_time_formatted_conversion.rb +49 -0
- data/lib/openc3/conversions/unix_time_seconds_conversion.rb +49 -0
- data/lib/openc3/conversions.rb +34 -0
- data/lib/openc3/core_ext/array.rb +416 -0
- data/lib/openc3/core_ext/binding.rb +29 -0
- data/lib/openc3/core_ext/class.rb +72 -0
- data/lib/openc3/core_ext/exception.rb +61 -0
- data/lib/openc3/core_ext/file.rb +83 -0
- data/lib/openc3/core_ext/hash.rb +37 -0
- data/lib/openc3/core_ext/io.rb +134 -0
- data/lib/openc3/core_ext/kernel.rb +42 -0
- data/lib/openc3/core_ext/math.rb +128 -0
- data/lib/openc3/core_ext/matrix.rb +156 -0
- data/lib/openc3/core_ext/objectspace.rb +36 -0
- data/lib/openc3/core_ext/openc3_io.rb +57 -0
- data/lib/openc3/core_ext/range.rb +27 -0
- data/lib/openc3/core_ext/socket.rb +38 -0
- data/lib/openc3/core_ext/string.rb +389 -0
- data/lib/openc3/core_ext/stringio.rb +33 -0
- data/lib/openc3/core_ext/time.rb +508 -0
- data/lib/openc3/core_ext.rb +36 -0
- data/lib/openc3/interfaces/interface.rb +498 -0
- data/lib/openc3/interfaces/linc_interface.rb +475 -0
- data/lib/openc3/interfaces/protocols/burst_protocol.rb +192 -0
- data/lib/openc3/interfaces/protocols/crc_protocol.rb +193 -0
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +155 -0
- data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +56 -0
- data/lib/openc3/interfaces/protocols/length_protocol.rb +165 -0
- data/lib/openc3/interfaces/protocols/override_protocol.rb +60 -0
- data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +206 -0
- data/lib/openc3/interfaces/protocols/protocol.rb +82 -0
- data/lib/openc3/interfaces/protocols/template_protocol.rb +261 -0
- data/lib/openc3/interfaces/protocols/terminated_protocol.rb +93 -0
- data/lib/openc3/interfaces/serial_interface.rb +94 -0
- data/lib/openc3/interfaces/simulated_target_interface.rb +168 -0
- data/lib/openc3/interfaces/stream_interface.rb +81 -0
- data/lib/openc3/interfaces/tcpip_client_interface.rb +69 -0
- data/lib/openc3/interfaces/tcpip_server_interface.rb +629 -0
- data/lib/openc3/interfaces/udp_interface.rb +169 -0
- data/lib/openc3/interfaces.rb +44 -0
- data/lib/openc3/io/buffered_file.rb +109 -0
- data/lib/openc3/io/io_multiplexer.rb +80 -0
- data/lib/openc3/io/json_api_object.rb +208 -0
- data/lib/openc3/io/json_drb.rb +335 -0
- data/lib/openc3/io/json_drb_object.rb +114 -0
- data/lib/openc3/io/json_drb_rack.rb +84 -0
- data/lib/openc3/io/json_rpc.rb +420 -0
- data/lib/openc3/io/openc3_snmp.rb +58 -0
- data/lib/openc3/io/posix_serial_driver.rb +156 -0
- data/lib/openc3/io/raw_logger.rb +167 -0
- data/lib/openc3/io/raw_logger_pair.rb +77 -0
- data/lib/openc3/io/serial_driver.rb +105 -0
- data/lib/openc3/io/stderr.rb +43 -0
- data/lib/openc3/io/stdout.rb +43 -0
- data/lib/openc3/io/udp_sockets.rb +194 -0
- data/lib/openc3/io/win32_serial_driver.rb +196 -0
- data/lib/openc3/logs/log_writer.rb +302 -0
- data/lib/openc3/logs/packet_log_constants.rb +62 -0
- data/lib/openc3/logs/packet_log_reader.rb +345 -0
- data/lib/openc3/logs/packet_log_writer.rb +299 -0
- data/lib/openc3/logs/text_log_writer.rb +68 -0
- data/lib/openc3/logs.rb +25 -0
- data/lib/openc3/microservices/cleanup_microservice.rb +68 -0
- data/lib/openc3/microservices/decom_microservice.rb +136 -0
- data/lib/openc3/microservices/interface_microservice.rb +532 -0
- data/lib/openc3/microservices/log_microservice.rb +108 -0
- data/lib/openc3/microservices/microservice.rb +204 -0
- data/lib/openc3/microservices/plugin_microservice.rb +43 -0
- data/lib/openc3/microservices/reaction_microservice.rb +541 -0
- data/lib/openc3/microservices/reducer_microservice.rb +313 -0
- data/lib/openc3/microservices/router_microservice.rb +44 -0
- data/lib/openc3/microservices/text_log_microservice.rb +84 -0
- data/lib/openc3/microservices/timeline_microservice.rb +363 -0
- data/lib/openc3/microservices/trigger_group_microservice.rb +638 -0
- data/lib/openc3/models/activity_model.rb +319 -0
- data/lib/openc3/models/auth_model.rb +65 -0
- data/lib/openc3/models/cvt_model.rb +185 -0
- data/lib/openc3/models/environment_model.rb +58 -0
- data/lib/openc3/models/gem_model.rb +137 -0
- data/lib/openc3/models/info_model.rb +31 -0
- data/lib/openc3/models/interface_model.rb +281 -0
- data/lib/openc3/models/interface_status_model.rb +117 -0
- data/lib/openc3/models/metadata_model.rb +139 -0
- data/lib/openc3/models/metric_model.rb +59 -0
- data/lib/openc3/models/microservice_model.rb +206 -0
- data/lib/openc3/models/microservice_status_model.rb +74 -0
- data/lib/openc3/models/model.rb +204 -0
- data/lib/openc3/models/note_model.rb +122 -0
- data/lib/openc3/models/notification_model.rb +40 -0
- data/lib/openc3/models/ping_model.rb +35 -0
- data/lib/openc3/models/plugin_model.rb +292 -0
- data/lib/openc3/models/process_status_model.rb +76 -0
- data/lib/openc3/models/reaction_model.rb +322 -0
- data/lib/openc3/models/reducer_model.rb +65 -0
- data/lib/openc3/models/router_model.rb +35 -0
- data/lib/openc3/models/router_status_model.rb +27 -0
- data/lib/openc3/models/scope_model.rb +153 -0
- data/lib/openc3/models/settings_model.rb +55 -0
- data/lib/openc3/models/sorted_model.rb +167 -0
- data/lib/openc3/models/target_model.rb +759 -0
- data/lib/openc3/models/timeline_model.rb +154 -0
- data/lib/openc3/models/tool_config_model.rb +38 -0
- data/lib/openc3/models/tool_model.rb +262 -0
- data/lib/openc3/models/trigger_group_model.rb +186 -0
- data/lib/openc3/models/trigger_model.rb +330 -0
- data/lib/openc3/models/widget_model.rb +138 -0
- data/lib/openc3/operators/microservice_operator.rb +128 -0
- data/lib/openc3/operators/operator.rb +277 -0
- data/lib/openc3/packets/binary_accessor.rb +1207 -0
- data/lib/openc3/packets/commands.rb +373 -0
- data/lib/openc3/packets/json_packet.rb +134 -0
- data/lib/openc3/packets/limits.rb +271 -0
- data/lib/openc3/packets/limits_response.rb +53 -0
- data/lib/openc3/packets/packet.rb +1168 -0
- data/lib/openc3/packets/packet_config.rb +625 -0
- data/lib/openc3/packets/packet_item.rb +586 -0
- data/lib/openc3/packets/packet_item_limits.rb +162 -0
- data/lib/openc3/packets/parsers/format_string_parser.rb +65 -0
- data/lib/openc3/packets/parsers/limits_parser.rb +159 -0
- data/lib/openc3/packets/parsers/limits_response_parser.rb +61 -0
- data/lib/openc3/packets/parsers/packet_item_parser.rb +272 -0
- data/lib/openc3/packets/parsers/packet_parser.rb +134 -0
- data/lib/openc3/packets/parsers/processor_parser.rb +73 -0
- data/lib/openc3/packets/parsers/state_parser.rb +127 -0
- data/lib/openc3/packets/parsers/xtce_converter.rb +442 -0
- data/lib/openc3/packets/parsers/xtce_parser.rb +722 -0
- data/lib/openc3/packets/structure.rb +553 -0
- data/lib/openc3/packets/structure_item.rb +365 -0
- data/lib/openc3/packets/telemetry.rb +487 -0
- data/lib/openc3/processors/processor.rb +86 -0
- data/lib/openc3/processors/statistics_processor.rb +82 -0
- data/lib/openc3/processors/watermark_processor.rb +58 -0
- data/lib/openc3/processors.rb +24 -0
- data/lib/openc3/script/api_shared.rb +828 -0
- data/lib/openc3/script/calendar.rb +89 -0
- data/lib/openc3/script/commands.rb +227 -0
- data/lib/openc3/script/exceptions.rb +29 -0
- data/lib/openc3/script/extract.rb +161 -0
- data/lib/openc3/script/limits.rb +60 -0
- data/lib/openc3/script/script.rb +299 -0
- data/lib/openc3/script/script_runner.rb +238 -0
- data/lib/openc3/script/storage.rb +146 -0
- data/lib/openc3/script/suite.rb +542 -0
- data/lib/openc3/script/suite_results.rb +196 -0
- data/lib/openc3/script/suite_runner.rb +217 -0
- data/lib/openc3/script.rb +21 -0
- data/lib/openc3/streams/serial_stream.rb +167 -0
- data/lib/openc3/streams/stream.rb +63 -0
- data/lib/openc3/streams/tcpip_client_stream.rb +116 -0
- data/lib/openc3/streams/tcpip_socket_stream.rb +195 -0
- data/lib/openc3/system/system.rb +127 -0
- data/lib/openc3/system/system_config.rb +411 -0
- data/lib/openc3/system/target.rb +269 -0
- data/lib/openc3/system.rb +24 -0
- data/lib/openc3/tools/cmd_tlm_server/api.rb +20 -0
- data/lib/openc3/tools/cmd_tlm_server/cmd_tlm_server_config.rb +320 -0
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +294 -0
- data/lib/openc3/tools/table_manager/table.rb +77 -0
- data/lib/openc3/tools/table_manager/table_config.rb +273 -0
- data/lib/openc3/tools/table_manager/table_item.rb +90 -0
- data/lib/openc3/tools/table_manager/table_item_parser.rb +66 -0
- data/lib/openc3/tools/table_manager/table_manager_core.rb +333 -0
- data/lib/openc3/tools/table_manager/table_parser.rb +93 -0
- data/lib/openc3/tools/test_runner/test.rb +67 -0
- data/lib/openc3/top_level.rb +595 -0
- data/lib/openc3/topics/autonomic_topic.rb +52 -0
- data/lib/openc3/topics/calendar_topic.rb +44 -0
- data/lib/openc3/topics/command_decom_topic.rb +76 -0
- data/lib/openc3/topics/command_topic.rb +83 -0
- data/lib/openc3/topics/config_topic.rb +68 -0
- data/lib/openc3/topics/interface_topic.rb +73 -0
- data/lib/openc3/topics/limits_event_topic.rb +109 -0
- data/lib/openc3/topics/notifications_topic.rb +28 -0
- data/lib/openc3/topics/router_topic.rb +85 -0
- data/lib/openc3/topics/telemetry_decom_topic.rb +54 -0
- data/lib/openc3/topics/telemetry_topic.rb +36 -0
- data/lib/openc3/topics/timeline_topic.rb +45 -0
- data/lib/openc3/topics/topic.rb +53 -0
- data/lib/openc3/utilities/authentication.rb +141 -0
- data/lib/openc3/utilities/authorization.rb +51 -0
- data/lib/openc3/utilities/crc.rb +278 -0
- data/lib/openc3/utilities/csv.rb +153 -0
- data/lib/openc3/utilities/logger.rb +187 -0
- data/lib/openc3/utilities/message_log.rb +91 -0
- data/lib/openc3/utilities/metric.rb +141 -0
- data/lib/openc3/utilities/process_manager.rb +139 -0
- data/lib/openc3/utilities/quaternion.rb +257 -0
- data/lib/openc3/utilities/ruby_lex_utils.rb +568 -0
- data/lib/openc3/utilities/s3.rb +202 -0
- data/lib/openc3/utilities/s3_autoload.rb +9 -0
- data/lib/openc3/utilities/s3_file_cache.rb +274 -0
- data/lib/openc3/utilities/simulated_target.rb +117 -0
- data/lib/openc3/utilities/sleeper.rb +51 -0
- data/lib/openc3/utilities/store.rb +23 -0
- data/lib/openc3/utilities/store_autoload.rb +237 -0
- data/lib/openc3/utilities/zip.rb +21 -0
- data/lib/openc3/utilities.rb +35 -0
- data/lib/openc3/version.rb +14 -0
- data/lib/openc3/win32/excel.rb +132 -0
- data/lib/openc3/win32/win32.rb +402 -0
- data/lib/openc3/win32/win32_main.rb +333 -0
- data/lib/openc3.rb +49 -0
- data/tasks/gemfile_stats.rake +113 -0
- data/tasks/spec.rake +30 -0
- data/templates/plugin-template/README.md +15 -0
- data/templates/plugin-template/Rakefile +12 -0
- data/templates/plugin-template/plugin.gemspec +23 -0
- data/templates/plugin-template/plugin.txt +9 -0
- data/templates/plugin-template/targets/TARGET/cmd_tlm/cmd.txt +8 -0
- data/templates/plugin-template/targets/TARGET/cmd_tlm/tlm.txt +8 -0
- data/templates/plugin-template/targets/TARGET/lib/target.rb +10 -0
- data/templates/plugin-template/targets/TARGET/procedures/procedure.rb +3 -0
- data/templates/plugin-template/targets/TARGET/screens/status.txt +9 -0
- data/templates/plugin-template/targets/TARGET/target.txt +5 -0
- metadata +849 -0
@@ -0,0 +1,187 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
|
16
|
+
# Modified by OpenC3, Inc.
|
17
|
+
# All changes Copyright 2022, OpenC3, Inc.
|
18
|
+
# All Rights Reserved
|
19
|
+
|
20
|
+
require 'openc3/core_ext/class'
|
21
|
+
require 'openc3/core_ext/time'
|
22
|
+
require 'openc3/topics/topic'
|
23
|
+
require 'socket'
|
24
|
+
require 'logger'
|
25
|
+
require 'time'
|
26
|
+
require 'json'
|
27
|
+
|
28
|
+
module OpenC3
|
29
|
+
# Supports different levels of logging and only writes if the level
|
30
|
+
# is exceeded.
|
31
|
+
class Logger
|
32
|
+
# @return [Boolean] Whether to output the message to stdout
|
33
|
+
instance_attr_accessor :stdout
|
34
|
+
|
35
|
+
# @return [Integer] The logging level
|
36
|
+
instance_attr_accessor :level
|
37
|
+
|
38
|
+
# @return [String] Additional detail to add to messages
|
39
|
+
instance_attr_accessor :detail_string
|
40
|
+
|
41
|
+
# @return [String] Fluent tag
|
42
|
+
instance_attr_accessor :tag
|
43
|
+
|
44
|
+
# @return [String] Microservice name
|
45
|
+
instance_attr_accessor :microservice_name
|
46
|
+
|
47
|
+
# @return [String] Scope
|
48
|
+
instance_attr_accessor :scope
|
49
|
+
|
50
|
+
@@mutex = Mutex.new
|
51
|
+
@@instance = nil
|
52
|
+
|
53
|
+
# DEBUG only prints DEBUG messages
|
54
|
+
DEBUG = ::Logger::DEBUG
|
55
|
+
# INFO prints INFO, DEBUG messages
|
56
|
+
INFO = ::Logger::INFO
|
57
|
+
# WARN prints WARN, INFO, DEBUG messages
|
58
|
+
WARN = ::Logger::WARN
|
59
|
+
# ERROR prints ERROR, WARN, INFO, DEBUG messages
|
60
|
+
ERROR = ::Logger::ERROR
|
61
|
+
# FATAL prints FATAL, ERROR, WARN, INFO, DEBUG messages
|
62
|
+
FATAL = ::Logger::FATAL
|
63
|
+
|
64
|
+
DEBUG_SEVERITY_STRING = 'DEBUG'
|
65
|
+
INFO_SEVERITY_STRING = 'INFO'
|
66
|
+
WARN_SEVERITY_STRING = 'WARN'
|
67
|
+
ERROR_SEVERITY_STRING = 'ERROR'
|
68
|
+
FATAL_SEVERITY_STRING = 'FATAL'
|
69
|
+
|
70
|
+
# @param level [Integer] The initial logging level
|
71
|
+
def initialize(level = Logger::INFO)
|
72
|
+
@stdout = true
|
73
|
+
@level = level
|
74
|
+
@scope = nil
|
75
|
+
@detail_string = nil
|
76
|
+
@container_name = Socket.gethostname
|
77
|
+
@microservice_name = nil
|
78
|
+
@tag = @container_name + ".log"
|
79
|
+
@mutex = Mutex.new
|
80
|
+
@no_store = ENV['OPENC3_NO_STORE']
|
81
|
+
end
|
82
|
+
|
83
|
+
# @param message [String] The message to print if the log level is at or
|
84
|
+
# below the method name log level.
|
85
|
+
# @param block [Proc] Block to call which should return a string to append
|
86
|
+
# to the log message
|
87
|
+
def debug(message = nil, scope: @scope, user: nil, &block)
|
88
|
+
log_message(DEBUG_SEVERITY_STRING, message, scope: scope, user: user, &block) if @level <= DEBUG
|
89
|
+
end
|
90
|
+
|
91
|
+
# (see #debug)
|
92
|
+
def info(message = nil, scope: @scope, user: nil, &block)
|
93
|
+
log_message(INFO_SEVERITY_STRING, message, scope: scope, user: user, &block) if @level <= INFO
|
94
|
+
end
|
95
|
+
|
96
|
+
# (see #debug)
|
97
|
+
def warn(message = nil, scope: @scope, user: nil, &block)
|
98
|
+
log_message(WARN_SEVERITY_STRING, message, scope: scope, user: user, &block) if @level <= WARN
|
99
|
+
end
|
100
|
+
|
101
|
+
# (see #debug)
|
102
|
+
def error(message = nil, scope: @scope, user: nil, &block)
|
103
|
+
log_message(ERROR_SEVERITY_STRING, message, scope: scope, user: user, &block) if @level <= ERROR
|
104
|
+
end
|
105
|
+
|
106
|
+
# (see #debug)
|
107
|
+
def fatal(message = nil, scope: @scope, user: nil, &block)
|
108
|
+
log_message(FATAL_SEVERITY_STRING, message, scope: scope, user: user, &block) if @level <= FATAL
|
109
|
+
end
|
110
|
+
|
111
|
+
# (see #debug)
|
112
|
+
def self.debug(message = nil, scope: nil, user: nil, &block)
|
113
|
+
args = {}
|
114
|
+
args[:scope] = scope if scope
|
115
|
+
args[:user] = user if user
|
116
|
+
self.instance.debug(message, **args, &block)
|
117
|
+
end
|
118
|
+
|
119
|
+
# (see #debug)
|
120
|
+
def self.info(message = nil, scope: nil, user: nil, &block)
|
121
|
+
args = {}
|
122
|
+
args[:scope] = scope if scope
|
123
|
+
args[:user] = user if user
|
124
|
+
self.instance.info(message, **args, &block)
|
125
|
+
end
|
126
|
+
|
127
|
+
# (see #debug)
|
128
|
+
def self.warn(message = nil, scope: nil, user: nil, &block)
|
129
|
+
args = {}
|
130
|
+
args[:scope] = scope if scope
|
131
|
+
args[:user] = user if user
|
132
|
+
self.instance.warn(message, **args, &block)
|
133
|
+
end
|
134
|
+
|
135
|
+
# (see #debug)
|
136
|
+
def self.error(message = nil, scope: nil, user: nil, &block)
|
137
|
+
args = {}
|
138
|
+
args[:scope] = scope if scope
|
139
|
+
args[:user] = user if user
|
140
|
+
self.instance.error(message, **args, &block)
|
141
|
+
end
|
142
|
+
|
143
|
+
# (see #debug)
|
144
|
+
def self.fatal(message = nil, scope: nil, user: nil, &block)
|
145
|
+
args = {}
|
146
|
+
args[:scope] = scope if scope
|
147
|
+
args[:user] = user if user
|
148
|
+
self.instance.fatal(message, **args, &block)
|
149
|
+
end
|
150
|
+
|
151
|
+
# @return [Logger] The logger instance
|
152
|
+
def self.instance
|
153
|
+
return @@instance if @@instance
|
154
|
+
|
155
|
+
@@mutex.synchronize do
|
156
|
+
@@instance ||= self.new
|
157
|
+
end
|
158
|
+
@@instance
|
159
|
+
end
|
160
|
+
|
161
|
+
protected
|
162
|
+
|
163
|
+
def log_message(severity_string, message, scope:, user:)
|
164
|
+
@mutex.synchronize do
|
165
|
+
data = { time: Time.now.to_nsec_from_epoch, '@timestamp' => Time.now.xmlschema(3), severity: severity_string }
|
166
|
+
data[:microservice_name] = @microservice_name if @microservice_name
|
167
|
+
data[:detail] = @detail_string if @detail_string
|
168
|
+
data[:user] = user['name'] || 'Unknown' if user # EE: If a user is passed, put its name ('Unknown' if it doesn't have a name). Don't include user data if no user was passed
|
169
|
+
if block_given?
|
170
|
+
message = yield
|
171
|
+
end
|
172
|
+
data[:container_name] = @container_name
|
173
|
+
data[:log] = message
|
174
|
+
puts data.as_json(:allow_nan => true).to_json(:allow_nan => true) if @stdout
|
175
|
+
unless @no_store
|
176
|
+
if scope
|
177
|
+
Topic.write_topic("#{scope}__openc3_log_messages", data)
|
178
|
+
else
|
179
|
+
# The base openc3_log_messages doesn't have an associated logger
|
180
|
+
# so it must be limited to prevent unbounded stream growth
|
181
|
+
Topic.write_topic("openc3_log_messages", data, '*', 1000)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
|
16
|
+
# Modified by OpenC3, Inc.
|
17
|
+
# All changes Copyright 2022, OpenC3, Inc.
|
18
|
+
# All Rights Reserved
|
19
|
+
|
20
|
+
require 'openc3/config/config_parser'
|
21
|
+
require 'openc3/system/system'
|
22
|
+
require 'fileutils'
|
23
|
+
require 'openc3/utilities/s3'
|
24
|
+
|
25
|
+
module OpenC3
|
26
|
+
# Handles writing message logs to a file
|
27
|
+
class MessageLog
|
28
|
+
# @return [String] The name of the message log file. Empty string until the
|
29
|
+
# write or start methods are called at which point it is set to the
|
30
|
+
# filename. Retains the last filename even after stop is called.
|
31
|
+
attr_reader :filename
|
32
|
+
|
33
|
+
# @param tool_name [String] The name of the tool creating the message log.
|
34
|
+
# This will be inserted into the message log filename to help identify it.
|
35
|
+
# @param log_dir [String] The filesystem path to store the message log file.
|
36
|
+
def initialize(tool_name, log_dir, scope:)
|
37
|
+
@remote_log_directory = "#{scope}/tool_logs/#{tool_name}/"
|
38
|
+
@tool_name = tool_name
|
39
|
+
@log_dir = log_dir
|
40
|
+
@filename = ''
|
41
|
+
@file = nil
|
42
|
+
@start_day = nil
|
43
|
+
@mutex = Mutex.new
|
44
|
+
end
|
45
|
+
|
46
|
+
# Ensures the log file is opened and ready to write. It then writes the
|
47
|
+
# message to the log and flushes it to force the write.
|
48
|
+
#
|
49
|
+
# @param message [String] Message to write to the log
|
50
|
+
def write(message, flush = false)
|
51
|
+
@mutex.synchronize do
|
52
|
+
if @file.nil? or @file.closed? or (not File.exist?(@filename))
|
53
|
+
start(false)
|
54
|
+
end
|
55
|
+
|
56
|
+
@file.write(message)
|
57
|
+
@file.flush if flush
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Closes the message log and marks it read only
|
62
|
+
def stop(take_mutex = true, s3_object_metadata: {})
|
63
|
+
@mutex.lock if take_mutex
|
64
|
+
if @file and not @file.closed?
|
65
|
+
@file.close
|
66
|
+
File.chmod(0444, @filename)
|
67
|
+
s3_key = File.join(@remote_log_directory, @start_day, File.basename(@filename))
|
68
|
+
begin
|
69
|
+
thread = S3Utilities.move_log_file_to_s3(@filename, s3_key, metadata: s3_object_metadata)
|
70
|
+
thread.join
|
71
|
+
rescue StandardError => e
|
72
|
+
Logger.error e.formatted
|
73
|
+
end
|
74
|
+
end
|
75
|
+
@mutex.unlock if take_mutex
|
76
|
+
end
|
77
|
+
|
78
|
+
# Creates a new message log and sets the filename
|
79
|
+
def start(take_mutex = true)
|
80
|
+
@mutex.lock if take_mutex
|
81
|
+
# Prevent starting files too fast
|
82
|
+
sleep(0.1) until !File.exist?(File.join(@log_dir, File.build_timestamped_filename([@tool_name, 'messages'])))
|
83
|
+
stop(false)
|
84
|
+
timed_filename = File.build_timestamped_filename([@tool_name, 'messages'])
|
85
|
+
@start_day = timed_filename[0..9].gsub("_", "") # YYYYMMDD
|
86
|
+
@filename = File.join(@log_dir, timed_filename)
|
87
|
+
@file = File.open(@filename, 'a')
|
88
|
+
@mutex.unlock if take_mutex
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
|
16
|
+
# Modified by OpenC3, Inc.
|
17
|
+
# All changes Copyright 2022, OpenC3, Inc.
|
18
|
+
# All Rights Reserved
|
19
|
+
|
20
|
+
require 'openc3/models/metric_model'
|
21
|
+
require 'thread'
|
22
|
+
|
23
|
+
module OpenC3
|
24
|
+
class Metric
|
25
|
+
# This class is designed to output metrics to the openc3-cmd-tlm-api
|
26
|
+
# InternalMetricsController. Output format can be read about here
|
27
|
+
# https://prometheus.io/docs/concepts/data_model/
|
28
|
+
#
|
29
|
+
# Warning contains some sorcery.
|
30
|
+
#
|
31
|
+
# examples:
|
32
|
+
# TYPE foobar histogram
|
33
|
+
# HELP foobar internal metric generated from openc3/utilities/metric.rb
|
34
|
+
# foobar{code="200",method="get",path="/metrics"} 5.0
|
35
|
+
#
|
36
|
+
# items = {"name|labels" => [value_array], ...}
|
37
|
+
|
38
|
+
attr_reader :items
|
39
|
+
attr_accessor :size
|
40
|
+
attr_reader :scope
|
41
|
+
attr_reader :microservice
|
42
|
+
|
43
|
+
def initialize(microservice:, scope:)
|
44
|
+
if microservice.include? '|' or scope.include? '|'
|
45
|
+
raise ArgumentError.new('invalid input must not contain: |')
|
46
|
+
end
|
47
|
+
|
48
|
+
@items = {}
|
49
|
+
@scope = scope
|
50
|
+
@microservice = microservice
|
51
|
+
@size = 5000
|
52
|
+
@mutex = Mutex.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_sample(name:, value:, labels:)
|
56
|
+
# add a value to the metric to report out later or a seperate thread
|
57
|
+
# name is a string often function_name_duration_seconds
|
58
|
+
# name: debug_duration_seconds
|
59
|
+
# value is a numerical value to add to a round robin array.
|
60
|
+
# value: 0.1211
|
61
|
+
# labels is a hash of values that could have an effect on the value.
|
62
|
+
# labels: {"code"=>200,"method"=>"get","path"=>"/metrics"}
|
63
|
+
# internal:
|
64
|
+
# the internal items hash is used as a lookup table to store unique
|
65
|
+
# varients of a similar metric. these varients are values that could
|
66
|
+
# cause a difference in run time to add context to the metric. the
|
67
|
+
# microservice and scope are added to the labels the labels are
|
68
|
+
# converted to a string and joined with the name to create a unique
|
69
|
+
# metric item. this is looked up in the items hash and if not found
|
70
|
+
# the key is created and an array of size @size is allocated. then
|
71
|
+
# the value is added to @items and the count of the value is increased
|
72
|
+
# if the count of the values exceed the size of the array it sets the
|
73
|
+
# count back to zero and the array will over write older data.
|
74
|
+
@mutex.synchronize do
|
75
|
+
key = "#{name}|" + labels.map { |k, v| "#{k}=#{v}" }.join(',')
|
76
|
+
if not @items.has_key?(key)
|
77
|
+
Logger.debug("new data for #{@scope}, #{key}")
|
78
|
+
@items[key] = { 'values' => Array.new(@size), 'count' => 0 }
|
79
|
+
end
|
80
|
+
count = @items[key]['count']
|
81
|
+
# Logger.info("adding data for #{@scope}, #{count} #{key}, #{value}")
|
82
|
+
@items[key]['values'][count] = value
|
83
|
+
@items[key]['count'] = count + 1 >= @size ? 0 : count + 1
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def percentile(sorted_values, percentile)
|
88
|
+
# get the percentile out of an ordered array
|
89
|
+
len = sorted_values.length
|
90
|
+
return sorted_values.first if len == 1
|
91
|
+
|
92
|
+
k = ((percentile / 100.0) * (len - 1) + 1).floor - 1
|
93
|
+
f = ((percentile / 100.0) * (len - 1) + 1).modulo(1)
|
94
|
+
return sorted_values[k] + (f * (sorted_values[k + 1] - sorted_values[k]))
|
95
|
+
end
|
96
|
+
|
97
|
+
def output
|
98
|
+
# Output percentile based metrics to Redis under the key of the
|
99
|
+
# #{@scope}__openc3__metric we will use hset with a subkey.
|
100
|
+
# internal:
|
101
|
+
# loop over the key value pairs within the @items hash, remove nil
|
102
|
+
# and sort the values added via the add_sample method. calculate the
|
103
|
+
# different percentiles. the labels are still only contained in the
|
104
|
+
# key of the @items hash to extract these you split the key on | the
|
105
|
+
# name|labels then to make the labels back into a hash we split the ,
|
106
|
+
# into an array ["foo=bar", ...] and split again this time on the =
|
107
|
+
# into [["foo","bar"], ...] to map the internal array into a hash
|
108
|
+
# [{"foo"=>"bar"}, ...] finally reducing the array into a single hash
|
109
|
+
# to add the percentile and percentile value. this hash is added to an
|
110
|
+
# array. to store the array as the value with the metric name again joined
|
111
|
+
# with the @microservice and @scope.
|
112
|
+
Logger.debug("#{@microservice} #{@scope} sending metrics to redis, #{@items.length}") if @items.length > 0
|
113
|
+
@mutex.synchronize do
|
114
|
+
@items.each do |key, values|
|
115
|
+
label_list = []
|
116
|
+
name, labels = key.split('|')
|
117
|
+
metric_labels = labels.nil? ? {} : labels.split(',').map { |x| x.split('=') }.map { |k, v| { k => v } }.reduce({}, :merge)
|
118
|
+
sorted_values = values['values'].compact.sort
|
119
|
+
for percentile_value in [10, 50, 90, 95, 99]
|
120
|
+
percentile_result = percentile(sorted_values, percentile_value)
|
121
|
+
labels = metric_labels.clone.merge({ 'scope' => @scope, 'microservice' => @microservice })
|
122
|
+
labels['percentile'] = percentile_value
|
123
|
+
labels['metric__value'] = percentile_result
|
124
|
+
label_list.append(labels)
|
125
|
+
end
|
126
|
+
begin
|
127
|
+
Logger.debug("sending metrics summary to redis key: #{@microservice}")
|
128
|
+
metric = MetricModel.new(name: @microservice, scope: @scope, metric_name: name, label_list: label_list)
|
129
|
+
metric.create(force: true)
|
130
|
+
rescue RuntimeError
|
131
|
+
Logger.error("failed attempt to update metric, #{key}, #{name} #{@scope}")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def destroy
|
138
|
+
MetricModel.destroy(scope: @scope, name: @microservice)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
|
16
|
+
# Modified by OpenC3, Inc.
|
17
|
+
# All changes Copyright 2022, OpenC3, Inc.
|
18
|
+
# All Rights Reserved
|
19
|
+
|
20
|
+
require 'openc3/operators/operator'
|
21
|
+
require 'openc3/models/process_status_model'
|
22
|
+
require 'openc3/models/scope_model'
|
23
|
+
require 'openc3/utilities/logger'
|
24
|
+
require 'socket'
|
25
|
+
|
26
|
+
module OpenC3
|
27
|
+
class ProcessManagerProcess < OperatorProcess
|
28
|
+
attr_accessor :process_type
|
29
|
+
attr_accessor :detail
|
30
|
+
attr_accessor :expires_at
|
31
|
+
attr_accessor :status
|
32
|
+
|
33
|
+
def initialize(cmd_array, process_type, detail, expires_at, **kw_args)
|
34
|
+
super(cmd_array, **kw_args)
|
35
|
+
@process_type = process_type
|
36
|
+
@detail = detail
|
37
|
+
@expires_at = expires_at
|
38
|
+
@status = nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def start
|
42
|
+
super()
|
43
|
+
if @process
|
44
|
+
@status = ProcessStatusModel.new(name: "#{Socket.gethostname}__#{@process.pid}", process_type: @process_type, detail: @detail, state: "Running", scope: @scope)
|
45
|
+
@status.create
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Spawns short lived processes and ensures they complete
|
51
|
+
class ProcessManager
|
52
|
+
MONITOR_CYCLE_SECONDS = 10
|
53
|
+
CLEANUP_CYCLE_SECONDS = 600
|
54
|
+
|
55
|
+
@@instance = nil
|
56
|
+
|
57
|
+
def self.instance
|
58
|
+
@@instance = ProcessManager.new unless @@instance
|
59
|
+
return @@instance
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize
|
63
|
+
@processes = []
|
64
|
+
@monitor_thread = Thread.new do
|
65
|
+
begin
|
66
|
+
monitor()
|
67
|
+
rescue => err
|
68
|
+
raise "ProcessManager unexpectedly died\n#{err.formatted}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def spawn(cmd_array, process_type, detail, expires_at, **kw_args)
|
74
|
+
process = ProcessManagerProcess.new(cmd_array, process_type, detail, expires_at, **kw_args)
|
75
|
+
process.start
|
76
|
+
@processes << process
|
77
|
+
end
|
78
|
+
|
79
|
+
def monitor
|
80
|
+
processes_to_delete = []
|
81
|
+
cleanup_time = Time.now
|
82
|
+
while true
|
83
|
+
current_time = Time.now
|
84
|
+
|
85
|
+
# Monitor Active Processes
|
86
|
+
@processes.each do |process|
|
87
|
+
# Check if the process is still alive
|
88
|
+
if !process.alive?
|
89
|
+
if process.exit_code != 0
|
90
|
+
process.status.state = "Crashed"
|
91
|
+
else
|
92
|
+
process.status.state = "Complete"
|
93
|
+
end
|
94
|
+
output = process.extract_output
|
95
|
+
process.status.output = output
|
96
|
+
process.hard_stop
|
97
|
+
processes_to_delete << process
|
98
|
+
elsif process.expires_at < current_time
|
99
|
+
process.status.state = "Expired"
|
100
|
+
output = process.extract_output
|
101
|
+
process.status.output = output
|
102
|
+
process.hard_stop
|
103
|
+
processes_to_delete << process
|
104
|
+
end
|
105
|
+
|
106
|
+
# Update Process Status
|
107
|
+
process.status.update
|
108
|
+
end
|
109
|
+
processes_to_delete.each do |process|
|
110
|
+
if process.status.state == "Complete"
|
111
|
+
Logger.info "Process #{process.status.name}:#{process.process_type}:#{process.detail} completed with state #{process.status.state}"
|
112
|
+
else
|
113
|
+
Logger.error "Process #{process.status.name}:#{process.process_type}:#{process.detail} completed with state #{process.status.state}"
|
114
|
+
Logger.error "Process Output:\n#{process.status.output}"
|
115
|
+
end
|
116
|
+
|
117
|
+
@processes.delete(process)
|
118
|
+
end
|
119
|
+
processes_to_delete.clear
|
120
|
+
|
121
|
+
# Cleanup Old Process Status
|
122
|
+
if (current_time - cleanup_time) > CLEANUP_CYCLE_SECONDS
|
123
|
+
scopes = ScopeModel.names
|
124
|
+
scopes.each do |scope|
|
125
|
+
statuses = ProcessStatusModel.get_all_models(scope: scope)
|
126
|
+
statuses.each do |status_name, status|
|
127
|
+
if (current_time - Time.from_nsec_from_epoch(status.updated_at)) > CLEANUP_CYCLE_SECONDS
|
128
|
+
status.destroy
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
sleep(MONITOR_CYCLE_SECONDS)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|