Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: dbus/dbus_statistics.cc

Issue 11363173: Add DBusStatistics and DBusLogSource to log and show dbus stats (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase + refactor + respond to feedback Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "dbus/dbus_statistics.h"
6
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/stl_util.h"
10 #include "base/stringprintf.h"
11
12 namespace dbus {
13
14 namespace {
15
16 // Used to store dbus statistics sorted alphabetically by service, interface,
17 // then method (using std::string <).
18 struct Stat {
19 Stat(const std::string& service,
20 const std::string& interface,
21 const std::string& method)
22 : service(service),
23 interface(interface),
24 method(method),
25 sent_calls(0),
26 received_calls(0),
27 sent_blocking_calls(0) {
28 }
29 std::string service;
30 std::string interface;
31 std::string method;
32 int sent_calls;
33 int received_calls;
34 int sent_blocking_calls;
35
36 bool Compare(const Stat& other) const {
37 if (service != other.service)
38 return service < other.service;
39 if (interface != other.interface)
40 return interface < other.interface;
41 return method < other.method;
42 }
43
44 struct PtrCompare {
45 bool operator()(Stat* lhs, Stat* rhs) const {
46 DCHECK(lhs != NULL && rhs != NULL);
gauravsh 2012/11/12 21:41:58 I'd be consistent with the pointer checks in the f
stevenjb 2012/11/12 22:34:40 Done.
47 return lhs->Compare(*rhs);
48 }
49 };
50 };
51
52 typedef std::set<Stat*, Stat::PtrCompare> StatSet;
53
54 //------------------------------------------------------------------------------
55 // DBusStatistics
56
57 // Simple class for gathering DBus usage statistics.
58 class DBusStatistics {
59 public:
60 DBusStatistics() : start_time_(base::Time::Now()) {
61 }
62
63 ~DBusStatistics() {
64 STLDeleteContainerPointers(stats_.begin(), stats_.end());
65 }
66
67 // Eunum to specify which field in Stat to incrament in AddStat
gauravsh 2012/11/12 21:41:58 NIT: Enum, increment
stevenjb 2012/11/12 22:34:40 Done.
68 enum StatType {
69 TYPE_SENT,
70 TYPE_RECEIVED,
71 TYPE_SENT_BLOCKING
72 };
73
74 // Add a call to |method| for |interface|. See also MethodCall in message.h.
75 void AddStat(const std::string& service,
76 const std::string& interface,
77 const std::string& method,
78 StatType type) {
79 Stat* stat = GetStat(service, interface, method, true);
80 if (type == TYPE_SENT)
81 ++stat->sent_calls;
82 else if (type == TYPE_RECEIVED)
83 ++stat->received_calls;
84 else if (type == TYPE_SENT_BLOCKING)
85 ++stat->sent_blocking_calls;
86 else
87 NOTREACHED();
88 }
89
90 // Look up the Stat entry in |stats_|. If |add_stat| is true, add a new entry
91 // if one does not already exist.
92 Stat* GetStat(const std::string& service,
93 const std::string& interface,
94 const std::string& method,
95 bool add_stat) {
96 scoped_ptr<Stat> stat(new Stat(service, interface, method));
97 StatSet::iterator found = stats_.find(stat.get());
98 if (found != stats_.end())
99 return *found;
100 if (!add_stat)
101 return NULL;
102 found = stats_.insert(stat.release()).first;
103 return *found;
104 }
105
106 StatSet& stats() { return stats_; }
107 base::Time start_time() { return start_time_; }
108
109 private:
110 StatSet stats_;
111 base::Time start_time_;
112
113 DISALLOW_COPY_AND_ASSIGN(DBusStatistics);
114 };
115
116 DBusStatistics* g_dbus_statistics = NULL;
117
118 } // namespace
119
120 //------------------------------------------------------------------------------
121
122 namespace statistics {
123
124 void Initialize() {
125 if (g_dbus_statistics)
126 delete g_dbus_statistics; // reset statistics
127 g_dbus_statistics = new DBusStatistics();
128 }
129
130 void Shutdown() {
131 delete g_dbus_statistics;
132 g_dbus_statistics = NULL;
133 }
134
135 void AddSentMethodCall(const std::string& service,
136 const std::string& interface,
137 const std::string& method) {
138 if (!g_dbus_statistics)
139 return;
140 g_dbus_statistics->AddStat(
141 service, interface, method, DBusStatistics::TYPE_SENT);
142 }
143
144 void AddReceivedMethodCall(const std::string& service,
145 const std::string& interface,
146 const std::string& method) {
147 if (!g_dbus_statistics)
148 return;
149 g_dbus_statistics->AddStat(
150 service, interface, method, DBusStatistics::TYPE_RECEIVED);
151 }
152
153 void AddBlockingSentMethodCall(const std::string& service,
154 const std::string& interface,
155 const std::string& method) {
156 if (!g_dbus_statistics)
157 return;
158 g_dbus_statistics->AddStat(
159 service, interface, method, DBusStatistics::TYPE_SENT_BLOCKING);
160 }
161
162 std::string GetAsString(ShowInString show, FormatString format) {
163 if (!g_dbus_statistics)
164 return "DBusStatistics not intitialized.";
gauravsh 2012/11/12 21:41:58 NIT: initialized
stevenjb 2012/11/12 22:34:40 Done.
165
166 const StatSet& stats = g_dbus_statistics->stats();
167 if (stats.empty())
168 return "No DBus calls.";
169
170 base::TimeDelta dtime = base::Time::Now() - g_dbus_statistics->start_time();
171 int dminutes = dtime.InMinutes();
172 dminutes = std::max(dminutes, 1);
173
174 std::string result;
175 int sent = 0, received = 0, sent_blocking = 0;
176 // Stats are stored in order by service, then interface, then method.
177 for (StatSet::const_iterator iter = stats.begin(); iter != stats.end(); ) {
178 StatSet::const_iterator cur_iter = iter++;
gauravsh 2012/11/12 21:41:58 Please do not use the postincrement operator with
stevenjb 2012/11/12 22:34:40 Postincrament is exactly what we want here, (prein
gauravsh 2012/11/12 23:07:34 Sorry, I should have been clearer. Google C++/Chro
179 const Stat* stat = *cur_iter;
180 sent += stat->sent_calls;
181 received += stat->received_calls;
182 sent_blocking += stat->sent_blocking_calls;
183 // If this is the last stat, or if the next stat should be on a different
184 // line, add a line to the result and clear the counts.
185 if (iter == stats.end() ||
gauravsh 2012/11/12 21:41:58 I'd suggest inverting this conditional (and adding
stevenjb 2012/11/12 22:34:40 Good suggestion. Done.
186 (*iter)->service != stat->service ||
187 (show >= SHOW_SERVICE && (*iter)->interface != stat->interface) ||
188 (show >= SHOW_METHOD && (*iter)->method != stat->method)) {
189 if (!sent && !received && !sent_blocking)
190 continue; // No stats collected for this line, skip it and continue.
191
192 std::string line;
193 if (show == SHOW_SERVICE) {
194 line += stat->service;
195 } else {
196 // The interface usually includes the service so don't show both.
197 line += stat->interface;
198 if (show >= SHOW_METHOD)
199 line += "." + stat->method;
200 }
201 line += StringPrintf(":");
202 if (sent_blocking) {
203 line += StringPrintf(" Sent (BLOCKING):");
204 if (format == FORMAT_TOTALS)
205 line += StringPrintf(" %d", sent_blocking);
206 else if (format == FORMAT_PER_MINUTE)
207 line += StringPrintf(" %d/min", sent_blocking / dminutes);
208 else if (format == FORMAT_ALL)
209 line += StringPrintf(" %d (%d/min)",
210 sent_blocking, sent_blocking / dminutes);
211 }
212 if (sent) {
213 line += StringPrintf(" Sent:");
214 if (format == FORMAT_TOTALS)
215 line += StringPrintf(" %d", sent);
216 else if (format == FORMAT_PER_MINUTE)
217 line += StringPrintf(" %d/min", sent / dminutes);
218 else if (format == FORMAT_ALL)
219 line += StringPrintf(" %d (%d/min)", sent, sent / dminutes);
220 }
221 if (received) {
222 line += StringPrintf(" Received:");
223 if (format == FORMAT_TOTALS)
224 line += StringPrintf(" %d", received);
225 else if (format == FORMAT_PER_MINUTE)
226 line += StringPrintf(" %d/min", received / dminutes);
227 else if (format == FORMAT_ALL)
228 line += StringPrintf(" %d (%d/min)", received, received / dminutes);
229 }
230 result += line + "\n";
231 sent = 0;
232 sent_blocking = 0;
233 received = 0;
234 }
235 }
236 return result;
237 }
238
239 namespace testing {
240
241 bool GetCalls(const std::string& service,
242 const std::string& interface,
243 const std::string& method,
244 int* sent,
245 int* received,
246 int* blocking) {
247 if (!g_dbus_statistics)
248 return false;
249 Stat* stat = g_dbus_statistics->GetStat(service, interface, method, false);
250 if (!stat)
251 return false;
252 *sent = stat->sent_calls;
253 *received = stat->received_calls;
254 *blocking = stat->sent_blocking_calls;
255 return true;
256 }
257
258 } // namespace testing
259
260 } // namespace statistics
261 } // namespace dbus
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698