KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > scriptella > execution > ExecutionStatistics


1 /*
2  * Copyright 2006-2007 The Scriptella Project Team.
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  */

16 package scriptella.execution;
17
18 import scriptella.spi.Connection;
19
20 import java.text.DecimalFormat JavaDoc;
21 import java.text.Format JavaDoc;
22 import java.text.NumberFormat JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Date JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.LinkedHashMap JavaDoc;
28 import java.util.Map JavaDoc;
29
30
31 /**
32  * Represents script execution statistics
33  * <p>The statistics is groupped by script elements i.e. script or query.
34  *
35  * @author Fyodor Kupolov
36  * @version 1.0
37  */

38 public class ExecutionStatistics {
39     int statements;
40     Map JavaDoc<String JavaDoc, ElementInfo> elements = new LinkedHashMap JavaDoc<String JavaDoc, ElementInfo>();
41     private Date JavaDoc started;
42     private Date JavaDoc finished;
43     private static final int MINUTE_MILLIS = 60 * 1000;
44     private static final int HOUR_MILLIS = 60 * MINUTE_MILLIS;
45     private static final int DAY_MILLIS = 24 * HOUR_MILLIS;
46     static final String JavaDoc DOUBLE_FORMAT_PTR = "0.##";
47
48
49     /**
50      * @return number of statements executed for all elements.
51      */

52     public int getExecutedStatementsCount() {
53         return statements;
54     }
55
56     public Collection JavaDoc<ElementInfo> getElements() {
57         return elements.values();
58     }
59
60     /**
61      * Returns the statistics on executed categories, e.g.
62      * queries-5times, scripts-10times.
63      * <p>Note the category names are xml element names, no plural form used.
64      *
65      * @return xmlelement->count map .
66      */

67     public Map JavaDoc<String JavaDoc, Integer JavaDoc> getCategoriesStatistics() {
68         Map JavaDoc<String JavaDoc, Integer JavaDoc> res = new HashMap JavaDoc<String JavaDoc, Integer JavaDoc>();
69         for (String JavaDoc xpath : elements.keySet()) {
70             String JavaDoc elementName = getElementName(xpath);
71             Integer JavaDoc cnt = res.get(elementName);
72             if (cnt == null) {
73                 cnt = 0;
74             }
75             res.put(elementName, ++cnt); //autoboxing works fine on small numbers
76
}
77         return res;
78     }
79
80     public String JavaDoc toString() {
81         final Collection JavaDoc<ElementInfo> elements = getElements();
82         if (elements.isEmpty()) {
83             return "No elements executed";
84         }
85         StringBuilder JavaDoc sb = new StringBuilder JavaDoc(1024);
86         NumberFormat JavaDoc doubleFormat = new DecimalFormat JavaDoc(DOUBLE_FORMAT_PTR);
87         sb.append("Executed ");
88
89         Map JavaDoc<String JavaDoc, Integer JavaDoc> cats = getCategoriesStatistics();
90         for (Iterator JavaDoc<Map.Entry JavaDoc<String JavaDoc, Integer JavaDoc>> it = cats.entrySet().iterator(); it.hasNext();) {
91             Map.Entry JavaDoc<String JavaDoc, Integer JavaDoc> category = it.next();
92             appendPlural(sb, category.getValue(), category.getKey());
93             if (it.hasNext()) {
94                 sb.append(", ");
95             }
96         }
97         if (statements > 0) {
98             sb.append(", ");
99             appendPlural(sb, statements, "statement");
100         }
101
102         sb.append('\n');
103
104         for (ElementInfo ei : elements) {
105             sb.append(ei.id).append(":");
106
107             if (ei.okCount > 0) {
108                 sb.append(" Element successfully executed");
109                 if (ei.okCount > 1) {
110                     sb.append(' ');
111                     appendPlural(sb, ei.okCount, "time");
112                 }
113                 if (ei.statements > 0) {
114                     sb.append(" (");
115                     appendPlural(sb, ei.statements, "statement").append(')');
116                 }
117                 sb.append('.');
118             }
119
120             if (ei.failedCount > 0) {
121                 sb.append(" Element failed ");
122                 appendPlural(sb, ei.failedCount, "time");
123                 sb.append('.');
124             }
125             sb.append(" Working time ").append(ei.workingTime / 1000000).append(" milliseconds.");
126             //Output throughput
127
double throughput = ei.getThroughput();
128             if (throughput >= 0) {
129                 sb.append(" Avg throughput: ").append(doubleFormat.format(throughput)).append(" statements/sec.");
130             }
131             sb.append('\n');
132
133         }
134         long totalTime = getTotalTime();
135         if (totalTime >= 0) {
136             sb.append("Total working time:");
137             appendTotalTimeDuration(totalTime, sb, doubleFormat);
138         }
139         return sb.toString();
140     }
141
142     /**
143      * A helper method to get element name from simplified location xpath.
144      *
145      * @param xpath xpath to get referenced element name.
146      * @return element name.
147      */

148     private static String JavaDoc getElementName(String JavaDoc xpath) {
149         int slash = xpath.lastIndexOf('/');
150         int br = xpath.lastIndexOf('[');
151         return xpath.substring(slash + 1, br);
152     }
153
154     private static StringBuilder JavaDoc appendPlural(final StringBuilder JavaDoc sb, final long num, final String JavaDoc singularNoun) {
155         sb.append(num).append(' ');
156         if (num > 1) { //plural form
157
if ("query".equals(singularNoun)) { //exceptions
158
sb.append("queries");
159             } else { //default rule appends S
160
sb.append(singularNoun).append('s');
161             }
162         } else {
163             sb.append(singularNoun); //singular form
164
}
165         return sb;
166     }
167
168     /**
169      * Appends total working time, i.e. d h m s ms
170      * The leading space is always present.
171      *
172      * @param timeMillis time interval in millis.
173      * @param sb output buffer.
174      * @param doubleFormat format seconds.
175      * @return the modified buffer.
176      */

177     static StringBuilder JavaDoc appendTotalTimeDuration(final long timeMillis, StringBuilder JavaDoc sb, Format JavaDoc doubleFormat) {
178         long time = timeMillis;
179         long days = time / DAY_MILLIS;
180         if (days > 0) {
181             time = time % DAY_MILLIS;
182             sb.append(' ');
183             appendPlural(sb, days, "day");
184         }
185         long hours = time / HOUR_MILLIS;
186         if (hours > 0) {
187             time = time % HOUR_MILLIS;
188             sb.append(' ');
189             appendPlural(sb, hours, "hour");
190         }
191         long minutes = time / MINUTE_MILLIS;
192         if (minutes > 0) {
193             time = time % MINUTE_MILLIS;
194             sb.append(' ');
195             appendPlural(sb, minutes, "minute");
196         }
197         double seconds = time / 1000d;
198         if (seconds > 0) {
199             sb.append(' ');
200             sb.append(doubleFormat.format(seconds)).append(" second");
201             if (seconds > 1) { //plural form
202
sb.append('s');
203             }
204         }
205         return sb;
206     }
207
208     /**
209      * Total ETL execution time or -1 if ETL hasn't completed.
210      *
211      * @return ETL execution time in milliseconds.
212      */

213     public long getTotalTime() {
214         return finished != null && started != null ? finished.getTime() - started.getTime() : -1;
215     }
216
217     /**
218      * Returns date/time when ETL was started.
219      *
220      * @return ETL start date/time.
221      */

222     public Date JavaDoc getStartDate() {
223         return started == null ? null : (Date JavaDoc) started.clone();
224     }
225
226     void setStarted(Date JavaDoc started) {
227         this.started = started;
228     }
229
230     /**
231      * Returns date/time when ETL was completed.
232      *
233      * @return ETL finish date/time.
234      */

235     public Date JavaDoc getFinishDate() {
236         return finished == null ? null : (Date JavaDoc) finished.clone();
237     }
238
239     void setFinished(Date JavaDoc finished) {
240         this.finished = finished;
241     }
242
243
244     public static class ElementInfo {
245         int okCount;
246         Connection connection;
247         long statementsOnStart;
248         long statements;
249         int failedCount;
250         long started;
251         long workingTime;
252         String JavaDoc id;
253
254         public int getSuccessfulExecutionCount() {
255             return okCount;
256         }
257
258         public int getFailedExecutionCount() {
259             return failedCount;
260         }
261
262         /**
263          * Returns total number of executed statements for this element.
264          * <p><b>Note:</b> execution in a loop affects total number,
265          * i.e. StatementsCount=loop_count*sql_statements_count
266          *
267          * @return number of executed statements.
268          */

269         public long getStatementsCount() {
270             return statements;
271         }
272
273         /**
274          * Returns the total number of nanoseconds spent while executing this element.
275          *
276          * @return total working time in nanoseconds.
277          */

278         public long getWorkingTime() {
279             return workingTime;
280         }
281
282         /**
283          * Returns throughput t=statements/workingTimeSeconds. The
284          * throughput has statement/second unit.
285          *
286          * @return statement/second thoughput or -1 if no statements info available or working time is zero.
287          */

288         public double getThroughput() {
289             return statements <= 0 || workingTime <= 0 ? -1 : 1000000000d * statements / workingTime;
290         }
291
292         public String JavaDoc getId() {
293             return id;
294         }
295     }
296 }
297
Popular Tags