artdaq_mfextensions  v1_03_05
Friendly_mfPlugin.cc
1 #include "cetlib/PluginTypeDeducer.h"
2 #include "cetlib/ostream_handle.h"
3 #include "fhiclcpp/ParameterSet.h"
4 
5 #include "cetlib/compiler_macros.h"
6 #include "messagefacility/MessageService/ELdestination.h"
7 #include "messagefacility/MessageService/ELostreamOutput.h"
8 #include "messagefacility/Utilities/ELseverityLevel.h"
9 #include "messagefacility/Utilities/exception.h"
10 
11 // C/C++ includes
12 #include <algorithm>
13 #include <iostream>
14 #include <memory>
15 
16 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
17 #define format_ format
18 #endif
19 
20 namespace mfplugins {
21 using namespace mf::service;
22 using mf::ELseverityLevel;
23 using mf::ErrorObj;
24 
28 class ELFriendly : public ELostreamOutput {
29 public:
33  struct Config {
35  fhicl::TableFragment<ELostreamOutput::Config> elOstrConfig;
37  fhicl::Atom<std::string> delimiter = fhicl::Atom<std::string>{
38  fhicl::Name{"field_delimiter"},
39  fhicl::Comment{"String to print between each message field"}, " "};
40  };
42  using Parameters = fhicl::WrappedTable<Config>;
43 
44  public:
49  ELFriendly(Parameters const& pset);
50 
56  virtual void fillPrefix(std::ostringstream& o, const ErrorObj& e) override;
62  virtual void fillUsrMsg(std::ostringstream& o, const ErrorObj& e) override;
68  virtual void fillSuffix(std::ostringstream& o, const ErrorObj& e) override;
69 
70  private:
71  std::string delimeter_;
72 };
73 
74 // END DECLARATION
75 //======================================================================
76 // BEGIN IMPLEMENTATION
77 
78 //======================================================================
79 // ELFriendly c'tor
80 //======================================================================
81 
83  : ELostreamOutput(pset().elOstrConfig(), cet::ostream_handle{std::cout}, false), delimeter_(pset().delimiter()) {}
84 
85 //======================================================================
86 // Message prefix filler ( overriddes ELdestination::fillPrefix )
87 //======================================================================
88 void ELFriendly::fillPrefix(std::ostringstream& oss, const ErrorObj& msg) {
89 // if (msg.is_verbatim()) return;
90 
91 // Output the prologue:
92 //
93 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
94  format_.preambleMode = true;
95 #endif
96 
97  auto const& xid = msg.xid();
98 
99  auto id = xid.id();
100  auto app = xid.application();
101  auto module = xid.module();
102  auto subroutine = xid.subroutine();
103  std::replace(id.begin(), id.end(), ' ', '-');
104  std::replace(app.begin(), app.end(), ' ', '-');
105  std::replace(module.begin(), module.end(), ' ', '-');
106  std::replace(subroutine.begin(), subroutine.end(), ' ', '-');
107 
108  emitToken(oss, "%MSG");
109  emitToken(oss, xid.severity().getSymbol());
110  emitToken(oss, delimeter_);
111  emitToken(oss, id);
112  emitToken(oss, msg.idOverflow());
113  emitToken(oss, ":");
114  emitToken(oss, delimeter_);
115 
116  // Output serial number of message:
117  //
118  if (format_.want(SERIAL)) {
119  std::ostringstream s;
120  s << msg.serial();
121  emitToken(oss, "[serial #" + s.str() + "]");
122  emitToken(oss, delimeter_);
123  }
124 
125  // Provide further identification:
126  //
127  bool needAspace = true;
128  if (format_.want(EPILOGUE_SEPARATE)) {
129  if (module.length() + subroutine.length() > 0) {
130  emitToken(oss, "\n");
131  needAspace = false;
132  } else if (format_.want(TIMESTAMP) && !format_.want(TIME_SEPARATE)) {
133  emitToken(oss, "\n");
134  needAspace = false;
135  }
136  }
137  if (format_.want(MODULE) && (module.length() > 0)) {
138  if (needAspace) {
139  emitToken(oss, delimeter_);
140  needAspace = false;
141  }
142  emitToken(oss, module + " ");
143  }
144  if (format_.want(SUBROUTINE) && (subroutine.length() > 0)) {
145  if (needAspace) {
146  emitToken(oss, delimeter_);
147  needAspace = false;
148  }
149  emitToken(oss, subroutine + "()");
150  emitToken(oss, delimeter_);
151  }
152 
153  // Provide time stamp:
154  //
155  if (format_.want(TIMESTAMP)) {
156  if (format_.want(TIME_SEPARATE)) {
157  emitToken(oss, "\n");
158  needAspace = false;
159  }
160  if (needAspace) {
161  emitToken(oss, delimeter_);
162  needAspace = false;
163  }
164  emitToken(oss, format_.timestamp(msg.timestamp()));
165  emitToken(oss, delimeter_);
166  }
167 
168  // Provide the context information:
169  //
170  if (format_.want(SOME_CONTEXT)) {
171  if (needAspace) {
172  emitToken(oss, delimeter_);
173  // needAspace = false; // Uncomment this line if more fields are added in the future
174  }
175  emitToken(oss, msg.context());
176  }
177 }
178 
179 //=============================================================================
180 void ELFriendly::fillUsrMsg(std::ostringstream& oss, ErrorObj const& msg) {
181  if (!format_.want(TEXT)) return;
182 
183 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
184  format_.preambleMode = false;
185 #endif
186  auto const usrMsgStart = std::next(msg.items().cbegin(), 4);
187  auto it = msg.items().cbegin();
188 
189  // Determine if file and line should be included
190  if (true || !msg.is_verbatim()) {
191  // The first four items are { " ", "<FILENAME>", ":", "<LINE>" }
192  while (it != usrMsgStart) {
193  if (!it->compare(" ") && !std::next(it)->compare("--")) {
194  // Do not emit if " --:0" is the match
195  std::advance(it, 4);
196  } else {
197  // Emit if <FILENAME> and <LINE> are meaningful
198  emitToken(oss, *it++);
199  }
200  }
201 
202  // Check for user-requested line breaks
203  if (format_.want(NO_LINE_BREAKS))
204  emitToken(oss, " ==> ");
205  else
206  emitToken(oss, "", true);
207  }
208 
209  // For verbatim (and user-supplied) messages, just print the contents
210  auto const end = msg.items().cend();
211  for (; it != end; ++it) {
212  emitToken(oss, *it);
213  }
214 }
215 
216 //=============================================================================
217 void ELFriendly::fillSuffix(std::ostringstream& oss, ErrorObj const& msg) {
218  if ((true || !msg.is_verbatim()) && !format_.want(NO_LINE_BREAKS)) {
219  emitToken(oss, "\n%MSG");
220  }
221  oss << '\n';
222 }
223 
224 } // end namespace mfplugins
225 
226 //======================================================================
227 //
228 // makePlugin function
229 //
230 //======================================================================
231 
232 #ifndef EXTERN_C_FUNC_DECLARE_START
233 #define EXTERN_C_FUNC_DECLARE_START extern "C" {
234 #endif
235 
236 EXTERN_C_FUNC_DECLARE_START
237 auto makePlugin(const std::string&, const fhicl::ParameterSet& pset) {
238  return std::make_unique<mfplugins::ELFriendly>(pset);
239 }
240 }
241 
242 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)
Parser-Friendly Message Facility destination plugin
virtual void fillSuffix(std::ostringstream &o, const ErrorObj &e) override
Fill the &quot;Suffix&quot; portion of the message.
ELFriendly(Parameters const &pset)
ELFriendly Constructor
fhicl::WrappedTable< Config > Parameters
Used for ParameterSet validation.
virtual void fillUsrMsg(std::ostringstream &o, const ErrorObj &e) override
Fill the &quot;User Message&quot; portion of the message.
fhicl::TableFragment< ELostreamOutput::Config > elOstrConfig
Configuration parameters for ELostreamOutput.
virtual void fillPrefix(std::ostringstream &o, const ErrorObj &e) override
Fill the &quot;Prefix&quot; portion of the message.
Configuration Parameters for ELFriendly.