artdaq_mfextensions  v1_03_06
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  public:
29  struct Config {
31  fhicl::TableFragment<ELostreamOutput::Config> elOstrConfig;
33  fhicl::Atom<std::string> delimiter = fhicl::Atom<std::string>{
34  fhicl::Name{"field_delimiter"}, fhicl::Comment{"String to print between each message field"}, " "};
35  };
37  using Parameters = fhicl::WrappedTable<Config>;
38 
39  public:
44  ELFriendly(Parameters const& pset);
45 
51  virtual void fillPrefix(std::ostringstream& o, const ErrorObj& e) override;
57  virtual void fillUsrMsg(std::ostringstream& o, const ErrorObj& e) override;
63  virtual void fillSuffix(std::ostringstream& o, const ErrorObj& e) override;
64 
65  private:
66  std::string delimeter_;
67 };
68 
69 // END DECLARATION
70 //======================================================================
71 // BEGIN IMPLEMENTATION
72 
73 //======================================================================
74 // ELFriendly c'tor
75 //======================================================================
76 
78  : ELostreamOutput(pset().elOstrConfig(), cet::ostream_handle{std::cout}, false), delimeter_(pset().delimiter()) {}
79 
80 //======================================================================
81 // Message prefix filler ( overriddes ELdestination::fillPrefix )
82 //======================================================================
83 void ELFriendly::fillPrefix(std::ostringstream& oss, const ErrorObj& msg) {
84  // if (msg.is_verbatim()) return;
85 
86  // Output the prologue:
87  //
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  auto const usrMsgStart = std::next(msg.items().cbegin(), 4);
176  auto it = msg.items().cbegin();
177 
178  // Determine if file and line should be included
179  if (true || !msg.is_verbatim()) {
180  // The first four items are { " ", "<FILENAME>", ":", "<LINE>" }
181  while (it != usrMsgStart) {
182  if (!it->compare(" ") && !std::next(it)->compare("--")) {
183  // Do not emit if " --:0" is the match
184  std::advance(it, 4);
185  } else {
186  // Emit if <FILENAME> and <LINE> are meaningful
187  emitToken(oss, *it++);
188  }
189  }
190 
191  // Check for user-requested line breaks
192  if (format_.want(NO_LINE_BREAKS))
193  emitToken(oss, " ==> ");
194  else
195  emitToken(oss, "", true);
196  }
197 
198  // For verbatim (and user-supplied) messages, just print the contents
199  auto const end = msg.items().cend();
200  for (; it != end; ++it) {
201  emitToken(oss, *it);
202  }
203 }
204 
205 //=============================================================================
206 void ELFriendly::fillSuffix(std::ostringstream& oss, ErrorObj const& msg) {
207  if ((true || !msg.is_verbatim()) && !format_.want(NO_LINE_BREAKS)) {
208  emitToken(oss, "\n%MSG");
209  }
210  oss << '\n';
211 }
212 
213 } // end namespace mfplugins
214 
215 //======================================================================
216 //
217 // makePlugin function
218 //
219 //======================================================================
220 
221 #ifndef EXTERN_C_FUNC_DECLARE_START
222 #define EXTERN_C_FUNC_DECLARE_START extern "C" {
223 #endif
224 
225 EXTERN_C_FUNC_DECLARE_START
226 auto makePlugin(const std::string&, const fhicl::ParameterSet& pset) {
227  return std::make_unique<mfplugins::ELFriendly>(pset);
228 }
229 }
230 
231 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.