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