openc3 5.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +18 -0
  3. data/Guardfile +35 -0
  4. data/LICENSE.txt +727 -0
  5. data/README.md +37 -0
  6. data/Rakefile +131 -0
  7. data/bin/cstol_converter +1178 -0
  8. data/bin/openc3cli +531 -0
  9. data/bin/rubysloc +139 -0
  10. data/data/config/_array_params.yaml +23 -0
  11. data/data/config/_id_items.yaml +24 -0
  12. data/data/config/_id_params.yaml +58 -0
  13. data/data/config/_interfaces.yaml +214 -0
  14. data/data/config/_interfaces.yaml.err +1017 -0
  15. data/data/config/_items.yaml +20 -0
  16. data/data/config/_params.yaml +60 -0
  17. data/data/config/cmd_tlm_server.yaml +136 -0
  18. data/data/config/command.yaml +44 -0
  19. data/data/config/command_modifiers.yaml +160 -0
  20. data/data/config/command_telemetry.yaml +3 -0
  21. data/data/config/interface_modifiers.yaml +104 -0
  22. data/data/config/item_modifiers.yaml +221 -0
  23. data/data/config/microservice.yaml +78 -0
  24. data/data/config/param_item_modifiers.yaml +52 -0
  25. data/data/config/parameter_modifiers.yaml +200 -0
  26. data/data/config/plugins.yaml +80 -0
  27. data/data/config/protocols.yaml +290 -0
  28. data/data/config/screen.yaml +147 -0
  29. data/data/config/table_manager.yaml +89 -0
  30. data/data/config/table_parameter_modifiers.yaml +9 -0
  31. data/data/config/target.yaml +142 -0
  32. data/data/config/target_config.yaml +94 -0
  33. data/data/config/telemetry.yaml +87 -0
  34. data/data/config/telemetry_modifiers.yaml +159 -0
  35. data/data/config/tool.yaml +63 -0
  36. data/data/config/unknown.yaml +3 -0
  37. data/data/config/widgets.yaml +1505 -0
  38. data/ext/mkrf_conf.rb +49 -0
  39. data/ext/openc3/ext/array/array.c +122 -0
  40. data/ext/openc3/ext/array/extconf.rb +13 -0
  41. data/ext/openc3/ext/buffered_file/buffered_file.c +198 -0
  42. data/ext/openc3/ext/buffered_file/extconf.rb +13 -0
  43. data/ext/openc3/ext/config_parser/config_parser.c +280 -0
  44. data/ext/openc3/ext/config_parser/extconf.rb +13 -0
  45. data/ext/openc3/ext/crc/crc.c +351 -0
  46. data/ext/openc3/ext/crc/extconf.rb +13 -0
  47. data/ext/openc3/ext/openc3_io/extconf.rb +13 -0
  48. data/ext/openc3/ext/openc3_io/openc3_io.c +158 -0
  49. data/ext/openc3/ext/packet/extconf.rb +13 -0
  50. data/ext/openc3/ext/packet/packet.c +318 -0
  51. data/ext/openc3/ext/platform/extconf.rb +13 -0
  52. data/ext/openc3/ext/platform/platform.c +134 -0
  53. data/ext/openc3/ext/polynomial_conversion/extconf.rb +13 -0
  54. data/ext/openc3/ext/polynomial_conversion/polynomial_conversion.c +79 -0
  55. data/ext/openc3/ext/string/extconf.rb +13 -0
  56. data/ext/openc3/ext/string/string.c +63 -0
  57. data/ext/openc3/ext/structure/structure.c +1719 -0
  58. data/ext/openc3/ext/tabbed_plots_config/extconf.rb +13 -0
  59. data/ext/openc3/ext/tabbed_plots_config/tabbed_plots_config.c +62 -0
  60. data/ext/openc3/ext/telemetry/extconf.rb +13 -0
  61. data/ext/openc3/ext/telemetry/telemetry.c +336 -0
  62. data/lib/cosmos.rb +20 -0
  63. data/lib/cosmosc2.rb +20 -0
  64. data/lib/openc3/api/api.rb +39 -0
  65. data/lib/openc3/api/authorized_api.rb +30 -0
  66. data/lib/openc3/api/cmd_api.rb +451 -0
  67. data/lib/openc3/api/config_api.rb +58 -0
  68. data/lib/openc3/api/interface_api.rb +117 -0
  69. data/lib/openc3/api/limits_api.rb +375 -0
  70. data/lib/openc3/api/router_api.rb +117 -0
  71. data/lib/openc3/api/settings_api.rb +70 -0
  72. data/lib/openc3/api/target_api.rb +78 -0
  73. data/lib/openc3/api/tlm_api.rb +455 -0
  74. data/lib/openc3/bridge/bridge.rb +54 -0
  75. data/lib/openc3/bridge/bridge_config.rb +167 -0
  76. data/lib/openc3/bridge/bridge_interface_thread.rb +42 -0
  77. data/lib/openc3/bridge/bridge_router_thread.rb +42 -0
  78. data/lib/openc3/ccsds/ccsds_packet.rb +68 -0
  79. data/lib/openc3/ccsds/ccsds_parser.rb +148 -0
  80. data/lib/openc3/config/config_parser.rb +549 -0
  81. data/lib/openc3/config/meta_config_parser.rb +74 -0
  82. data/lib/openc3/conversions/conversion.rb +70 -0
  83. data/lib/openc3/conversions/generic_conversion.rb +83 -0
  84. data/lib/openc3/conversions/packet_time_formatted_conversion.rb +43 -0
  85. data/lib/openc3/conversions/packet_time_seconds_conversion.rb +43 -0
  86. data/lib/openc3/conversions/polynomial_conversion.rb +87 -0
  87. data/lib/openc3/conversions/processor_conversion.rb +70 -0
  88. data/lib/openc3/conversions/received_count_conversion.rb +38 -0
  89. data/lib/openc3/conversions/received_time_formatted_conversion.rb +42 -0
  90. data/lib/openc3/conversions/received_time_seconds_conversion.rb +42 -0
  91. data/lib/openc3/conversions/segmented_polynomial_conversion.rb +171 -0
  92. data/lib/openc3/conversions/unix_time_conversion.rb +68 -0
  93. data/lib/openc3/conversions/unix_time_formatted_conversion.rb +49 -0
  94. data/lib/openc3/conversions/unix_time_seconds_conversion.rb +49 -0
  95. data/lib/openc3/conversions.rb +34 -0
  96. data/lib/openc3/core_ext/array.rb +416 -0
  97. data/lib/openc3/core_ext/binding.rb +29 -0
  98. data/lib/openc3/core_ext/class.rb +72 -0
  99. data/lib/openc3/core_ext/exception.rb +61 -0
  100. data/lib/openc3/core_ext/file.rb +83 -0
  101. data/lib/openc3/core_ext/hash.rb +37 -0
  102. data/lib/openc3/core_ext/io.rb +134 -0
  103. data/lib/openc3/core_ext/kernel.rb +42 -0
  104. data/lib/openc3/core_ext/math.rb +128 -0
  105. data/lib/openc3/core_ext/matrix.rb +156 -0
  106. data/lib/openc3/core_ext/objectspace.rb +36 -0
  107. data/lib/openc3/core_ext/openc3_io.rb +57 -0
  108. data/lib/openc3/core_ext/range.rb +27 -0
  109. data/lib/openc3/core_ext/socket.rb +38 -0
  110. data/lib/openc3/core_ext/string.rb +389 -0
  111. data/lib/openc3/core_ext/stringio.rb +33 -0
  112. data/lib/openc3/core_ext/time.rb +508 -0
  113. data/lib/openc3/core_ext.rb +36 -0
  114. data/lib/openc3/interfaces/interface.rb +498 -0
  115. data/lib/openc3/interfaces/linc_interface.rb +475 -0
  116. data/lib/openc3/interfaces/protocols/burst_protocol.rb +192 -0
  117. data/lib/openc3/interfaces/protocols/crc_protocol.rb +193 -0
  118. data/lib/openc3/interfaces/protocols/fixed_protocol.rb +155 -0
  119. data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +56 -0
  120. data/lib/openc3/interfaces/protocols/length_protocol.rb +165 -0
  121. data/lib/openc3/interfaces/protocols/override_protocol.rb +60 -0
  122. data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +206 -0
  123. data/lib/openc3/interfaces/protocols/protocol.rb +82 -0
  124. data/lib/openc3/interfaces/protocols/template_protocol.rb +261 -0
  125. data/lib/openc3/interfaces/protocols/terminated_protocol.rb +93 -0
  126. data/lib/openc3/interfaces/serial_interface.rb +94 -0
  127. data/lib/openc3/interfaces/simulated_target_interface.rb +168 -0
  128. data/lib/openc3/interfaces/stream_interface.rb +81 -0
  129. data/lib/openc3/interfaces/tcpip_client_interface.rb +69 -0
  130. data/lib/openc3/interfaces/tcpip_server_interface.rb +629 -0
  131. data/lib/openc3/interfaces/udp_interface.rb +169 -0
  132. data/lib/openc3/interfaces.rb +44 -0
  133. data/lib/openc3/io/buffered_file.rb +109 -0
  134. data/lib/openc3/io/io_multiplexer.rb +80 -0
  135. data/lib/openc3/io/json_api_object.rb +208 -0
  136. data/lib/openc3/io/json_drb.rb +335 -0
  137. data/lib/openc3/io/json_drb_object.rb +114 -0
  138. data/lib/openc3/io/json_drb_rack.rb +84 -0
  139. data/lib/openc3/io/json_rpc.rb +420 -0
  140. data/lib/openc3/io/openc3_snmp.rb +58 -0
  141. data/lib/openc3/io/posix_serial_driver.rb +156 -0
  142. data/lib/openc3/io/raw_logger.rb +167 -0
  143. data/lib/openc3/io/raw_logger_pair.rb +77 -0
  144. data/lib/openc3/io/serial_driver.rb +105 -0
  145. data/lib/openc3/io/stderr.rb +43 -0
  146. data/lib/openc3/io/stdout.rb +43 -0
  147. data/lib/openc3/io/udp_sockets.rb +194 -0
  148. data/lib/openc3/io/win32_serial_driver.rb +196 -0
  149. data/lib/openc3/logs/log_writer.rb +302 -0
  150. data/lib/openc3/logs/packet_log_constants.rb +62 -0
  151. data/lib/openc3/logs/packet_log_reader.rb +345 -0
  152. data/lib/openc3/logs/packet_log_writer.rb +299 -0
  153. data/lib/openc3/logs/text_log_writer.rb +68 -0
  154. data/lib/openc3/logs.rb +25 -0
  155. data/lib/openc3/microservices/cleanup_microservice.rb +68 -0
  156. data/lib/openc3/microservices/decom_microservice.rb +136 -0
  157. data/lib/openc3/microservices/interface_microservice.rb +532 -0
  158. data/lib/openc3/microservices/log_microservice.rb +108 -0
  159. data/lib/openc3/microservices/microservice.rb +204 -0
  160. data/lib/openc3/microservices/plugin_microservice.rb +43 -0
  161. data/lib/openc3/microservices/reaction_microservice.rb +541 -0
  162. data/lib/openc3/microservices/reducer_microservice.rb +313 -0
  163. data/lib/openc3/microservices/router_microservice.rb +44 -0
  164. data/lib/openc3/microservices/text_log_microservice.rb +84 -0
  165. data/lib/openc3/microservices/timeline_microservice.rb +363 -0
  166. data/lib/openc3/microservices/trigger_group_microservice.rb +638 -0
  167. data/lib/openc3/models/activity_model.rb +319 -0
  168. data/lib/openc3/models/auth_model.rb +65 -0
  169. data/lib/openc3/models/cvt_model.rb +185 -0
  170. data/lib/openc3/models/environment_model.rb +58 -0
  171. data/lib/openc3/models/gem_model.rb +137 -0
  172. data/lib/openc3/models/info_model.rb +31 -0
  173. data/lib/openc3/models/interface_model.rb +281 -0
  174. data/lib/openc3/models/interface_status_model.rb +117 -0
  175. data/lib/openc3/models/metadata_model.rb +139 -0
  176. data/lib/openc3/models/metric_model.rb +59 -0
  177. data/lib/openc3/models/microservice_model.rb +206 -0
  178. data/lib/openc3/models/microservice_status_model.rb +74 -0
  179. data/lib/openc3/models/model.rb +204 -0
  180. data/lib/openc3/models/note_model.rb +122 -0
  181. data/lib/openc3/models/notification_model.rb +40 -0
  182. data/lib/openc3/models/ping_model.rb +35 -0
  183. data/lib/openc3/models/plugin_model.rb +292 -0
  184. data/lib/openc3/models/process_status_model.rb +76 -0
  185. data/lib/openc3/models/reaction_model.rb +322 -0
  186. data/lib/openc3/models/reducer_model.rb +65 -0
  187. data/lib/openc3/models/router_model.rb +35 -0
  188. data/lib/openc3/models/router_status_model.rb +27 -0
  189. data/lib/openc3/models/scope_model.rb +153 -0
  190. data/lib/openc3/models/settings_model.rb +55 -0
  191. data/lib/openc3/models/sorted_model.rb +167 -0
  192. data/lib/openc3/models/target_model.rb +759 -0
  193. data/lib/openc3/models/timeline_model.rb +154 -0
  194. data/lib/openc3/models/tool_config_model.rb +38 -0
  195. data/lib/openc3/models/tool_model.rb +262 -0
  196. data/lib/openc3/models/trigger_group_model.rb +186 -0
  197. data/lib/openc3/models/trigger_model.rb +330 -0
  198. data/lib/openc3/models/widget_model.rb +138 -0
  199. data/lib/openc3/operators/microservice_operator.rb +128 -0
  200. data/lib/openc3/operators/operator.rb +277 -0
  201. data/lib/openc3/packets/binary_accessor.rb +1207 -0
  202. data/lib/openc3/packets/commands.rb +373 -0
  203. data/lib/openc3/packets/json_packet.rb +134 -0
  204. data/lib/openc3/packets/limits.rb +271 -0
  205. data/lib/openc3/packets/limits_response.rb +53 -0
  206. data/lib/openc3/packets/packet.rb +1168 -0
  207. data/lib/openc3/packets/packet_config.rb +625 -0
  208. data/lib/openc3/packets/packet_item.rb +586 -0
  209. data/lib/openc3/packets/packet_item_limits.rb +162 -0
  210. data/lib/openc3/packets/parsers/format_string_parser.rb +65 -0
  211. data/lib/openc3/packets/parsers/limits_parser.rb +159 -0
  212. data/lib/openc3/packets/parsers/limits_response_parser.rb +61 -0
  213. data/lib/openc3/packets/parsers/packet_item_parser.rb +272 -0
  214. data/lib/openc3/packets/parsers/packet_parser.rb +134 -0
  215. data/lib/openc3/packets/parsers/processor_parser.rb +73 -0
  216. data/lib/openc3/packets/parsers/state_parser.rb +127 -0
  217. data/lib/openc3/packets/parsers/xtce_converter.rb +442 -0
  218. data/lib/openc3/packets/parsers/xtce_parser.rb +722 -0
  219. data/lib/openc3/packets/structure.rb +553 -0
  220. data/lib/openc3/packets/structure_item.rb +365 -0
  221. data/lib/openc3/packets/telemetry.rb +487 -0
  222. data/lib/openc3/processors/processor.rb +86 -0
  223. data/lib/openc3/processors/statistics_processor.rb +82 -0
  224. data/lib/openc3/processors/watermark_processor.rb +58 -0
  225. data/lib/openc3/processors.rb +24 -0
  226. data/lib/openc3/script/api_shared.rb +828 -0
  227. data/lib/openc3/script/calendar.rb +89 -0
  228. data/lib/openc3/script/commands.rb +227 -0
  229. data/lib/openc3/script/exceptions.rb +29 -0
  230. data/lib/openc3/script/extract.rb +161 -0
  231. data/lib/openc3/script/limits.rb +60 -0
  232. data/lib/openc3/script/script.rb +299 -0
  233. data/lib/openc3/script/script_runner.rb +238 -0
  234. data/lib/openc3/script/storage.rb +146 -0
  235. data/lib/openc3/script/suite.rb +542 -0
  236. data/lib/openc3/script/suite_results.rb +196 -0
  237. data/lib/openc3/script/suite_runner.rb +217 -0
  238. data/lib/openc3/script.rb +21 -0
  239. data/lib/openc3/streams/serial_stream.rb +167 -0
  240. data/lib/openc3/streams/stream.rb +63 -0
  241. data/lib/openc3/streams/tcpip_client_stream.rb +116 -0
  242. data/lib/openc3/streams/tcpip_socket_stream.rb +195 -0
  243. data/lib/openc3/system/system.rb +127 -0
  244. data/lib/openc3/system/system_config.rb +411 -0
  245. data/lib/openc3/system/target.rb +269 -0
  246. data/lib/openc3/system.rb +24 -0
  247. data/lib/openc3/tools/cmd_tlm_server/api.rb +20 -0
  248. data/lib/openc3/tools/cmd_tlm_server/cmd_tlm_server_config.rb +320 -0
  249. data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +294 -0
  250. data/lib/openc3/tools/table_manager/table.rb +77 -0
  251. data/lib/openc3/tools/table_manager/table_config.rb +273 -0
  252. data/lib/openc3/tools/table_manager/table_item.rb +90 -0
  253. data/lib/openc3/tools/table_manager/table_item_parser.rb +66 -0
  254. data/lib/openc3/tools/table_manager/table_manager_core.rb +333 -0
  255. data/lib/openc3/tools/table_manager/table_parser.rb +93 -0
  256. data/lib/openc3/tools/test_runner/test.rb +67 -0
  257. data/lib/openc3/top_level.rb +595 -0
  258. data/lib/openc3/topics/autonomic_topic.rb +52 -0
  259. data/lib/openc3/topics/calendar_topic.rb +44 -0
  260. data/lib/openc3/topics/command_decom_topic.rb +76 -0
  261. data/lib/openc3/topics/command_topic.rb +83 -0
  262. data/lib/openc3/topics/config_topic.rb +68 -0
  263. data/lib/openc3/topics/interface_topic.rb +73 -0
  264. data/lib/openc3/topics/limits_event_topic.rb +109 -0
  265. data/lib/openc3/topics/notifications_topic.rb +28 -0
  266. data/lib/openc3/topics/router_topic.rb +85 -0
  267. data/lib/openc3/topics/telemetry_decom_topic.rb +54 -0
  268. data/lib/openc3/topics/telemetry_topic.rb +36 -0
  269. data/lib/openc3/topics/timeline_topic.rb +45 -0
  270. data/lib/openc3/topics/topic.rb +53 -0
  271. data/lib/openc3/utilities/authentication.rb +141 -0
  272. data/lib/openc3/utilities/authorization.rb +51 -0
  273. data/lib/openc3/utilities/crc.rb +278 -0
  274. data/lib/openc3/utilities/csv.rb +153 -0
  275. data/lib/openc3/utilities/logger.rb +187 -0
  276. data/lib/openc3/utilities/message_log.rb +91 -0
  277. data/lib/openc3/utilities/metric.rb +141 -0
  278. data/lib/openc3/utilities/process_manager.rb +139 -0
  279. data/lib/openc3/utilities/quaternion.rb +257 -0
  280. data/lib/openc3/utilities/ruby_lex_utils.rb +568 -0
  281. data/lib/openc3/utilities/s3.rb +202 -0
  282. data/lib/openc3/utilities/s3_autoload.rb +9 -0
  283. data/lib/openc3/utilities/s3_file_cache.rb +274 -0
  284. data/lib/openc3/utilities/simulated_target.rb +117 -0
  285. data/lib/openc3/utilities/sleeper.rb +51 -0
  286. data/lib/openc3/utilities/store.rb +23 -0
  287. data/lib/openc3/utilities/store_autoload.rb +237 -0
  288. data/lib/openc3/utilities/zip.rb +21 -0
  289. data/lib/openc3/utilities.rb +35 -0
  290. data/lib/openc3/version.rb +14 -0
  291. data/lib/openc3/win32/excel.rb +132 -0
  292. data/lib/openc3/win32/win32.rb +402 -0
  293. data/lib/openc3/win32/win32_main.rb +333 -0
  294. data/lib/openc3.rb +49 -0
  295. data/tasks/gemfile_stats.rake +113 -0
  296. data/tasks/spec.rake +30 -0
  297. data/templates/plugin-template/README.md +15 -0
  298. data/templates/plugin-template/Rakefile +12 -0
  299. data/templates/plugin-template/plugin.gemspec +23 -0
  300. data/templates/plugin-template/plugin.txt +9 -0
  301. data/templates/plugin-template/targets/TARGET/cmd_tlm/cmd.txt +8 -0
  302. data/templates/plugin-template/targets/TARGET/cmd_tlm/tlm.txt +8 -0
  303. data/templates/plugin-template/targets/TARGET/lib/target.rb +10 -0
  304. data/templates/plugin-template/targets/TARGET/procedures/procedure.rb +3 -0
  305. data/templates/plugin-template/targets/TARGET/screens/status.txt +9 -0
  306. data/templates/plugin-template/targets/TARGET/target.txt +5 -0
  307. 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