artdaq_mfextensions  v1_04_00
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 namespace mfplugins {
17 using namespace mf::service;
18 using mf::ELseverityLevel;
19 using mf::ErrorObj;
20 
24 class ELFriendly : public ELostreamOutput
25 {
26 public:
30  struct Config
31  {
33  fhicl::TableFragment<ELostreamOutput::Config> elOstrConfig;
35  fhicl::Atom<std::string> delimiter = fhicl::Atom<std::string>{
36  fhicl::Name{"field_delimiter"}, fhicl::Comment{"String to print between each message field"}, " "};
37  };
39  using Parameters = fhicl::WrappedTable<Config>;
40 
41 public:
46  ELFriendly(Parameters const& pset);
47 
53  virtual void fillPrefix(std::ostringstream& o, const ErrorObj& e) override;
59  virtual void fillUsrMsg(std::ostringstream& o, const ErrorObj& e) override;
65  virtual void fillSuffix(std::ostringstream& o, const ErrorObj& e) override;
66 
67 private:
68  std::string delimeter_;
69 };
70 
71 // END DECLARATION
72 //======================================================================
73 // BEGIN IMPLEMENTATION
74 
75 //======================================================================
76 // ELFriendly c'tor
77 //======================================================================
78 
80  : ELostreamOutput(pset().elOstrConfig(), cet::ostream_handle{std::cout}, false), delimeter_(pset().delimiter()) {}
81 
82 //======================================================================
83 // Message prefix filler ( overriddes ELdestination::fillPrefix )
84 //======================================================================
85 void ELFriendly::fillPrefix(std::ostringstream& oss, const ErrorObj& msg)
86 {
87  // if (msg.is_verbatim()) return;
88 
89  // Output the prologue:
90  //
91 
92  auto const& xid = msg.xid();
93 
94  auto id = xid.id();
95  auto app = xid.application();
96  auto module = xid.module();
97  auto subroutine = xid.subroutine();
98  std::replace(id.begin(), id.end(), ' ', '-');
99  std::replace(app.begin(), app.end(), ' ', '-');
100  std::replace(module.begin(), module.end(), ' ', '-');
101  std::replace(subroutine.begin(), subroutine.end(), ' ', '-');
102 
103  emitToken(oss, "%MSG");
104  emitToken(oss, xid.severity().getSymbol());
105  emitToken(oss, delimeter_);
106  emitToken(oss, id);
107  emitToken(oss, msg.idOverflow());
108  emitToken(oss, ":");
109  emitToken(oss, delimeter_);
110 
111  // Output serial number of message:
112  //
113  if (format_.want(SERIAL))
114  {
115  std::ostringstream s;
116  s << msg.serial();
117  emitToken(oss, "[serial #" + s.str() + "]");
118  emitToken(oss, delimeter_);
119  }
120 
121  // Provide further identification:
122  //
123  bool needAspace = true;
124  if (format_.want(EPILOGUE_SEPARATE))
125  {
126  if (module.length() + subroutine.length() > 0)
127  {
128  emitToken(oss, "\n");
129  needAspace = false;
130  }
131  else if (format_.want(TIMESTAMP) && !format_.want(TIME_SEPARATE))
132  {
133  emitToken(oss, "\n");
134  needAspace = false;
135  }
136  }
137  if (format_.want(MODULE) && (module.length() > 0))
138  {
139  if (needAspace)
140  {
141  emitToken(oss, delimeter_);
142  needAspace = false;
143  }
144  emitToken(oss, module + " ");
145  }
146  if (format_.want(SUBROUTINE) && (subroutine.length() > 0))
147  {
148  if (needAspace)
149  {
150  emitToken(oss, delimeter_);
151  needAspace = false;
152  }
153  emitToken(oss, subroutine + "()");
154  emitToken(oss, delimeter_);
155  }
156 
157  // Provide time stamp:
158  //
159  if (format_.want(TIMESTAMP))
160  {
161  if (format_.want(TIME_SEPARATE))
162  {
163  emitToken(oss, "\n");
164  needAspace = false;
165  }
166  if (needAspace)
167  {
168  emitToken(oss, delimeter_);
169  needAspace = false;
170  }
171  emitToken(oss, format_.timestamp(msg.timestamp()));
172  emitToken(oss, delimeter_);
173  }
174 
175  // Provide the context information:
176  //
177  if (format_.want(SOME_CONTEXT))
178  {
179  if (needAspace)
180  {
181  emitToken(oss, delimeter_);
182  // needAspace = false; // Uncomment this line if more fields are added in the future
183  }
184  emitToken(oss, msg.context());
185  }
186 }
187 
188 //=============================================================================
189 void ELFriendly::fillUsrMsg(std::ostringstream& oss, ErrorObj const& msg)
190 {
191  if (!format_.want(TEXT)) return;
192 
193  auto const usrMsgStart = std::next(msg.items().cbegin(), 4);
194  auto it = msg.items().cbegin();
195 
196  // Determine if file and line should be included
197  if (true || !msg.is_verbatim())
198  {
199  // The first four items are { " ", "<FILENAME>", ":", "<LINE>" }
200  while (it != usrMsgStart)
201  {
202  if (!it->compare(" ") && !std::next(it)->compare("--"))
203  {
204  // Do not emit if " --:0" is the match
205  std::advance(it, 4);
206  }
207  else
208  {
209  // Emit if <FILENAME> and <LINE> are meaningful
210  emitToken(oss, *it++);
211  }
212  }
213 
214  // Check for user-requested line breaks
215  if (format_.want(NO_LINE_BREAKS))
216  emitToken(oss, " ==> ");
217  else
218  emitToken(oss, "", true);
219  }
220 
221  // For verbatim (and user-supplied) messages, just print the contents
222  auto const end = msg.items().cend();
223  for (; it != end; ++it)
224  {
225  emitToken(oss, *it);
226  }
227 }
228 
229 //=============================================================================
230 void ELFriendly::fillSuffix(std::ostringstream& oss, ErrorObj const& msg)
231 {
232  if ((true || !msg.is_verbatim()) && !format_.want(NO_LINE_BREAKS))
233  {
234  emitToken(oss, "\n%MSG");
235  }
236  oss << '\n';
237 }
238 
239 } // end namespace mfplugins
240 
241 //======================================================================
242 //
243 // makePlugin function
244 //
245 //======================================================================
246 
247 #ifndef EXTERN_C_FUNC_DECLARE_START
248 #define EXTERN_C_FUNC_DECLARE_START extern "C" {
249 #endif
250 
251 EXTERN_C_FUNC_DECLARE_START
252 auto makePlugin(const std::string&, const fhicl::ParameterSet& pset)
253 {
254  return std::make_unique<mfplugins::ELFriendly>(pset);
255 }
256 }
257 
258 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.