libadc-cxx 1.0.0
Structured logging for scientific computing
Loading...
Searching...
No Matches
file.ipp
Go to the documentation of this file.
3#include <cstdlib>
4#include <iostream>
5#include <fstream>
6#include <filesystem>
7
8namespace adc {
9
10using std::cout;
11
12typedef std::string string;
13typedef std::string_view string_view;
14
15
16/*! \brief File output publisher_api implementation.
17 This plugin generates writes each message to the configured file, with
18 <json></json> delimiters surrounding it.
19 The output directory is "." by default, but may be overriden with
20 a full path defined in env("ADC_FILE_PLUGIN_DIRECTORY").
21 The file name is adc.file_plugin.log by default, and may be overridden
22 with a path name in env("ADC_FILE_PLUGIN_FILE").
23 The file is overwritten when the file_plugin is created, unless
24 env("ADC_FILE_PLUGIN_APPEND") is "true".
25 Debugging output is enabled if
26 env("ADC_FILE_PLUGIN_DEBUG") is a number greater than 0.
27
28 Multiple independent file publishers may be created; if the same file name
29 and directory are used for distinct instances, output file content
30 is undefined.
31 */
32class file_plugin : public publisher_api {
33 enum state {
34 ok,
35 err
36 };
37 enum mode {
38 /* the next mode needed for correct operation */
39 pi_config,
40 pi_init,
41 pi_pub_or_final
42 };
43
44private:
45 inline static const std::map< const string, const string > plugin_file_config_defaults =
46 {{ "DIRECTORY", "."},
47 { "FILE", "adc.file_plugin.log" },
48 { "DEBUG", "0" },
49 { "APPEND", "false" }
50 };
51 inline static const char *plugin_file_prefix = "ADC_FILE_PLUGIN_";
52 const string vers;
53 const std::vector<string> tags;
54 string fname;
55 string fdir;
56 bool fappend;
57 std::ofstream out;
58 int debug;
59 enum state state;
60 bool paused;
61 enum mode mode;
62
63 int config(const string dir, const string file, bool append, const string& sdebug) {
64 if (mode != pi_config)
65 return 2;
66 fname = file;
67 fappend = append;
68 fdir = dir;
69 mode = pi_init;
70 std::stringstream ss(sdebug);
71 ss >> debug;
72 if (debug < 0) {
73 debug = 0;
74 }
75 if (debug > 0) {
76 std::cout<< "file plugin configured" <<std::endl;
77 }
78 return 0;
79 }
80
81 // find field in m, then with prefix in env, then the default.
82 const string get(const std::map< string, string >& m,
83 string field, string_view env_prefix) {
84 // fields not defined in config_defaults raise an exception.
85 auto it = m.find(field);
86 if (it != m.end()) {
87 return it->second;
88 }
89 string en = string(env_prefix) += field;
90 char *ec = getenv(en.c_str());
91 if (!ec) {
92 return plugin_file_config_defaults.at(field);
93 } else {
94 return string(ec);
95 }
96 }
97
98
99public:
100 file_plugin() : vers("1.0.0") , tags({"none"}), fappend(false), debug(0),
101 state(ok), paused(false), mode(pi_config) { }
102
103 int publish(std::shared_ptr<builder_api> b) {
104 if (paused)
105 return 0;
106 if (state != ok)
107 return 1;
108 if (mode != pi_pub_or_final)
109 return 2;
110 // write to stream
111 if (out.good()) {
112 out << "<json>" << b->serialize() << "</json>" << std::endl;
113 if (debug) {
114 std::cout << "'file' wrote" << std::endl;
115 }
116 return 0;
117 }
118 if (debug) {
119 std::cout << "plugin 'file' failed out.good" << std::endl;
120 }
121 return 1;
122 }
123
124 int config(const std::map< std::string, std::string >& m) {
125 return config(m, plugin_file_prefix);
126 }
127
128 int config(const std::map< std::string, std::string >& m, string_view env_prefix) {
129 bool app = ( get(m, "APPEND", env_prefix) == "true");
130 string d = get(m, "DIRECTORY", env_prefix);
131 string f = get(m, "FILE", env_prefix);
132 string sdebug = get(m, "DEBUG", env_prefix);
133 return config(d, std::move(f), app, sdebug);
134 }
135
136 const std::map< const std::string, const std::string> & get_option_defaults() {
137 return plugin_file_config_defaults;
138 }
139
141 std::map <string, string >m;
142 // config if never config'd
143 if (!fname.size())
144 config(m);
145 if (mode != pi_init) {
146 return 2;
147 }
148 if ( state == err ) {
149 std::cout << "file plugin initialize found pre-existing error" << std::endl;
150 return 3;
151 }
152 std::error_code ec;
153 std::filesystem::create_directories(fdir, ec);
154 if (ec.value() != 0 && ec.value() != EEXIST ) {
155 state = err;
156 std::cout << "unable to create output directory for plugin 'file'; "
157 << fdir << " : " << ec.message() << std::endl;
158 return ec.value();
159 }
160 string fpath = fdir + "/" + fname;
161 // open dump file; messages are null separated, not endl separated, as content may include \n.
162 out.open(fpath, std::ofstream::out |
163 (fappend ? std::ofstream::app : std::ofstream::trunc));
164 if (out.good()) {
165 mode = pi_pub_or_final;
166 return 0;
167 }
168 state = err;
169 return EBADF;
170 }
171
172 void finalize() {
173 if (mode == pi_pub_or_final) {
174 state = ok;
175 paused = false;
176 mode = pi_config;
177 out.close();
178 } else {
179 if (debug) {
180 std::cout << "file plugin finalize on non-running plugin" << std::endl;
181 }
182 }
183 }
184
185 void pause() {
186 paused = true;
187 }
188
189 void resume() {
190 paused = false;
191 }
192
194 return "file";
195 }
196
198 return vers;
199 }
200
202 if (debug) {
203 std::cout << "Destructing file_plugin" << std::endl;
204 }
205 }
206};
207
208} // adc
File output publisher_api implementation. This plugin generates writes each message to the configured...
Definition file.ipp:32
void resume()
Resume publishing Duplicate calls are allowed.
Definition file.ipp:189
void pause()
Pause publishing until a call to resume. Duplicate calls are allowed.
Definition file.ipp:185
int initialize()
Ready the plugin to publish following the configuration options set or defaulted.
Definition file.ipp:140
string_view version() const
Definition file.ipp:197
void finalize()
Stop publishing and release any resources held for managing publication.
Definition file.ipp:172
int config(const std::map< std::string, std::string > &m)
Configure the plugin with the options given.
Definition file.ipp:124
int publish(std::shared_ptr< builder_api > b)
Publish the content of the builder.
Definition file.ipp:103
const std::map< const std::string, const std::string > & get_option_defaults()
Look up the settable options and their defaults.
Definition file.ipp:136
int config(const std::map< std::string, std::string > &m, string_view env_prefix)
Configure the plugin with the options given and the corresponding environment variables.
Definition file.ipp:128
string_view name() const
Definition file.ipp:193
Publisher plugin interface.
Definition publisher.hpp:44
Definition adc.hpp:75
std::string_view string_view
Definition curl.ipp:14
std::string string
Definition curl.ipp:13