-
Notifications
You must be signed in to change notification settings - Fork 663
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SOLR-4587: integrate lucene-monitor into solr #2382
base: main
Are you sure you want to change the base?
Changes from all commits
bba4191
fe3b413
0989f1c
62ddcbc
33eccf7
fa7fb40
11a1138
7526b2f
6ac7a5e
2362ce7
e5a1382
b7b58b3
ce40d60
a201676
60b0eb5
fd04c4e
32cb6f6
b6d369b
0ab5a6b
0b0120e
24c1bf5
ee2992d
6815ea1
995cfa2
a2419ff
0fde7ef
5968754
bb11982
eba6e2d
d3ccf0c
e12ec6f
6d4986c
3aae9f0
0915ce1
e6e25a5
8bb7151
e1365ad
5b37a6a
e4af381
7be05a3
f2d47be
d359f80
4af2c57
ef8dafd
f3b33b1
7feb415
a3c4d36
ebc4fb9
e33e8ae
05438f4
483e46f
9ed6b48
28bf264
908f462
13dffda
cbf45de
a3fc3d5
a24d66a
44eea79
bf0daf7
3e7a53c
113ca8f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
fa731be343ec79d940c7abd0dd8ff1de9bf9c7f1 |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,33 @@ | ||||||||
/* | ||||||||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||||||||
* contributor license agreements. See the NOTICE file distributed with | ||||||||
* this work for additional information regarding copyright ownership. | ||||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||||||||
* (the "License"); you may not use this file except in compliance with | ||||||||
* the License. You may obtain a copy of the License at | ||||||||
* | ||||||||
* http://www.apache.org/licenses/LICENSE-2.0 | ||||||||
* | ||||||||
* Unless required by applicable law or agreed to in writing, software | ||||||||
* distributed under the License is distributed on an "AS IS" BASIS, | ||||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||||
* See the License for the specific language governing permissions and | ||||||||
* limitations under the License. | ||||||||
*/ | ||||||||
|
||||||||
apply plugin: 'java-library' | ||||||||
|
||||||||
description = 'Apache Solr Monitor' | ||||||||
|
||||||||
dependencies { | ||||||||
|
||||||||
implementation project(":solr:core") | ||||||||
implementation project(":solr:solrj") | ||||||||
implementation "org.apache.lucene:lucene-core" | ||||||||
implementation "org.apache.lucene:lucene-monitor" | ||||||||
implementation 'com.github.ben-manes.caffeine:caffeine' | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the CI says
and a remedy might be (something like)
Suggested change
however with that and
instead i.e. the opposite. |
||||||||
testImplementation project(':solr:test-framework') | ||||||||
testImplementation 'junit:junit' | ||||||||
} | ||||||||
|
||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.apache.lucene.monitor; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.TimeUnit; | ||
import org.apache.lucene.search.IndexSearcher; | ||
import org.apache.lucene.search.Query; | ||
|
||
/** Class used to match candidate queries selected by a Presearcher from a Monitor query index. */ | ||
public abstract class CandidateMatcher<T extends QueryMatch> { | ||
|
||
/** The searcher to run candidate queries against */ | ||
protected final IndexSearcher searcher; | ||
|
||
private final Map<String, Exception> errors = new HashMap<>(); | ||
private final List<MatchHolder<T>> matches; | ||
|
||
private long searchTime = System.nanoTime(); | ||
|
||
private static class MatchHolder<T> { | ||
Map<String, T> matches = new HashMap<>(); | ||
} | ||
|
||
/** | ||
* Creates a new CandidateMatcher for the supplied DocumentBatch | ||
* | ||
* @param searcher the IndexSearcher to run queries against | ||
*/ | ||
public CandidateMatcher(IndexSearcher searcher) { | ||
this.searcher = searcher; | ||
int docCount = searcher.getIndexReader().maxDoc(); | ||
this.matches = new ArrayList<>(docCount); | ||
for (int i = 0; i < docCount; i++) { | ||
this.matches.add(new MatchHolder<>()); | ||
} | ||
} | ||
|
||
/** | ||
* Runs the supplied query against this CandidateMatcher's set of documents, storing any resulting | ||
* match, and recording the query in the presearcher hits | ||
* | ||
* @param queryId the query id | ||
* @param matchQuery the query to run | ||
* @param metadata the query metadata | ||
* @throws IOException on IO errors | ||
*/ | ||
public abstract void matchQuery(String queryId, Query matchQuery, Map<String, String> metadata) | ||
throws IOException; | ||
|
||
/** | ||
* Record a match | ||
* | ||
* @param match a QueryMatch object | ||
*/ | ||
protected final void addMatch(T match, int doc) { | ||
MatchHolder<T> docMatches = matches.get(doc); | ||
docMatches.matches.compute( | ||
match.getQueryId(), | ||
(key, oldValue) -> { | ||
if (oldValue != null) { | ||
return resolve(match, oldValue); | ||
} | ||
return match; | ||
}); | ||
} | ||
|
||
/** | ||
* If two matches from the same query are found (for example, two branches of a disjunction), | ||
* combine them. | ||
* | ||
* @param match1 the first match found | ||
* @param match2 the second match found | ||
* @return a Match object that combines the two | ||
*/ | ||
public abstract T resolve(T match1, T match2); | ||
|
||
/** Called by the Monitor if running a query throws an Exception */ | ||
void reportError(String queryId, Exception e) { | ||
this.errors.put(queryId, e); | ||
} | ||
|
||
/** | ||
* @return the matches from this matcher | ||
*/ | ||
public final MultiMatchingQueries<T> finish(long buildTime, int queryCount) { | ||
doFinish(); | ||
this.searchTime = | ||
TimeUnit.MILLISECONDS.convert(System.nanoTime() - searchTime, TimeUnit.NANOSECONDS); | ||
List<Map<String, T>> results = new ArrayList<>(); | ||
for (MatchHolder<T> matchHolder : matches) { | ||
results.add(matchHolder.matches); | ||
} | ||
return new MultiMatchingQueries<>( | ||
results, errors, buildTime, searchTime, queryCount, matches.size()); | ||
} | ||
|
||
/** Called when all monitoring of a batch of documents is complete */ | ||
protected void doFinish() {} | ||
|
||
/** Copy all matches from another CandidateMatcher */ | ||
protected void copyMatches(CandidateMatcher<T> other) { | ||
this.matches.clear(); | ||
this.matches.addAll(other.matches); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* | ||
* * Licensed to the Apache Software Foundation (ASF) under one or more | ||
* * contributor license agreements. See the NOTICE file distributed with | ||
* * this work for additional information regarding copyright ownership. | ||
* * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* * (the "License"); you may not use this file except in compliance with | ||
* * the License. You may obtain a copy of the License at | ||
* * | ||
* * http://www.apache.org/licenses/LICENSE-2.0 | ||
* * | ||
* * Unless required by applicable law or agreed to in writing, software | ||
* * distributed under the License is distributed on an "AS IS" BASIS, | ||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* * See the License for the specific language governing permissions and | ||
* * limitations under the License. | ||
* | ||
*/ | ||
|
||
package org.apache.lucene.monitor; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opened apache/lucene#13993 to propose to make |
||
|
||
import java.io.Closeable; | ||
import java.io.IOException; | ||
import java.util.List; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Collectors; | ||
import org.apache.lucene.analysis.Analyzer; | ||
import org.apache.lucene.document.Document; | ||
import org.apache.lucene.index.LeafReader; | ||
|
||
public class DocumentBatchVisitor implements Closeable, Supplier<LeafReader> { | ||
|
||
private final DocumentBatch batch; | ||
private final List<Document> docs; | ||
|
||
private DocumentBatchVisitor(DocumentBatch batch, List<Document> docs) { | ||
this.batch = batch; | ||
this.docs = docs; | ||
} | ||
|
||
public static DocumentBatchVisitor of(Analyzer analyzer, List<Document> docs) { | ||
return new DocumentBatchVisitor( | ||
DocumentBatch.of(analyzer, docs.toArray(new Document[0])), docs); | ||
} | ||
|
||
@Override | ||
public void close() throws IOException { | ||
batch.close(); | ||
} | ||
|
||
@Override | ||
public LeafReader get() { | ||
return batch.get(); | ||
} | ||
|
||
public int size() { | ||
return docs.size(); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return docs.stream().map(Document::toString).collect(Collectors.joining(" ")); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* | ||
* * Licensed to the Apache Software Foundation (ASF) under one or more | ||
* * contributor license agreements. See the NOTICE file distributed with | ||
* * this work for additional information regarding copyright ownership. | ||
* * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* * (the "License"); you may not use this file except in compliance with | ||
* * the License. You may obtain a copy of the License at | ||
* * | ||
* * http://www.apache.org/licenses/LICENSE-2.0 | ||
* * | ||
* * Unless required by applicable law or agreed to in writing, software | ||
* * distributed under the License is distributed on an "AS IS" BASIS, | ||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* * See the License for the specific language governing permissions and | ||
* * limitations under the License. | ||
* | ||
*/ | ||
package org.apache.lucene.monitor; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import org.apache.lucene.search.Query; | ||
|
||
public class MatchesAggregator<T extends QueryMatch> extends CandidateMatcher<T> { | ||
|
||
private final CandidateMatcher<T> resolvingMatcher; | ||
|
||
private MatchesAggregator( | ||
List<CandidateMatcher<T>> matchers, CandidateMatcher<T> resolvingMatcher) { | ||
super(resolvingMatcher.searcher); | ||
this.resolvingMatcher = resolvingMatcher; | ||
for (var matcher : matchers) { | ||
var matches = matcher.finish(Long.MIN_VALUE, -1); | ||
for (int doc = 0; doc < matches.getBatchSize(); doc++) { | ||
for (T match : matches.getMatches(doc)) { | ||
this.addMatch(match, doc); | ||
} | ||
} | ||
for (Map.Entry<String, Exception> error : matches.getErrors().entrySet()) { | ||
this.reportError(error.getKey(), error.getValue()); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void matchQuery(String queryId, Query matchQuery, Map<String, String> metadata) { | ||
throw new UnsupportedOperationException("only use for aggregating other matchers"); | ||
} | ||
|
||
@Override | ||
public T resolve(T match1, T match2) { | ||
return resolvingMatcher.resolve(match1, match2); | ||
} | ||
|
||
public static <T extends QueryMatch> MultiMatchingQueries<T> aggregate( | ||
List<CandidateMatcher<T>> matchers, CandidateMatcher<T> resolver, int queryCount) { | ||
return new MatchesAggregator<>(matchers, resolver).finish(Long.MIN_VALUE, queryCount); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* | ||
* * Licensed to the Apache Software Foundation (ASF) under one or more | ||
* * contributor license agreements. See the NOTICE file distributed with | ||
* * this work for additional information regarding copyright ownership. | ||
* * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* * (the "License"); you may not use this file except in compliance with | ||
* * the License. You may obtain a copy of the License at | ||
* * | ||
* * http://www.apache.org/licenses/LICENSE-2.0 | ||
* * | ||
* * Unless required by applicable law or agreed to in writing, software | ||
* * distributed under the License is distributed on an "AS IS" BASIS, | ||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* * See the License for the specific language governing permissions and | ||
* * limitations under the License. | ||
* | ||
*/ | ||
|
||
package org.apache.lucene.monitor; | ||
|
||
import java.util.Set; | ||
|
||
public class MonitorFields { | ||
|
||
public static final String QUERY_ID = QueryIndex.FIELDS.query_id + "_"; | ||
public static final String CACHE_ID = QueryIndex.FIELDS.cache_id + "_"; | ||
public static final String MONITOR_QUERY = QueryIndex.FIELDS.mq + "_"; | ||
|
||
public static final Set<String> REQUIRED_MONITOR_SCHEMA_FIELDS = | ||
Set.of(QUERY_ID, CACHE_ID, MONITOR_QUERY); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is so puzzling to anyone who isn't intimately familiar with Lucene Monitor. I don't even think we should be calling this "Solr Monitor"; looks like infrastructure monitoring thing. Possibly "Solr-Lucene-Monitor" but still... a puzzling name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great point .. The library used to be called luwak which I find to be a much better name... I'll try to think of a better name (maybe solr-reverse-search or solr-query-alerting). I'll reply in more detail to your mailing list message also touching on solr.cool and the sandbox.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Saved Searches is a common name, I assume it is possible to list a users's saved searches too. Or Alerting, but then most people will expect there to be some functionality to ship alerts somewhere...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, if anything this might be a part of some larger alerting system, but "saved search" is more accurate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Saved searches is a pretty indicative name. Percolator is also a known name for this kind of functionally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, I thought ES invented "percolator" as more of a metaphor... I wasn't aware that this is a more generic name. I was worried that "percolator" might clash too much with ES.