Open
[feat]: 支持可观测gauge仪表 #104
[feat]: 支持可观测gauge仪表 #104
Open
zhangyuxian3Add on 28 days ago
Total: 7 files changed+33-74
MCHANGELOG.md+3-0File content is under review, please try again later
@@ -2,7 +2,7 @@
2 "name": "observability",2 "name": "observability",
3 "type": "application",3 "type": "application",
4 "deployConfig": "om_priv.service",4 "deployConfig": "om_priv.service",
5- "version": "1.90.35",5+ "version": "1.90.36",
6 "author": "Huawei",6 "author": "Huawei",
7 "license": "Mulan PSL v2",7 "license": "Mulan PSL v2",
8 "description": " ",8 "description": " ",
@@ -26,7 +26,7 @@
26 "conan": "mdb_interface/[>=1.80.1]"26 "conan": "mdb_interface/[>=1.80.1]"
27 },27 },
28 {28 {
29- "conan": "opentelemetry/1.13.0.018"29+ "conan": "opentelemetry/1.13.0.019"
30 }30 }
31 ]31 ]
32 },32 },
@@ -182,74 +182,21 @@ class SharedHistogram {
182 std::mutex m_mutex;182 std::mutex m_mutex;
183};183};
184 184 
185-// 辅助函数:比较两个AttributeMap是否相等
186-static bool attributes_equal(const AttributeMap &a, const AttributeMap &b)
187-{
188- if (a.size() != b.size()) {
189- return false;
190- }
191- for (const auto &pair : a) {
192- auto it = b.find(pair.first);
193- if (it == b.end()) {
194- return false;
195- }
196- if (!Utils::AttributeValueEqual<nostd::string_view>(it->second, pair.second) &&
197- !Utils::AttributeValueEqual<int64_t>(it->second, pair.second) &&
198- !Utils::AttributeValueEqual<double>(it->second, pair.second) &&
199- !Utils::AttributeValueEqual<bool>(it->second, pair.second)) {
200- return false;
201- }
202- }
203- return true;
204-}
205- 
206class SharedGauge {185class SharedGauge {
207public:186public:
208- SharedGauge(nostd::shared_ptr<metrics_api::ObservableInstrument> observable_gauge)187+ SharedGauge(nostd::unique_ptr<metrics_api::Gauge<double>> gauge)
209- : m_observable_gauge(std::move(observable_gauge))188+ : m_gauge(std::move(gauge))
210 {189 {
211- // 注册回调函数,返回所有存储的值(每个属性标签组合对应一个值)
212- auto callback_func = [](metrics_api::ObserverResult observer, void *state) {
213- SharedGauge *gauge = static_cast<SharedGauge *>(state);
214- if (!gauge) {
215- return;
216- }
217- 
218- if (absl::holds_alternative<opentelemetry::nostd::shared_ptr<metrics_api::ObserverResultT<double>>>(observer)) {
219- auto result_ptr =
220- absl::get<opentelemetry::nostd::shared_ptr<metrics_api::ObserverResultT<double>>>(observer);
221- auto &result = *result_ptr;
222- // 返回所有存储的值,每个属性标签组合对应一个值
223- std::lock_guard<std::mutex> guard(gauge->m_mutex);
224- for (const auto &entry : gauge->m_values) {
225- // 调用Observe时传入值和对应的属性标签
226- result.Observe(entry.second, entry.first);
227- }
228- }
229- };
230- m_observable_gauge->AddCallback(callback_func, this);
231 }190 }
232 191 
233 void Record(double value, AttributeMap &attributes)192 void Record(double value, AttributeMap &attributes)
234 {193 {
235 std::lock_guard<std::mutex> guard(m_mutex);194 std::lock_guard<std::mutex> guard(m_mutex);
236- // 查找是否已存在相同的属性标签组合195+ m_gauge->Record(value, attributes);
237- for (auto &entry : m_values) {
238- if (attributes_equal(entry.first, attributes)) {
239- // 如果找到相同的属性标签组合,更新值
240- entry.second = value;
241- return;
242- }
243- }
244- // 如果没有找到,添加新的条目
245- m_values.push_back(std::make_pair(attributes, value));
246 }196 }
247 197 
248private:198private:
249- nostd::shared_ptr<metrics_api::ObservableInstrument> m_observable_gauge;199+ nostd::unique_ptr<metrics_api::Gauge<double>> m_gauge;
250- // 存储每个属性标签组合对应的值
251- // 使用vector存储,因为AttributeMap不能直接作为map的key(没有比较操作符)
252- std::vector<std::pair<AttributeMap, double>> m_values;
253 std::mutex m_mutex;200 std::mutex m_mutex;
254};201};
255 202 
@@ -322,10 +269,8 @@ public:
322 if (iter != gauge_map.end()) {269 if (iter != gauge_map.end()) {
323 return iter->second;270 return iter->second;
324 }271 }
325- // 基于ObservableGauge创建同步Gauge272+ nostd::unique_ptr<metrics_api::Gauge<double>> m = m_meter->CreateDoubleGauge(name, description, unit);
326- nostd::shared_ptr<metrics_api::ObservableInstrument> observable_gauge = 273+ nostd::shared_ptr<SharedGauge> n = nostd::shared_ptr<SharedGauge>(new SharedGauge(std::move(m)));
327- m_meter->CreateDoubleObservableGauge(name, description, unit);
328- nostd::shared_ptr<SharedGauge> n = nostd::shared_ptr<SharedGauge>(new SharedGauge(observable_gauge));
329 gauge_map.insert(std::pair<std::string, nostd::shared_ptr<SharedGauge>>(name.data(), n));274 gauge_map.insert(std::pair<std::string, nostd::shared_ptr<SharedGauge>>(name.data(), n));
330 return n;275 return n;
331 }276 }
@@ -38,6 +38,16 @@ function observability_client:OnAssemblyPropertiesChanged(cb)
38 'bmc.kepler.Assembly', {'HostName'})38 'bmc.kepler.Assembly', {'HostName'})
39end39end
40 40 
41+function observability_client:OnCertificatePropertiesChanged(cb)
42+ self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), '/bmc', cb,
43+ 'bmc.kepler.CertificateService.Certificate', {'FilePath'})
44+end
45+ 
46+function observability_client:OnCertificateInterfacesRemoved(cb)
47+ self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
48+ 'bmc.kepler.CertificateService.Certificate')
49+end
50+ 
41function observability_client:GetDashboardObservabilityTracesObject()51function observability_client:GetDashboardObservabilityTracesObject()
42 return {52 return {
43 SamplingRate = 0.5,53 SamplingRate = 0.5,
@@ -16,7 +16,6 @@ local skynet = require 'skynet'
16require 'skynet.manager'16require 'skynet.manager'
17require 'observability.json_types.Receiver'17require 'observability.json_types.Receiver'
18local log = require 'mc.logging'18local log = require 'mc.logging'
19-local utils = require 'mc.utils'
20local mdb = require 'mc.mdb'19local mdb = require 'mc.mdb'
21local dbus = require 'sd_bus'20local dbus = require 'sd_bus'
22local lu = require 'luaunit'21local lu = require 'luaunit'
@@ -43,13 +42,15 @@ end
43local function clear_test_data(exit_test)42local function clear_test_data(exit_test)
44 log:info('clear test data')43 log:info('clear test data')
45 local test_data_dir = skynet.getenv('TEST_DATA_DIR')44 local test_data_dir = skynet.getenv('TEST_DATA_DIR')
46- if not exit_test then return utils.remove_file(test_data_dir) end45+ -- 目录内含持久化 db 文件,utils.remove_file 无法删除非空目录,用 rm -rf 保证清理生效
46+ if not exit_test then return os.execute('rm -rf "' .. test_data_dir .. '"') end
47 47 
48 skynet.timeout(0, function()48 skynet.timeout(0, function()
49 skynet.sleep(20)49 skynet.sleep(20)
50+ -- 先清理测试数据再退出进程:skynet.abort 会直接结束进程,
51+ -- 放在 abort 之后的清理永远不会执行,残留的持久化数据会导致下次运行断言失败
52+ os.execute('rm -rf "' .. test_data_dir .. '" /tmp/test_dump')
50 skynet.abort()53 skynet.abort()
51- utils.remove_file(test_data_dir)
52- utils.remove_file('/tmp/test_dump')
53 end)54 end)
54end55end
55 56 
@@ -10,4 +10,4 @@
10 10 
11require 'test_otel.test_logs'11require 'test_otel.test_logs'
12require 'test_otel.test_trace'12require 'test_otel.test_trace'
13--- require 'test_otel.test_metrics'13+require 'test_otel.test_metrics'
@@ -272,14 +272,14 @@
272 "name": "bmc.system.uptime",272 "name": "bmc.system.uptime",
273 "description": "BMC系统已经运行的时间",273 "description": "BMC系统已经运行的时间",
274 "unit": "s",274 "unit": "s",
275- "type": "Counter",275+ "type": "Gauge",
276 "attributes": []276 "attributes": []
277 },277 },
278 {278 {
279 "name": "bmc.system.cpu.usage",279 "name": "bmc.system.cpu.usage",
280 "description": "BMC CPU的使用情况",280 "description": "BMC CPU的使用情况",
281 "unit": "percent",281 "unit": "percent",
282- "type": "UpDownCounter",282+ "type": "Gauge",
283 "attributes": [283 "attributes": [
284 {284 {
285 "name": "cpu.mode",285 "name": "cpu.mode",
@@ -293,7 +293,7 @@
293 "name": "bmc.system.memory.usage",293 "name": "bmc.system.memory.usage",
294 "description": "BMC使用的物理内存",294 "description": "BMC使用的物理内存",
295 "unit": "By",295 "unit": "By",
296- "type": "UpDownCounter",296+ "type": "Gauge",
297 "attributes": [297 "attributes": [
298 {298 {
299 "name": "system.memory.usage",299 "name": "system.memory.usage",
@@ -307,7 +307,7 @@
307 "name": "bmc.process.cpu.usage",307 "name": "bmc.process.cpu.usage",
308 "description": "BMC进程CPU的使用情况",308 "description": "BMC进程CPU的使用情况",
309 "unit": "percent",309 "unit": "percent",
310- "type": "UpDownCounter",310+ "type": "Gauge",
311 "attributes": [311 "attributes": [
312 {312 {
313 "name": "process.name",313 "name": "process.name",
@@ -321,7 +321,7 @@
321 "name": "bmc.process.memory.usage",321 "name": "bmc.process.memory.usage",
322 "description": "BMC进程使用的物理内存",322 "description": "BMC进程使用的物理内存",
323 "unit": "By",323 "unit": "By",
324- "type": "UpDownCounter",324+ "type": "Gauge",
325 "attributes": [325 "attributes": [
326 {326 {
327 "name": "process.name",327 "name": "process.name",
@@ -349,7 +349,7 @@
349 "name": "bmc.system.flash.lifeleft",349 "name": "bmc.system.flash.lifeleft",
350 "description": "BMC Flash的剩余寿命",350 "description": "BMC Flash的剩余寿命",
351 "unit": "percent",351 "unit": "percent",
352- "type": "UpDownCounter",352+ "type": "Gauge",
353 "attributes": []353 "attributes": []
354 }354 }
355 ]355 ]