00001 #include "cetlib/PluginTypeDeducer.h"
00002 #include "cetlib/ostream_handle.h"
00003 #include "fhiclcpp/ParameterSet.h"
00004
00005 #include "messagefacility/MessageService/ELdestination.h"
00006 #include "messagefacility/MessageService/ELostreamOutput.h"
00007 #include "messagefacility/Utilities/ELseverityLevel.h"
00008 #include "messagefacility/Utilities/exception.h"
00009 #include "cetlib/compiler_macros.h"
00010
00011
00012 #include <iostream>
00013 #include <memory>
00014 #include <algorithm>
00015
00016 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
00017 #define format_ format
00018 #endif
00019
00020 namespace mfplugins
00021 {
00022 using namespace mf::service;
00023 using mf::ELseverityLevel;
00024 using mf::ErrorObj;
00025
00029 class ELFriendly : public ELostreamOutput
00030 {
00031 #if MESSAGEFACILITY_HEX_VERSION >= 0x20103
00032 struct Config
00033 {
00034 fhicl::TableFragment<ELostreamOutput::Config> elOstrConfig;
00035 fhicl::Atom<std::string> delimiter{ fhicl::Name{ "field_delimiter" },fhicl::Comment{ "String to print between each message field" }," " };
00036 };
00037 using Parameters = fhicl::WrappedTable<Config>;
00038 #endif
00039 public:
00044 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
00045 ELFriendly(const fhicl::ParameterSet& pset);
00046 #else
00047 ELFriendly(Parameters const& pset);
00048 #endif
00049
00055 virtual void fillPrefix(std::ostringstream& o, const ErrorObj& e) override;
00061 virtual void fillUsrMsg(std::ostringstream& o, const ErrorObj& e) override;
00067 virtual void fillSuffix(std::ostringstream& o, const ErrorObj& e) override;
00068
00069 private:
00070 std::string delimeter_;
00071 };
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
00083 ELFriendly::ELFriendly(const fhicl::ParameterSet& pset)
00084 : ELostreamOutput(pset, cet::ostream_handle{ std::cout }, false)
00085 , delimeter_(pset.get<std::string>("field_delimeter", " "))
00086 #else
00087 ELFriendly::ELFriendly(Parameters const& pset)
00088 : ELostreamOutput(pset().elOstrConfig(), cet::ostream_handle{ std::cout }, false)
00089 , delimeter_(pset().delimiter())
00090 #endif
00091 {}
00092
00093
00094
00095
00096 void ELFriendly::fillPrefix(std::ostringstream& oss, const ErrorObj& msg)
00097 {
00098
00099
00100
00101
00102 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
00103 format_.preambleMode = true;
00104 #endif
00105
00106 auto const& xid = msg.xid();
00107
00108 auto id = xid.id();
00109 auto app = xid.application();
00110 auto module = xid.module();
00111 auto subroutine = xid.subroutine();
00112 std::replace(id.begin(), id.end(), ' ', '-');
00113 std::replace(app.begin(), app.end(), ' ', '-');
00114 std::replace(module.begin(), module.end(), ' ', '-');
00115 std::replace(subroutine.begin(), subroutine.end(), ' ', '-');
00116
00117 emitToken(oss, "%MSG");
00118 emitToken(oss, xid.severity().getSymbol());
00119 emitToken(oss, delimeter_);
00120 emitToken(oss, id);
00121 emitToken(oss, msg.idOverflow());
00122 emitToken(oss, ":");
00123 emitToken(oss, delimeter_);
00124
00125
00126
00127 if (format_.want(SERIAL))
00128 {
00129 std::ostringstream s;
00130 s << msg.serial();
00131 emitToken(oss, "[serial #" + s.str() + "]");
00132 emitToken(oss, delimeter_);
00133 }
00134
00135
00136
00137 bool needAspace = true;
00138 if (format_.want(EPILOGUE_SEPARATE))
00139 {
00140 if (module.length() + subroutine.length() > 0)
00141 {
00142 emitToken(oss, "\n");
00143 needAspace = false;
00144 }
00145 else if (format_.want(TIMESTAMP) && !format_.want(TIME_SEPARATE))
00146 {
00147 emitToken(oss, "\n");
00148 needAspace = false;
00149 }
00150 }
00151 if (format_.want(MODULE) && (module.length() > 0))
00152 {
00153 if (needAspace)
00154 {
00155 emitToken(oss, delimeter_);
00156 needAspace = false;
00157 }
00158 emitToken(oss, module + " ");
00159 }
00160 if (format_.want(SUBROUTINE) && (subroutine.length() > 0))
00161 {
00162 if (needAspace)
00163 {
00164 emitToken(oss, delimeter_);
00165 needAspace = false;
00166 }
00167 emitToken(oss, subroutine + "()");
00168 emitToken(oss, delimeter_);
00169 }
00170
00171
00172
00173 if (format_.want(TIMESTAMP))
00174 {
00175 if (format_.want(TIME_SEPARATE))
00176 {
00177 emitToken(oss, "\n");
00178 needAspace = false;
00179 }
00180 if (needAspace)
00181 {
00182 emitToken(oss, delimeter_);
00183 needAspace = false;
00184 }
00185 emitToken(oss, format_.timestamp(msg.timestamp()));
00186 emitToken(oss, delimeter_);
00187 }
00188
00189
00190
00191 if (format_.want(SOME_CONTEXT))
00192 {
00193 if (needAspace)
00194 {
00195 emitToken(oss, delimeter_);
00196 needAspace = false;
00197 }
00198 emitToken(oss, msg.context());
00199 }
00200
00201 }
00202
00203
00204
00205 void ELFriendly::fillUsrMsg(std::ostringstream& oss, ErrorObj const& msg)
00206 {
00207 if (!format_.want(TEXT)) return;
00208
00209 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
00210 format_.preambleMode = false;
00211 #endif
00212 auto const usrMsgStart = std::next(msg.items().cbegin(), 4);
00213 auto it = msg.items().cbegin();
00214
00215
00216 if (true || !msg.is_verbatim())
00217 {
00218
00219
00220 while (it != usrMsgStart)
00221 {
00222 if (!it->compare(" ") && !std::next(it)->compare("--"))
00223 {
00224
00225 std::advance(it, 4);
00226 }
00227 else
00228 {
00229
00230 emitToken(oss, *it++);
00231 }
00232 }
00233
00234
00235 if (format_.want(NO_LINE_BREAKS)) emitToken(oss, " ==> ");
00236 else emitToken(oss, "", true);
00237 }
00238
00239
00240 auto const end = msg.items().cend();
00241 for (; it != end; ++it)
00242 {
00243 emitToken(oss, *it);
00244 }
00245
00246 }
00247
00248
00249
00250 void ELFriendly::fillSuffix(std::ostringstream& oss, ErrorObj const& msg)
00251 {
00252 if ((true || !msg.is_verbatim()) && !format_.want(NO_LINE_BREAKS))
00253 {
00254 emitToken(oss, "\n%MSG");
00255 }
00256 oss << '\n';
00257 }
00258
00259
00260
00261 }
00262
00263
00264
00265
00266
00267
00268
00269 #ifndef EXTERN_C_FUNC_DECLARE_START
00270 #define EXTERN_C_FUNC_DECLARE_START extern "C" {
00271 #endif
00272
00273 EXTERN_C_FUNC_DECLARE_START
00274 auto makePlugin(const std::string&,
00275 const fhicl::ParameterSet& pset)
00276 {
00277 return std::make_unique<mfplugins::ELFriendly>(pset);
00278 }
00279 }
00280
00281 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)