Line data Source code
1 : #include "cetlib/PluginTypeDeducer.h"
2 : #include "cetlib/ostream_handle.h"
3 : #include "fhiclcpp/ParameterSet.h"
4 : #include "fhiclcpp/types/ConfigurationTable.h"
5 :
6 : #include "cetlib/compiler_macros.h"
7 : #include "messagefacility/MessageService/ELdestination.h"
8 : #include "messagefacility/Utilities/ELseverityLevel.h"
9 : #include "messagefacility/Utilities/exception.h"
10 :
11 : #include <fstream>
12 :
13 : namespace mfplugins {
14 : using mf::ErrorObj;
15 : using mf::service::ELdestination;
16 :
17 : /// <summary>
18 : /// Message Facility Destination which automatically opens files and sorts messages into them based on given criteria
19 : /// </summary>
20 : class ELMultiFileOutput : public ELdestination
21 : {
22 : public:
23 : /**
24 : * \brief Configuration parameters for ELMultiFileOutput
25 : */
26 : struct Config
27 : {
28 : /// ELdestination common config parameters
29 : fhicl::TableFragment<ELdestination::Config> elDestConfig;
30 : /// "base_directory" (Default: "/tmp"): Directory where log files will be created
31 : fhicl::Atom<std::string> baseDir = fhicl::Atom<std::string>{
32 : fhicl::Name{"base_directory"}, fhicl::Comment{"Directory where log files will be created"}, "/tmp"};
33 : /// "append" (Default: true): Append to existing log files
34 : fhicl::Atom<bool> append =
35 : fhicl::Atom<bool>{fhicl::Name{"append"}, fhicl::Comment{"Append to existing log files"}, true};
36 : /// "use_hostname" (Default: true): Use the hostname when generating log file names
37 : fhicl::Atom<bool> useHostname = fhicl::Atom<bool>{
38 : fhicl::Name{"use_hostname"}, fhicl::Comment{"Use the hostname when generating log file names"}, true};
39 : /// "use_application" (Default: true): Use the application field when generating log file names
40 : fhicl::Atom<bool> useApplication =
41 : fhicl::Atom<bool>{fhicl::Name{"use_application"},
42 : fhicl::Comment{"Use the application field when generating log file names"}, true};
43 : /// "use_category" (Default: false): Use the category field when generating log file names
44 : fhicl::Atom<bool> useCategory = fhicl::Atom<bool>{
45 : fhicl::Name{"use_category"}, fhicl::Comment{"Use the category field when generating log file names"}, false};
46 : /// "use_module" (Default: false): Use the module field when generating log file names
47 : fhicl::Atom<bool> useModule = fhicl::Atom<bool>{
48 : fhicl::Name{"use_module"}, fhicl::Comment{"Use the module field when generating log file names"}, false};
49 : };
50 : /// Used for ParameterSet validation
51 : using Parameters = fhicl::WrappedTable<Config>;
52 :
53 : public:
54 : /// <summary>
55 : /// ELMultiFileOutput Constructor
56 : /// </summary>
57 : /// <param name="pset">ParameterSet used to configure ELMultiFileOutput</param>
58 : explicit ELMultiFileOutput(Parameters const& pset);
59 :
60 : /// <summary>
61 : /// Default virtual Destructor
62 : /// </summary>
63 0 : ~ELMultiFileOutput() override = default;
64 :
65 : /**
66 : * \brief Serialize a MessageFacility message to the output
67 : * \param oss Stringstream object containing message data
68 : * \param msg MessageFacility object containing header information
69 : */
70 : void routePayload(const std::ostringstream& oss, const ErrorObj& msg) override;
71 :
72 : /**
73 : * \brief Flush any text in the ostream buffer to disk
74 : */
75 : void flush() override;
76 :
77 : private:
78 : ELMultiFileOutput(ELMultiFileOutput const&) = delete;
79 : ELMultiFileOutput(ELMultiFileOutput&&) = delete;
80 : ELMultiFileOutput& operator=(ELMultiFileOutput const&) = delete;
81 : ELMultiFileOutput& operator=(ELMultiFileOutput&&) = delete;
82 :
83 : std::string baseDir_;
84 : bool append_;
85 : std::unordered_map<std::string, std::unique_ptr<cet::ostream_handle>> outputs_;
86 :
87 : bool useHost_;
88 : bool useApplication_;
89 : bool useCategory_;
90 : bool useModule_;
91 : };
92 :
93 : // END DECLARATION
94 : //======================================================================
95 : // BEGIN IMPLEMENTATION
96 :
97 : //======================================================================
98 : // ELMultiFileOutput c'tor
99 : //======================================================================
100 0 : ELMultiFileOutput::ELMultiFileOutput(Parameters const& pset)
101 0 : : ELdestination(pset().elDestConfig()), baseDir_(pset().baseDir()), append_(pset().append()), useHost_(pset().useHostname()), useApplication_(pset().useApplication()), useCategory_(pset().useCategory()), useModule_(pset().useModule()) {}
102 :
103 : //======================================================================
104 : // Message router ( overriddes ELdestination::routePayload )
105 : //======================================================================
106 0 : void ELMultiFileOutput::routePayload(const std::ostringstream& oss, const ErrorObj& msg)
107 : {
108 0 : const auto& xid = msg.xid();
109 0 : std::string fileName = baseDir_ + "/";
110 0 : if (useModule_)
111 : {
112 0 : fileName += xid.module() + "-";
113 : }
114 0 : if (useCategory_)
115 : {
116 0 : fileName += xid.id() + "-";
117 : }
118 0 : if (useApplication_)
119 : {
120 0 : fileName += xid.application() + "-";
121 : }
122 0 : if (useHost_)
123 : {
124 0 : fileName += xid.hostname() + "-";
125 : }
126 0 : fileName += std::to_string(xid.pid()) + ".log";
127 0 : if (outputs_.count(fileName) == 0)
128 : {
129 0 : outputs_[fileName] =
130 0 : std::make_unique<cet::ostream_handle>(fileName.c_str(), append_ ? std::ios::app : std::ios::trunc);
131 : }
132 0 : *outputs_[fileName] << oss.str();
133 0 : flush();
134 0 : }
135 :
136 0 : void ELMultiFileOutput::flush()
137 : {
138 0 : for (auto& output : outputs_)
139 : {
140 0 : output.second->flush();
141 : }
142 0 : }
143 : } // end namespace mfplugins
144 :
145 : //======================================================================
146 : //
147 : // makePlugin function
148 : //
149 : //======================================================================
150 :
151 : #ifndef EXTERN_C_FUNC_DECLARE_START
152 : #define EXTERN_C_FUNC_DECLARE_START extern "C" {
153 : #endif
154 :
155 : EXTERN_C_FUNC_DECLARE_START
156 0 : auto makePlugin(const std::string& /*unused*/, const fhicl::ParameterSet& pset)
157 : {
158 0 : return std::make_unique<mfplugins::ELMultiFileOutput>(pset);
159 : }
160 : }
161 :
162 0 : DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)
|