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