Skip to content

Commit

Permalink
TSDB: Add dimensions and timestamp to parse errors (#84962)
Browse files Browse the repository at this point in the history
This adds a list of dimensions and `@timestamp` to the parse errors we
make in tsdb if the `_tsid` or `@timestamp` are built.
  • Loading branch information
nik9000 authored Mar 17, 2022
1 parent e6dfc83 commit 22824e4
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public final void seqID(SeqNoFieldMapper.SequenceIDFields seqID) {
*/
public final String documentDescription() {
IdFieldMapper idMapper = (IdFieldMapper) getMetadataMapper(IdFieldMapper.NAME);
return idMapper.documentDescription(sourceToParse);
return idMapper.documentDescription(this);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ protected final String contentType() {
* Description on the document being parsed used in error messages. Not
* called unless there is an error.
*/
public abstract String documentDescription(SourceToParse source);
public abstract String documentDescription(DocumentParserContext context);

/**
* Create a {@link Field} to store the provided {@code _id} that "stores"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ public void preParse(DocumentParserContext context) {
}

@Override
public String documentDescription(SourceToParse source) {
return "document with id '" + source.id() + "'";
public String documentDescription(DocumentParserContext context) {
return "document with id '" + context.sourceToParse().id() + "'";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
*/
public class TsidExtractingIdFieldMapper extends IdFieldMapper {
private static final FieldType FIELD_TYPE = new FieldType();
/**
* Maximum length of the {@code _tsid} in the {@link #documentDescription}.
*/
static final int DESCRIPTION_TSID_LIMIT = 1000;

static {
FIELD_TYPE.setTokenized(false);
FIELD_TYPE.setIndexOptions(IndexOptions.DOCS);
Expand Down Expand Up @@ -156,13 +161,28 @@ public void createField(DocumentParserContext context, BytesRef tsid) {
}

@Override
public String documentDescription(SourceToParse source) {
public String documentDescription(DocumentParserContext context) {
/*
* We don't yet have an _id because it'd be generated by the document
* parsing process. And the _id isn't all that useful anyway - what
* folks really want to to see is the dimensions and timestamp. And
* those too aren't available until after we've parsed the document.
* parsing process. But we *might* have something more useful - the
* time series dimensions and the timestamp! If we have those, then
* include them in the description. If not, all we know is
* "a time series document".
*/
return "a time series document";
StringBuilder description = new StringBuilder("a time series document");
IndexableField tsidField = context.doc().getField(TimeSeriesIdFieldMapper.NAME);
if (tsidField != null) {
String tsid = TimeSeriesIdFieldMapper.decodeTsid(tsidField.binaryValue()).toString();
if (tsid.length() > DESCRIPTION_TSID_LIMIT) {
tsid = tsid.substring(0, DESCRIPTION_TSID_LIMIT) + "...}";
}
description.append(" with dimensions ").append(tsid);
}
IndexableField timestampField = context.doc().getField(DataStreamTimestampFieldMapper.DEFAULT_PATH);
if (timestampField != null) {
String timestamp = DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.formatMillis(timestampField.numericValue().longValue());
description.append(" at [").append(timestamp).append(']');
}
return description.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2049,7 +2049,23 @@ public void testDocumentDescriptionInTsdb() throws IOException {
MapperException.class,
() -> mapper.parse(source(null, b -> b.field("foo", true), null))
);
assertThat(exception.getMessage(), containsString("failed to parse field [foo] of type [long] in a time series document"));
assertThat(
exception.getMessage(),
equalTo("failed to parse field [foo] of type [long] in a time series document. Preview of field's value: 'true'")
);
}
{
MapperException exception = expectThrows(
MapperException.class,
() -> mapper.parse(source(null, b -> b.field("@timestamp", "2021-04-28T00:01:00Z").field("foo", true), null))
);
assertThat(
exception.getMessage(),
equalTo(
"failed to parse field [foo] of type [long] in a time series document at "
+ "[2021-04-28T00:01:00.000Z]. Preview of field's value: 'true'"
)
);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.IndexSearcher;
import org.elasticsearch.Version;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.query.SearchExecutionContext;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.search.lookup.SearchLookup;
Expand Down Expand Up @@ -89,7 +91,15 @@ public void testFetchIdFieldValue() throws IOException {
public void testDescription() throws IOException {
String id = randomAlphaOfLength(4);
assertThat(
ProvidedIdFieldMapper.NO_FIELD_DATA.documentDescription(source(id, b -> {}, randomAlphaOfLength(2))),
ProvidedIdFieldMapper.NO_FIELD_DATA.documentDescription(
new TestDocumentParserContext(
MappingLookup.EMPTY,
MapperTestCase.createIndexSettings(Version.CURRENT, Settings.EMPTY),
null,
null,
source(id, b -> {}, randomAlphaOfLength(2))
)
),
equalTo("document with id '" + id + "'")
);
}
Expand Down
Loading

0 comments on commit 22824e4

Please sign in to comment.