private Stats getLastCallTimeCollection( String requestName, Map<String, Map<String, Number>> fallbackValues, long fallbackStartTime) throws IOException { File dataFile = new File(context.getResourceDataDirectory(), requestName); if (!dataFile.exists()) { return Stats.fromMap( fallbackValues, requestName, System.currentTimeMillis(), fallbackStartTime); } else { ObjectInputStream in = null; try { in = new ObjectInputStream(new FileInputStream(dataFile)); Stats stats = (Stats) in.readObject(); if (stats.serverStartTime == 0) { // we might get serverStartTime == 0 if the datafile comes from the old version of the // plugin // in that case just fallback to the old behavior that assumed no server restarts. // After that we save the new version of the stats with the start time remembered and we // will // switch to the new correct behavior from the next collection. stats.serverStartTime = fallbackStartTime; } return stats; } catch (IOException e) { throw new IOException( "Couldn't read the stored calltime data from file " + dataFile + ".", e); } catch (ClassNotFoundException e) { throw new IllegalStateException("Couldn't find plugin API classes. This is serious!", e); } finally { StreamUtil.safeClose(in); } } }
@Override public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception { // we'll handling the rest of the metrics using the super method, but we may leave out some of // the requests // if we handle them here. Right now, just use the obtained set. We only create a copy of the // (unmodifiable) set // of requests if necessary. Set<MeasurementScheduleRequest> metricsToPassDown = metrics; for (MeasurementScheduleRequest request : metrics) { if (request.getDataType() == DataType.CALLTIME) { ensureGlobalEJB3StatisticsEnabled(); // make a copy to pass down to super class if necessary if (metricsToPassDown == metrics) { metricsToPassDown = new HashSet<MeasurementScheduleRequest>(metrics); } metricsToPassDown.remove(request); // handle this ourselves // the name of the metric is actually the name of the stat collected for each method. we // then provide // the calltime data for each method. Result result = getASConnection().execute(new ReadAttribute(address, METHODS_ATTRIBUTE)); Object value = result.getResult(); if (value instanceof Map) { @SuppressWarnings("unchecked") Map<String, Map<String, Number>> allMethodStats = (Map<String, Map<String, Number>>) value; if (allMethodStats.isEmpty()) { continue; } // first we need to know since when the values were collected result = getASConnection() .execute(new ReadAttribute(RUNTIME_MBEAN_ADDRESS, START_TIME_ATTRIBUTE)); long serverStartTime = (Long) result.getResult(); // now process the calltime value String requestedMetric = request.getName().substring(CALLTIME_METRIC_NAME_PREFIX_LENGTH); Stats lastCollection = getLastCallTimeCollection(requestedMetric, allMethodStats, serverStartTime); Stats thisCollection = Stats.fromMap( allMethodStats, requestedMetric, System.currentTimeMillis(), serverStartTime); CallTimeData callTime = new CallTimeData(request); fillCallTimeData(callTime, thisCollection, lastCollection); saveCallTimeCollection(requestedMetric, thisCollection); report.addData(callTime); } else { OSGiVersion currentAsVersion = getASVersion(); if (currentAsVersion == null) { getLog() .warn( "Could not determine the AS version while reporting unexpected result of method" + " stats. Request: " + request); } else if (FIRST_VERSION_SUPPORTING_METHOD_STATS.compareTo(currentAsVersion) <= 0) { getLog() .error( "Unexpected type of results when querying method stats for measurement request " + request + ". Expected map but got " + (value == null ? "null" : value.getClass().getName())); } } } } super.getValues(report, metricsToPassDown); }