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