1 /* telemetry.c -- common server telemetry
2 *
3 * Copyright (c) 1994-2008 Carnegie Mellon University. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * 3. The name "Carnegie Mellon University" must not be used to
18 * endorse or promote products derived from this software without
19 * prior written permission. For permission or any legal
20 * details, please contact
21 * Carnegie Mellon University
22 * Center for Technology Transfer and Enterprise Creation
23 * 4615 Forbes Avenue
24 * Suite 302
25 * Pittsburgh, PA 15213
26 * (412) 268-7393, fax: (412) 268-7395
27 * innovation@andrew.cmu.edu
28 *
29 * 4. Redistributions of any form whatsoever must retain the following
30 * acknowledgment:
31 * "This product includes software developed by Computing Services
32 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33 *
34 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41 */
42
43 #include <config.h>
44
45 #ifdef HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif
48 #include <sys/time.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <sys/resource.h>
52 #include <fcntl.h>
53 #include <string.h>
54 #include <syslog.h>
55
56 #include "prot.h"
57 #include "global.h"
58
59 /* create telemetry log; return fd of log */
telemetry_log(const char * userid,struct protstream * pin,struct protstream * pout,int usetimestamp)60 EXPORTED int telemetry_log(const char *userid, struct protstream *pin,
61 struct protstream *pout, int usetimestamp)
62 {
63 char buf[1024];
64 char buf2[1024];
65 int fd = -1;
66 time_t now;
67 int r;
68
69 if (usetimestamp) {
70 struct timeval tv;
71
72 gettimeofday(&tv, NULL);
73
74 /* use sec.clocks */
75 snprintf(buf, sizeof(buf), "%s%s%s/%s-%lu.%lu",
76 config_dir, FNAME_LOGDIR, userid, config_ident,
77 (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec);
78 }
79 else if (config_getswitch(IMAPOPT_TELEMETRY_BYSESSIONID)) {
80 const char *sid = session_id();
81 /* use pid */
82 snprintf(buf, sizeof(buf), "%s%s%s/%s-%s",
83 config_dir, FNAME_LOGDIR, userid, config_ident, sid);
84 }
85 else {
86 /* use pid */
87 snprintf(buf, sizeof(buf), "%s%s%s/%s-%lu",
88 config_dir, FNAME_LOGDIR, userid, config_ident,
89 (unsigned long) getpid());
90 }
91
92 fd = open(buf, O_CREAT | O_APPEND | O_WRONLY, 0644);
93
94 if (fd != -1) {
95 now = time(NULL);
96 snprintf(buf2, sizeof(buf2), "---------- %s %s\n",
97 userid, ctime(&now));
98 r = write(fd, buf2, strlen(buf2));
99 if (r < 0)
100 syslog(LOG_ERR, "IOERROR: unable to write to telemetry log %s: %m", buf);
101
102 if (pin) prot_setlog(pin, fd);
103 if (pout) prot_setlog(pout, fd);
104 }
105
106 return fd;
107 }
108
telemetry_rusage(char * userid)109 EXPORTED void telemetry_rusage(char *userid)
110 {
111 static struct rusage previous;
112 struct rusage current;
113 struct timeval sys, user;
114
115 if (userid && *userid) {
116 if (getrusage(RUSAGE_SELF, ¤t) != 0) {
117 syslog(LOG_ERR, "getrusage: %s", userid);
118 return;
119 }
120
121 user.tv_sec = current.ru_utime.tv_sec - previous.ru_utime.tv_sec;
122 user.tv_usec = current.ru_utime.tv_usec - previous.ru_utime.tv_usec;
123 if (user.tv_usec < 0) {
124 user.tv_sec--;
125 user.tv_usec += 1000000;
126 }
127
128 sys.tv_sec = current.ru_stime.tv_sec - previous.ru_stime.tv_sec;
129 sys.tv_usec = current.ru_stime.tv_usec - previous.ru_stime.tv_usec;
130 if (sys.tv_usec < 0) {
131 sys.tv_sec--;
132 sys.tv_usec += 1000000;
133 }
134
135 /*
136 * Some systems provide significantly more data, but POSIX
137 * guarantees user & sys CPU time.
138 */
139 syslog(LOG_NOTICE, "USAGE %s user: %lu.%.6d sys: %lu.%.6d", userid,
140 (unsigned long)user.tv_sec, (int)user.tv_usec,
141 (unsigned long)sys.tv_sec, (int)sys.tv_usec);
142
143 previous = current;
144 }
145
146 return;
147 }
148