FlightGear next
logger.cxx
Go to the documentation of this file.
1// logger.cxx - log properties.
2// Written by David Megginson, started 2002.
3//
4// This file is in the Public Domain, and comes with no warranty.
5
6#ifdef HAVE_CONFIG_H
7# include "config.h"
8#endif
9
10#include "logger.hxx"
11
12#include <ios>
13#include <string>
14#include <cstdlib>
15
16#include <simgear/debug/logstream.hxx>
17#include <simgear/io/iostreams/sgstream.hxx>
18#include <simgear/misc/sg_path.hxx>
19
20#include "fg_props.hxx"
21#include "globals.hxx"
22
23using std::string;
24using std::endl;
25
26
28// Implementation of FGLogger
30
31void
33{
34 SGPropertyNode * logging = fgGetNode("/logging");
35 if (logging == 0)
36 return;
37
38 std::vector<SGPropertyNode_ptr> children = logging->getChildren("log");
39 _logs.reserve(children.size());
40
41 for (const auto& child: children) {
42 if (!child->getBoolValue("enabled", false))
43 continue;
44
45 string filename = child->getStringValue("filename");
46 if (filename.empty()) {
47 filename = "fg_log.csv";
48 child->setStringValue("filename", filename.c_str());
49 }
50
51 // Security: the path comes from the global Property Tree; it *must* be
52 // validated before we overwrite the file.
53 const SGPath authorizedPath = SGPath::fromUtf8(filename).validate(
54 /* write */ true);
55
56 if (authorizedPath.isNull()) {
57 const string propertyPath = child->getChild("filename")
58 ->getPath(/* simplify */ true);
59 const string msg =
60 "The FGLogger logging system, via the '" + propertyPath + "' property, "
61 "was asked to write to '" + filename + "', however this path is not "
62 "authorized for writing anymore for security reasons. " +
63 "Please choose another location, for instance in the $FG_HOME/Export "
64 "folder (" + (globals->get_fg_home() / "Export").utf8Str() + ").";
65
66 SG_LOG(SG_GENERAL, SG_ALERT, msg);
67 return;
68 }
69
70 _logs.emplace_back(new Log());
71 Log &log = *_logs.back();
72
73 string delimiter = child->getStringValue("delimiter");
74 if (delimiter.empty()) {
75 delimiter = ",";
76 child->setStringValue("delimiter", delimiter.c_str());
77 }
78
79 log.interval_ms = child->getLongValue("interval-ms");
80 log.last_time_ms = globals->get_sim_time_sec() * 1000;
81 log.delimiter = delimiter.c_str()[0];
82 // Security: use the return value of SGPath::validate()
83 log.output.reset(new sg_ofstream(authorizedPath, std::ios_base::out));
84 if ( !(*log.output) ) {
85 SG_LOG(SG_GENERAL, SG_ALERT, "Cannot write log to " << filename);
86 _logs.pop_back();
87 continue;
88 }
89
90 //
91 // Process the individual entries (Time is automatic).
92 //
93 std::vector<SGPropertyNode_ptr> entries = child->getChildren("entry");
94 (*log.output) << "Time";
95 for (unsigned int j = 0; j < entries.size(); j++) {
96 SGPropertyNode * entry = entries[j];
97
98 //
99 // Set up defaults.
100 //
101 if (!entry->hasValue("property")) {
102 entry->setBoolValue("enabled", false);
103 continue;
104 }
105
106 if (!entry->getBoolValue("enabled"))
107 continue;
108
109 SGPropertyNode * node =
110 fgGetNode(entry->getStringValue("property"), true);
111 log.nodes.push_back(node);
112 (*log.output) << log.delimiter
113 << entry->getStringValue("title", node->getPath().c_str());
114 }
115 (*log.output) << endl;
116 }
117}
118
119void
121{
122 _logs.clear();
123 init();
124}
125
126void
128{
129}
130
131void
133{
134}
135
136void
138{
139 double sim_time_sec = globals->get_sim_time_sec();
140 double sim_time_ms = sim_time_sec * 1000;
141 for (unsigned int i = 0; i < _logs.size(); i++) {
142 while ((sim_time_ms - _logs[i]->last_time_ms) >= _logs[i]->interval_ms) {
143 _logs[i]->last_time_ms += _logs[i]->interval_ms;
144 (*_logs[i]->output) << sim_time_sec;
145 for (unsigned int j = 0; j < _logs[i]->nodes.size(); j++) {
146 (*_logs[i]->output) << _logs[i]->delimiter
147 << _logs[i]->nodes[j]->getStringValue();
148 }
149 (*_logs[i]->output) << endl;
150 }
151 }
152}
153
154
156// Implementation of FGLogger::Log
158
159FGLogger::Log::Log ()
160 : interval_ms(0),
161 last_time_ms(-999999.0),
162 delimiter(',')
163{
164}
165
166
167// Register the subsystem.
168SGSubsystemMgr::Registrant<FGLogger> registrantFGLogger;
169
170// end of logger.cxx
#define i(x)
void init() override
Definition logger.cxx:32
void reinit() override
Definition logger.cxx:120
void bind() override
Definition logger.cxx:127
void update(double dt) override
Definition logger.cxx:137
void unbind() override
Definition logger.cxx:132
FGGlobals * globals
Definition globals.cxx:142
SGSubsystemMgr::Registrant< FGLogger > registrantFGLogger
Definition logger.cxx:168
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
Definition proptest.cpp:27