/** * Returns the sketch metadata as a {@link Meta} object. * * @param metaKey The key to add the metadata as. * @param conceptKeys If provided, these {@link Concept} names will be added to the metadata. * @return The metadata object or an empty one if no metadata was collected. */ public Meta getMetadata(String metaKey, Map<String, String> conceptKeys) { if (metaKey == null) { return new Meta(); } return new Meta().add(metaKey, addMetadata(conceptKeys)); }
/** * Tags additional metadata. Merges any new metadata with existing metadata, if present. * * @param meta Any Meta to add to the Clip. The objects in the Meta must be * serializable to JSON with {@link com.google.gson.Gson}. * @return This Clip for chaining */ public Clip add(Meta meta) { if (meta != null) { this.meta.merge(meta); } return this; }
private Meta getResultMetadata() { String metaKey = getMetaKey(); if (metaKey == null) { return null; } Map<String, Object> meta = new HashMap<>(); addIfNonNull(meta, metaKeys, Concept.QUERY_ID, runningQuery::getId); addIfNonNull(meta, metaKeys, Concept.QUERY_BODY, runningQuery::toString); addIfNonNull(meta, metaKeys, Concept.QUERY_RECEIVE_TIME, runningQuery::getStartTime); return new Meta().add(metaKey, meta); }
private Meta getErrorMeta(Exception e) { return Meta.of(BulletError.makeError(e.getMessage(), TRY_AGAIN_LATER)); }
/** * Return any {@link Meta} for this windowing scheme and the {@link Strategy}. * * @return A non-null Meta object. */ @Override public Meta getMetadata() { Meta meta = new Meta(); if (shouldMeta) { String key = getMetaKey(); if (key != null) { meta.add(key, getMetadata(metadataKeys)); } meta.merge(aggregation.getMetadata()); } return meta; }
@Override protected Map<String, Object> getMetadata(Map<String, String> metadataKeys) { Map<String, Object> meta = new HashMap<>(); addIfNonNull(meta, metadataKeys, Meta.Concept.WINDOW_NAME, this::name); addIfNonNull(meta, metadataKeys, Meta.Concept.WINDOW_NUMBER, this::count); addIfNonNull(meta, metadataKeys, Meta.Concept.WINDOW_EMIT_TIME, System::currentTimeMillis); return meta; }
/** * Get the {@link Meta} so far. By default, returns an empty one. * * @return The resulting metadata of the data aggregated so far. */ @Override default Meta getMetadata() { return new Meta(); } }
private void addFinishTime(Meta meta) { Map<String, Object> queryMeta = (Map<String, Object>) meta.asMap().get(getMetaKey()); if (queryMeta != null) { addIfNonNull(queryMeta, metaKeys, Concept.QUERY_FINISH_TIME, System::currentTimeMillis); } }
/** * Merge another Meta into this Meta. * * @param meta A Meta to merge. * @return This Object after the merge. */ public Meta merge(Meta meta) { if (meta != null) { this.meta.putAll(meta.asMap()); } return this; }
/** * Write this error as a JSON Bullet error response in the {@link Meta} of a {@link Clip}. * * @return A String JSON version of this error. */ public String asJSONClip() { return Clip.of(Meta.of(this)).asJSON(); } }
/** * Adds the common metadata for this Sketch to {@link Map}. * * @param conceptKeys The {@link Map} of {@link Concept} names to their keys. * @return The created {@link Map} of sketch metadata. */ protected Map<String, Object> addMetadata(Map<String, String> conceptKeys) { Map<String, Object> metadata = new HashMap<>(); addIfNonNull(metadata, conceptKeys, Concept.SKETCH_FAMILY, this::getFamily); addIfNonNull(metadata, conceptKeys, Concept.SKETCH_SIZE, this::getSize); addIfNonNull(metadata, conceptKeys, Concept.SKETCH_ESTIMATED_RESULT, this::isEstimationMode); return metadata; }
@Override public String asJSON() { Map<String, Object> wrapper = new HashMap<>(); wrapper.put(META_KEY, meta.asMap()); wrapper.put(RECORDS_KEY, records.stream().map(Clip::asMap).collect(Collectors.toList())); return JSONFormatter.asJSON(wrapper); }
/** * Write this error as a JSON Bullet error response in the {@link Meta} of a {@link Clip}. * * @return A String JSON version of this error. */ public String asJSONClip() { return Clip.of(Meta.of(this)).asJSON(); } }
@Test public void testQueryIdentifierMetadata() { config = configWithRawMaxAndEmptyMeta(); enableMetadataInConfig(config, Concept.QUERY_METADATA.getName(), "meta"); enableMetadataInConfig(config, Concept.QUERY_ID.getName(), "id"); setup(new JoinBolt(config)); Tuple query = TupleUtils.makeIDTuple(TupleClassifier.Type.QUERY_TUPLE, "42", "{}", EMPTY); bolt.execute(query); List<BulletRecord> sent = sendRawRecordTuplesTo(bolt, "42"); Meta meta = new Meta(); meta.add("meta", singletonMap("id", "42")); Tuple expected = TupleUtils.makeTuple(TupleClassifier.Type.RESULT_TUPLE, "42", Clip.of(sent).add(meta).asJSON(), COMPLETED); Assert.assertTrue(wasResultEmittedTo(TopologyConstants.RESULT_STREAM, expected)); Tuple metadata = TupleUtils.makeTuple(TupleClassifier.Type.FEEDBACK_TUPLE, "42", new Metadata(Metadata.Signal.COMPLETE, null)); Assert.assertTrue(wasMetadataEmittedTo(TopologyConstants.FEEDBACK_STREAM, metadata)); Assert.assertEquals(collector.getAllEmittedTo(TopologyConstants.RESULT_STREAM).count(), 1); Assert.assertEquals(collector.getAllEmittedTo(TopologyConstants.FEEDBACK_STREAM).count(), 1); }
/** * Returns the {@link Meta} of the result so far. See {@link #getResult()} for the full result with the data. * * @return The metadata part of the result. */ @Override public Meta getMetadata() { Meta meta; try { meta = window.getMetadata(); meta.merge(getResultMetadata()); } catch (RuntimeException e) { log.error("Unable to get metadata for query {}", this); meta = getErrorMeta(e); } return meta; }
@Override protected Map<String, Object> addMetadata(Map<String, String> conceptKeys) { Map<String, Object> metadata = super.addMetadata(conceptKeys); addIfNonNull(metadata, conceptKeys, Concept.SKETCH_ITEMS_SEEN, this::getStreamLength); addIfNonNull(metadata, conceptKeys, Concept.SKETCH_ACTIVE_ITEMS, this::getItemsStored); addIfNonNull(metadata, conceptKeys, Concept.SKETCH_MAXIMUM_COUNT_ERROR, this::getMaximumError); return metadata; }
private void emitErrorsAsResult(String id, Metadata metadata, List<BulletError> errors) { updateCount(improperQueriesCount, 1L); emitResult(id, withSignal(metadata, Metadata.Signal.FAIL), Clip.of(Meta.of(errors))); }
@Test public void testUnknownConceptMetadata() { config = configWithRawMaxAndEmptyMeta(); enableMetadataInConfig(config, Concept.QUERY_METADATA.getName(), "meta"); enableMetadataInConfig(config, Concept.QUERY_ID.getName(), "id"); enableMetadataInConfig(config, "foo", "bar"); setup(new JoinBolt(config)); Tuple query = TupleUtils.makeIDTuple(TupleClassifier.Type.QUERY_TUPLE, "42", "{}", EMPTY); bolt.execute(query); List<BulletRecord> sent = sendRawRecordTuplesTo(bolt, "42"); Meta meta = new Meta(); meta.add("meta", singletonMap("id", "42")); Tuple expected = TupleUtils.makeTuple(TupleClassifier.Type.RESULT_TUPLE, "42", Clip.of(sent).add(meta).asJSON(), COMPLETED); Assert.assertTrue(wasResultEmittedTo(TopologyConstants.RESULT_STREAM, expected)); Tuple metadata = TupleUtils.makeTuple(TupleClassifier.Type.FEEDBACK_TUPLE, "42", new Metadata(Metadata.Signal.COMPLETE, null)); Assert.assertTrue(wasMetadataEmittedTo(TopologyConstants.FEEDBACK_STREAM, metadata)); Assert.assertEquals(collector.getAllEmittedTo(TopologyConstants.RESULT_STREAM).count(), 1); Assert.assertEquals(collector.getAllEmittedTo(TopologyConstants.FEEDBACK_STREAM).count(), 1); }