$treeview $search $mathjax $extrastylesheet
artdaq_mfextensions
v1_03_03
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "cetlib/PluginTypeDeducer.h" 00002 #include "cetlib/ostream_handle.h" 00003 #include "fhiclcpp/ParameterSet.h" 00004 00005 #include "cetlib/compiler_macros.h" 00006 #include "messagefacility/MessageService/ELdestination.h" 00007 #include "messagefacility/MessageService/ELostreamOutput.h" 00008 #include "messagefacility/Utilities/ELseverityLevel.h" 00009 #include "messagefacility/Utilities/exception.h" 00010 00011 // C/C++ includes 00012 #include <algorithm> 00013 #include <iostream> 00014 #include <memory> 00015 00016 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67 00017 #define format_ format 00018 #endif 00019 00020 namespace mfplugins { 00021 using namespace mf::service; 00022 using mf::ELseverityLevel; 00023 using mf::ErrorObj; 00024 00028 class ELFriendly : public ELostreamOutput { 00029 struct Config { 00030 fhicl::TableFragment<ELostreamOutput::Config> elOstrConfig; 00031 fhicl::Atom<std::string> delimiter{fhicl::Name{"field_delimiter"}, 00032 fhicl::Comment{"String to print between each message field"}, " "}; 00033 }; 00034 using Parameters = fhicl::WrappedTable<Config>; 00035 00036 public: 00041 ELFriendly(Parameters const& pset); 00042 00048 virtual void fillPrefix(std::ostringstream& o, const ErrorObj& e) override; 00054 virtual void fillUsrMsg(std::ostringstream& o, const ErrorObj& e) override; 00060 virtual void fillSuffix(std::ostringstream& o, const ErrorObj& e) override; 00061 00062 private: 00063 std::string delimeter_; 00064 }; 00065 00066 // END DECLARATION 00067 //====================================================================== 00068 // BEGIN IMPLEMENTATION 00069 00070 //====================================================================== 00071 // ELFriendly c'tor 00072 //====================================================================== 00073 00074 ELFriendly::ELFriendly(Parameters const& pset) 00075 : ELostreamOutput(pset().elOstrConfig(), cet::ostream_handle{std::cout}, false), delimeter_(pset().delimiter()) {} 00076 00077 //====================================================================== 00078 // Message prefix filler ( overriddes ELdestination::fillPrefix ) 00079 //====================================================================== 00080 void ELFriendly::fillPrefix(std::ostringstream& oss, const ErrorObj& msg) { 00081 // if (msg.is_verbatim()) return; 00082 00083 // Output the prologue: 00084 // 00085 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67 00086 format_.preambleMode = true; 00087 #endif 00088 00089 auto const& xid = msg.xid(); 00090 00091 auto id = xid.id(); 00092 auto app = xid.application(); 00093 auto module = xid.module(); 00094 auto subroutine = xid.subroutine(); 00095 std::replace(id.begin(), id.end(), ' ', '-'); 00096 std::replace(app.begin(), app.end(), ' ', '-'); 00097 std::replace(module.begin(), module.end(), ' ', '-'); 00098 std::replace(subroutine.begin(), subroutine.end(), ' ', '-'); 00099 00100 emitToken(oss, "%MSG"); 00101 emitToken(oss, xid.severity().getSymbol()); 00102 emitToken(oss, delimeter_); 00103 emitToken(oss, id); 00104 emitToken(oss, msg.idOverflow()); 00105 emitToken(oss, ":"); 00106 emitToken(oss, delimeter_); 00107 00108 // Output serial number of message: 00109 // 00110 if (format_.want(SERIAL)) { 00111 std::ostringstream s; 00112 s << msg.serial(); 00113 emitToken(oss, "[serial #" + s.str() + "]"); 00114 emitToken(oss, delimeter_); 00115 } 00116 00117 // Provide further identification: 00118 // 00119 bool needAspace = true; 00120 if (format_.want(EPILOGUE_SEPARATE)) { 00121 if (module.length() + subroutine.length() > 0) { 00122 emitToken(oss, "\n"); 00123 needAspace = false; 00124 } else if (format_.want(TIMESTAMP) && !format_.want(TIME_SEPARATE)) { 00125 emitToken(oss, "\n"); 00126 needAspace = false; 00127 } 00128 } 00129 if (format_.want(MODULE) && (module.length() > 0)) { 00130 if (needAspace) { 00131 emitToken(oss, delimeter_); 00132 needAspace = false; 00133 } 00134 emitToken(oss, module + " "); 00135 } 00136 if (format_.want(SUBROUTINE) && (subroutine.length() > 0)) { 00137 if (needAspace) { 00138 emitToken(oss, delimeter_); 00139 needAspace = false; 00140 } 00141 emitToken(oss, subroutine + "()"); 00142 emitToken(oss, delimeter_); 00143 } 00144 00145 // Provide time stamp: 00146 // 00147 if (format_.want(TIMESTAMP)) { 00148 if (format_.want(TIME_SEPARATE)) { 00149 emitToken(oss, "\n"); 00150 needAspace = false; 00151 } 00152 if (needAspace) { 00153 emitToken(oss, delimeter_); 00154 needAspace = false; 00155 } 00156 emitToken(oss, format_.timestamp(msg.timestamp())); 00157 emitToken(oss, delimeter_); 00158 } 00159 00160 // Provide the context information: 00161 // 00162 if (format_.want(SOME_CONTEXT)) { 00163 if (needAspace) { 00164 emitToken(oss, delimeter_); 00165 // needAspace = false; // Uncomment this line if more fields are added in the future 00166 } 00167 emitToken(oss, msg.context()); 00168 } 00169 } 00170 00171 //============================================================================= 00172 void ELFriendly::fillUsrMsg(std::ostringstream& oss, ErrorObj const& msg) { 00173 if (!format_.want(TEXT)) return; 00174 00175 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67 00176 format_.preambleMode = false; 00177 #endif 00178 auto const usrMsgStart = std::next(msg.items().cbegin(), 4); 00179 auto it = msg.items().cbegin(); 00180 00181 // Determine if file and line should be included 00182 if (true || !msg.is_verbatim()) { 00183 // The first four items are { " ", "<FILENAME>", ":", "<LINE>" } 00184 while (it != usrMsgStart) { 00185 if (!it->compare(" ") && !std::next(it)->compare("--")) { 00186 // Do not emit if " --:0" is the match 00187 std::advance(it, 4); 00188 } else { 00189 // Emit if <FILENAME> and <LINE> are meaningful 00190 emitToken(oss, *it++); 00191 } 00192 } 00193 00194 // Check for user-requested line breaks 00195 if (format_.want(NO_LINE_BREAKS)) 00196 emitToken(oss, " ==> "); 00197 else 00198 emitToken(oss, "", true); 00199 } 00200 00201 // For verbatim (and user-supplied) messages, just print the contents 00202 auto const end = msg.items().cend(); 00203 for (; it != end; ++it) { 00204 emitToken(oss, *it); 00205 } 00206 } 00207 00208 //============================================================================= 00209 void ELFriendly::fillSuffix(std::ostringstream& oss, ErrorObj const& msg) { 00210 if ((true || !msg.is_verbatim()) && !format_.want(NO_LINE_BREAKS)) { 00211 emitToken(oss, "\n%MSG"); 00212 } 00213 oss << '\n'; 00214 } 00215 00216 } // end namespace mfplugins 00217 00218 //====================================================================== 00219 // 00220 // makePlugin function 00221 // 00222 //====================================================================== 00223 00224 #ifndef EXTERN_C_FUNC_DECLARE_START 00225 #define EXTERN_C_FUNC_DECLARE_START extern "C" { 00226 #endif 00227 00228 EXTERN_C_FUNC_DECLARE_START 00229 auto makePlugin(const std::string&, const fhicl::ParameterSet& pset) { 00230 return std::make_unique<mfplugins::ELFriendly>(pset); 00231 } 00232 } 00233 00234 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)