XRootD
Loading...
Searching...
No Matches
XrdStats.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d S t a t s . c c */
4/* */
5/* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Department of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include <cstdio>
31#include <cstdlib>
32#include <sys/time.h>
33#include <sys/resource.h>
34#include <sys/uio.h>
35
36#include "XrdVersion.hh"
37#include "Xrd/XrdBuffer.hh"
38#include "Xrd/XrdJob.hh"
39#include "Xrd/XrdLink.hh"
40#include "Xrd/XrdMonitor.hh"
41#include "Xrd/XrdPoll.hh"
42#include "Xrd/XrdProtLoad.hh"
43#include "Xrd/XrdScheduler.hh"
44#include "Xrd/XrdStats.hh"
45#include "XrdOuc/XrdOucEnv.hh"
46#include "XrdNet/XrdNetMsg.hh"
48#include "XrdSys/XrdSysTimer.hh"
49
50/******************************************************************************/
51/* S t a t i c O b j e c t s */
52/******************************************************************************/
53
54 long XrdStats::tBoot = static_cast<long>(time(0));
55
56/******************************************************************************/
57/* L o c a l C l a s s X r d S t a t s J o b */
58/******************************************************************************/
59
61{
62public:
63
64 void DoIt() {Stats->Report();
65 Sched->Schedule((XrdJob *)this, time(0)+iVal);
66 }
67
68 XrdStatsJob(XrdScheduler *schP, XrdStats *sP, int iV)
69 : XrdJob("stats reporter"),
70 Sched(schP), Stats(sP), iVal(iV)
71 {Sched->Schedule((XrdJob *)this, time(0)+iVal);}
73private:
74XrdScheduler *Sched;
75XrdStats *Stats;
76int iVal;
77};
78
79/******************************************************************************/
80/* C o n s t r c u t o r */
81/******************************************************************************/
82
84 const char *hname, int port,
85 const char *iname, const char *pname, const char *site)
86{
87 XrdLog = eP;
88 XrdSched = sP;
89 BuffPool = bP;
90
91 myHost = hname;
92 myName = iname;
93 myProg = pname;
94 mySite = (site ? site : "");
95 Head = Jead = 0;
96 SetPort(port);
97
98// Allocate a shared buffer. Buffer use is serialized via the statsMutex.
99//
100 blen = 64*1024; // 64K which is the largest allowed UDP packet
101 if (posix_memalign((void **)&buff, getpagesize(), blen)) buff = 0;
102
103 theMon = new XrdMonitor;
104}
105
106/******************************************************************************/
107/* S e t P o r t */
108/******************************************************************************/
109
110void XrdStats::SetPort(int port)
111{
112 const char *head =
113 "<statistics tod=\"%%ld\" ver=\"" XrdVERSION "\" src=\"%s:%d\" "
114 "tos=\"%ld\" pgm=\"%s\" ins=\"%s\" pid=\"%d\" "
115 "site=\"%s\">";
116 Hend = "</statistics>";
117 Htln = strlen(Hend);
118
119 const char *jead =
120 "{\"statistics\":{\"tod\":%%ld,\"ver\":\"" XrdVERSION "\",\"src\":\"%s:%d\","
121 "\"tos\":%ld,\"pgm\":\"%s\",\"ins\":\"%s\",\"pid\":%d,"
122 "\"site\":\"%s\",";
123 Jend = "}}";
124 Jtln = 2;
125
126 char myBuff[1024];
127
128 myPort = port;
129
130 sprintf(myBuff, head, myHost, port, tBoot, myProg, myName,
131 static_cast<int>(getpid()), mySite);
132 if (Head) free(Head);
133 Head = strdup(myBuff);
134
135 sprintf(myBuff, jead, myHost, port, tBoot, myProg, myName,
136 static_cast<int>(getpid()), mySite);
137 if (Jead) free(Jead);
138 Jead = strdup(myBuff);
139}
140
141/******************************************************************************/
142/* E x p o r t */
143/******************************************************************************/
144
146{
147 XrdMonRoll* monRoll = new XrdMonRoll(*theMon);
148 theEnv.PutPtr("XrdMonRoll*", monRoll);
149}
150
151/******************************************************************************/
152/* I n i t */
153/******************************************************************************/
154
155void XrdStats::Init(char **Dest, int iVal, int xOpts, int jOpts)
156{
157
158// Establish up to two destinations
159//
160 if (Dest[0]) netDest[0] = new XrdNetMsg(XrdLog, Dest[0]);
161 if (Dest[1]) netDest[1] = new XrdNetMsg(XrdLog, Dest[1]);
162
163// Establish auto reporting options
164//
165 if (!(jOpts & XRD_STATS_ALLJ) && !(xOpts & XRD_STATS_ALLX))
166 xOpts |= XRD_STATS_ALLX; // ALLX includes ALLJ
167 jsonOpts = (jOpts & XRD_STATS_ALLJ) | XRD_STATS_JSON; xmlOpts = xOpts;
168 autoSync = xOpts & XRD_STATS_SYNCA;
169
170// Get and schedule a new job to report
171//
172 if (netDest[0]) new XrdStatsJob(XrdSched, this, iVal);
173 return;
174}
175
176/******************************************************************************/
177/* R e p o r t */
178/******************************************************************************/
179
181{
182 char udpBuff[64*1024];
183 const char *Data;
184 int theOpts, Dlen;
185
186// This is an entry for reporting purposes, establish the sync flag
187//
188 if (!autoSync || XrdSched->Active() <= 30) theOpts = xmlOpts;
189 else theOpts = xmlOpts & ~XRD_STATS_SYNC;
190
191// Now get the statistics in xml format. Note that there is only one buufer
192// so we lock this code path to protect it. Skip this if no specific reports
193// in the xml category are requested.
194//
195 if (theOpts)
196 {statsMutex.Lock();
197 if ((Data = GenStats(Dlen, theOpts)))
198 {netDest[0]->Send(Data, Dlen);
199 if (netDest[1]) netDest[1]->Send(Data, Dlen);
200 }
201 statsMutex.UnLock();
202 }
203
204// Check if we have additional data registered via addons and plugins that
205// we need in JSON format. These are sent as separate udp packets.
206//
207 theOpts = XrdMonitor::F_JSON;
208 if (jsonOpts & XRD_STATS_ADON) theOpts |= XrdMonitor::X_ADON;
209 if (jsonOpts & XRD_STATS_PLUG) theOpts |= XrdMonitor::X_PLUG;
210 if (!(theOpts & ~XrdMonitor::F_JSON) || !theMon->Registered()) return;
211
212// Format the header and setup for sending packets
213//
214 int hL = sprintf(udpBuff, Jead, time(0));
215 int bL = sizeof(udpBuff) - hL - Jtln - 8;
216 char* bP = udpBuff + hL;
217
218// Get each item and send it off
219//
220 struct iovec ioV[3];
221 ioV[0].iov_base = udpBuff;
222 ioV[0].iov_len = hL;
223 ioV[1].iov_base = bP;
224 ioV[2].iov_base = (void*)Jend;
225 ioV[2].iov_len = Jtln;
226 int uL, sItem = 0;
227 while((uL = theMon->Format(bP, bL, sItem, theOpts)))
228 {ioV[1].iov_len = uL;
229 netDest[0]->Send(ioV, 3);
230 if (netDest[1]) netDest[1]->Send(ioV, 3);
231 }
232}
233
234/******************************************************************************/
235/* S t a t s */
236/******************************************************************************/
237
238void XrdStats::Stats(XrdStats::CallBack *cbP, int xOpts, int jOpts)
239{
240 const char *info;
241 int sz, opts;
242
243// Note that currently we do not support json for client requests, so we
244// ignore the jOpts as they should never be set.
245//
246 opts = xOpts;
247
248// Lock the buffer,
249//
250 statsMutex.Lock();
251
252// Obtain the stats, if we have some, do the callback. We currently do not
253// support return of JSON format as some statistics can't provide it.
254//
255 if ((info = GenStats(sz, opts))) cbP->Info(info, sz);
256
257// Unlock the buffer
258//
259 statsMutex.UnLock();
260}
261
262/******************************************************************************/
263/* P r i v a t e M e t h o d s */
264/******************************************************************************/
265/******************************************************************************/
266/* G e n S t a t s */
267/******************************************************************************/
268
269const char *XrdStats::GenStats(int &rsz, int opts) // statsMutex must be locked!
270{
271 static const char *sgen = "<stats id=\"sgen\">"
272 "<as>%d</as><et>%lu</et><toe>%ld</toe></stats>";
273 static const char *tail = "</statistics>";
274 static const char *snul = "<statistics tod=\"0\" ver=\"" XrdVSTRING "\">"
275 "</statistics>";
276
277 static const int snulsz = strlen(snul);
278 static const int ovrhed = 256+strlen(sgen)+strlen(tail);
279 XrdSysTimer myTimer;
280 char *bp;
281 int n, bl, sz, do_sync = (opts & XRD_STATS_SYNC ? 1 : 0);
282
283// If buffer is not allocated we cannot generate a report (not likely)
284//
285 if (!(bp = buff)) {rsz = snulsz; return snul;}
286 bl = blen - ovrhed;
287
288// Start the time if need be
289//
290 if (opts & XRD_STATS_SGEN) myTimer.Reset();
291
292// Insert the heading
293//
294 sz = sprintf(buff, Head, static_cast<long>(time(0)));
295 bl -= sz; bp += sz;
296
297// Extract out the statistics, as needed
298//
299 if (opts & XRD_STATS_INFO)
300 {sz = InfoStats(bp, bl, do_sync);
301 bp += sz; bl -= sz;
302 }
303
304 if (opts & XRD_STATS_BUFF)
305 {sz = BuffPool->Stats(bp, bl, do_sync);
306 bp += sz; bl -= sz;
307 }
308
309 if (opts & XRD_STATS_LINK)
310 {sz = XrdLink::Stats(bp, bl, do_sync);
311 bp += sz; bl -= sz;
312 }
313
314 if (opts & XRD_STATS_POLL)
315 {sz = XrdPoll::Stats(bp, bl, do_sync);
316 bp += sz; bl -= sz;
317 }
318
319 if (opts & XRD_STATS_PROC)
320 {sz = ProcStats(bp, bl, do_sync);
321 bp += sz; bl -= sz;
322 }
323
324 if (opts & XRD_STATS_PROT)
325 {sz = XrdProtLoad::Statistics(bp, bl, do_sync);
326 bp += sz; bl -= sz;
327 }
328
329 if (opts & XRD_STATS_SCHD)
330 {sz = XrdSched->Stats(bp, bl, do_sync);
331 bp += sz; bl -= sz;
332 }
333
334 if (opts & XRD_STATS_SGEN)
335 {unsigned long totTime = 0;
336 myTimer.Report(totTime);
337 sz = snprintf(bp,bl,sgen,do_sync==0,totTime,static_cast<long>(time(0)));
338 bp += sz; bl -= sz;
339 }
340
341// Set the type of object we are interested in
342//
343 int fOpts = 0;
344 if (opts & XRD_STATS_ADON) fOpts |= XrdMonitor::X_ADON;
345 if (opts & XRD_STATS_PLUG) fOpts |= XrdMonitor::X_PLUG;
346 if (fOpts)
347 {int uL, sItem = 0;
348 while(bl > 0 && (uL = theMon->Format(bp, bl, sItem, fOpts)))
349 {bp += uL; bl -= uL;}
350 }
351
352 sz = bp - buff;
353 if (bl > 0) n = strlcpy(bp, tail, bl);
354 else n = 0;
355 rsz = sz + (n >= bl ? bl : n);
356 return buff;
357}
358
359/******************************************************************************/
360
361
362void XrdStats::GenStats(std::vector<struct iovec>& ioVec, int opts)
363{
364 const char* sTail;
365 char *sbP, sBuff[64*1024]; // Maximum size of UDP packet
366 std::vector<struct iovec> ioV;
367 int sTLen, sbFree, sdSZ, fOpts, sItem = 0;
368
369// Insert the header in the buffer
370//
371 if (opts & XRD_STATS_JSON)
372 {int Jlen = sprintf(sBuff, Jead, time(0));
373 sdSZ = sbFree = sizeof(sBuff) - Jlen - 64; // Generous extra for tail
374 sbP = sBuff + Jlen;
375 sTail = Jend;
376 sTLen = Jtln;
377 fOpts = XrdMonitor::F_JSON;
378 } else {
379 int Hlen = sprintf(sBuff, Head, time(0));
380 sdSZ = sbFree = sizeof(sBuff) - Hlen - 64; // Generous extra for tail
381 sbP = sBuff + Hlen;
382 sTail = Hend;
383 sTLen = Htln;
384 fOpts = 0;
385 }
386
387// Set the type of object we are interested in
388//
389 if (opts & XRD_STATS_ADON) fOpts |= XrdMonitor::X_ADON;
390 if (opts & XRD_STATS_PLUG) fOpts |= XrdMonitor::X_PLUG;
391
392// Generate all plugin statistics, one at a time
393//
394 while((sdSZ = theMon->Format(sbP, sbFree, sItem, fOpts)))
395 {if (sdSZ > 0 && sdSZ <= sbFree)
396 {char* bP = sbP + sdSZ;
397 struct iovec ioV;
398 strcpy(bP, sTail);
399 strcpy(bP+sTLen, "\n");
400 bP++;
401 ioV.iov_base = strdup(sBuff);
402 ioV.iov_len = bP - sBuff + sTLen;
403 ioVec.push_back(ioV);
404 }
405 }
406}
407
408/******************************************************************************/
409/* I n f o S t a t s */
410/******************************************************************************/
411
412int XrdStats::InfoStats(char *bfr, int bln, int do_sync)
413{
414 static const char statfmt[] = "<stats id=\"info\"><host>%s</host>"
415 "<port>%d</port><name>%s</name></stats>";
416
417// Check if actual length wanted
418//
419 if (!bfr) return sizeof(statfmt)+24 + strlen(myHost);
420
421// Format the statistics
422//
423 return snprintf(bfr, bln, statfmt, myHost, myPort, myName);
424}
425
426/******************************************************************************/
427/* P r o c S t a t s */
428/******************************************************************************/
429
430int XrdStats::ProcStats(char *bfr, int bln, int do_sync)
431{
432 static const char statfmt[] = "<stats id=\"proc\">"
433 "<usr><s>%lld</s><u>%lld</u></usr>"
434 "<sys><s>%lld</s><u>%lld</u></sys>"
435 "</stats>";
436 struct rusage r_usage;
437 long long utime_sec, utime_usec, stime_sec, stime_usec;
438// long long ru_maxrss, ru_majflt, ru_nswap, ru_inblock, ru_oublock;
439// long long ru_msgsnd, ru_msgrcv, ru_nsignals;
440
441// Check if actual length wanted
442//
443 if (!bfr) return sizeof(statfmt)+16*13;
444
445// Get the statistics
446//
447 if (getrusage(RUSAGE_SELF, &r_usage)) return 0;
448
449// Convert fields to correspond to the format we are using. Commented out fields
450// are either not uniformaly reported or are incorrectly reported making them
451// useless across multiple platforms.
452//
453//
454 utime_sec = static_cast<long long>(r_usage.ru_utime.tv_sec);
455 utime_usec = static_cast<long long>(r_usage.ru_utime.tv_usec);
456 stime_sec = static_cast<long long>(r_usage.ru_stime.tv_sec);
457 stime_usec = static_cast<long long>(r_usage.ru_stime.tv_usec);
458// ru_maxrss = static_cast<long long>(r_usage.ru_maxrss);
459// ru_majflt = static_cast<long long>(r_usage.ru_majflt);
460// ru_nswap = static_cast<long long>(r_usage.ru_nswap);
461// ru_inblock = static_cast<long long>(r_usage.ru_inblock);
462// ru_oublock = static_cast<long long>(r_usage.ru_oublock);
463// ru_msgsnd = static_cast<long long>(r_usage.ru_msgsnd);
464// ru_msgrcv = static_cast<long long>(r_usage.ru_msgrcv);
465// ru_nsignals = static_cast<long long>(r_usage.ru_nsignals);
466
467// Format the statistics
468//
469 return snprintf(bfr, bln, statfmt,
470 utime_sec, utime_usec, stime_sec, stime_usec
471// ru_maxrss, ru_majflt, ru_nswap, ru_inblock, ru_oublock,
472// ru_msgsnd, ru_msgrcv, ru_nsignals
473 );
474}
struct myOpts opts
#define XRD_STATS_POLL
Definition XrdStats.hh:44
#define XRD_STATS_ADON
Definition XrdStats.hh:37
#define XRD_STATS_JSON
Definition XrdStats.hh:52
#define XRD_STATS_SYNC
Definition XrdStats.hh:49
#define XRD_STATS_INFO
Definition XrdStats.hh:40
#define XRD_STATS_LINK
Definition XrdStats.hh:42
#define XRD_STATS_BUFF
Definition XrdStats.hh:41
#define XRD_STATS_SYNCA
Definition XrdStats.hh:50
#define XRD_STATS_PLUG
Definition XrdStats.hh:43
#define XRD_STATS_SCHD
Definition XrdStats.hh:47
#define XRD_STATS_ALLX
Definition XrdStats.hh:39
#define XRD_STATS_PROT
Definition XrdStats.hh:46
#define XRD_STATS_PROC
Definition XrdStats.hh:45
#define XRD_STATS_SGEN
Definition XrdStats.hh:48
#define XRD_STATS_ALLJ
Definition XrdStats.hh:38
size_t strlcpy(char *dst, const char *src, size_t sz)
friend class XrdScheduler
Definition XrdJob.hh:44
XrdJob(const char *desc="")
Definition XrdJob.hh:51
XrdMonRoll(XrdMonitor &xMon)
Definition XrdMonRoll.cc:46
XrdNetMsg(XrdSysError *erp, const char *dest=0, bool *aOK=0, bool refr=false)
Definition XrdNetMsg.cc:66
void PutPtr(const char *varname, void *value)
Definition XrdOucEnv.cc:298
static int Stats(char *buff, int blen, int do_sync=0)
Definition XrdPoll.cc:332
static int Statistics(char *buff, int blen, int do_sync=0)
void DoIt()
Definition XrdStats.cc:64
XrdStatsJob(XrdScheduler *schP, XrdStats *sP, int iV)
Definition XrdStats.cc:68
virtual void Info(const char *data, int dlen)=0
void Init(char **Dest, int iVal=600, int xOpts=0, int jOpts=0)
Definition XrdStats.cc:155
XrdStats(XrdSysError *eP, XrdScheduler *sP, XrdBuffManager *bP, const char *hn, int port, const char *in, const char *pn, const char *sn)
Definition XrdStats.cc:83
void SetPort(int port)
Definition XrdStats.cc:110
void Report()
Definition XrdStats.cc:180
void Export(XrdOucEnv &env)
Definition XrdStats.cc:145
virtual void Stats(XrdStats::CallBack *InfoBack, int xOpts, int jOpts=0)
Definition XrdStats.cc:238
unsigned long Report(double &)