Apollo 11.0
自动驾驶开放平台
process_statistic_component.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2023 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
17
18#include <utility>
19
22
23namespace apollo {
24namespace process_statistic {
25
27 // hook: Apollo License Verification: v_apollo_park
29 if (!ComponentBase::GetProtoConfig(&conf)) {
30 AERROR << "Unable to load process statistic conf file: " << ComponentBase::ConfigFilePath();
31 return false;
32 }
33 AINFO << "read conf success.";
34 LoadConf(conf);
35 // create metric writer
36 metric_writer_ = node_->CreateWriter<ProcessMetrics>(FLAGS_process_statistic_topic);
37 return true;
38}
39
40void ProcessStatisticComponent::LoadConf(const ProcessStatisticConf& conf) {
41 if (conf.has_general_process()) {
42 for (auto& regex_str : conf.general_process().regex()) {
43 try {
44 general_process_regex_list_.emplace_back(regex_str);
45 } catch (std::regex_error& e) {
46 AERROR << "error general process conf: " << regex_str << ", regex_error caught: " << e.what();
47 }
48 }
49 }
50}
51
53 auto metrics = std::make_shared<ProcessMetrics>();
54 apollo::common::util::FillHeader(node_->Name(), metrics.get());
55
56 for (const auto& cmd_file : cyber::common::Glob("/proc/[0-9]*/cmdline")) {
57 // Get process command string.
58 std::string cmd_string;
59 if (cyber::common::GetContent(cmd_file, &cmd_string) && !cmd_string.empty()) {
60 // In /proc/<PID>/cmdline, the parts are separated with \0, which will be
61 // converted back to whitespaces here.
62 std::replace(cmd_string.begin(), cmd_string.end(), '\0', ' ');
63
64 if (ParseFromCache(cmd_string, metrics)) {
65 continue;
66 }
67 ParseCmd(cmd_string, metrics, cache_.at(cmd_string));
68 }
69 }
70 // write metrics
71 metric_writer_->Write(metrics);
72
73 // clean cache
74 if (++cycles % cache_clean_cycles == 0) {
75 cycles = 0;
76 CleanCache();
77 }
78 return true;
79}
80
81bool ProcessStatisticComponent::ParseFromCache(const std::string& cmd_string, std::shared_ptr<ProcessMetrics> metrics) {
82 auto now = cyber::Time().Now().ToNanosecond();
83 if (cache_.find(cmd_string) == cache_.end()) {
84 std::shared_ptr<CacheMetric> cache_metric = std::make_shared<CacheMetric>();
85 cache_metric->timestamp = now;
86 cache_[cmd_string] = std::move(cache_metric);
87 return false;
88 }
89 auto& cache_metric = cache_[cmd_string];
90 cache_metric->timestamp = now;
91 for (const auto& dag : cache_metric->mainboard_dags) {
92 metrics->mutable_mainboard_dag()->add_name(dag);
93 }
94 if (!cache_metric->mainboard_process.empty()) {
95 metrics->mutable_mainboard_process_group()->add_name(cache_metric->mainboard_process);
96 }
97 if (!cache_metric->general_process.empty()) {
98 metrics->mutable_general_process()->add_name(cache_metric->general_process);
99 }
100 return true;
101}
102
103void ProcessStatisticComponent::ParseCmd(
104 const std::string& cmd_string,
105 std::shared_ptr<ProcessMetrics> metrics,
106 std::shared_ptr<CacheMetric> cache_metric) {
107 // mainboard match
108 if (cmd_string.find("mainboard") != cmd_string.npos) {
109 auto end = std::sregex_iterator();
110 // dag
111 auto dag_begin = std::sregex_iterator(cmd_string.begin(), cmd_string.end(), mainboard_dag_regex);
112
113 for (auto it = dag_begin; it != end; ++it) {
114 std::string name = (*it).str(1);
115 metrics->mutable_mainboard_dag()->add_name(name);
116 cache_metric->mainboard_dags.push_back(std::move(name));
117 }
118 // process group
119 auto process_begin = std::sregex_iterator(cmd_string.begin(), cmd_string.end(), mainboard_process_regex);
120 for (auto it = process_begin; it != end; ++it) {
121 std::string name = (*it).str(1);
122 metrics->mutable_mainboard_process_group()->add_name(name);
123 cache_metric->mainboard_process = std::move(name);
124 }
125 } else {
126 // general process match
127 for (auto& re : general_process_regex_list_) {
128 if (std::regex_match(cmd_string, re)) {
129 metrics->mutable_general_process()->add_name(cmd_string);
130 cache_metric->general_process = cmd_string;
131 }
132 }
133 }
134}
135
136void ProcessStatisticComponent::CleanCache() {
137 for (auto it = cache_.begin(); it != cache_.end();) {
138 // clean process 10 seconds ago
139 auto threshold = cyber::Time().Now().ToNanosecond() - 1e+10;
140 if (it->second->timestamp < threshold) {
141 it = cache_.erase(it);
142 } else {
143 ++it;
144 }
145 }
146}
147
148} // namespace process_statistic
149} // namespace apollo
std::shared_ptr< Node > node_
Cyber has builtin time type Time.
Definition time.h:31
uint64_t ToNanosecond() const
convert time to nanosecond.
Definition time.cc:83
static Time Now()
get the current time.
Definition time.cc:57
bool Proc() override
The Proc logic of the component, which called by the CyberRT frame.
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
Some string util functions.
std::vector< std::string > Glob(const std::string &pattern)
Expand path pattern to matched paths.
Definition file.cc:212
bool GetContent(const std::string &file_name, std::string *content)
Get file content as string.
Definition file.cc:167
Image< uchar > * threshold(Image< T > *src, int t)
Threshold image
Definition imutil.h:79
class register implement
Definition arena_queue.h:37