/** * Builds the 'time' portion of the row key * @param period The ProfilePeriod in which the ProfileMeasurement was taken. */ private static byte[] timeKey(ProfilePeriod period) { return timeKey(period.getPeriod()); }
/** * Calculates a salt value that is used as part of the row key. * * The salt is calculated as 'md5(period) % N' where N is a configurable value that ideally * is close to the number of nodes in the Hbase cluster. * * @param period The period in which a profile measurement is taken. */ public static byte[] getSalt(ProfilePeriod period, int saltDivisor) { return getSalt(period.getPeriod(), saltDivisor); }
/** * Build the row key. * @param profile The name of the profile. * @param entity The name of the entity. * @param period The period in which the measurement was taken. * @param groups The groups. * @return The HBase row key. */ public byte[] rowKey(String profile, String entity, ProfilePeriod period, List<Object> groups) { return rowKey(profile, entity, period.getPeriod(), groups); }
/** * Creates a message that will be emitted to Kafka. * * @param measurement The profile measurement used as a basis for the message. * @return A message that can be emitted to Kafka. */ private JSONObject createMessage(ProfileMeasurement measurement) { JSONObject message = new JSONObject(); message.put(PROFILE_FIELD, measurement.getDefinition().getProfile()); message.put(ENTITY_FIELD, measurement.getEntity()); message.put(PERIOD_ID_FIELD, measurement.getPeriod().getPeriod()); message.put(PERIOD_START_FIELD, measurement.getPeriod().getStartTimeMillis()); message.put(PERIOD_END_FIELD, measurement.getPeriod().getEndTimeMillis()); message.put(TIMESTAMP_FIELD, System.currentTimeMillis()); message.put(Constants.SENSOR_TYPE, sourceType); message.put(ALERT_FIELD, "true"); message.put(Constants.GUID, UUID.randomUUID().toString()); return message; }
/** * Renders a view of the profile measurement. * @param measurement The profile measurement to render. */ private Map<String, Object> render(ProfileMeasurement measurement) { Map<String, Object> view = new HashMap<>(); view.put(PROFILE_KEY, measurement.getProfileName()); view.put(ENTITY_KEY, measurement.getEntity()); view.put(PERIOD_KEY, measurement.getPeriod().getPeriod()); view.put(PERIOD_START_KEY, measurement.getPeriod().getStartTimeMillis()); view.put(PERIOD_END_KEY, measurement.getPeriod().getEndTimeMillis()); view.put(VALUE_KEY, measurement.getProfileValue()); view.put(GROUPS_KEY, measurement.getGroups()); return view; }
@Override public Object apply(List<Object> args, Context context) throws ParseException { // user must provide the stand-alone profiler StandAloneProfiler profiler = Util.getArg(0, StandAloneProfiler.class, args); if(profiler == null) { throw new IllegalArgumentException(format("expected the profiler returned by PROFILER_INIT, found null")); } // transform the profile measurements into maps to simplify manipulation in stellar List<Map<String, Object>> measurements = new ArrayList<>(); for(ProfileMeasurement m : profiler.flush()) { // create a map for the profile period Map<String, Object> period = new HashMap<>(); period.put("period", m.getPeriod().getPeriod()); period.put("start", m.getPeriod().getStartTimeMillis()); period.put("duration", m.getPeriod().getDurationMillis()); period.put("end", m.getPeriod().getEndTimeMillis()); // create a map for the measurement Map<String, Object> measurement = new HashMap<>(); measurement.put("profile", m.getProfileName()); measurement.put("entity", m.getEntity()); measurement.put("value", m.getProfileValue()); measurement.put("groups", m.getGroups()); measurement.put("period", period); measurements.add(measurement); } return measurements; } }
m.getProfileName(), m.getEntity(), m.getPeriod().getPeriod(), m.getProfileValue()); return new ProfileMeasurementAdapter(m);
@Override public String call(MessageRoute route) { ProfilePeriod period = ProfilePeriod.fromTimestamp(route.getTimestamp(), periodDuration, periodDurationUnits); return route.getProfileDefinition().getProfile() + "-" + route.getEntity() + "-" + period.getPeriod(); } }
entity, maxTimestamp, period.getPeriod(), period.getStartTimeMillis(), period.getEndTimeMillis(),
public ProfileMeasurementAdapter(ProfileMeasurement measurement) { this.profileName = measurement.getProfileName(); this.entity = measurement.getEntity(); this.periodId = measurement.getPeriod().getPeriod(); this.durationMillis = measurement.getPeriod().getDurationMillis(); this.profileValue = SerDeUtils.toBytes(measurement.getProfileValue()); }
/** * Handles the {@code ProfileMeasurement}s that are created when a profile is flushed. * * @param measurements The measurements to handle. */ private void emitMeasurements(List<ProfileMeasurement> measurements) { // flush each profile for(ProfileMeasurement measurement: measurements) { // allow each 'emitter' to emit the measurement for (ProfileMeasurementEmitter emitter : emitters) { emitter.emit(measurement, collector); LOG.debug("Measurement emitted; stream={}, profile={}, entity={}, value={}, start={}, end={}, duration={}, period={}", emitter.getStreamId(), measurement.getProfileName(), measurement.getEntity(), measurement.getProfileValue(), measurement.getPeriod().getStartTimeMillis(), measurement.getPeriod().getEndTimeMillis(), measurement.getPeriod().getDurationMillis(), measurement.getPeriod().getPeriod()); } } LOG.debug("Emitted {} measurement(s).", measurements.size()); }
@Override public void emit(ProfileMeasurement measurement, OutputCollector collector) { // measurements are always emitted to hbase collector.emit(getStreamId(), new Values(measurement)); LOG.debug("Emitted measurement; stream={}, profile={}, entity={}, period={}, start={}, end={}", getStreamId(), measurement.getProfileName(), measurement.getEntity(), measurement.getPeriod().getPeriod(), measurement.getPeriod().getStartTimeMillis(), measurement.getPeriod().getEndTimeMillis()); }
@Override public void emit(ProfileMeasurement measurement, OutputCollector collector) { // only need to emit, if there are triage values Map<String, Object> triageValues = measurement.getTriageValues(); if(MapUtils.isNotEmpty(triageValues)) { JSONObject message = createMessage(measurement); appendTriageValues(measurement, message); collector.emit(getStreamId(), new Values(message)); LOG.debug("Emitted measurement; stream={}, profile={}, entity={}, period={}, start={}, end={}", getStreamId(), measurement.getProfileName(), measurement.getEntity(), measurement.getPeriod().getPeriod(), measurement.getPeriod().getStartTimeMillis(), measurement.getPeriod().getEndTimeMillis()); } else { LOG.debug("No triage values, nothing to emit; stream={}, profile={}, entity={}, period={}, start={}, end={}", getStreamId(), measurement.getProfileName(), measurement.getEntity(), measurement.getPeriod().getPeriod(), measurement.getPeriod().getStartTimeMillis(), measurement.getPeriod().getEndTimeMillis()); } }