Coverage Report

Created: 2026-10-28 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ntopng/src/CHTimeseriesExporter.cpp
Line
Count
Source
1
/*
2
 *
3
 * (C) 2024-26 - ntop.org
4
 *
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software Foundation,
18
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
 *
20
 */
21
22
#include "ntop_includes.h"
23
24
/* ******************************************************* */
25
26
CHTimeseriesExporter::CHTimeseriesExporter(NetworkInterface* _if)
27
0
    : TimeseriesExporter(_if) {
28
0
  if (trace_new_delete)
29
0
    ntop->getTrace()->traceEvent(TRACE_NORMAL, "[new] %s", __FILE__);
30
0
  ts_queue = new (std::nothrow) CHTSPointFifoQueue(ntop->getPrefs()->get_ch_ts_queue_size());
31
0
}
32
33
/* ******************************************************* */
34
35
0
CHTimeseriesExporter::~CHTimeseriesExporter() { delete ts_queue; }
36
37
/* ******************************************************* */
38
39
/* Read a Lua table into a vector<pair<std::string,V>>, converting each value with to_val */
40
template <typename V>
41
static void lua_table_to_vector(lua_State* vm, int index,
42
                                std::vector<std::pair<std::string, V>>& out,
43
0
                                V (*to_val)(lua_State*, int)) {
44
0
  lua_pushnil(vm);
45
46
0
  while (lua_next(vm, index) != 0) {
47
0
    const char* k = lua_tostring(vm, -2);
48
49
0
    if (k) out.push_back(std::make_pair(std::string(k), to_val(vm, -1)));
50
51
0
    lua_pop(vm, 1);
52
0
  }
53
0
}
Unexecuted instantiation: CHTimeseriesExporter.cpp:void lua_table_to_vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(lua_State*, int, std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > (*)(lua_State*, int))
Unexecuted instantiation: CHTimeseriesExporter.cpp:void lua_table_to_vector<double>(lua_State*, int, std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, double>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, double> > >&, double (*)(lua_State*, int))
54
55
0
static std::string lua_val_to_string(lua_State* vm, int index) {
56
0
  const char* s = lua_tostring(vm, index);
57
0
  return s ? std::string(s) : std::string();
58
0
}
59
60
0
static double lua_val_to_double(lua_State* vm, int index) {
61
0
  return (double)lua_tonumber(vm, index);
62
0
}
63
64
/* ******************************************************* */
65
66
/* Builds a CHTSPoint from Lua */
67
0
bool CHTimeseriesExporter::enqueueData(lua_State* vm, bool do_lock) {
68
  /* schema */
69
0
  if (ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) {
70
0
    qdrops++;
71
0
    return false;
72
0
  }
73
74
  /* timestamp */
75
0
  if (ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) {
76
0
    qdrops++;
77
0
    return false;
78
0
  }
79
80
  /* tags */
81
0
  if (ntop_lua_check(vm, __FUNCTION__, 3, LUA_TTABLE) != CONST_LUA_OK) {
82
0
    qdrops++;
83
0
    return false;
84
0
  }
85
86
  /* metrics */
87
0
  if (ntop_lua_check(vm, __FUNCTION__, 4, LUA_TTABLE) != CONST_LUA_OK) {
88
0
    qdrops++;
89
0
    return false;
90
0
  }
91
92
  /* ifid: passed separately from tags (every schema requires an 'ifid' tag,
93
   * see ts_schema.lua) so it can be stored directly on CHTSPoint without
94
   * scanning the tags vector for it on every point. */
95
0
  if (ntop_lua_check(vm, __FUNCTION__, 5, LUA_TNUMBER) != CONST_LUA_OK) {
96
0
    qdrops++;
97
0
    return false;
98
0
  }
99
100
0
  CHTSPoint* point = new (std::nothrow) CHTSPoint();
101
0
  if (!point) {
102
0
    qdrops++;
103
0
    return false;
104
0
  }
105
106
0
  point->schema_name = lua_tostring(vm, 1);
107
0
  point->tstamp = (time_t)lua_tonumber(vm, 2);
108
0
  lua_table_to_vector<std::string>(vm, 3, point->tags, lua_val_to_string);
109
0
  lua_table_to_vector<double>(vm, 4, point->metrics, lua_val_to_double);
110
0
  point->ifid = (int16_t)lua_tonumber(vm, 5);
111
112
0
  if (!ts_queue->enqueue(point)) {
113
0
    delete point;
114
0
    qdrops++;
115
0
    return false;
116
0
  }
117
118
0
  return true;
119
0
}
120
121
/* ******************************************************* */
122
123
/* Not used: exportBatch() is used with ClickHouse timeseries */
124
0
char* CHTimeseriesExporter::dequeueData() { return NULL; }
125
126
/* ******************************************************* */
127
128
0
u_int64_t CHTimeseriesExporter::queueLength() const {
129
0
  return ts_queue->getLength();
130
0
}
131
132
/* ******************************************************* */
133
134
0
void CHTimeseriesExporter::flush() {}
135
136
/* ******************************************************* */
137
138
u_int32_t CHTimeseriesExporter::exportBatch(u_int32_t max_rows,
139
0
                                            std::string& err) {
140
0
  std::vector<CHTSPoint*> points;
141
0
  u_int32_t num_exported = 0;
142
143
0
  ts_queue->dequeueBatch(max_rows, points);
144
145
0
  if (points.empty()) return 0;
146
147
0
  if (iface->getDB() &&
148
0
      iface->getDB()->insertTimeseriesBatch("timeseries", points, err))
149
0
    num_exported = (u_int32_t)points.size();
150
151
0
  for (std::vector<CHTSPoint*>::iterator it = points.begin();
152
0
       it != points.end(); ++it)
153
0
    delete *it;
154
155
0
  return num_exported;
156
0
}