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