1 | package de.uka.ipd.sdq.reliability.core; |
2 | |
3 | import java.util.HashMap; |
4 | import java.util.HashSet; |
5 | import java.util.Iterator; |
6 | import java.util.List; |
7 | import java.util.Map; |
8 | import java.util.TreeSet; |
9 | |
10 | import org.apache.log4j.Logger; |
11 | |
12 | /** |
13 | * Singleton class that is used for counting simulated failures and printing |
14 | * statistics. |
15 | */ |
16 | public class FailureStatistics { |
17 | |
18 | /** |
19 | * Singleton instance. |
20 | */ |
21 | private static FailureStatistics instance = new FailureStatistics(); |
22 | |
23 | /** |
24 | * Retrieves the singleton instance. |
25 | * |
26 | * @return the singleton instance |
27 | */ |
28 | public static synchronized FailureStatistics getInstance() { |
29 | return instance; |
30 | } |
31 | |
32 | /** |
33 | * Maps numeric IDs to failure type names. |
34 | */ |
35 | private Map<Integer, String> executionResultTypes; |
36 | |
37 | /** |
38 | * Stores the session ids of all failed usage scenario runs. |
39 | * |
40 | * This is required because with forked behaviours, multiple failures can |
41 | * occur in one usage scenario run. If so, the counter for failed runs must |
42 | * not be incremented for the second or any further failure within the same |
43 | * run. |
44 | */ |
45 | private HashSet<Long> failedRuns; |
46 | |
47 | /** |
48 | * Counts all handled failure occurrences since last reset. |
49 | */ |
50 | private long handledFailureCount; |
51 | |
52 | /** |
53 | * Counters for all handled failure occurrences since last reset. |
54 | */ |
55 | private Map<MarkovFailureType, Integer> handledFailureCounters; |
56 | |
57 | /** |
58 | * Counts usage scenario runs since last reset. |
59 | */ |
60 | private long runCount; |
61 | |
62 | /** |
63 | * Maps failure types to numeric IDs. |
64 | */ |
65 | private Map<MarkovFailureType, Integer> simFailureTypes; |
66 | |
67 | /** |
68 | * Counts all failure occurrences (handled and unhandled) since last reset. |
69 | */ |
70 | private long totalFailureCount; |
71 | |
72 | /** |
73 | * Counters for all failure occurrences since last reset. |
74 | */ |
75 | private Map<MarkovFailureType, Integer> totalFailureCounters; |
76 | |
77 | /** |
78 | * Counts all unhandled failure occurrences since last reset. |
79 | */ |
80 | private long unhandledFailureCount; |
81 | |
82 | /** |
83 | * Counters for all unhandled failure occurrences since last reset. |
84 | */ |
85 | private Map<MarkovFailureType, Integer> unhandledFailureCounters; |
86 | |
87 | /** |
88 | * The constructor. |
89 | */ |
90 | private FailureStatistics() { |
91 | reset(); |
92 | } |
93 | |
94 | /** |
95 | * Retrieves the id of a given execution result. |
96 | * |
97 | * Used for logging sensor data. |
98 | * |
99 | * @param failureType |
100 | * the failure type that occurred as an execution result |
101 | * @return the numerical id of the execution result |
102 | */ |
103 | public int getExecutionResultId(MarkovFailureType failureType) { |
104 | if (failureType == null) { |
105 | return 0; |
106 | } |
107 | return simFailureTypes.get(failureType); |
108 | } |
109 | |
110 | /** |
111 | * Retrieves a complete mapping from numeric IDs to failure type names. |
112 | * |
113 | * Used for building up execution result sensors. |
114 | * |
115 | * @return a mapping from numeric IDs to failure type names |
116 | */ |
117 | public Map<Integer, String> getExecutionResultTypes() { |
118 | return executionResultTypes; |
119 | } |
120 | |
121 | /** |
122 | * Retrieves the system-external hardware-induced failure type with the |
123 | * given ids. |
124 | * |
125 | * @param resourceTypeId |
126 | * the resource type id |
127 | * @param systemRequiredRoleId |
128 | * the id of the corresponding system-external role |
129 | * @param signatureId |
130 | * the id of the corresponding system-external signature |
131 | * @return the corresponding failure type |
132 | */ |
133 | public MarkovFailureType getExternalHardwareFailureType( |
134 | final String resourceTypeId, final String systemRequiredRoleId, |
135 | final String signatureId) { |
136 | MarkovHardwareInducedFailureType comparator = MarkovHardwareInducedFailureType |
137 | .createExternalFailureType( |
138 | MarkovEvaluationType.POINTSOFFAILURE, resourceTypeId, |
139 | signatureId, systemRequiredRoleId); |
140 | return getFailureType(comparator); |
141 | } |
142 | |
143 | /** |
144 | * Retrieves the system-external network-induced failure type with the given |
145 | * ids. |
146 | * |
147 | * @param commLinkResourceTypeId |
148 | * the communication link resource type id |
149 | * @param systemRequiredRoleId |
150 | * the id of the corresponding system-external role |
151 | * @param signatureId |
152 | * the id of the corresponding system-external signature |
153 | * @return the corresponding failure type |
154 | */ |
155 | public MarkovFailureType getExternalNetworkFailureType( |
156 | final String commLinkResourceTypeId, |
157 | final String systemRequiredRoleId, final String signatureId) { |
158 | MarkovNetworkInducedFailureType comparator = MarkovNetworkInducedFailureType |
159 | .createExternalFailureType( |
160 | MarkovEvaluationType.POINTSOFFAILURE, |
161 | commLinkResourceTypeId, signatureId, |
162 | systemRequiredRoleId); |
163 | return getFailureType(comparator); |
164 | } |
165 | |
166 | /** |
167 | * Retrieves the system-external software-induced failure type with the |
168 | * given id. |
169 | * |
170 | * @param softwareFailureId |
171 | * the software-induced failure type id |
172 | * @param systemRequiredRoleId |
173 | * the id of the corresponding system-external role |
174 | * @param signatureId |
175 | * the id of the corresponding system-external signature |
176 | * @return the corresponding failure type |
177 | */ |
178 | public MarkovFailureType getExternalSoftwareFailureType( |
179 | final String softwareFailureId, final String systemRequiredRoleId, |
180 | final String signatureId) { |
181 | MarkovSoftwareInducedFailureType comparator = MarkovSoftwareInducedFailureType |
182 | .createExternalFailureType( |
183 | MarkovEvaluationType.POINTSOFFAILURE, |
184 | softwareFailureId, signatureId, systemRequiredRoleId); |
185 | return getFailureType(comparator); |
186 | } |
187 | |
188 | /** |
189 | * Retrieves the failure type with the given id. |
190 | * |
191 | * @param failureTypeId |
192 | * the failure type id |
193 | * @return the failure type |
194 | */ |
195 | public MarkovFailureType getFailureType(String failureTypeId) { |
196 | Iterator<MarkovFailureType> iterator = simFailureTypes.keySet() |
197 | .iterator(); |
198 | while (iterator.hasNext()) { |
199 | MarkovFailureType failureType = iterator.next(); |
200 | if (failureType.getId().equals(failureTypeId)) { |
201 | return failureType; |
202 | } |
203 | } |
204 | return null; |
205 | } |
206 | |
207 | /** |
208 | * Retrieves the numerical index that corresponds to a given failure type |
209 | * |
210 | * @param failureType |
211 | * the failure type |
212 | * @return the corresponding index |
213 | */ |
214 | public int getFailureTypeIndex(final MarkovFailureType failureType) { |
215 | return simFailureTypes.get(failureType); |
216 | } |
217 | |
218 | /** |
219 | * Retrieves the total number of handled failure occurrences. |
220 | * |
221 | * @return The number of handled failure occurrences |
222 | */ |
223 | public long getHandledFailureCount() { |
224 | return handledFailureCount; |
225 | } |
226 | |
227 | /** |
228 | * Retrieves the counters for all handled failure occurrences. |
229 | * |
230 | * @return the counters |
231 | */ |
232 | public Map<MarkovFailureType, Integer> getHandledFailureCounters() { |
233 | return handledFailureCounters; |
234 | } |
235 | |
236 | /** |
237 | * Retrieves the system-internal hardware-induced failure type with the |
238 | * given ids. |
239 | * |
240 | * @param resourceContainerId |
241 | * the resource container id |
242 | * @param resourceTypeId |
243 | * the resource type id |
244 | * @return the corresponding failure type |
245 | */ |
246 | public MarkovFailureType getInternalHardwareFailureType( |
247 | final String resourceContainerId, final String resourceTypeId) { |
248 | MarkovHardwareInducedFailureType comparator = MarkovHardwareInducedFailureType |
249 | .createInternalFailureType( |
250 | MarkovEvaluationType.POINTSOFFAILURE, |
251 | resourceContainerId, resourceTypeId); |
252 | return getFailureType(comparator); |
253 | } |
254 | |
255 | /** |
256 | * Retrieves the system-internal network-induced failure type with the given |
257 | * ids. |
258 | * |
259 | * @param linkingResourceId |
260 | * the linking resource id |
261 | * @param commLinkResourceTypeId |
262 | * the communication link resource type id |
263 | * @return the corresponding failure type |
264 | */ |
265 | public MarkovFailureType getInternalNetworkFailureType( |
266 | final String linkingResourceId, final String commLinkResourceTypeId) { |
267 | MarkovNetworkInducedFailureType comparator = MarkovNetworkInducedFailureType |
268 | .createInternalFailureType( |
269 | MarkovEvaluationType.POINTSOFFAILURE, |
270 | linkingResourceId, commLinkResourceTypeId); |
271 | return getFailureType(comparator); |
272 | } |
273 | |
274 | /** |
275 | * Retrieves the system-internal software-induced failure type with the |
276 | * given id. |
277 | * |
278 | * @param softwareFailureId |
279 | * the software-induced failure type id |
280 | * @param internalActionId |
281 | * the surrounding internal action id |
282 | * @return the corresponding failure type |
283 | */ |
284 | public MarkovFailureType getInternalSoftwareFailureType( |
285 | final String softwareFailureId, final String internalActionId) { |
286 | MarkovSoftwareInducedFailureType comparator = MarkovSoftwareInducedFailureType |
287 | .createInternalFailureType( |
288 | MarkovEvaluationType.POINTSOFFAILURE, |
289 | softwareFailureId, internalActionId); |
290 | return getFailureType(comparator); |
291 | |
292 | } |
293 | |
294 | /** |
295 | * Retrieves the system-internal passive resource timeout failure type with |
296 | * the given ids. |
297 | * |
298 | * @param assemblyContextId |
299 | * the id of the surrounding assembly context |
300 | * @param passiveResourceId |
301 | * the passive resource id |
302 | * @return the corresponding failure type |
303 | */ |
304 | public MarkovFailureType getResourceTimeoutFailureType( |
305 | final String assemblyContextId, final String passiveResourceId) { |
306 | MarkovResourceTimeoutFailureType comparator = MarkovResourceTimeoutFailureType |
307 | .createResourceTimeoutFailureType( |
308 | MarkovEvaluationType.POINTSOFFAILURE, |
309 | assemblyContextId, passiveResourceId); |
310 | return getFailureType(comparator); |
311 | } |
312 | |
313 | /** |
314 | * Retrieves the current usage scenario run count. |
315 | * |
316 | * @return the usage scenario run count |
317 | */ |
318 | public long getRunCount() { |
319 | return runCount; |
320 | } |
321 | |
322 | /** |
323 | * Retrieves the total number of failure occurrences (handled and |
324 | * unhandled). |
325 | * |
326 | * @return the number of all failure occurrences |
327 | */ |
328 | public long getTotalFailureCount() { |
329 | return totalFailureCount; |
330 | } |
331 | |
332 | /** |
333 | * Retrieves the counters for all failure occurrences (handled and |
334 | * unhandled). |
335 | * |
336 | * @return the counters |
337 | */ |
338 | public Map<MarkovFailureType, Integer> getTotalFailureCounters() { |
339 | return totalFailureCounters; |
340 | } |
341 | |
342 | /** |
343 | * Retrieves the total number of unhandled failure occurrences. |
344 | * |
345 | * @return the number of unhandled failure occurrences |
346 | */ |
347 | public long getUnhandledFailureCount() { |
348 | return unhandledFailureCount; |
349 | } |
350 | |
351 | /** |
352 | * Retrieves the counters for all unhandled failure occurrences. |
353 | * |
354 | * @return the counters |
355 | */ |
356 | public Map<MarkovFailureType, Integer> getUnhandledFailureCounters() { |
357 | return unhandledFailureCounters; |
358 | } |
359 | |
360 | /** |
361 | * Increases the counter for handled failures for the defined type. |
362 | * |
363 | * @param MarkovFailureType |
364 | * the failure type |
365 | */ |
366 | public synchronized void increaseHandledFailureCounter( |
367 | final MarkovFailureType failureType) { |
368 | Integer count = handledFailureCounters.get(failureType); |
369 | if (count == null) { |
370 | count = 0; |
371 | } |
372 | handledFailureCounters.put(failureType, ++count); |
373 | ++handledFailureCount; |
374 | } |
375 | |
376 | /** |
377 | * Increases total scenario run counter by one. |
378 | */ |
379 | public synchronized void increaseRunCount() { |
380 | ++runCount; |
381 | } |
382 | |
383 | /** |
384 | * Increases the total failure counter for the defined type. |
385 | * |
386 | * @param failureType |
387 | * the failure type |
388 | */ |
389 | public synchronized void increaseTotalFailureCounter( |
390 | final MarkovFailureType failureType) { |
391 | Integer count = totalFailureCounters.get(failureType); |
392 | if (count == null) { |
393 | count = 0; |
394 | } |
395 | totalFailureCounters.put(failureType, ++count); |
396 | ++totalFailureCount; |
397 | } |
398 | |
399 | /** |
400 | * Inceases the unhandled failure counter for the defined type. |
401 | * |
402 | * An unhandled failure means also a failed run. Thus, the list of failed |
403 | * runs is also updated with the given session id. |
404 | * |
405 | * @param failureType |
406 | * the failure type |
407 | * @param sessionId |
408 | * the session id of the current run |
409 | */ |
410 | public synchronized void increaseUnhandledFailureCounter( |
411 | final MarkovFailureType failureType, final Long sessionId) { |
412 | Integer count = unhandledFailureCounters.get(failureType); |
413 | if (count == null) { |
414 | count = 0; |
415 | } |
416 | unhandledFailureCounters.put(failureType, ++count); |
417 | ++unhandledFailureCount; |
418 | if (!failedRuns.contains(sessionId)) { |
419 | failedRuns.add(sessionId); |
420 | } |
421 | } |
422 | |
423 | /** |
424 | * Prints failure and handling statistics to a logger. |
425 | * |
426 | * @param logger |
427 | * The logger to write the statistics to |
428 | */ |
429 | public void printFailureStatistics(final Logger logger) { |
430 | logger.warn("---- System Failure Statistics: START ----"); |
431 | logger.warn("- Total usage scenario runs: " + runCount); |
432 | logger.warn("- Total failed usage scenario runs: " + failedRuns.size()); |
433 | logger.warn("- Total probability of success: " |
434 | + (1 - failedRuns.size() / ((double) runCount))); |
435 | for (String failureString : getFailureStringsSorted()) { |
436 | logger.warn(failureString); |
437 | } |
438 | printHandledFailuresStatistics(logger); |
439 | logger.warn("---- System Failure Statistics: END -----"); |
440 | } |
441 | |
442 | /** |
443 | * Prints every one out of 1000 run counts to a logger. |
444 | * |
445 | * @param logger |
446 | * The logger to write the statistics to |
447 | */ |
448 | public synchronized void printRunCount(final Logger logger) { |
449 | if ((runCount % 50000) == 0) { |
450 | // logger.warn("Current usage scenario runs: " + runCount); |
451 | printFailureStatistics(logger); |
452 | } else if ((runCount % 10000) == 0) { |
453 | logger.warn("Current usage scenario runs: " + runCount); |
454 | } |
455 | } |
456 | |
457 | /** |
458 | * Resets all counters. |
459 | */ |
460 | public void reset() { |
461 | unhandledFailureCounters = new HashMap<MarkovFailureType, Integer>(); |
462 | totalFailureCounters = new HashMap<MarkovFailureType, Integer>(); |
463 | handledFailureCounters = new HashMap<MarkovFailureType, Integer>(); |
464 | failedRuns = new HashSet<Long>(); |
465 | |
466 | unhandledFailureCount = 0; |
467 | handledFailureCount = 0; |
468 | totalFailureCount = 0; |
469 | |
470 | runCount = 0; |
471 | } |
472 | |
473 | /** |
474 | * Sets the failure types that may occur during the simulation. |
475 | * |
476 | * @param failureTypes |
477 | * the list of failure types |
478 | */ |
479 | public void setFailureTypes(final List<MarkovFailureType> failureTypes) { |
480 | |
481 | // Build failure type mapping: |
482 | simFailureTypes = new HashMap<MarkovFailureType, Integer>(); |
483 | for (int index = 0; index < failureTypes.size(); index++) { |
484 | if (!simFailureTypes.containsKey(failureTypes.get(index))) { |
485 | // Reserve index = 0 for the success case: |
486 | simFailureTypes.put(failureTypes.get(index), index + 1); |
487 | } |
488 | } |
489 | |
490 | // Build result type mapping: |
491 | executionResultTypes = new HashMap<Integer, String>(); |
492 | executionResultTypes.put(0, "Success"); |
493 | for (MarkovFailureType failureType : simFailureTypes.keySet()) { |
494 | executionResultTypes.put(simFailureTypes.get(failureType), |
495 | failureType.getName()); |
496 | } |
497 | } |
498 | |
499 | /** |
500 | * Retrieves the sorted list of recorded failure occurrences. |
501 | * |
502 | * @return the failure occurrences list |
503 | */ |
504 | private TreeSet<String> getFailureStringsSorted() { |
505 | TreeSet<String> result = new TreeSet<String>(); |
506 | for (MarkovFailureType failureType : unhandledFailureCounters.keySet()) { |
507 | double count = unhandledFailureCounters.get(failureType); |
508 | result.add("- " + failureType.getName() + ": " + (int) count + " (" |
509 | + count / runCount + ")"); |
510 | } |
511 | return result; |
512 | } |
513 | |
514 | /** |
515 | * Retrieves the failure type that equals to the given comparator. |
516 | * |
517 | * @param comparator |
518 | * the comparator failure type |
519 | * @return the corresponding failure type |
520 | */ |
521 | private MarkovFailureType getFailureType(final MarkovFailureType comparator) { |
522 | Iterator<MarkovFailureType> iterator = simFailureTypes.keySet() |
523 | .iterator(); |
524 | while (iterator.hasNext()) { |
525 | MarkovFailureType failureType = iterator.next(); |
526 | if (failureType.equals(comparator)) { |
527 | return failureType; |
528 | } |
529 | } |
530 | return null; |
531 | } |
532 | |
533 | /** |
534 | * Prints handling statistics to a logger. |
535 | * |
536 | * @param logger |
537 | * The logger to write the statistics to |
538 | */ |
539 | private void printHandledFailuresStatistics(final Logger logger) { |
540 | boolean headerPrinted = false; |
541 | for (MarkovFailureType failureType : handledFailureCounters.keySet()) { |
542 | int handledCount = handledFailureCounters.get(failureType); |
543 | Integer totalFailureCount = totalFailureCounters.get(failureType); |
544 | if (totalFailureCount == null) { |
545 | totalFailureCount = 0; |
546 | } |
547 | if (!headerPrinted) { |
548 | logger.warn("---- Handled Failures:"); |
549 | headerPrinted = true; |
550 | } |
551 | logger.warn("- " + failureType.getName() + ": Handled " |
552 | + handledCount + " out of " + totalFailureCount + " (" |
553 | + ((double) handledCount) / (totalFailureCount) + ")"); |
554 | } |
555 | } |
556 | } |