Fix doc-level monitor failure on source indices with custom analysis or malformed mappings - #2223
Conversation
PR Reviewer Guide 🔍(Review updated until commit 99dd424)Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Latest suggestions up to 99dd424 Explore these optional code suggestions:
Previous suggestionsSuggestions up to commit 0e80b45
Suggestions up to commit 5a796b4
Suggestions up to commit 8ff6a8e
Suggestions up to commit b282a54
Suggestions up to commit 7cab7b2
|
e3fc792 to
7cab7b2
Compare
|
Persistent review updated to latest commit 7cab7b2 |
7cab7b2 to
b282a54
Compare
|
Persistent review updated to latest commit b282a54 |
|
Persistent review updated to latest commit 8ff6a8e |
…or malformed mappings When a doc-level monitor is created against a source index whose field mappings contain attributes that are incompatible with the query index, the PutMappingRequest submitted by DocLevelMonitorQueries fails with either an IllegalArgumentException or a MapperParsingException. Two distinct failure categories exist: Category 1 — analysis resource references: Fields may carry attributes such as `analyzer`, `normalizer`, `search_analyzer`, `search_quote_analyzer`, or `similarity` that reference custom analysis objects defined in the source index's `settings.analysis.*` block. The doc-level query index is created from a fixed settings resource with no custom analysis block, so OpenSearch rejects any PutMappingRequest that includes these attributes with: "analyzer [x] has not been configured in mappings". Category 2 — `properties` on a scalar field type: Dynamic mapping collisions can produce cluster-state entries where a scalar field (e.g. `text`) carries a `properties` sub-block — valid only on `object`/`nested` mappers. OpenSearch accepts this at ingestion time but rejects it via the explicit PUT mapping API with MapperParsingException[unknown parameter [properties] on mapper of type [text]]. Fix: add `sanitizeFieldMappingAttributes()` to the companion object of DocLevelMonitorQueries and call it on `newProps` inside leafNodeProcessor immediately after the `toMutableMap()` copy. The function: - strips all five analysis-reference attributes (Category 1) - strips `properties` from any field whose type is explicitly set to something other than `object` or `nested` (Category 2) - recurses into multi-fields (`fields` sub-map) No index close/open cycle is required; the change is confined to the in-memory PutMappingRequest payload. The query index stores percolator query documents for doc-level matching only, so dropping these attributes is safe and lossless for its purpose. Relates: opensearch-project#961 Signed-off-by: thecodingshrimp <leonard.stutzer@sap.com>
Covers both failure categories fixed in the previous commit: - Category 1: analysis resource attributes (analyzer, normalizer, similarity, search_analyzer, search_quote_analyzer) are stripped from text/keyword fields and from multi-fields recursively - Category 2: properties block is stripped from scalar-typed fields but preserved on object, nested, and type-absent fields - Clean field with no invalid attributes passes through unmodified Signed-off-by: thecodingshrimp <leonard.stutzer@sap.com>
8ff6a8e to
5a796b4
Compare
|
Persistent review updated to latest commit 5a796b4 |
5a796b4 to
0e80b45
Compare
|
Persistent review updated to latest commit 0e80b45 |
…erties
Gap 1: sanitizeFieldMappingAttributes only recursed into multi-fields ("fields")
but not into sub-properties of object/implicit-object fields. Any leaf inside an
object field carrying an analysis attribute (analyzer, normalizer, etc.) survived
sanitization and caused the PutMappingRequest to fail with
"analyzer [x] has not been configured in mappings".
Gap 2: traverseMappingsAndUpdate already passes sub-properties by live reference
in this repo, so no change needed there.
Fix: recurse into mapping["properties"] when fieldType is null, "object", or NESTED.
Add 6 regression tests covering both gap scenarios.
Signed-off-by: thecodingshrimp <leonard.stutzer@sap.com>
0e80b45 to
99dd424
Compare
|
Persistent review updated to latest commit 99dd424 |
Problem
Doc-level monitors fail at creation time when the source index has field mappings that contain attributes incompatible with the query index. Two distinct failure categories have been observed.
Category 1 — analysis resource references
Fields such as
textorkeywordcan carryanalyzer,normalizer,search_analyzer,search_quote_analyzer, orsimilarityattributes that reference custom analysis objects defined in the source index'ssettings.analysis.*block. The doc-level query index is created from a fixed settings resource with no custom analysis block. WhenDocLevelMonitorQueriescopies field mappings verbatim viaprops.toMutableMap()and submits them in aPutMappingRequest, OpenSearch rejects the request:Category 2 —
propertieson a scalar field typeDynamic mapping collisions can leave a field in cluster state with both
"type": "text"(or any scalar type) and apropertiessub-block, which is only valid onobject/nestedmappers. OpenSearch stores this silently at ingestion time but rejects it when submitted explicitly via the PUT mapping API:Both failures block monitor creation on any real-world index that uses custom analyzers, normalizers, or has experienced dynamic mapping collisions — a common production pattern. The issue is actively tracked in alerting#961 and affects Security Analytics detector creation as reported in security-analytics#697 and security-analytics#1798.
Root cause
leafNodeProcessorinDocLevelMonitorQueries.ktperforms an unconditionalprops.toMutableMap()copy of every source field attribute before building thePutMappingRequest. No filtering is applied to remove attributes that are invalid on the query index.Fix
Add
sanitizeFieldMappingAttributes(fieldType, mapping)to theDocLevelMonitorQueriescompanion object and call it onnewPropsimmediately after thetoMutableMap()copy insideleafNodeProcessor.The function:
analyzer,search_analyzer,search_quote_analyzer,normalizer,similarity) — Category 1propertiesfrom any field whose type is explicitly set to something other thanobjectornested— Category 2fieldssub-mapNo index close/open cycle is required. The change is confined to the in-memory
PutMappingRequestpayload. The query index stores Percolator query documents for doc-level matching only, not user-facing search data, so dropping these attributes is safe and lossless for its purpose.This approach resolves the architectural concern raised in alerting#961: the original "won't fix" closure described Strategy B (copying
settings.analysis.*from the source index into the query index), which is genuinely blocked because the shared query index cannot safely merge conflicting analysis configurations from multiple source indices. This fix implements Strategy A (strip the incompatible attributes before the PUT), which is independent of that constraint.Changes
alerting/src/main/kotlin/org/opensearch/alerting/util/DocLevelMonitorQueries.kt: addANALYSIS_ATTRIBUTESconstant andsanitizeFieldMappingAttributes()to companion object; wire intoleafNodeProcessoralerting/src/test/kotlin/org/opensearch/alerting/util/AlertingUtilsTests.kt: 7 unit tests covering both failure categories, edge cases (object/nested/absent type), multi-field recursion, and clean pass-throughRelated issues
Testing
Unit tests added in
AlertingUtilsTests. All existing tests in that file continue to pass unchanged.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
cudos: claude