1#!/usr/sbin/dtrace -s
2/*
3 * httpdstat.d - realtime httpd statistics. Uses DTrace.
4 *
5 * $Id: httpdstat.d 2 2007-08-01 10:01:43Z brendan $
6 *
7 * USAGE:	httpdstat.d [interval [count]]
8 *
9 *		interval	seconds
10 *		count		number of samples
11 *
12 * FIELDS:
13 *		TIME		Time, string
14 *		NUM		Number of connections
15 *		GET		Number of "GET"s
16 *		POST		Number of "POST"s
17 *		HEAD		Number of "HEAD"s
18 *		TRACE		Number of "TRACE"s
19 *
20 * All of the statistics are printed as a value per interval (not per second).
21 *
22 * NOTE: This version does not process subsequent operations on keepalives.
23 *
24 * IDEA: Ryan Matteson (who first wrote a solution to this).
25 *
26 * COPYRIGHT: Copyright (c) 2005 Brendan Gregg.
27 *
28 * CDDL HEADER START
29 *
30 *  The contents of this file are subject to the terms of the
31 *  Common Development and Distribution License, Version 1.0 only
32 *  (the "License").  You may not use this file except in compliance
33 *  with the License.
34 *
35 *  You can obtain a copy of the license at Docs/cddl1.txt
36 *  or http://www.opensolaris.org/os/licensing.
37 *  See the License for the specific language governing permissions
38 *  and limitations under the License.
39 *
40 * CDDL HEADER END
41 *
42 * 20-Nov-2005	Brendan Gregg	Created this.
43 */
44
45#pragma D option quiet
46#pragma D option defaultargs
47
48inline int SCREEN = 21;
49
50/*
51 * Program Start
52 */
53dtrace:::BEGIN
54{
55	num = 0; get = 0; head = 0; post = 0; trac = 0;
56	lines = SCREEN + 1;
57	secs = $1 ? $1 : 1;
58	counts = $2 ? $2 : -1;
59	first = 1;
60}
61
62profile:::tick-1sec
63{
64	secs--;
65}
66
67/*
68 * Print Header
69 */
70dtrace:::BEGIN,
71profile:::tick-1sec
72/first || (secs == 0 && lines > SCREEN)/
73{
74	printf("%-20s %6s %6s %5s %5s %5s\n", "TIME",
75	    "NUM", "GET", "POST", "HEAD", "TRACE");
76	lines = 0;
77	first = 0;
78}
79
80/*
81 * Track Accept Events
82 */
83syscall::accept:return
84/execname == "httpd"/
85{
86	self->buf = 1;
87}
88
89syscall::read:entry
90/self->buf/
91{
92	self->buf = arg1;
93}
94
95/*
96 * Tally Data
97 */
98syscall::read:return
99/self->buf && arg0/
100{
101	this->str = (char *)copyin(self->buf, arg0);
102	this->str[4] = '\0';
103	get  += stringof(this->str) == "GET " ? 1 : 0;
104	post += stringof(this->str) == "POST" ? 1 : 0;
105	head += stringof(this->str) == "HEAD" ? 1 : 0;
106	trac += stringof(this->str) == "TRAC" ? 1 : 0;
107	num++;
108	self->buf = 0;
109}
110
111/*
112 * Print Output
113 */
114profile:::tick-1sec
115/secs == 0/
116{
117	printf("%-20Y %6d %6d %5d %5d %5d\n", walltimestamp,
118	    num, get, post, head, trac);
119	num = 0; get = 0; head = 0; post = 0; trac = 0;
120	secs = $1 ? $1 : 1;
121	lines++;
122	counts--;
123}
124
125/*
126 * End
127 */
128profile:::tick-1sec
129/counts == 0/
130{
131	exit(0);
132}
133