mirror of https://github.com/apache/lucene.git
Adding 'Luke' request handler and other admin helpers: SOLR-163
git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@532975 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
26b8cae1f8
commit
593e218d6d
|
@ -399,6 +399,13 @@
|
|||
<requestHandler name="/update/csv" class="solr.CSVRequestHandler" startup="lazy">
|
||||
</requestHandler>
|
||||
|
||||
<!-- Admin Handlers. TODO? There could be a single handler that loads them all... -->
|
||||
<requestHandler name="/admin/luke" class="org.apache.solr.handler.admin.LukeRequestHandler" />
|
||||
<requestHandler name="/admin/system" class="org.apache.solr.handler.admin.SystemInfoHandler" />
|
||||
<requestHandler name="/admin/plugins" class="org.apache.solr.handler.admin.PluginInfoHandler" />
|
||||
<requestHandler name="/admin/threads" class="org.apache.solr.handler.admin.ThreadDumpHandler" />
|
||||
<requestHandler name="/admin/properties" class="org.apache.solr.handler.admin.PropertiesRequestHandler" />
|
||||
|
||||
|
||||
<!-- queryResponseWriter plugins... query responses will be written using the
|
||||
writer specified by the 'wt' request parameter matching the name of a registered
|
||||
|
|
|
@ -32,6 +32,11 @@ import java.util.Collection;
|
|||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* TODO? delete me? This is now a subset of LukeRequestHandler.
|
||||
* Since it was not released in 1.1 should it be deleted before 1.2?
|
||||
*/
|
||||
@Deprecated
|
||||
public class IndexInfoRequestHandler extends RequestHandlerBase {
|
||||
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
|
@ -99,3 +104,4 @@ public class IndexInfoRequestHandler extends RequestHandlerBase {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,479 @@
|
|||
/**
|
||||
* 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.solr.handler.admin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Fieldable;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.index.TermEnum;
|
||||
import org.apache.lucene.index.TermFreqVector;
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.PriorityQueue;
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.core.SolrException;
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
import org.apache.solr.handler.RequestHandlerUtils;
|
||||
import org.apache.solr.request.SolrParams;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.schema.FieldType;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
import org.apache.solr.search.SolrQueryParser;
|
||||
import org.apache.solr.util.NamedList;
|
||||
import org.apache.solr.util.SimpleOrderedMap;
|
||||
|
||||
/**
|
||||
* This handler exposes the internal lucene index. It is inspired by and
|
||||
* modeled on Luke, the Lucene Index Browser by Andrzej Bialecki.
|
||||
* http://www.getopt.org/luke/
|
||||
* <p>
|
||||
* NOTE: the response format is still likely to change. It should be designed so
|
||||
* that it works nicely with an XSLT transformation. Untill we have a nice
|
||||
* XSLT frontend for /admin, the format is still open to change.
|
||||
* </p>
|
||||
*
|
||||
* For more documentation see:
|
||||
*
|
||||
*
|
||||
* @author ryan
|
||||
* @version $Id$
|
||||
* @since solr 1.2
|
||||
*/
|
||||
public class LukeRequestHandler extends RequestHandlerBase
|
||||
{
|
||||
private static Logger log = Logger.getLogger(LukeRequestHandler.class.getName());
|
||||
|
||||
public static final String NUMTERMS = "numTerms";
|
||||
public static final String DOC_ID = "docID";
|
||||
public static final String ID = "id";
|
||||
public static final int DEFAULT_COUNT = 10;
|
||||
|
||||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception
|
||||
{
|
||||
RequestHandlerUtils.addExperimentalFormatWarning( rsp );
|
||||
|
||||
IndexSchema schema = req.getSchema();
|
||||
SolrIndexSearcher searcher = req.getSearcher();
|
||||
IndexReader reader = searcher.getReader();
|
||||
SolrParams params = req.getParams();
|
||||
|
||||
// Always show the core lucene info
|
||||
rsp.add("index", getIndexInfo(reader) );
|
||||
|
||||
Integer docID = params.getInt( DOC_ID );
|
||||
if( docID == null && params.get( ID ) != null ) {
|
||||
// Look for somethign with a given solr ID
|
||||
SchemaField uniqueKey = schema.getUniqueKeyField();
|
||||
String v = uniqueKey.getType().toInternal( params.get(ID) );
|
||||
Term t = new Term( uniqueKey.getName(), v );
|
||||
docID = searcher.getFirstMatch( t );
|
||||
if( docID < 0 ) {
|
||||
throw new SolrException( 404, "Can't find document: "+params.get( ID ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Read the document from the index
|
||||
if( docID != null ) {
|
||||
Document doc = null;
|
||||
try {
|
||||
doc = reader.document( docID );
|
||||
}
|
||||
catch( Exception ex ) {}
|
||||
if( doc == null ) {
|
||||
throw new SolrException( 404, "Can't find document: "+docID );
|
||||
}
|
||||
|
||||
SimpleOrderedMap<Object> info = getDocumentFieldsInfo( doc, docID, reader, schema );
|
||||
|
||||
SimpleOrderedMap<Object> docinfo = new SimpleOrderedMap<Object>();
|
||||
docinfo.add( "docID", docID );
|
||||
docinfo.add( "lucene", info );
|
||||
docinfo.add( "solr", doc );
|
||||
rsp.add( "doc", docinfo );
|
||||
}
|
||||
else {
|
||||
// If no doc is given, show all fields and top terms
|
||||
int numTerms = params.getInt( NUMTERMS, DEFAULT_COUNT );
|
||||
Set<String> fields = null;
|
||||
if( params.get( SolrParams.FL ) != null ) {
|
||||
fields = new HashSet<String>();
|
||||
for( String f : params.getParams( SolrParams.FL ) ) {
|
||||
fields.add( f );
|
||||
}
|
||||
}
|
||||
rsp.add( "key", getFieldFlagsKey() );
|
||||
rsp.add( "fields", getIndexedFieldsInfo( searcher, fields, numTerms ) ) ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a string representing a Fieldable's flags.
|
||||
*/
|
||||
private static String getFieldFlags( Fieldable f )
|
||||
{
|
||||
StringBuilder flags = new StringBuilder();
|
||||
flags.append( (f != null && f.isIndexed()) ? 'I' : '-' );
|
||||
flags.append( (f != null && f.isTokenized()) ? 'T' : '-' );
|
||||
flags.append( (f != null && f.isStored()) ? 'S' : '-' );
|
||||
flags.append( (false) ? 'M' : '-' ); // SchemaField Specific
|
||||
flags.append( (f != null && f.isTermVectorStored()) ? 'V' : '-' );
|
||||
flags.append( (f != null && f.isStoreOffsetWithTermVector()) ? 'o' : '-' );
|
||||
flags.append( (f != null && f.isStorePositionWithTermVector()) ? 'p' : '-' );
|
||||
flags.append( (f != null && f.getOmitNorms()) ? 'O' : '-' );
|
||||
flags.append( (f != null && f.isLazy()) ? 'L' : '-' );
|
||||
flags.append( (f != null && f.isBinary()) ? 'B' : '-' );
|
||||
flags.append( (f != null && f.isCompressed()) ? 'C' : '-' );
|
||||
flags.append( (false) ? 'f' : '-' ); // SchemaField Specific
|
||||
flags.append( (false) ? 'l' : '-' ); // SchemaField Specific
|
||||
return flags.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a string representing a SchemaField's flags.
|
||||
*/
|
||||
private static String getFieldFlags( SchemaField f )
|
||||
{
|
||||
FieldType t = (f==null) ? null : f.getType();
|
||||
|
||||
// see: http://www.nabble.com/schema-field-properties-tf3437753.html#a9585549
|
||||
boolean lazy = false; // "lazy" is purely a property of reading fields
|
||||
boolean binary = false; // Currently not possible
|
||||
|
||||
StringBuilder flags = new StringBuilder();
|
||||
flags.append( (f != null && f.indexed()) ? 'I' : '-' );
|
||||
flags.append( (t != null && t.isTokenized()) ? 'T' : '-' );
|
||||
flags.append( (f != null && f.stored()) ? 'S' : '-' );
|
||||
flags.append( (f != null && f.multiValued()) ? 'M' : '-' );
|
||||
flags.append( (f != null && f.storeTermVector() ) ? 'V' : '-' );
|
||||
flags.append( (f != null && f.storeTermOffsets() ) ? 'o' : '-' );
|
||||
flags.append( (f != null && f.storeTermPositions() ) ? 'p' : '-' );
|
||||
flags.append( (f != null && f.omitNorms()) ? 'O' : '-' );
|
||||
flags.append( (lazy) ? 'L' : '-' );
|
||||
flags.append( (binary) ? 'B' : '-' );
|
||||
flags.append( (f != null && f.isCompressed()) ? 'C' : '-' );
|
||||
flags.append( (f != null && f.sortMissingFirst() ) ? 'f' : '-' );
|
||||
flags.append( (f != null && f.sortMissingLast() ) ? 'l' : '-' );
|
||||
return flags.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a key to what each character means
|
||||
*/
|
||||
private static SimpleOrderedMap<String> getFieldFlagsKey()
|
||||
{
|
||||
SimpleOrderedMap<String> key = new SimpleOrderedMap<String>();
|
||||
key.add( "I", "Indexed" );
|
||||
key.add( "T", "Tokenized" );
|
||||
key.add( "S", "Stored" );
|
||||
key.add( "M", "Multivalued" );
|
||||
key.add( "V", "TermVector Stored" );
|
||||
key.add( "o", "Store Offset With TermVector" );
|
||||
key.add( "p", "Store Position With TermVector" );
|
||||
key.add( "O", "Omit Norms" );
|
||||
key.add( "L", "Lazy" );
|
||||
key.add( "B", "Binary" );
|
||||
key.add( "C", "Compressed" );
|
||||
key.add( "f", "Sort Missing First" );
|
||||
key.add( "l", "Sort Missing Last" );
|
||||
return key;
|
||||
}
|
||||
|
||||
private static SimpleOrderedMap<Object> getDocumentFieldsInfo( Document doc, int docID, IndexReader reader, IndexSchema schema ) throws IOException
|
||||
{
|
||||
SimpleOrderedMap<Object> finfo = new SimpleOrderedMap<Object>();
|
||||
for( Object o : doc.getFields() ) {
|
||||
Fieldable fieldable = (Fieldable)o;
|
||||
SimpleOrderedMap<Object> f = new SimpleOrderedMap<Object>();
|
||||
|
||||
SchemaField sfield = schema.getFieldOrNull( fieldable.name() );
|
||||
FieldType ftype = (sfield==null)?null:sfield.getType();
|
||||
|
||||
f.add( "type", (ftype==null)?null:ftype.getTypeName() );
|
||||
f.add( "schema", getFieldFlags( sfield ) );
|
||||
f.add( "flags", getFieldFlags( fieldable ) );
|
||||
|
||||
Term t = new Term( fieldable.name(), fieldable.stringValue() );
|
||||
f.add( "value", (ftype==null)?null:ftype.toExternal( fieldable ) );
|
||||
f.add( "internal", fieldable.stringValue() ); // may be a binary number
|
||||
f.add( "boost", fieldable.getBoost() );
|
||||
|
||||
// TODO? how can this ever be 0?! it is in the document!
|
||||
int freq = reader.docFreq( t );
|
||||
if( freq > 0 ) {
|
||||
f.add( "docFreq", reader.docFreq( t ) );
|
||||
}
|
||||
else {
|
||||
f.add( "docFreq", "zero! How can that be?" );
|
||||
}
|
||||
|
||||
// If we have a term vector, return that
|
||||
if( fieldable.isTermVectorStored() ) {
|
||||
try {
|
||||
TermFreqVector v = reader.getTermFreqVector( docID, fieldable.name() );
|
||||
if( v != null ) {
|
||||
SimpleOrderedMap<Integer> tfv = new SimpleOrderedMap<Integer>();
|
||||
for( int i=0; i<v.size(); i++ ) {
|
||||
tfv.add( v.getTerms()[i], v.getTermFrequencies()[i] );
|
||||
}
|
||||
f.add( "termVector", tfv );
|
||||
}
|
||||
}
|
||||
catch( Exception ex ) {
|
||||
log.log( Level.WARNING, "error writing term vector", ex );
|
||||
}
|
||||
}
|
||||
|
||||
finfo.add( fieldable.name(), f );
|
||||
}
|
||||
return finfo;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static SimpleOrderedMap<Object> getIndexedFieldsInfo(
|
||||
final SolrIndexSearcher searcher, final Set<String> fields, final int numTerms )
|
||||
throws Exception
|
||||
{
|
||||
Query matchAllDocs = new MatchAllDocsQuery();
|
||||
SolrQueryParser qp = searcher.getSchema().getSolrQueryParser(null);
|
||||
|
||||
int filterCacheSize = SolrConfig.config.getInt( "query/filterCache/@size", -1 );
|
||||
IndexReader reader = searcher.getReader();
|
||||
IndexSchema schema = searcher.getSchema();
|
||||
|
||||
// Walk the term enum and keep a priority quey for each map in our set
|
||||
Map<String,TopTermQueue> ttinfo = getTopTerms(reader, fields, numTerms, null );
|
||||
SimpleOrderedMap<Object> finfo = new SimpleOrderedMap<Object>();
|
||||
Collection<String> fieldNames = reader.getFieldNames(IndexReader.FieldOption.ALL);
|
||||
for (String fieldName : fieldNames) {
|
||||
if( fields != null && !fields.contains( fieldName ) ) {
|
||||
continue; // if a field is specified, only return one
|
||||
}
|
||||
|
||||
SimpleOrderedMap<Object> f = new SimpleOrderedMap<Object>();
|
||||
|
||||
SchemaField sfield = schema.getFieldOrNull( fieldName );
|
||||
FieldType ftype = (sfield==null)?null:sfield.getType();
|
||||
|
||||
f.add( "type", (ftype==null)?null:ftype.getTypeName() );
|
||||
f.add( "schema", getFieldFlags( sfield ) );
|
||||
|
||||
Query q = qp.parse( fieldName+":[* TO *]" );
|
||||
int docCount = searcher.numDocs( q, matchAllDocs );
|
||||
// TODO? Is there a way to get the Fieldable infomation for this field?
|
||||
// The following approach works fine for stored fields, but does not work for non-stored fields
|
||||
// if( docCount > 0 ) {
|
||||
// // Find a document with this field
|
||||
// DocList ds = searcher.getDocList( q, (Query)null, (Sort)null, 0, 1 );
|
||||
// try {
|
||||
// Document doc = searcher.doc( ds.iterator().next() );
|
||||
// Fieldable fld = doc.getFieldable( fieldName );
|
||||
// f.add( "index", getFieldFlags( fld ) );
|
||||
// }
|
||||
// catch( Exception ex ) {
|
||||
// log.warning( "error reading field: "+fieldName );
|
||||
// }
|
||||
// // Find one document so we can get the fieldable
|
||||
// }
|
||||
f.add( "docs", docCount );
|
||||
|
||||
TopTermQueue topTerms = ttinfo.get( fieldName );
|
||||
if( topTerms != null ) {
|
||||
f.add( "distinct", topTerms.distinctTerms );
|
||||
|
||||
// TODO? is this the correct logic?
|
||||
f.add( "cacheableFaceting", topTerms.distinctTerms < filterCacheSize );
|
||||
|
||||
// Only show them if we specify something
|
||||
f.add( "topTerms", topTerms.toNamedList( searcher.getSchema() ) );
|
||||
}
|
||||
|
||||
// Add the field
|
||||
finfo.add( fieldName, f );
|
||||
}
|
||||
return finfo;
|
||||
}
|
||||
|
||||
|
||||
private static SimpleOrderedMap<Object> getIndexInfo( IndexReader reader ) throws IOException
|
||||
{
|
||||
// Count the terms
|
||||
TermEnum te = reader.terms();
|
||||
int numTerms = 0;
|
||||
while (te.next()) {
|
||||
numTerms++;
|
||||
}
|
||||
|
||||
Directory dir = reader.directory();
|
||||
SimpleOrderedMap<Object> indexInfo = new SimpleOrderedMap<Object>();
|
||||
indexInfo.add("numDocs", reader.numDocs());
|
||||
indexInfo.add("maxDoc", reader.maxDoc());
|
||||
indexInfo.add("numTerms", numTerms );
|
||||
indexInfo.add("version", reader.getVersion()); // TODO? Is this different then: IndexReader.getCurrentVersion( dir )?
|
||||
indexInfo.add("optimized", reader.isOptimized() );
|
||||
indexInfo.add("current", reader.isCurrent() );
|
||||
indexInfo.add("hasDeletions", reader.hasDeletions() );
|
||||
indexInfo.add("directory", dir );
|
||||
indexInfo.add("lastModified", new Date(IndexReader.lastModified(dir)) );
|
||||
return indexInfo;
|
||||
}
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Lucene Index Browser. Inspired and modeled after Luke: http://www.getopt.org/luke/";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "$Revision: 501512 $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceId() {
|
||||
return "$Id: IndexInfoRequestHandler.java 487199 2006-12-14 13:03:40Z bdelacretaz $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "$URL: https://svn.apache.org/repos/asf/lucene/solr/trunk/src/java/org/apache/solr/request/IndexInfoRequestHandler.java $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL[] getDocs() {
|
||||
try {
|
||||
return new URL[] { new URL("http://wiki.apache.org/solr/LukeRequestHandler") };
|
||||
}
|
||||
catch( MalformedURLException ex ) { return null; }
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Private internal class that counts up frequent terms
|
||||
*/
|
||||
private static class TopTermQueue extends PriorityQueue
|
||||
{
|
||||
static class TermInfo {
|
||||
TermInfo(Term t, int df) {
|
||||
term = t;
|
||||
docFreq = df;
|
||||
}
|
||||
int docFreq;
|
||||
Term term;
|
||||
}
|
||||
|
||||
public int minFreq = 0;
|
||||
public int distinctTerms = 0;
|
||||
|
||||
TopTermQueue(int size) {
|
||||
initialize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean lessThan(Object a, Object b) {
|
||||
TermInfo termInfoA = (TermInfo)a;
|
||||
TermInfo termInfoB = (TermInfo)b;
|
||||
return termInfoA.docFreq < termInfoB.docFreq;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a destructive call... the queue is empty at the end
|
||||
*/
|
||||
public NamedList<Integer> toNamedList( IndexSchema schema )
|
||||
{
|
||||
// reverse the list..
|
||||
List<TermInfo> aslist = new LinkedList<TermInfo>();
|
||||
while( size() > 0 ) {
|
||||
aslist.add( 0, (TermInfo)pop() );
|
||||
}
|
||||
|
||||
NamedList<Integer> list = new NamedList<Integer>();
|
||||
for (TermInfo i : aslist) {
|
||||
String txt = i.term.text();
|
||||
SchemaField ft = schema.getFieldOrNull( i.term.field() );
|
||||
if( ft != null ) {
|
||||
txt = ft.getType().indexedToReadable( txt );
|
||||
}
|
||||
list.add( txt, i.docFreq );
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String,TopTermQueue> getTopTerms( IndexReader reader, Set<String> fields, int numTerms, Set<String> junkWords ) throws Exception
|
||||
{
|
||||
Map<String,TopTermQueue> info = new HashMap<String, TopTermQueue>();
|
||||
TermEnum terms = reader.terms();
|
||||
|
||||
while (terms.next()) {
|
||||
String field = terms.term().field();
|
||||
String t = terms.term().text();
|
||||
|
||||
// Compute distinct terms for every field
|
||||
TopTermQueue tiq = info.get( field );
|
||||
if( tiq == null ) {
|
||||
tiq = new TopTermQueue( numTerms );
|
||||
info.put( field, tiq );
|
||||
}
|
||||
tiq.distinctTerms++;
|
||||
|
||||
// Only save the distinct terms for fields we worry about
|
||||
if (fields != null && fields.size() > 0) {
|
||||
if( !fields.contains( field ) ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( junkWords != null && junkWords.contains( t ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if( terms.docFreq() > tiq.minFreq ) {
|
||||
tiq.put(new TopTermQueue.TermInfo(terms.term(), terms.docFreq()));
|
||||
if (tiq.size() >= numTerms) { // if tiq overfull
|
||||
tiq.pop(); // remove lowest in tiq
|
||||
tiq.minFreq = ((TopTermQueue.TermInfo)tiq.top()).docFreq; // reset minFreq
|
||||
}
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/**
|
||||
* 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.solr.handler.admin;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.solr.core.SolrInfoMBean;
|
||||
import org.apache.solr.core.SolrInfoRegistry;
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
import org.apache.solr.handler.RequestHandlerUtils;
|
||||
import org.apache.solr.request.SolrParams;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.util.SimpleOrderedMap;
|
||||
|
||||
/**
|
||||
* similar to "admin/registry.jsp"
|
||||
*
|
||||
* NOTE: the response format is still likely to change. It should be designed so
|
||||
* that it works nicely with an XSLT transformation. Untill we have a nice
|
||||
* XSLT frontend for /admin, the format is still open to change.
|
||||
*
|
||||
* @author ryan
|
||||
* @version $Id$
|
||||
* @since solr 1.2
|
||||
*/
|
||||
public class PluginInfoHandler extends RequestHandlerBase
|
||||
{
|
||||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception
|
||||
{
|
||||
RequestHandlerUtils.addExperimentalFormatWarning( rsp );
|
||||
SolrParams params = req.getParams();
|
||||
|
||||
boolean stats = params.getBool( "stats", false );
|
||||
rsp.add( "plugins", getSolrInfoBeans( stats ) );
|
||||
}
|
||||
|
||||
private static SimpleOrderedMap<Object> getSolrInfoBeans( boolean stats )
|
||||
{
|
||||
SimpleOrderedMap<Object> list = new SimpleOrderedMap<Object>();
|
||||
for (SolrInfoMBean.Category cat : SolrInfoMBean.Category.values())
|
||||
{
|
||||
SimpleOrderedMap<Object> category = new SimpleOrderedMap<Object>();
|
||||
list.add( cat.name(), category );
|
||||
Map<String, SolrInfoMBean> reg = SolrInfoRegistry.getRegistry();
|
||||
synchronized(reg) {
|
||||
for (Map.Entry<String,SolrInfoMBean> entry : reg.entrySet()) {
|
||||
SolrInfoMBean m = entry.getValue();
|
||||
if (m.getCategory() != cat) continue;
|
||||
|
||||
String na = "Not Declared";
|
||||
SimpleOrderedMap<Object> info = new SimpleOrderedMap<Object>();
|
||||
category.add( entry.getKey(), info );
|
||||
|
||||
info.add( "name", (m.getName() !=null ? m.getName() : na) );
|
||||
info.add( "version", (m.getVersion() !=null ? m.getVersion() : na) );
|
||||
info.add( "description", (m.getDescription()!=null ? m.getDescription() : na) );
|
||||
|
||||
info.add( "sourceId", (m.getSourceId() !=null ? m.getSourceId() : na) );
|
||||
info.add( "source", (m.getSource() !=null ? m.getSource() : na) );
|
||||
|
||||
URL[] urls = m.getDocs();
|
||||
if ((urls != null) && (urls.length > 0)) {
|
||||
ArrayList<String> docs = new ArrayList<String>(urls.length);
|
||||
for( URL u : urls ) {
|
||||
docs.add( u.toExternalForm() );
|
||||
}
|
||||
info.add( "docs", docs );
|
||||
}
|
||||
|
||||
if( stats ) {
|
||||
info.add( "stats", m.getStatistics() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Registry";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "$Revision: 501512 $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceId() {
|
||||
return "$Id: DumpRequestHandler.java 501512 2007-01-30 18:36:32Z yonik $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "$URL: http://svn.apache.org/repos/asf/lucene/solr/trunk/src/java/org/apache/solr/handler/DumpRequestHandler.java $";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* 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.solr.handler.admin;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.util.SimpleOrderedMap;
|
||||
|
||||
/**
|
||||
* @author ryan
|
||||
* @version $Id$
|
||||
* @since solr 1.2
|
||||
*/
|
||||
public class PropertiesRequestHandler extends RequestHandlerBase
|
||||
{
|
||||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException
|
||||
{
|
||||
SimpleOrderedMap<String> props = new SimpleOrderedMap<String>();
|
||||
String name = req.getParams().get( "name" );
|
||||
if( name != null ) {
|
||||
props.add( name, System.getProperty(name) );
|
||||
}
|
||||
else {
|
||||
java.util.Enumeration e = System.getProperties().propertyNames();
|
||||
while(e.hasMoreElements()) {
|
||||
String prop = (String)e.nextElement();
|
||||
props.add( prop, System.getProperty(prop) );
|
||||
}
|
||||
}
|
||||
rsp.add( "system.properties", props );
|
||||
}
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Get System Properties";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "$Revision: 501512 $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceId() {
|
||||
return "$Id: DumpRequestHandler.java 501512 2007-01-30 18:36:32Z yonik $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "$URL: http://svn.apache.org/repos/asf/lucene/solr/trunk/src/java/org/apache/solr/handler/DumpRequestHandler.java $";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,299 @@
|
|||
/**
|
||||
* 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.solr.handler.admin;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.lucene.LucenePackage;
|
||||
import org.apache.solr.core.Config;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
import org.apache.solr.handler.RequestHandlerUtils;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.util.NamedList;
|
||||
import org.apache.solr.util.SimpleOrderedMap;
|
||||
import org.apache.solr.util.XML;
|
||||
|
||||
|
||||
/**
|
||||
* This handler returns system info
|
||||
*
|
||||
* NOTE: the response format is still likely to change. It should be designed so
|
||||
* that it works nicely with an XSLT transformation. Untill we have a nice
|
||||
* XSLT frontend for /admin, the format is still open to change.
|
||||
*
|
||||
* @author ryan
|
||||
* @version $Id$
|
||||
* @since solr 1.2
|
||||
*/
|
||||
public class SystemInfoHandler extends RequestHandlerBase
|
||||
{
|
||||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception
|
||||
{
|
||||
RequestHandlerUtils.addExperimentalFormatWarning( rsp );
|
||||
|
||||
rsp.add( "core", getCoreInfo( req.getCore() ) );
|
||||
rsp.add( "lucene", getLuceneInfo() );
|
||||
rsp.add( "jvm", getJvmInfo() );
|
||||
rsp.add( "system", getSystemInfo() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get system info
|
||||
*/
|
||||
private static SimpleOrderedMap<Object> getCoreInfo( SolrCore core ) throws Exception
|
||||
{
|
||||
SimpleOrderedMap<Object> info = new SimpleOrderedMap<Object>();
|
||||
|
||||
IndexSchema schema = core.getSchema();
|
||||
info.add( "schema", schema != null ? schema.getName():"no schema!" );
|
||||
|
||||
// Host
|
||||
InetAddress addr = InetAddress.getLocalHost();
|
||||
info.add( "host", addr.getCanonicalHostName() );
|
||||
|
||||
// Now
|
||||
info.add( "now", new Date() );
|
||||
|
||||
// Start Time
|
||||
info.add( "start", new Date(core.getStartTime()) );
|
||||
|
||||
// Solr Home
|
||||
SimpleOrderedMap<Object> dirs = new SimpleOrderedMap<Object>();
|
||||
dirs.add( "instance", new File( Config.getInstanceDir() ).getAbsolutePath() );
|
||||
dirs.add( "data", new File( core.getDataDir() ).getAbsolutePath() );
|
||||
dirs.add( "index", new File( core.getIndexDir() ).getAbsolutePath() );
|
||||
info.add( "directory", dirs );
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get system info
|
||||
*/
|
||||
private static SimpleOrderedMap<Object> getSystemInfo() throws Exception
|
||||
{
|
||||
SimpleOrderedMap<Object> info = new SimpleOrderedMap<Object>();
|
||||
|
||||
OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
|
||||
info.add( "name", os.getName() );
|
||||
info.add( "version", os.getVersion() );
|
||||
info.add( "arch", os.getArch() );
|
||||
|
||||
// Java 1.6
|
||||
addGetterIfAvaliable( os, "systemLoadAverage", info );
|
||||
|
||||
// com.sun.management.UnixOperatingSystemMXBean
|
||||
addGetterIfAvaliable( os, "openFileDescriptorCount", info );
|
||||
addGetterIfAvaliable( os, "maxFileDescriptorCount", info );
|
||||
|
||||
// com.sun.management.OperatingSystemMXBean
|
||||
addGetterIfAvaliable( os, "committedVirtualMemorySize", info );
|
||||
addGetterIfAvaliable( os, "totalPhysicalMemorySize", info );
|
||||
addGetterIfAvaliable( os, "totalSwapSpaceSize", info );
|
||||
addGetterIfAvaliable( os, "processCpuTime", info );
|
||||
|
||||
try {
|
||||
if( !os.getName().toLowerCase().startsWith( "windows" ) ) {
|
||||
// Try some command line things
|
||||
info.add( "uname", execute( "uname -a" ) );
|
||||
info.add( "ulimit", execute( "ulimit -n" ) );
|
||||
info.add( "uptime", execute( "uptime" ) );
|
||||
}
|
||||
}
|
||||
catch( Throwable ex ) {} // ignore
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to run a getter function. This is usefull because java 1.6 has a few extra
|
||||
* usefull functions on the <code>OperatingSystemMXBean</code>
|
||||
*
|
||||
* If you are running a sun jvm, there are nice functions in:
|
||||
* UnixOperatingSystemMXBean and com.sun.management.OperatingSystemMXBean
|
||||
*
|
||||
* it is package protected so it can be tested...
|
||||
*/
|
||||
static void addGetterIfAvaliable( Object obj, String getter, NamedList<Object> info )
|
||||
{
|
||||
// This is a 1.6 functon, so lets do a little magic to *try* to make it work
|
||||
try {
|
||||
String n = Character.toUpperCase( getter.charAt(0) ) + getter.substring( 1 );
|
||||
Method m = obj.getClass().getMethod( "get" + n );
|
||||
Object v = m.invoke( obj, (Object[])null );
|
||||
if( v != null ) {
|
||||
info.add( getter, v );
|
||||
}
|
||||
}
|
||||
catch( Exception ex ) {} // don't worry, this only works for 1.6
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility function to execute a funciton
|
||||
*/
|
||||
private static String execute( String cmd )
|
||||
{
|
||||
DataInputStream in = null;
|
||||
BufferedReader reader = null;
|
||||
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(cmd);
|
||||
in = new DataInputStream( process.getInputStream() );
|
||||
return IOUtils.toString( in );
|
||||
}
|
||||
catch( Exception ex ) {
|
||||
ex.printStackTrace();
|
||||
return "(error executing: " + cmd + ")";
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly( reader );
|
||||
IOUtils.closeQuietly( in );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JVM Info - including memory info
|
||||
*/
|
||||
private static SimpleOrderedMap<Object> getJvmInfo()
|
||||
{
|
||||
SimpleOrderedMap<Object> jvm = new SimpleOrderedMap<Object>();
|
||||
jvm.add( "version", System.getProperty("java.vm.version") );
|
||||
jvm.add( "name", System.getProperty("java.vm.name") );
|
||||
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
jvm.add( "processors", runtime.availableProcessors() );
|
||||
|
||||
long used = runtime.totalMemory() - runtime.freeMemory();
|
||||
int percentUsed = (int)(((double)(used)/(double)runtime.maxMemory())*100);
|
||||
|
||||
|
||||
SimpleOrderedMap<Object> mem = new SimpleOrderedMap<Object>();
|
||||
mem.add( "free", FileUtils.byteCountToDisplaySize( runtime.freeMemory() ) );
|
||||
mem.add( "total", FileUtils.byteCountToDisplaySize( runtime.totalMemory() ) );
|
||||
mem.add( "max", FileUtils.byteCountToDisplaySize( runtime.maxMemory() ) );
|
||||
mem.add( "used", FileUtils.byteCountToDisplaySize( used ) + " (%"+percentUsed+")");
|
||||
jvm.add( "memory", mem );
|
||||
|
||||
// JMX properties -- probably should be moved to a different handler
|
||||
SimpleOrderedMap<Object> jmx = new SimpleOrderedMap<Object>();
|
||||
try{
|
||||
RuntimeMXBean mx = ManagementFactory.getRuntimeMXBean();
|
||||
jmx.add( "bootclasspath", mx.getBootClassPath());
|
||||
jmx.add( "classpath", mx.getClassPath() );
|
||||
|
||||
// the input arguments passed to the Java virtual machine
|
||||
// which does not include the arguments to the main method.
|
||||
jmx.add( "commandLineArgs", mx.getInputArguments());
|
||||
// a map of names and values of all system properties.
|
||||
//jmx.add( "SYSTEM PROPERTIES", mx.getSystemProperties());
|
||||
|
||||
jmx.add( "startTime", new Date(mx.getStartTime()));
|
||||
jmx.add( "upTimeMS", mx.getUptime() );
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
jvm.add( "jmx", jmx );
|
||||
return jvm;
|
||||
}
|
||||
|
||||
private static SimpleOrderedMap<Object> getLuceneInfo() throws Exception
|
||||
{
|
||||
SimpleOrderedMap<Object> info = new SimpleOrderedMap<Object>();
|
||||
|
||||
String solrImplVersion = "";
|
||||
String solrSpecVersion = "";
|
||||
String luceneImplVersion = "";
|
||||
String luceneSpecVersion = "";
|
||||
|
||||
// ---
|
||||
Package p = SolrCore.class.getPackage();
|
||||
StringWriter tmp = new StringWriter();
|
||||
solrImplVersion = p.getImplementationVersion();
|
||||
if (null != solrImplVersion) {
|
||||
XML.escapeCharData(solrImplVersion, tmp);
|
||||
solrImplVersion = tmp.toString();
|
||||
}
|
||||
tmp = new StringWriter();
|
||||
solrSpecVersion = p.getSpecificationVersion() ;
|
||||
if (null != solrSpecVersion) {
|
||||
XML.escapeCharData(solrSpecVersion, tmp);
|
||||
solrSpecVersion = tmp.toString();
|
||||
}
|
||||
|
||||
p = LucenePackage.class.getPackage();
|
||||
tmp = new StringWriter();
|
||||
luceneImplVersion = p.getImplementationVersion();
|
||||
if (null != luceneImplVersion) {
|
||||
XML.escapeCharData(luceneImplVersion, tmp);
|
||||
luceneImplVersion = tmp.toString();
|
||||
}
|
||||
tmp = new StringWriter();
|
||||
luceneSpecVersion = p.getSpecificationVersion() ;
|
||||
if (null != luceneSpecVersion) {
|
||||
XML.escapeCharData(luceneSpecVersion, tmp);
|
||||
luceneSpecVersion = tmp.toString();
|
||||
}
|
||||
|
||||
// Add it to the list
|
||||
info.add( "solr-spec-version", solrSpecVersion );
|
||||
info.add( "solr-impl-version", solrImplVersion );
|
||||
info.add( "lucene-spec-version", luceneSpecVersion );
|
||||
info.add( "lucene-impl-version", luceneImplVersion );
|
||||
return info;
|
||||
}
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Get System Info";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "$Revision: 501512 $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceId() {
|
||||
return "$Id: IndexInfoRequestHandler.java 487199 2006-12-14 13:03:40Z bdelacretaz $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "$URL: https://svn.apache.org/repos/asf/lucene/solr/trunk/src/java/org/apache/solr/request/IndexInfoRequestHandler.java $";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
* 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.solr.handler.admin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.lang.management.ThreadMXBean;
|
||||
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
import org.apache.solr.handler.RequestHandlerUtils;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.util.NamedList;
|
||||
import org.apache.solr.util.SimpleOrderedMap;
|
||||
|
||||
/**
|
||||
* Copied from "admin/threaddump.jsp"
|
||||
*
|
||||
* NOTE: the response format is still likely to change. It should be designed so
|
||||
* that it works nicely with an XSLT transformation. Untill we have a nice
|
||||
* XSLT frontend for /admin, the format is still open to change.
|
||||
*
|
||||
* @author ryan
|
||||
* @version $Id$
|
||||
* @since solr 1.2
|
||||
*/
|
||||
public class ThreadDumpHandler extends RequestHandlerBase
|
||||
{
|
||||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException
|
||||
{
|
||||
RequestHandlerUtils.addExperimentalFormatWarning( rsp );
|
||||
|
||||
SimpleOrderedMap<Object> system = new SimpleOrderedMap<Object>();
|
||||
rsp.add( "system", system );
|
||||
|
||||
ThreadMXBean tmbean = ManagementFactory.getThreadMXBean();
|
||||
|
||||
// Thread Count
|
||||
SimpleOrderedMap<Object> nl = new SimpleOrderedMap<Object>();
|
||||
nl.add( "current",tmbean.getThreadCount() );
|
||||
nl.add( "peak", tmbean.getPeakThreadCount() );
|
||||
nl.add( "daemon", tmbean.getDaemonThreadCount() );
|
||||
system.add( "threadCount", nl );
|
||||
|
||||
// Deadlocks
|
||||
ThreadInfo[] tinfos;
|
||||
long[] tids = tmbean.findMonitorDeadlockedThreads();
|
||||
if (tids != null) {
|
||||
tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
|
||||
NamedList<SimpleOrderedMap<Object>> lst = new NamedList<SimpleOrderedMap<Object>>();
|
||||
for (ThreadInfo ti : tinfos) {
|
||||
lst.add( "thread", getThreadInfo( ti, tmbean ) );
|
||||
}
|
||||
system.add( "deadlocks", lst );
|
||||
}
|
||||
|
||||
// Now show all the threads....
|
||||
tids = tmbean.getAllThreadIds();
|
||||
tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
|
||||
NamedList<SimpleOrderedMap<Object>> lst = new NamedList<SimpleOrderedMap<Object>>();
|
||||
for (ThreadInfo ti : tinfos) {
|
||||
lst.add( "thread", getThreadInfo( ti, tmbean ) );
|
||||
}
|
||||
system.add( "threadDump", lst );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
private static SimpleOrderedMap<Object> getThreadInfo( ThreadInfo ti, ThreadMXBean tmbean ) throws IOException
|
||||
{
|
||||
SimpleOrderedMap<Object> info = new SimpleOrderedMap<Object>();
|
||||
long tid = ti.getThreadId();
|
||||
|
||||
info.add( "id", tid );
|
||||
info.add( "name", ti.getThreadName() );
|
||||
info.add( "state", ti.getThreadState().toString() );
|
||||
|
||||
if (ti.getLockName() != null) {
|
||||
info.add( "lock", ti.getLockName() );
|
||||
}
|
||||
if (ti.isSuspended()) {
|
||||
info.add( "suspended", true );
|
||||
}
|
||||
if (ti.isInNative()) {
|
||||
info.add( "native", true );
|
||||
}
|
||||
|
||||
if (tmbean.isThreadCpuTimeSupported()) {
|
||||
info.add( "cpuTime", formatNanos(tmbean.getThreadCpuTime(tid)) );
|
||||
info.add( "userTime", formatNanos(tmbean.getThreadUserTime(tid)) );
|
||||
}
|
||||
|
||||
if (ti.getLockOwnerName() != null) {
|
||||
SimpleOrderedMap<Object> owner = new SimpleOrderedMap<Object>();
|
||||
owner.add( "name", ti.getLockOwnerName() );
|
||||
owner.add( "id", ti.getLockOwnerId() );
|
||||
}
|
||||
|
||||
// Add the stack trace
|
||||
int i=0;
|
||||
String[] trace = new String[ti.getStackTrace().length];
|
||||
for( StackTraceElement ste : ti.getStackTrace()) {
|
||||
trace[i++] = ste.toString();
|
||||
}
|
||||
info.add( "stackTrace", trace );
|
||||
return info;
|
||||
}
|
||||
|
||||
private static String formatNanos(long ns) {
|
||||
return String.format("%.4fms", ns / (double) 1000000);
|
||||
}
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Thread Dump";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "$Revision: 501512 $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceId() {
|
||||
return "$Id: DumpRequestHandler.java 501512 2007-01-30 18:36:32Z yonik $";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "$URL: http://svn.apache.org/repos/asf/lucene/solr/trunk/src/java/org/apache/solr/handler/DumpRequestHandler.java $";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 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.solr.handler.admin;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.solr.util.SimpleOrderedMap;
|
||||
|
||||
|
||||
public class SystemInfoHandlerTest extends TestCase {
|
||||
|
||||
public void testMagickGetter() {
|
||||
|
||||
OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
|
||||
|
||||
// make one directly
|
||||
SimpleOrderedMap<Object> info = new SimpleOrderedMap<Object>();
|
||||
info.add( "name", os.getName() );
|
||||
info.add( "version", os.getVersion() );
|
||||
info.add( "arch", os.getArch() );
|
||||
|
||||
// make another using addGetterIfAvaliable
|
||||
SimpleOrderedMap<Object> info2 = new SimpleOrderedMap<Object>();
|
||||
SystemInfoHandler.addGetterIfAvaliable( os, "name", info2 );
|
||||
SystemInfoHandler.addGetterIfAvaliable( os, "version", info2 );
|
||||
SystemInfoHandler.addGetterIfAvaliable( os, "arch", info2 );
|
||||
|
||||
// make sure they got the same thing
|
||||
assertEquals( info.toString(), info2.toString() );
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue