7 #ifndef __EPICS_METRIC__
8 #define __EPICS_METRIC__ 1
10 #include "TRACE/tracemf.h"
11 #define TRACE_NAME (app_name_ + "_epics_metric").c_str()
13 #include <unordered_map>
15 #include "artdaq-utilities/Plugins/MetricMacros.hh"
16 #include "messagefacility/MessageLogger/MessageLogger.h"
20 #pragma clang diagnostic push
21 #pragma clang diagnostic ignored "-Wunused-parameter"
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wdeprecated-copy"
28 #pragma clang diagnostic pop
30 #pragma GCC diagnostic pop
44 std::unordered_map<std::string, chid> channels_;
46 bool checkChannel_(
const std::string& name)
48 if (channels_.count(name) == 0u)
51 ca_search(name.c_str(), &channel);
52 auto sts = ca_pend_io(5.0);
53 if (sts != ECA_NORMAL)
55 SEVCHK(ca_clear_channel(channel), NULL);
56 METLOG(TLVL_WARNING) <<
"Channel \"" << name <<
"\" not found!";
57 channels_[name] =
nullptr;
60 channels_[name] = channel;
63 return channels_[name] !=
nullptr;
66 std::string parseChannelName_(std::string prefix_, std::string name)
68 std::string caName = std::move(name);
69 const std::string& caPrefix_ = std::move(prefix_);
71 while (caName.find(
' ') != std::string::npos)
73 caName = caName.replace(caName.find(
' '), 1,
"_");
75 while (caName.find(
'.') != std::string::npos)
77 caName = caName.replace(caName.find(
'.'), 1,
":");
79 while (caName.find(
'/') != std::string::npos)
81 caName = caName.replace(caName.find(
'/'), 1,
"_");
83 while (caName.find(
"_%") != std::string::npos)
85 caName = caName.replace(caName.find(
"_%"), 2,
"");
87 caName = caPrefix_ +
":" + caName;
89 METLOG(TLVL_DEBUG + 32) <<
"Channel name is: \"" << caName <<
"\"";
105 explicit EpicsMetric(fhicl::ParameterSet
const& pset, std::string
const& app_name, std::string
const& metric_name)
106 : MetricPlugin(pset, app_name, metric_name), prefix_(pset.get<std::string>(
"channel_name_prefix",
"artdaq")), channels_() {
107 METLOG(TLVL_DEBUG + 30) <<
"EpicsMetric CONSTRUCTOR";
111 TLOG(TLVL_INFO) <<
"EPICS Metric Destructor";
112 MetricPlugin::stopMetrics(); }
125 TLOG(TLVL_INFO) <<
"EpicsMetric::stopMetrics_";
126 for (
const auto& channel : channels_)
128 if (channel.second != 0)
130 TLOG(TLVL_INFO) <<
"Clearing channel " << channel.first;
131 SEVCHK(ca_clear_channel(channel.second), NULL);
135 ca_context_destroy();
142 SEVCHK(ca_context_create(ca_enable_preemptive_callback), NULL);
155 void sendMetric_(
const std::string& name,
const std::string& value,
const std::string& unit,
const std::chrono::system_clock::time_point&)
override
158 std::string caName = parseChannelName_(prefix_, name);
160 std::string tmpValue = value +
" " + unit;
162 if (checkChannel_(caName))
165 if (tmpValue.size() > 40)
167 tmpValue = tmpValue.erase(40);
169 TLOG(TLVL_DEBUG) <<
"Putting value " << tmpValue <<
" into " << caName;
170 SEVCHK(ca_put(DBR_STRING, channels_[caName], tmpValue.c_str()), NULL);
171 SEVCHK(ca_flush_io(), NULL);
185 void sendMetric_(
const std::string& name,
const int& value,
const std::string& unit,
const std::chrono::system_clock::time_point&)
override
189 std::string caName = parseChannelName_(prefix_, name);
193 METLOG(TLVL_DEBUG + 32) <<
"Not sure if I can send ChannelAccess Units...configure in db instead.";
196 if (checkChannel_(caName))
198 auto val =
static_cast<dbr_long_t
>(value);
199 TLOG(TLVL_DEBUG) <<
"Putting value " << value <<
" into " << caName;
200 SEVCHK(ca_put(DBR_LONG, channels_[caName], &val), NULL);
201 SEVCHK(ca_flush_io(), NULL);
215 void sendMetric_(
const std::string& name,
const double& value,
const std::string& unit,
const std::chrono::system_clock::time_point&)
override
219 std::string caName = parseChannelName_(prefix_, name);
223 METLOG(TLVL_DEBUG + 32) <<
"Not sure if I can send ChannelAccess Units...configure in db instead.";
226 if (checkChannel_(caName))
228 auto val =
static_cast<dbr_double_t
>(value);
229 TLOG(TLVL_DEBUG) <<
"Putting value " << value <<
" into " << caName;
230 SEVCHK(ca_put(DBR_DOUBLE, channels_[caName], &val), NULL);
231 SEVCHK(ca_flush_io(), NULL);
245 void sendMetric_(
const std::string& name,
const float& value,
const std::string& unit,
const std::chrono::system_clock::time_point&)
override
249 std::string caName = parseChannelName_(prefix_, name);
253 METLOG(TLVL_DEBUG + 32) <<
"Not sure if I can send ChannelAccess Units...configure in db instead.";
256 if (checkChannel_(caName))
258 auto val =
static_cast<dbr_float_t
>(value);
259 TLOG(TLVL_DEBUG) <<
"Putting value " << value <<
" into " << caName;
260 SEVCHK(ca_put(DBR_FLOAT, channels_[caName], &val), NULL);
261 SEVCHK(ca_flush_io(), NULL);
275 void sendMetric_(
const std::string& name,
const uint64_t& value,
const std::string& unit,
const std::chrono::system_clock::time_point&)
override
279 std::string caName = parseChannelName_(prefix_, name);
283 METLOG(TLVL_DEBUG + 32) <<
"Not sure if I can send ChannelAccess Units...configure in db instead.";
286 if (checkChannel_(caName))
288 auto val =
static_cast<dbr_ulong_t
>(value);
289 TLOG(TLVL_DEBUG) <<
"Putting value " << value <<
" into " << caName;
290 SEVCHK(ca_put(DBR_LONG, channels_[caName], &val), NULL);
291 SEVCHK(ca_flush_io(), NULL);
299 #endif // End ifndef __EPICS_METRIC__
An instance of the MetricPlugin class that sends metric data using the Channel Access protocol from E...
void stopMetrics_() override
Clears the registered ChannelAccess channels.
void startMetrics_() override
No initialization is needed to start sending metrics.
std::string getLibName() const override
Gets the unique library name of this plugin.
void sendMetric_(const std::string &name, const std::string &value, const std::string &unit, const std::chrono::system_clock::time_point &) override
Send a string metric data point to ChannelAccess.
void sendMetric_(const std::string &name, const float &value, const std::string &unit, const std::chrono::system_clock::time_point &) override
Send a float metric data point to ChannelAccess.
EpicsMetric(fhicl::ParameterSet const &pset, std::string const &app_name, std::string const &metric_name)
Construct an instance of the EpicsMetric plugin.
void sendMetric_(const std::string &name, const double &value, const std::string &unit, const std::chrono::system_clock::time_point &) override
Send a double metric data point to ChannelAccess.
void sendMetric_(const std::string &name, const uint64_t &value, const std::string &unit, const std::chrono::system_clock::time_point &) override
Send an unsigned integer metric data point to ChannelAccess.
void sendMetric_(const std::string &name, const int &value, const std::string &unit, const std::chrono::system_clock::time_point &) override
Send an integer metric data point to ChannelAccess.