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:
00040 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
00041 ELFriendly(const fhicl::ParameterSet& pset);
00042 #else
00043 ELFriendly(Parameters const& pset);
00044 #endif
00045
00046 virtual void fillPrefix(std::ostringstream&, const ErrorObj&) override;
00047 virtual void fillUsrMsg(std::ostringstream&, const ErrorObj&) override;
00048 virtual void fillSuffix(std::ostringstream&, const ErrorObj&) override;
00049
00050 private:
00051 std::string delimeter_;
00052 };
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
00064 ELFriendly::ELFriendly(const fhicl::ParameterSet& pset)
00065 : ELostreamOutput(pset, cet::ostream_handle{ std::cout }, false)
00066 , delimeter_(pset.get<std::string>("field_delimeter", " "))
00067 #else
00068 ELFriendly::ELFriendly(Parameters const& pset)
00069 : ELostreamOutput(pset().elOstrConfig(), cet::ostream_handle{ std::cout }, false)
00070 , delimeter_(pset().delimiter())
00071 #endif
00072 {}
00073
00074
00075
00076
00077 void ELFriendly::fillPrefix(std::ostringstream& oss, const ErrorObj& msg)
00078 {
00079
00080
00081
00082
00083 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
00084 format_.preambleMode = true;
00085 #endif
00086
00087 auto const& xid = msg.xid();
00088
00089 auto id = xid.id();
00090 auto app = xid.application();
00091 auto module = xid.module();
00092 auto subroutine = xid.subroutine();
00093 std::replace(id.begin(), id.end(), ' ', '-');
00094 std::replace(app.begin(), app.end(), ' ', '-');
00095 std::replace(module.begin(), module.end(), ' ', '-');
00096 std::replace(subroutine.begin(), subroutine.end(), ' ', '-');
00097
00098 emitToken(oss, "%MSG");
00099 emitToken(oss, xid.severity().getSymbol());
00100 emitToken(oss, delimeter_);
00101 emitToken(oss, id);
00102 emitToken(oss, msg.idOverflow());
00103 emitToken(oss, ":");
00104 emitToken(oss, delimeter_);
00105
00106
00107
00108 if (format_.want(SERIAL))
00109 {
00110 std::ostringstream s;
00111 s << msg.serial();
00112 emitToken(oss, "[serial #" + s.str() + "]");
00113 emitToken(oss, delimeter_);
00114 }
00115
00116
00117
00118 bool needAspace = true;
00119 if (format_.want(EPILOGUE_SEPARATE))
00120 {
00121 if (module.length() + subroutine.length() > 0)
00122 {
00123 emitToken(oss, "\n");
00124 needAspace = false;
00125 }
00126 else if (format_.want(TIMESTAMP) && !format_.want(TIME_SEPARATE))
00127 {
00128 emitToken(oss, "\n");
00129 needAspace = false;
00130 }
00131 }
00132 if (format_.want(MODULE) && (module.length() > 0))
00133 {
00134 if (needAspace)
00135 {
00136 emitToken(oss, delimeter_);
00137 needAspace = false;
00138 }
00139 emitToken(oss, module + " ");
00140 }
00141 if (format_.want(SUBROUTINE) && (subroutine.length() > 0))
00142 {
00143 if (needAspace)
00144 {
00145 emitToken(oss, delimeter_);
00146 needAspace = false;
00147 }
00148 emitToken(oss, subroutine + "()");
00149 emitToken(oss, delimeter_);
00150 }
00151
00152
00153
00154 if (format_.want(TIMESTAMP))
00155 {
00156 if (format_.want(TIME_SEPARATE))
00157 {
00158 emitToken(oss, "\n");
00159 needAspace = false;
00160 }
00161 if (needAspace)
00162 {
00163 emitToken(oss, delimeter_);
00164 needAspace = false;
00165 }
00166 emitToken(oss, format_.timestamp(msg.timestamp()));
00167 emitToken(oss, delimeter_);
00168 }
00169
00170
00171
00172 if (format_.want(SOME_CONTEXT))
00173 {
00174 if (needAspace)
00175 {
00176 emitToken(oss, delimeter_);
00177 needAspace = false;
00178 }
00179 emitToken(oss, msg.context());
00180 }
00181
00182 }
00183
00184
00185
00186 void ELFriendly::fillUsrMsg(std::ostringstream& oss, ErrorObj const& msg)
00187 {
00188 if (!format_.want(TEXT)) return;
00189
00190 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
00191 format_.preambleMode = false;
00192 #endif
00193 auto const usrMsgStart = std::next(msg.items().cbegin(), 4);
00194 auto it = msg.items().cbegin();
00195
00196
00197 if (true || !msg.is_verbatim())
00198 {
00199
00200
00201 while (it != usrMsgStart)
00202 {
00203 if (!it->compare(" ") && !std::next(it)->compare("--"))
00204 {
00205
00206 std::advance(it, 4);
00207 }
00208 else
00209 {
00210
00211 emitToken(oss, *it++);
00212 }
00213 }
00214
00215
00216 if (format_.want(NO_LINE_BREAKS)) emitToken(oss, " ==> ");
00217 else emitToken(oss, "", true);
00218 }
00219
00220
00221 auto const end = msg.items().cend();
00222 for (; it != end; ++it)
00223 {
00224 emitToken(oss, *it);
00225 }
00226
00227 }
00228
00229
00230
00231 void ELFriendly::fillSuffix(std::ostringstream& oss, ErrorObj const& msg)
00232 {
00233 if ((true || !msg.is_verbatim()) && !format_.want(NO_LINE_BREAKS))
00234 {
00235 emitToken(oss, "\n%MSG");
00236 }
00237 oss << '\n';
00238 }
00239
00240
00241
00242 }
00243
00244
00245
00246
00247
00248
00249
00250 #ifndef EXTERN_C_FUNC_DECLARE_START
00251 #define EXTERN_C_FUNC_DECLARE_START extern "C" {
00252 #endif
00253
00254 EXTERN_C_FUNC_DECLARE_START
00255 auto makePlugin(const std::string&,
00256 const fhicl::ParameterSet& pset)
00257 {
00258 return std::make_unique<mfplugins::ELFriendly>(pset);
00259 }
00260 }
00261
00262 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)