artdaq_mfextensions  1.08.05
Friendly_mfPlugin.cc
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/MessageService/ELostreamOutput.h"
9 #include "messagefacility/Utilities/ELseverityLevel.h"
10 #include "messagefacility/Utilities/exception.h"
11 
12 // C/C++ includes
13 #include <algorithm>
14 #include <iostream>
15 #include <memory>
16 
17 namespace mfplugins {
18 using namespace mf::service;
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  explicit ELFriendly(Parameters const& pset);
47 
53  void fillPrefix(std::ostringstream& o, const ErrorObj& msg) override;
59  void fillUsrMsg(std::ostringstream& o, const ErrorObj& msg) override;
65  void fillSuffix(std::ostringstream& o, const ErrorObj& msg) 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))
192  {
193  return;
194  }
195 
196  auto const usrMsgStart = std::next(msg.items().cbegin(), 4);
197  auto it = msg.items().cbegin();
198 
199  // Determine if file and line should be included
200 
201  // The first four items are { " ", "<FILENAME>", ":", "<LINE>" }
202  while (it != usrMsgStart)
203  {
204  if ((*it == " ") && (*std::next(it) == "--"))
205  {
206  // Do not emit if " --:0" is the match
207  std::advance(it, 4);
208  }
209  else
210  {
211  // Emit if <FILENAME> and <LINE> are meaningful
212  emitToken(oss, *it++);
213  }
214  }
215 
216  // Check for user-requested line breaks
217  if (format_.want(NO_LINE_BREAKS))
218  {
219  emitToken(oss, " ==> ");
220  }
221  else
222  {
223  emitToken(oss, "", true);
224  }
225 
226  // For verbatim (and user-supplied) messages, just print the contents
227  auto const end = msg.items().cend();
228  for (; it != end; ++it)
229  {
230  emitToken(oss, *it);
231  }
232 }
233 
234 //=============================================================================
235 void ELFriendly::fillSuffix(std::ostringstream& oss, ErrorObj const& /*msg*/)
236 {
237  if (!format_.want(NO_LINE_BREAKS))
238  {
239  emitToken(oss, "\n%MSG");
240  }
241  oss << '\n';
242 }
243 
244 } // end namespace mfplugins
245 
246 //======================================================================
247 //
248 // makePlugin function
249 //
250 //======================================================================
251 
252 #ifndef EXTERN_C_FUNC_DECLARE_START
253 #define EXTERN_C_FUNC_DECLARE_START extern "C" {
254 #endif
255 
256 EXTERN_C_FUNC_DECLARE_START
257 auto makePlugin(const std::string& /*unused*/, const fhicl::ParameterSet& pset)
258 {
259  return std::make_unique<mfplugins::ELFriendly>(pset);
260 }
261 }
262 
263 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)
Parser-Friendly Message Facility destination plugin
void fillUsrMsg(std::ostringstream &o, const ErrorObj &msg) override
Fill the &quot;User Message&quot; portion of the message.
ELFriendly(Parameters const &pset)
ELFriendly Constructor
void fillPrefix(std::ostringstream &o, const ErrorObj &msg) override
Fill the &quot;Prefix&quot; portion of the message.
fhicl::WrappedTable< Config > Parameters
Used for ParameterSet validation.
fhicl::TableFragment< ELostreamOutput::Config > elOstrConfig
Configuration parameters for ELostreamOutput.
Configuration Parameters for ELFriendly.
void fillSuffix(std::ostringstream &o, const ErrorObj &msg) override
Fill the &quot;Suffix&quot; portion of the message.