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