You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2016/11/29 17:06:18 UTC
[1/2] lucene-solr:feature/metrics: SOLR-4735 Improve Solr metric
reporting (Alan Woodward, Kelvin Wong, Christine Poerschke, Jeff Wartes, ab)
Repository: lucene-solr
Updated Branches:
refs/heads/feature/metrics 540a73a6f -> db1339ff6
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/licenses/metrics-json-LICENSE-ASL.txt
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-json-LICENSE-ASL.txt b/solr/licenses/metrics-json-LICENSE-ASL.txt
new file mode 100644
index 0000000..ccb320c
--- /dev/null
+++ b/solr/licenses/metrics-json-LICENSE-ASL.txt
@@ -0,0 +1,203 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2010-2012 Coda Hale and Yammer, Inc.
+
+ Licensed 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.
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/licenses/metrics-json-NOTICE.txt
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-json-NOTICE.txt b/solr/licenses/metrics-json-NOTICE.txt
new file mode 100644
index 0000000..b4c6298
--- /dev/null
+++ b/solr/licenses/metrics-json-NOTICE.txt
@@ -0,0 +1,12 @@
+Metrics
+Copyright 2010-2013 Coda Hale and Yammer, Inc.
+
+This product includes software developed by Coda Hale and Yammer, Inc.
+
+This product includes code derived from the JSR-166 project (ThreadLocalRandom, Striped64,
+LongAdder), which was released with the following comments:
+
+ Written by Doug Lea with assistance from members of JCP JSR-166
+ Expert Group and released to the public domain, as explained at
+ http://creativecommons.org/publicdomain/zero/1.0/
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/licenses/metrics-servlets-3.1.2.jar.sha1
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-servlets-3.1.2.jar.sha1 b/solr/licenses/metrics-servlets-3.1.2.jar.sha1
new file mode 100644
index 0000000..ba941e5
--- /dev/null
+++ b/solr/licenses/metrics-servlets-3.1.2.jar.sha1
@@ -0,0 +1 @@
+f552e662d790b805f01a8b2997dc4ae9409cd4c8
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/licenses/metrics-servlets-LICENSE-ASL.txt
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-servlets-LICENSE-ASL.txt b/solr/licenses/metrics-servlets-LICENSE-ASL.txt
new file mode 100644
index 0000000..ccb320c
--- /dev/null
+++ b/solr/licenses/metrics-servlets-LICENSE-ASL.txt
@@ -0,0 +1,203 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2010-2012 Coda Hale and Yammer, Inc.
+
+ Licensed 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.
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/licenses/metrics-servlets-NOTICE.txt
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-servlets-NOTICE.txt b/solr/licenses/metrics-servlets-NOTICE.txt
new file mode 100644
index 0000000..b4c6298
--- /dev/null
+++ b/solr/licenses/metrics-servlets-NOTICE.txt
@@ -0,0 +1,12 @@
+Metrics
+Copyright 2010-2013 Coda Hale and Yammer, Inc.
+
+This product includes software developed by Coda Hale and Yammer, Inc.
+
+This product includes code derived from the JSR-166 project (ThreadLocalRandom, Striped64,
+LongAdder), which was released with the following comments:
+
+ Written by Doug Lea with assistance from members of JCP JSR-166
+ Expert Group and released to the public domain, as explained at
+ http://creativecommons.org/publicdomain/zero/1.0/
+
[2/2] lucene-solr:feature/metrics: SOLR-4735 Improve Solr metric
reporting (Alan Woodward, Kelvin Wong, Christine Poerschke, Jeff Wartes, ab)
Posted by ab...@apache.org.
SOLR-4735 Improve Solr metric reporting (Alan Woodward, Kelvin Wong,
Christine Poerschke, Jeff Wartes, ab)
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/db1339ff
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/db1339ff
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/db1339ff
Branch: refs/heads/feature/metrics
Commit: db1339ff622cc73871897f8b345a9be19134a95e
Parents: 540a73a
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Tue Nov 29 18:02:04 2016 +0100
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Tue Nov 29 18:02:04 2016 +0100
----------------------------------------------------------------------
lucene/ivy-versions.properties | 2 +-
.../src/java/org/apache/solr/core/SolrCore.java | 40 +++
.../apache/solr/handler/RequestHandlerBase.java | 54 ++--
.../solr/metrics/SolrCoreMetricManager.java | 161 ++++++++++++
.../org/apache/solr/metrics/SolrMetricInfo.java | 104 ++++++++
.../apache/solr/metrics/SolrMetricManager.java | 198 +++++++++++++++
.../apache/solr/metrics/SolrMetricProducer.java | 37 +++
.../apache/solr/metrics/SolrMetricReporter.java | 66 +++++
.../org/apache/solr/metrics/package-info.java | 23 ++
.../solr/metrics/reporters/SolrJmxReporter.java | 254 +++++++++++++++++++
.../solr/metrics/reporters/package-info.java | 22 ++
.../src/java/org/apache/solr/util/JmxUtil.java | 93 +++++++
.../solr/metrics/SolrCoreMetricManagerTest.java | 151 +++++++++++
.../solr/metrics/SolrMetricReporterTest.java | 115 +++++++++
.../solr/metrics/SolrMetricTestUtils.java | 142 +++++++++++
.../metrics/reporters/SolrJmxReporterTest.java | 158 ++++++++++++
solr/licenses/metrics-jetty-LICENSE-ASL.txt | 203 +++++++++++++++
solr/licenses/metrics-jetty-NOTICE.txt | 12 +
solr/licenses/metrics-jetty9-3.1.2.jar.sha1 | 1 +
solr/licenses/metrics-json-3.1.2.jar.sha1 | 1 +
solr/licenses/metrics-json-LICENSE-ASL.txt | 203 +++++++++++++++
solr/licenses/metrics-json-NOTICE.txt | 12 +
solr/licenses/metrics-servlets-3.1.2.jar.sha1 | 1 +
solr/licenses/metrics-servlets-LICENSE-ASL.txt | 203 +++++++++++++++
solr/licenses/metrics-servlets-NOTICE.txt | 12 +
25 files changed, 2248 insertions(+), 20 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/lucene/ivy-versions.properties
----------------------------------------------------------------------
diff --git a/lucene/ivy-versions.properties b/lucene/ivy-versions.properties
index 4f07f09..1f3953d 100644
--- a/lucene/ivy-versions.properties
+++ b/lucene/ivy-versions.properties
@@ -77,8 +77,8 @@ io.dropwizard.metrics.version = 3.1.2
/io.dropwizard.metrics/metrics-core = ${io.dropwizard.metrics.version}
/io.dropwizard.metrics/metrics-healthchecks = ${io.dropwizard.metrics.version}
/io.dropwizard.metrics/metrics-jetty9 = ${io.dropwizard.metrics.version}
-/io.dropwizard.metrics/metrics-servlets = ${io.dropwizard.metrics.version}
/io.dropwizard.metrics/metrics-json = ${io.dropwizard.metrics.version}
+/io.dropwizard.metrics/metrics-servlets = ${io.dropwizard.metrics.version}
io.netty.netty-all.version = 4.0.36.Final
/io.netty/netty-all = ${io.netty.netty-all.version}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/core/SolrCore.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index e5bc53d..e2bf222 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -94,6 +94,8 @@ import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.handler.component.HighlightComponent;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.logging.MDCLoggingContext;
+import org.apache.solr.metrics.SolrCoreMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.BinaryResponseWriter;
@@ -188,6 +190,7 @@ public final class SolrCore implements SolrInfoMBean, Closeable {
private final PluginBag<SearchComponent> searchComponents = new PluginBag<>(SearchComponent.class, this);
private final PluginBag<UpdateRequestProcessorFactory> updateProcessors = new PluginBag<>(UpdateRequestProcessorFactory.class, this, true);
private final Map<String,UpdateRequestProcessorChain> updateProcessorChains;
+ private final SolrCoreMetricManager metricManager;
private final Map<String, SolrInfoMBean> infoRegistry;
private final IndexDeletionPolicyWrapper solrDelPolicy;
private final SolrSnapshotMetaDataManager snapshotMgr;
@@ -839,6 +842,9 @@ public final class SolrCore implements SolrInfoMBean, Closeable {
checkVersionFieldExistsInSchema(schema, coreDescriptor);
+ // Initialize the metrics manager
+ this.metricManager = initMetricManager(config);
+
// Initialize JMX
this.infoRegistry = initInfoRegistry(name, config);
infoRegistry.put("fieldCache", new SolrFieldCacheMBean());
@@ -1042,6 +1048,26 @@ public final class SolrCore implements SolrInfoMBean, Closeable {
setLatestSchema(schema);
}
+ /**
+ * Initializes the core's {@link SolrCoreMetricManager} with a given configuration.
+ * If metric reporters are configured, they are also registered with the manager.
+ *
+ * @param config the given configuration
+ * @return an instance of {@link SolrCoreMetricManager}
+ */
+ private SolrCoreMetricManager initMetricManager(SolrConfig config) {
+ SolrCoreMetricManager metricManager = new SolrCoreMetricManager(this);
+ for (PluginInfo pluginInfo : config.readPluginInfos("metricReporter", true, true)) {
+ try {
+ metricManager.loadReporter(pluginInfo);
+ } catch (IOException e) {
+ log.error("Failed to load reporter for plugin info = {}.", pluginInfo);
+ // TODO: shall we re-throw the exception here?
+ }
+ }
+ return metricManager;
+ }
+
private Map<String,SolrInfoMBean> initInfoRegistry(String name, SolrConfig config) {
if (config.jmxConfig.enabled) {
return new JmxMonitoredMap<String, SolrInfoMBean>(name, String.valueOf(this.hashCode()), config.jmxConfig);
@@ -1362,6 +1388,15 @@ public final class SolrCore implements SolrInfoMBean, Closeable {
}
}
+ try {
+ metricManager.close();
+ } catch (Throwable e) {
+ SolrException.log(log, e);
+ if (e instanceof Error) {
+ throw (Error) e;
+ }
+ }
+
// Close the snapshots meta-data directory.
Directory snapshotsDir = snapshotMgr.getSnapshotsDir();
try {
@@ -2752,6 +2787,11 @@ public final class SolrCore implements SolrInfoMBean, Closeable {
public void registerInfoBean(String name, SolrInfoMBean solrInfoMBean) {
infoRegistry.put(name, solrInfoMBean);
+
+ if (solrInfoMBean instanceof SolrMetricProducer) {
+ SolrMetricProducer producer = (SolrMetricProducer) solrInfoMBean;
+ metricManager.registerMetricProducer(name, producer);
+ }
}
private static boolean checkStale(SolrZkClient zkClient, String zkPath, int currentVersion) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
index 218b6de..2f00767 100644
--- a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
+++ b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
@@ -18,8 +18,11 @@ package org.apache.solr.handler;
import java.lang.invoke.MethodHandles;
import java.net.URL;
-import java.util.concurrent.atomic.LongAdder;
+import java.util.Arrays;
+import java.util.Collection;
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Meter;
import com.codahale.metrics.Timer;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
@@ -29,6 +32,8 @@ import org.apache.solr.common.util.SuppressForbidden;
import org.apache.solr.core.PluginBag;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.SolrQueryResponse;
@@ -43,7 +48,7 @@ import static org.apache.solr.core.RequestParams.USEPARAM;
/**
*
*/
-public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfoMBean, NestedRequestHandler {
+public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfoMBean, SolrMetricProducer, NestedRequestHandler {
protected NamedList initArgs = null;
protected SolrParams defaults;
@@ -52,11 +57,12 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
protected boolean httpCaching = true;
// Statistics
- private final LongAdder numRequests = new LongAdder();
- private final LongAdder numServerErrors = new LongAdder();
- private final LongAdder numClientErrors = new LongAdder();
- private final LongAdder numTimeouts = new LongAdder();
- private final Timer requestTimes = new Timer();
+ private Meter numErrors = new Meter();
+ private Meter numServerErrors = new Meter();
+ private Meter numClientErrors = new Meter();
+ private Meter numTimeouts = new Meter();
+ private Counter requests = new Counter();
+ private Timer requestTimes = new Timer();
private final long handlerStart;
@@ -126,6 +132,17 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
}
+ @Override
+ public Collection<String> initializeMetrics(String registryName, String scope) {
+ numErrors = SolrMetricManager.getOrCreateMeter(registryName, "errors", getCategory().toString(), scope);
+ numServerErrors = SolrMetricManager.getOrCreateMeter(registryName, "serverErrors", getCategory().toString(), scope);
+ numClientErrors = SolrMetricManager.getOrCreateMeter(registryName, "clientErrors", getCategory().toString(), scope);
+ numTimeouts = SolrMetricManager.getOrCreateMeter(registryName, "timeouts", getCategory().toString(), scope);
+ requests = SolrMetricManager.getOrCreateCounter(registryName, "requests", getCategory().toString(), scope);
+ requestTimes = SolrMetricManager.getOrCreateTimer(registryName, "requestTimes", getCategory().toString(), scope);
+ return Arrays.asList("errors", "serverErrors", "clientErrors", "timeouts", "requestTimes", "requests");
+ }
+
public static SolrParams getSolrParamsFromNamedList(NamedList args, String key) {
Object o = args.get(key);
if (o != null && o instanceof NamedList) {
@@ -142,7 +159,7 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
@Override
public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
- numRequests.increment();
+ requests.inc();
Timer.Context timer = requestTimes.time();
try {
if(pluginInfo != null && pluginInfo.attributes.containsKey(USEPARAM)) req.getContext().put(USEPARAM,pluginInfo.attributes.get(USEPARAM));
@@ -156,7 +173,7 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
Object partialResults = header.get(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY);
boolean timedOut = partialResults == null ? false : (Boolean)partialResults;
if( timedOut ) {
- numTimeouts.increment();
+ numTimeouts.mark();
rsp.setHttpCaching(false);
}
}
@@ -182,14 +199,14 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
if (incrementErrors) {
SolrException.log(log, e);
+ numErrors.mark();
if (isServerError) {
- numServerErrors.increment();
+ numServerErrors.mark();
} else {
- numClientErrors.increment();
+ numClientErrors.mark();
}
}
- }
- finally {
+ } finally {
timer.stop();
}
}
@@ -268,15 +285,14 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
public NamedList<Object> getStatistics() {
NamedList<Object> lst = new SimpleOrderedMap<>();
lst.add("handlerStart",handlerStart);
- lst.add("requests", numRequests.longValue());
- lst.add("errors", numServerErrors.longValue() + numClientErrors.longValue());
- lst.add("serverErrors", numServerErrors.longValue());
- lst.add("clientErrors", numClientErrors.longValue());
- lst.add("timeouts", numTimeouts.longValue());
+ lst.add("requests", requests.getCount());
+ lst.add("errors", numErrors.getCount());
+ lst.add("serverErrors", numServerErrors.getCount());
+ lst.add("clientErrors", numClientErrors.getCount());
+ lst.add("timeouts", numTimeouts.getCount());
TimerUtils.addMetrics(lst, requestTimes);
return lst;
}
-
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java b/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
new file mode 100644
index 0000000..d7322a3
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
@@ -0,0 +1,161 @@
+/*
+ * 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.metrics;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.lang.invoke.MethodHandles;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.SolrResourceLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Responsible for collecting metrics from {@link SolrMetricProducer}'s
+ * and exposing metrics to {@link SolrMetricReporter}'s.
+ */
+public class SolrCoreMetricManager implements Closeable {
+
+ public static final String REGISTRY_PREFIX = "core";
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private final SolrCore core;
+ private final String registryName;
+ private final ConcurrentHashMap<String, SolrMetricReporter> reporters;
+
+ /**
+ * Constructs a metric manager.
+ *
+ * @param core the metric manager's core
+ */
+ public SolrCoreMetricManager(SolrCore core) {
+ this.core = core;
+ this.registryName = MetricRegistry.name(REGISTRY_PREFIX, core.getName());
+ this.reporters = new ConcurrentHashMap<>();
+ }
+
+ /**
+ * Registers a mapping of name/metric's with the manager's metric registry.
+ * If a metric with the same metric name has already been registered, this method
+ * replaces the original metric with the new metric.
+ *
+ * @param scope the scope of the metrics to be registered (e.g. `/admin/ping`)
+ * @param producer producer of metrics to be registered
+ */
+ public void registerMetricProducer(String scope, SolrMetricProducer producer) {
+ if (scope == null || producer == null || producer.getCategory() == null) {
+ throw new IllegalArgumentException("registerMetricProducer() called with illegal arguments: " +
+ "scope = " + scope + ", producer = " + producer);
+ }
+ Collection<String> registered = producer.initializeMetrics(registryName, scope);
+ if (registered == null || registered.isEmpty()) {
+ throw new IllegalArgumentException("registerMetricProducer() did not register any metrics " +
+ "for scope = " + scope + ", producer = " + producer);
+ }
+ }
+
+ /**
+ * Loads a reporter and registers it to listen to the manager's metric registry.
+ * If a reporter with the same name has already been registered, this method
+ * closes the original reporter and registers the new reporter.
+ *
+ * @param pluginInfo the configuration of the reporter
+ * @throws IOException if the reporter could not be loaded
+ */
+ public void loadReporter(PluginInfo pluginInfo) throws IOException {
+ if (pluginInfo == null) {
+ throw new IllegalArgumentException("loadReporter called with null plugin info.");
+ }
+
+ SolrResourceLoader resourceLoader = core.getResourceLoader();
+ SolrMetricReporter reporter = resourceLoader.newInstance(
+ pluginInfo.className,
+ SolrMetricReporter.class,
+ new String[0],
+ new Class[] { String.class },
+ new Object[] { registryName }
+ );
+
+ try {
+ reporter.init(pluginInfo);
+ } catch (IllegalStateException e) {
+ throw new IllegalArgumentException("loadReporter called with invalid plugin info = " + pluginInfo);
+ }
+
+ SolrMetricReporter existing = reporters.putIfAbsent(pluginInfo.name, reporter);
+ if (existing != null) {
+ log.warn("{} has already been register; replacing existing reporter = {}.", pluginInfo.name, existing);
+ synchronized (reporters) {
+ reporters.get(pluginInfo.name).close(); // Get the existing reporter again in case it was replaced
+ reporters.put(pluginInfo.name, reporter); // Replace the existing reporter with the new one
+ }
+ }
+
+ log.info("{} is successfully registered.", pluginInfo.name);
+ }
+
+ /**
+ * Closes registered reporters.
+ */
+ @Override
+ public void close() throws IOException {
+ // Close reporters first to ensure no reporter is listening to the registry.
+ Iterator<Map.Entry<String, SolrMetricReporter>> it = reporters.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, SolrMetricReporter> entry = it.next();
+ entry.getValue().close();
+ it.remove();
+ }
+ }
+
+ /**
+ * Retrieves the solr core of the manager.
+ *
+ * @return the solr core of the manager.
+ */
+ public SolrCore getCore() {
+ return core;
+ }
+
+ /**
+ * Retrieves the metric registry name of the manager.
+ *
+ * @return the metric registry name of the manager.
+ */
+ public String getRegistryName() {
+ return registryName;
+ }
+
+ /**
+ * Retrieves all registered reporters and their names.
+ *
+ * @return all registered reporters and their names
+ */
+ public Map<String, SolrMetricReporter> getReporters() {
+ return Collections.unmodifiableMap(reporters);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/metrics/SolrMetricInfo.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricInfo.java b/solr/core/src/java/org/apache/solr/metrics/SolrMetricInfo.java
new file mode 100644
index 0000000..f0bc8a1
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricInfo.java
@@ -0,0 +1,104 @@
+/*
+ * 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.metrics;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.solr.core.SolrInfoMBean;
+
+/**
+ * Wraps meta-data for a metric.
+ */
+public final class SolrMetricInfo {
+ public final String name;
+ public final String scope;
+ public final SolrInfoMBean.Category category;
+
+ /**
+ * Creates a new instance of {@link SolrMetricInfo}.
+ *
+ * @param category the category of the metric (e.g. `QUERYHANDLERS`)
+ * @param scope the scope of the metric (e.g. `/admin/ping`)
+ * @param name the name of the metric (e.g. `Requests`)
+ */
+ public SolrMetricInfo(SolrInfoMBean.Category category, String scope, String name) {
+ this.name = name;
+ this.scope = scope;
+ this.category = category;
+ }
+
+ public static SolrMetricInfo of(String fullName) {
+ if (fullName == null || fullName.isEmpty()) {
+ return null;
+ }
+ String[] names = fullName.split("\\.");
+ if (names.length < 3) { // not a valid info
+ return null;
+ }
+ // check top-level name for valid category
+ SolrInfoMBean.Category category;
+ try {
+ category = SolrInfoMBean.Category.valueOf(names[0]);
+ } catch (IllegalArgumentException e) { // not a valid category
+ return null;
+ }
+ String scope = names[1];
+ String name = fullName.substring(names[0].length() + names[1].length() + 2);
+ return new SolrMetricInfo(category, scope, name);
+ }
+
+ /**
+ * Returns the metric name defined by this object.
+ * For example, if the name is `Requests`, scope is `/admin/ping`,
+ * and category is `QUERYHANDLERS`, then the metric name is
+ * `QUERYHANDLERS./admin/ping.Requests`.
+ *
+ * @return the metric name defined by this object
+ */
+ public String getMetricName() {
+ return MetricRegistry.name(category.toString(), scope, name);
+ }
+
+ @Override
+ public String toString() {
+ return "SolrMetricInfo{" +
+ "name='" + name + '\'' +
+ ", scope='" + scope + '\'' +
+ ", category=" + category +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ SolrMetricInfo that = (SolrMetricInfo) o;
+
+ if (name != null ? !name.equals(that.name) : that.name != null) return false;
+ if (scope != null ? !scope.equals(that.scope) : that.scope != null) return false;
+ return category == that.category;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (scope != null ? scope.hashCode() : 0);
+ result = 31 * result + (category != null ? category.hashCode() : 0);
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
new file mode 100644
index 0000000..872db18
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
@@ -0,0 +1,198 @@
+/*
+ * 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.metrics;
+
+import java.util.Set;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricFilter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.SharedMetricRegistries;
+import com.codahale.metrics.Snapshot;
+import com.codahale.metrics.Timer;
+import org.apache.solr.common.util.NamedList;
+
+/**
+ *
+ */
+public class SolrMetricManager {
+
+ public static final String REGISTRY_NAME_PREFIX = "solr";
+ public static final String DEFAULT_REGISTRY = MetricRegistry.name(REGISTRY_NAME_PREFIX, "default");
+
+ // don't create instances of this class
+ private SolrMetricManager() { }
+
+
+ /**
+ * Return a set of existing registry names.
+ */
+ public static Set<String> registryNames() {
+ return SharedMetricRegistries.names();
+ }
+
+ /**
+ * Get (or create if not present) a named registry
+ * @param registry name of the registry
+ * @return existing or newly created registry
+ */
+ public static MetricRegistry registryFor(String registry) {
+ return SharedMetricRegistries.getOrCreate(overridableRegistryName(registry));
+ }
+
+ /**
+ * Remove all metrics from a specified registry.
+ * @param registry registry name
+ */
+ public static void clearRegistryFor(String registry) {
+ SharedMetricRegistries.getOrCreate(overridableRegistryName(registry)).removeMatching(MetricFilter.ALL);
+ }
+
+ /**
+ * Remove a single specific metric from a named registry
+ * @param registry registry name
+ * @param metricName metric name, either final name or a fully-qualified name
+ * using dotted notation
+ * @param metricPath (optional) additional top-most metric name path elements
+ */
+ public static void clearMetric(String registry, String metricName, String... metricPath) {
+ SharedMetricRegistries.getOrCreate(overridableRegistryName(registry)).
+ remove(mkName(metricName, metricPath));
+ }
+
+ /**
+ * Create or get an existing named {@link Meter}
+ * @param registry registry name
+ * @param metricName metric name, either final name or a fully-qualified name
+ * using dotted notation
+ * @param metricPath (optional) additional top-most metric name path elements
+ * @return existing or a newly created {@link Meter}
+ */
+ public static Meter getOrCreateMeter(String registry, String metricName, String... metricPath) {
+ return SharedMetricRegistries.getOrCreate(overridableRegistryName(registry)).
+ meter(mkName(metricName, metricPath));
+ }
+
+ /**
+ * Create or get an existing named {@link Timer}
+ * @param registry registry name
+ * @param metricName metric name, either final name or a fully-qualified name
+ * using dotted notation
+ * @param metricPath (optional) additional top-most metric name path elements
+ * @return existing or a newly created {@link Timer}
+ */
+ public static Timer getOrCreateTimer(String registry, String metricName, String... metricPath) {
+ return SharedMetricRegistries.getOrCreate(overridableRegistryName(registry)).
+ timer(mkName(metricName, metricPath));
+ }
+
+ /**
+ * Create or get an existing named {@link Counter}
+ * @param registry registry name
+ * @param metricName metric name, either final name or a fully-qualified name
+ * using dotted notation
+ * @param metricPath (optional) additional top-most metric name path elements
+ * @return existing or a newly created {@link Counter}
+ */
+ public static Counter getOrCreateCounter(String registry, String metricName, String... metricPath) {
+ return SharedMetricRegistries.getOrCreate(overridableRegistryName(registry)).
+ counter(mkName(metricName, metricPath));
+ }
+
+ /**
+ * Create or get an existing named {@link Histogram}
+ * @param registry registry name
+ * @param metricName metric name, either final name or a fully-qualified name
+ * using dotted notation
+ * @param metricPath (optional) additional top-most metric name path elements
+ * @return existing or a newly created {@link Histogram}
+ */
+ public static Histogram getOrCreateHistogram(String registry, String metricName, String... metricPath) {
+ return SharedMetricRegistries.getOrCreate(overridableRegistryName(registry)).
+ histogram(mkName(metricName, metricPath));
+ }
+
+ /**
+ * This method creates a hierarchical name with arbitrary levels of hierarchy
+ * @param name the final segment of the name, must not be null or empty.
+ * @param path optional path segments, starting from the top level. Empty or null
+ * segments will be skipped.
+ * @return fully-qualified name using dotted notation, with all valid hierarchy
+ * segments prepended to the name.
+ */
+ public static String mkName(String name, String... path) {
+ if (name == null || name.isEmpty()) {
+ throw new IllegalArgumentException("name must not be empty");
+ }
+ if (path == null || path.length == 0) {
+ return name;
+ } else {
+ StringBuilder sb = new StringBuilder();
+ for (String s : path) {
+ if (s == null || s.isEmpty()) {
+ continue;
+ }
+ if (sb.length() > 0) {
+ sb.append('.');
+ }
+ sb.append(s);
+ }
+ if (sb.length() > 0) {
+ sb.append('.');
+ }
+ sb.append(name);
+ return sb.toString();
+ }
+ }
+
+ /**
+ * Allows named registries to be renamed using System properties.
+ * This would be mostly be useful if you want to combine the metrics from a few registries for a single
+ * reporter.
+ * @param registry The name of the registry
+ * @return A potentially overridden (via System properties) registry name
+ */
+ public static String overridableRegistryName(String registry) {
+ String fqRegistry = enforcePrefix(registry);
+ return enforcePrefix(System.getProperty(fqRegistry,fqRegistry));
+ }
+
+ /**
+ * Enforces the leading {@link #REGISTRY_NAME_PREFIX} in a name.
+ * @param name input name, possibly without the prefix
+ * @return original name if it contained the prefix, or the
+ * input name with the prefix prepended.
+ */
+ public static String enforcePrefix(String name) {
+ if (name.startsWith(REGISTRY_NAME_PREFIX))
+ return name;
+ else
+ return MetricRegistry.name(REGISTRY_NAME_PREFIX, name);
+ }
+
+ /**
+ * Timers return measurements as a double representing nanos.
+ * This converts that to a double representing millis.
+ * @param ns Nanoseconds
+ * @return Milliseconds
+ */
+ public static double nsToMs(double ns) {
+ return ns / 1000000; // Using TimeUnit involves casting to Long, so don't bother.
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java b/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
new file mode 100644
index 0000000..929e6a2
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
@@ -0,0 +1,37 @@
+/*
+ * 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.metrics;
+
+import java.util.Collection;
+
+import org.apache.solr.core.SolrInfoMBean;
+
+/**
+ * Extension of {@link SolrInfoMBean} for use by objects that
+ * expose metrics through {@link SolrCoreMetricManager}.
+ */
+public interface SolrMetricProducer extends SolrInfoMBean {
+
+ /**
+ * Initializes metrics specific to this producer
+ * @param registry registry name where metrics are registered
+ * @param scope scope of the metrics (eg. handler name) to separate metrics of
+ * instances of the same component executing in different contexts
+ * @return registered (or existing) unqualified names of metrics specific to this producer.
+ */
+ Collection<String> initializeMetrics(String registry, String scope);
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/metrics/SolrMetricReporter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricReporter.java b/solr/core/src/java/org/apache/solr/metrics/SolrMetricReporter.java
new file mode 100644
index 0000000..0adb7bf
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricReporter.java
@@ -0,0 +1,66 @@
+/*
+ * 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.metrics;
+
+import java.io.Closeable;
+import java.util.Locale;
+
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.util.SolrPluginUtils;
+import org.apache.solr.util.plugin.PluginInfoInitialized;
+
+/**
+ * Interface for 'pluggable' metric reporters.
+ */
+public abstract class SolrMetricReporter implements Closeable, PluginInfoInitialized {
+
+ protected final String registryName;
+
+ /**
+ * Create a reporter for metrics managed in a named registry.
+ * @param registryName registry to use, one of registries managed by
+ * {@link SolrMetricManager}
+ */
+ protected SolrMetricReporter(String registryName) {
+ this.registryName = registryName;
+ }
+ /**
+ * Initializes a {@link SolrMetricReporter} with the plugin's configuration.
+ *
+ * @param pluginInfo the plugin's configuration
+ */
+ @SuppressWarnings("unchecked")
+ public void init(PluginInfo pluginInfo) {
+ if (pluginInfo != null && pluginInfo.initArgs != null) {
+ SolrPluginUtils.invokeSetters(this, pluginInfo.initArgs);
+ }
+
+ validate();
+ }
+
+ /**
+ * Validates that the reporter has been correctly configured.
+ *
+ * @throws IllegalStateException if the reporter is not properly configured
+ */
+ protected abstract void validate() throws IllegalStateException;
+
+ @Override
+ public String toString() {
+ return String.format(Locale.ENGLISH, "[%s@%s]", getClass().getName(), Integer.toHexString(hashCode()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/metrics/package-info.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/package-info.java b/solr/core/src/java/org/apache/solr/metrics/package-info.java
new file mode 100644
index 0000000..a007b8b
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * The {@link org.apache.solr.metrics.SolrCoreMetricManager} is responsible for
+ * collecting metrics from {@link org.apache.solr.metrics.SolrMetricProducer}'s
+ * and exposing metrics to {@link org.apache.solr.metrics.SolrMetricReporter}'s.
+ */
+package org.apache.solr.metrics;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/metrics/reporters/SolrJmxReporter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/reporters/SolrJmxReporter.java b/solr/core/src/java/org/apache/solr/metrics/reporters/SolrJmxReporter.java
new file mode 100644
index 0000000..1bedc56
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/reporters/SolrJmxReporter.java
@@ -0,0 +1,254 @@
+/*
+ * 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.metrics.reporters;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.Hashtable;
+import java.util.Locale;
+
+import com.codahale.metrics.JmxReporter;
+import com.codahale.metrics.ObjectNameFactory;
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.metrics.SolrMetricInfo;
+import org.apache.solr.metrics.SolrCoreMetricManager;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricReporter;
+import org.apache.solr.util.JmxUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A {@link SolrMetricReporter} that finds (or creates) a MBeanServer from
+ * the given configuration and registers metrics to it with JMX.
+ */
+public class SolrJmxReporter extends SolrMetricReporter {
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private String domain;
+ private String agentId;
+ private String serviceUrl;
+
+ private JmxReporter reporter;
+ private MBeanServer mBeanServer;
+
+ /**
+ * Creates a new instance of {@link SolrJmxReporter}.
+ *
+ * @param registryName name of the registry to report
+ */
+ public SolrJmxReporter(String registryName) {
+ super(registryName);
+ this.domain = registryName;
+ }
+
+ /**
+ * Initializes the reporter by finding (or creating) a MBeanServer
+ * and registering the metricManager's metric registry.
+ *
+ * @param pluginInfo the configuration for the reporter
+ */
+ @Override
+ public synchronized void init(PluginInfo pluginInfo) {
+ super.init(pluginInfo);
+
+ if (serviceUrl != null && agentId != null) {
+ mBeanServer = JmxUtil.findFirstMBeanServer();
+ log.warn("No more than one of serviceUrl(%s) and agentId(%s) should be configured, using first MBeanServer instead of configuration.",
+ serviceUrl, agentId, mBeanServer);
+ }
+ else if (serviceUrl != null) {
+ try {
+ mBeanServer = JmxUtil.findMBeanServerForServiceUrl(serviceUrl);
+ } catch (IOException e) {
+ log.warn("findMBeanServerForServiceUrl(%s) exception: %s", serviceUrl, e);
+ mBeanServer = null;
+ }
+ }
+ else if (agentId != null) {
+ mBeanServer = JmxUtil.findMBeanServerForAgentId(agentId);
+ } else {
+ mBeanServer = JmxUtil.findFirstMBeanServer();
+ log.warn("No serviceUrl or agentId was configured, using first MBeanServer.", mBeanServer);
+ }
+
+ if (mBeanServer == null) {
+ log.warn("No JMX server found. Not exposing Solr metrics.");
+ return;
+ }
+
+ JmxObjectNameFactory jmxObjectNameFactory = new JmxObjectNameFactory(registryName);
+
+ reporter = JmxReporter.forRegistry(SolrMetricManager.registryFor(registryName))
+ .registerWith(mBeanServer)
+ .inDomain(domain)
+ .createsObjectNamesWith(jmxObjectNameFactory)
+ .build();
+ reporter.start();
+
+ log.info("JMX monitoring enabled at server: " + mBeanServer);
+ }
+
+ /**
+ * Stops the reporter from publishing metrics.
+ */
+ @Override
+ public synchronized void close() {
+ if (reporter != null) {
+ reporter.stop();
+ // TODO: stop() vs. close() // change or add comment re: why stop instead of close is called
+ // maybe TODO: reporter = null;
+ }
+ }
+
+ /**
+ * Validates that the reporter has been correctly configured.
+ * Note that all configurable arguments are currently optional.
+ *
+ * @throws IllegalStateException if the reporter is not properly configured
+ */
+ @Override
+ protected void validate() throws IllegalStateException {
+ // Nothing to validate
+ }
+
+ /**
+ * Sets the domain with which MBeans are published. If none is set,
+ * the domain defaults to the name of the core.
+ *
+ * @param domain the domain
+ */
+ public void setDomain(String domain) {
+ if (domain != null) {
+ this.domain = domain;
+ } else {
+ this.domain = registryName;
+ }
+ }
+
+ /**
+ * Sets the service url for a JMX server.
+ * Note that this configuration is optional.
+ *
+ * @param serviceUrl the service url
+ */
+ public void setServiceUrl(String serviceUrl) {
+ this.serviceUrl = serviceUrl;
+ }
+
+ /**
+ * Sets the agent id for a JMX server.
+ * Note that this configuration is optional.
+ *
+ * @param agentId the agent id
+ */
+ public void setAgentId(String agentId) {
+ this.agentId = agentId;
+ }
+
+ /**
+ * Retrieves the reporter's MBeanServer.
+ *
+ * @return the reporter's MBeanServer
+ */
+ public MBeanServer getMBeanServer() {
+ return mBeanServer;
+ }
+
+ @Override
+ public String toString() {
+ return String.format(Locale.ENGLISH, "[%s@%s: domain = %s, service url = %s, agent id = %s]",
+ getClass().getName(), Integer.toHexString(hashCode()), domain, serviceUrl, agentId);
+ }
+
+ /**
+ * Factory to create MBean names for a given metric.
+ */
+ private static class JmxObjectNameFactory implements ObjectNameFactory {
+
+ private final String registryName;
+
+ JmxObjectNameFactory(String registryName) {
+ this.registryName = registryName;
+ }
+
+ /**
+ * TODO description
+ *
+ * @param type TODO description, example
+ * @param domain TODO description, example
+ * @param name TODO description, example
+ */
+ @Override
+ public ObjectName createName(String type, String domain, String name) {
+ SolrMetricInfo metricInfo = SolrMetricInfo.of(name);
+
+ // It turns out that ObjectName(String) mostly preserves key ordering
+ // as specified in the constructor (except for the 'type' key that ends
+ // up at top level) - unlike ObjectName(String, Map) constructor
+ // that seems to have a mind of its own...
+ StringBuilder sb = new StringBuilder(domain);
+ sb.append(':');
+ if (metricInfo != null) {
+ sb.append("category=");
+ sb.append(metricInfo.category.toString());
+ sb.append(",scope=");
+ sb.append(metricInfo.scope);
+ // split by type, but don't call it 'type' :)
+ sb.append(",class=");
+ sb.append(type);
+ sb.append(",name=");
+ sb.append(metricInfo.name);
+ } else {
+ // make dotted names into hierarchies
+ String[] path = name.split("\\.");
+ for (int i = 0; i < path.length - 1; i++) {
+ if (i > 0) {
+ sb.append(',');
+ }
+ sb.append("name"); sb.append(String.valueOf(i));
+ sb.append('=');
+ sb.append(path[i]);
+ }
+ if (path.length > 1) {
+ sb.append(',');
+ }
+ // split by type
+ sb.append("class=");
+ sb.append(type);
+ sb.append(",name=");
+ sb.append(path[path.length - 1]);
+ }
+
+ ObjectName objectName;
+
+ try {
+ objectName = new ObjectName(sb.toString());
+ } catch (MalformedObjectNameException e) {
+ throw new RuntimeException(e);
+ }
+
+ return objectName;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/metrics/reporters/package-info.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/reporters/package-info.java b/solr/core/src/java/org/apache/solr/metrics/reporters/package-info.java
new file mode 100644
index 0000000..5ad7a80
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/reporters/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/**
+ * This package houses 'pluggable' metric reporters that
+ * inherit from the {@link org.apache.solr.metrics.SolrMetricReporter} class.
+ */
+package org.apache.solr.metrics.reporters;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/java/org/apache/solr/util/JmxUtil.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/JmxUtil.java b/solr/core/src/java/org/apache/solr/util/JmxUtil.java
new file mode 100644
index 0000000..2224022
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/util/JmxUtil.java
@@ -0,0 +1,93 @@
+/*
+ * 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.util;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.List;
+
+/**
+ * Utility methods to find a MBeanServer.
+ *
+ * This was factored out from {@link org.apache.solr.core.JmxMonitoredMap}
+ * and can eventually replace the logic used there.
+ */
+public final class JmxUtil {
+
+ /**
+ * Retrieve the first MBeanServer found.
+ *
+ * @return the first MBeanServer found
+ */
+ public static MBeanServer findFirstMBeanServer() {
+ // TODO: does findMBeanServerForAgentId need the getPlatformMBeanServer call also?
+ // TODO: can findFirstMBeanServer be implemented as findMBeanServerForAgentId(null)?
+ // Ensure we have at least one MBeanServer available
+ MBeanServer platformServer = ManagementFactory.getPlatformMBeanServer();
+
+ List<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
+ if (servers == null || servers.isEmpty()) {
+ return null;
+ }
+
+ return servers.get(0);
+ }
+
+ /**
+ * Find a MBeanServer given a service url.
+ *
+ * @param serviceUrl the service url
+ * @return a MBeanServer
+ */
+ public static MBeanServer findMBeanServerForServiceUrl(String serviceUrl) throws IOException {
+ if (serviceUrl == null) {
+ return null;
+ }
+
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+ JMXConnectorServer connector = JMXConnectorServerFactory
+ .newJMXConnectorServer(new JMXServiceURL(serviceUrl), null, server);
+ connector.start();
+
+ return server;
+ }
+
+ /**
+ * Find a MBeanServer given an agent id.
+ *
+ * @param agentId the agent id
+ * @return a MBeanServer
+ */
+ public static MBeanServer findMBeanServerForAgentId(String agentId) {
+ if (agentId == null) {
+ return null;
+ }
+
+ List<MBeanServer> servers = MBeanServerFactory.findMBeanServer(agentId);
+ if (servers == null || servers.isEmpty()) {
+ return null;
+ }
+
+ return servers.get(0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java
new file mode 100644
index 0000000..d046916
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.metrics;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.stream.Collectors;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Metric;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.lucene.util.TestUtil;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.metrics.reporters.SolrJmxReporter;
+import org.apache.solr.schema.FieldType;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SolrCoreMetricManagerTest extends SolrTestCaseJ4 {
+ private static final int MAX_ITERATIONS = 100;
+
+ private SolrCoreMetricManager metricManager;
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ initCore("solrconfig-basic.xml", "schema.xml");
+ }
+
+ @Before
+ public void beforeTest() {
+ metricManager = new SolrCoreMetricManager(h.getCore());
+ }
+
+ @After
+ public void afterTest() throws IOException {
+ metricManager.close();
+ assertTrue(metricManager.getReporters().isEmpty());
+ }
+
+ @Test
+ public void testRegisterMetrics() {
+ Random random = random();
+
+ String scope = SolrMetricTestUtils.getRandomScope(random);
+ SolrInfoMBean.Category category = SolrMetricTestUtils.getRandomCategory(random);
+ Map<String, Counter> metrics = SolrMetricTestUtils.getRandomMetrics(random);
+ SolrMetricProducer producer = SolrMetricTestUtils.getProducerOf(category, scope, metrics);
+ try {
+ metricManager.registerMetricProducer(scope, producer);
+ assertNotNull(scope);
+ assertNotNull(category);
+ assertNotNull(metrics);
+ assertRegistered(scope, metrics, metricManager);
+ } catch (final IllegalArgumentException e) {
+ assertTrue("expected at least one null but got: scope="+scope+" category="+category+" metrics="+metrics,
+ (scope == null || category == null || metrics == null));
+ assertRegistered(scope, new HashMap<>(), metricManager);
+ }
+ }
+
+ @Test
+ public void testRegisterMetricsWithReplacements() {
+ Random random = random();
+
+ Map<String, Counter> registered = new HashMap<>();
+ String scope = SolrMetricTestUtils.getRandomScope(random, true);
+ SolrInfoMBean.Category category = SolrMetricTestUtils.getRandomCategory(random, true);
+
+ int iterations = TestUtil.nextInt(random, 0, MAX_ITERATIONS);
+ for (int i = 0; i < iterations; ++i) {
+ Map<String, Counter> metrics = SolrMetricTestUtils.getRandomMetricsWithReplacements(random, registered);
+ if (metrics.isEmpty()) {
+ continue;
+ }
+ SolrMetricProducer producer = SolrMetricTestUtils.getProducerOf(category, scope, metrics);
+ metricManager.registerMetricProducer(scope, producer);
+ registered.putAll(metrics);
+ assertRegistered(scope, registered, metricManager);
+ }
+ }
+
+ @Test
+ public void testLoadReporter() throws Exception {
+ Random random = random();
+
+ String className = SolrJmxReporter.class.getName();
+ String reporterName = TestUtil.randomUnicodeString(random);
+
+ Map<String, Object> attrs = new HashMap<>();
+ attrs.put(FieldType.CLASS_NAME, className);
+ attrs.put(CoreAdminParams.NAME, reporterName);
+
+ boolean shouldDefinePlugin = random.nextBoolean();
+ PluginInfo pluginInfo = shouldDefinePlugin ? new PluginInfo(TestUtil.randomUnicodeString(random), attrs) : null;
+
+ try {
+ metricManager.loadReporter(pluginInfo);
+ assertNotNull(pluginInfo);
+ assertEquals(1, metricManager.getReporters().size());
+ assertNotNull(metricManager.getReporters().get(reporterName));
+ assertTrue(metricManager.getReporters().get(reporterName) instanceof SolrJmxReporter);
+ } catch (IllegalArgumentException e) {
+ assertNull(pluginInfo);
+ assertTrue(metricManager.getReporters().isEmpty());
+ }
+ }
+
+ private static void assertRegistered(String scope, Map<String, Counter> newMetrics, SolrCoreMetricManager metricManager) {
+ if (scope == null) {
+ return;
+ }
+ String filter = "." + scope + ".";
+ MetricRegistry registry = SolrMetricManager.registryFor(metricManager.getRegistryName());
+ assertEquals(newMetrics.size(), registry.getMetrics().
+ keySet().stream().filter(s -> s.contains(filter)).count());
+
+ Map<String, Metric> registeredMetrics = registry.getMetrics().
+ entrySet().stream().filter(e -> e.getKey() != null && e.getKey().contains(filter)).
+ collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
+ for (Map.Entry<String, Metric> entry : registeredMetrics.entrySet()) {
+ String name = entry.getKey();
+ Metric expectedMetric = entry.getValue();
+
+ Metric actualMetric = registry.getMetrics().get(name);
+
+ assertNotNull(actualMetric);
+ assertEquals(expectedMetric, actualMetric);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/test/org/apache/solr/metrics/SolrMetricReporterTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricReporterTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricReporterTest.java
new file mode 100644
index 0000000..76344c4
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricReporterTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.metrics;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+import org.apache.lucene.util.TestUtil;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.schema.FieldType;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SolrMetricReporterTest extends SolrTestCaseJ4 {
+
+ private SolrCoreMetricManager metricManager;
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ initCore("solrconfig-basic.xml", "schema.xml");
+ }
+
+ @Before
+ public void beforeTest() {
+ metricManager = new SolrCoreMetricManager(h.getCore());
+ }
+
+ @After
+ public void afterTest() throws Exception {
+ metricManager.close();
+ }
+
+ @Test
+ public void testInit() throws Exception {
+ Random random = random();
+
+ MockReporter reporter = new MockReporter(h.getCore().getName());
+
+ Map<String, Object> attrs = new HashMap<>();
+ attrs.put(FieldType.CLASS_NAME, MockReporter.class.getName());
+ attrs.put(CoreAdminParams.NAME, TestUtil.randomUnicodeString(random));
+
+ boolean shouldDefineConfigurable = random.nextBoolean();
+ String configurable = TestUtil.randomUnicodeString(random);
+ if (shouldDefineConfigurable) attrs.put("configurable", configurable);
+
+ boolean shouldDefinePlugin = random.nextBoolean();
+ String type = TestUtil.randomUnicodeString(random);
+ PluginInfo pluginInfo = shouldDefinePlugin ? new PluginInfo(type, attrs) : null;
+
+ try {
+ reporter.init(pluginInfo);
+ assertTrue(reporter.didValidate);
+ assertNotNull(reporter.configurable);
+ assertEquals(configurable, reporter.configurable);
+ assertTrue(pluginInfo != null && attrs.get("configurable") == configurable);
+ } catch (IllegalStateException e) {
+ assertTrue(reporter.didValidate);
+ assertNull(reporter.configurable);
+ assertTrue(pluginInfo == null || attrs.get("configurable") == null);
+ } finally {
+ reporter.close();
+ }
+ }
+
+ public static class MockReporter extends SolrMetricReporter {
+ String configurable;
+ boolean didValidate = false;
+
+ MockReporter(String registryName) {
+ super(registryName);
+ }
+
+ @Override
+ public void init(PluginInfo pluginInfo) {
+ super.init(pluginInfo);
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+
+ @Override
+ protected void validate() throws IllegalStateException {
+ didValidate = true;
+ if (configurable == null) {
+ throw new IllegalStateException("MockReporter::configurable not configured.");
+ }
+ }
+
+ public void setConfigurable(String configurable) {
+ this.configurable = configurable;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/test/org/apache/solr/metrics/SolrMetricTestUtils.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricTestUtils.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricTestUtils.java
new file mode 100644
index 0000000..7f69461
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricTestUtils.java
@@ -0,0 +1,142 @@
+/*
+ * 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.metrics;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Metric;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.lucene.util.TestUtil;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrInfoMBean;
+
+public final class SolrMetricTestUtils {
+
+ private static final int MAX_ITERATIONS = 100;
+ private static final SolrInfoMBean.Category CATEGORIES[] = SolrInfoMBean.Category.values();
+
+ public static String getRandomScope(Random random) {
+ return getRandomScope(random, random.nextBoolean());
+ }
+
+ public static String getRandomScope(Random random, boolean shouldDefineScope) {
+ return shouldDefineScope ? TestUtil.randomSimpleString(random, 1, 10) : null; // must be simple string for JMX publishing
+ }
+
+ public static SolrInfoMBean.Category getRandomCategory(Random random) {
+ return getRandomCategory(random, random.nextBoolean());
+ }
+
+ public static SolrInfoMBean.Category getRandomCategory(Random random, boolean shouldDefineCategory) {
+ return shouldDefineCategory ? CATEGORIES[TestUtil.nextInt(random, 0, CATEGORIES.length - 1)] : null;
+ }
+
+ public static Map<String, Counter> getRandomMetrics(Random random) {
+ return getRandomMetrics(random, random.nextBoolean());
+ }
+
+ public static Map<String, Counter> getRandomMetrics(Random random, boolean shouldDefineMetrics) {
+ return shouldDefineMetrics ? getRandomMetricsWithReplacements(random, new HashMap<>()) : null;
+ }
+
+ public static final String SUFFIX = "_testing";
+
+ public static Map<String, Counter> getRandomMetricsWithReplacements(Random random, Map<String, Counter> existing) {
+ HashMap<String, Counter> metrics = new HashMap<>();
+ ArrayList<String> existingKeys = new ArrayList<>(existing.keySet());
+
+ int numMetrics = TestUtil.nextInt(random, 1, MAX_ITERATIONS);
+ for (int i = 0; i < numMetrics; ++i) {
+ boolean shouldReplaceMetric = !existing.isEmpty() && random.nextBoolean();
+ String name = shouldReplaceMetric
+ ? existingKeys.get(TestUtil.nextInt(random, 0, existingKeys.size() - 1))
+ : TestUtil.randomSimpleString(random, 1, 10) + SUFFIX; // must be simple string for JMX publishing
+
+ Counter counter = new Counter();
+ counter.inc(random.nextLong());
+ metrics.put(name, counter);
+ }
+
+ return metrics;
+ }
+
+ public static SolrMetricProducer getProducerOf(SolrInfoMBean.Category category, String scope, Map<String, Counter> metrics) {
+ return new SolrMetricProducer() {
+ @Override
+ public Collection<String> initializeMetrics(String registry, String scope) {
+ if (metrics == null || metrics.isEmpty()) {
+ return Collections.emptyList();
+ }
+ for (Map.Entry<String, Counter> entry : metrics.entrySet()) {
+ SolrMetricManager.getOrCreateCounter(registry, entry.getKey(), category.toString(), scope);
+ }
+ return metrics.keySet();
+ }
+
+ @Override
+ public String getName() {
+ return scope;
+ }
+
+ @Override
+ public String getVersion() {
+ return "0.0";
+ }
+
+ @Override
+ public String getDescription() {
+ return "foo";
+ }
+
+ @Override
+ public Category getCategory() {
+ return category;
+ }
+
+ @Override
+ public String getSource() {
+ return null;
+ }
+
+ @Override
+ public URL[] getDocs() {
+ return new URL[0];
+ }
+
+ @Override
+ public NamedList getStatistics() {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "SolrMetricProducer.of{" +
+ "\ncategory=" + category +
+ "\nscope=" + scope +
+ "\nmetrics=" + metrics +
+ "\n}";
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/core/src/test/org/apache/solr/metrics/reporters/SolrJmxReporterTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrJmxReporterTest.java b/solr/core/src/test/org/apache/solr/metrics/reporters/SolrJmxReporterTest.java
new file mode 100644
index 0000000..23d15ed
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/metrics/reporters/SolrJmxReporterTest.java
@@ -0,0 +1,158 @@
+/*
+ * 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.metrics.reporters;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+import java.lang.management.ManagementFactory;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Metric;
+import com.codahale.metrics.MetricRegistryListener;
+import org.apache.lucene.util.TestUtil;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.metrics.SolrCoreMetricManager;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
+import org.apache.solr.metrics.SolrMetricTestUtils;
+import org.apache.solr.schema.FieldType;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SolrJmxReporterTest extends SolrTestCaseJ4 {
+
+ private static final int MAX_ITERATIONS = 20;
+
+ private String domain;
+
+ private SolrCoreMetricManager metricManager;
+ private SolrJmxReporter reporter;
+ private MBeanServer mBeanServer;
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ initCore("solrconfig-basic.xml", "schema.xml");
+ }
+
+ @Before
+ public void beforeTest() throws Exception {
+ // Ensure we have at least one MBeanServer available
+ MBeanServer platformServer = ManagementFactory.getPlatformMBeanServer();
+ // TODO: can we skip this call? either always or randomly?
+
+ Random random = random();
+
+ final SolrCore core = h.getCore();
+ domain = core.getName();
+
+ String className = SolrJmxReporter.class.getName();
+ String reporterName = TestUtil.randomUnicodeString(random);
+
+ Map<String, Object> attrs = new HashMap<>();
+ attrs.put(FieldType.CLASS_NAME, className);
+ attrs.put(CoreAdminParams.NAME, reporterName);
+
+ boolean shouldOverrideDomain = random.nextBoolean();
+ if (shouldOverrideDomain) {
+ domain = TestUtil.randomSimpleString(random);
+ attrs.put("domain", domain);
+ }
+
+ PluginInfo pluginInfo = new PluginInfo(TestUtil.randomUnicodeString(random), attrs);
+ metricManager = new SolrCoreMetricManager(core);
+ metricManager.loadReporter(pluginInfo);
+
+ assertEquals(1, metricManager.getReporters().size());
+ assertNotNull(metricManager.getReporters().get(reporterName));
+ assertTrue(metricManager.getReporters().get(reporterName) instanceof SolrJmxReporter);
+
+ reporter = (SolrJmxReporter) metricManager.getReporters().get(reporterName);
+ mBeanServer = reporter.getMBeanServer();
+ assertNotNull("MBean server not found.", mBeanServer);
+ }
+
+ @After
+ public void afterTest() throws Exception {
+ reporter.close();
+ Set<ObjectInstance> objects =
+ mBeanServer.queryMBeans(ObjectName.getInstance(domain + ":*"), null);
+ assertTrue(objects.isEmpty());
+
+ metricManager.close();
+ }
+
+ @Test
+ public void testReportMetrics() throws Exception {
+ Random random = random();
+
+ Map<String, Counter> registered = new HashMap<>();
+ String scope = SolrMetricTestUtils.getRandomScope(random, true);
+ SolrInfoMBean.Category category = SolrMetricTestUtils.getRandomCategory(random, true);
+
+ int iterations = TestUtil.nextInt(random, 0, MAX_ITERATIONS);
+ for (int i = 0; i < iterations; ++i) {
+ Map<String, Counter> metrics = SolrMetricTestUtils.getRandomMetricsWithReplacements(random, registered);
+ SolrMetricProducer producer = SolrMetricTestUtils.getProducerOf(category, scope, metrics);
+ metricManager.registerMetricProducer(scope, producer);
+ registered.putAll(metrics);
+ //waitForListener();
+ Set<ObjectInstance> objects = mBeanServer.queryMBeans(null, null);
+ assertEquals(registered.size(), objects.stream().
+ filter(o -> o.getObjectName().getKeyProperty("scope") != null &&
+ o.getObjectName().getKeyProperty("scope").equals(scope)).count());
+ }
+ }
+
+ @Test
+ public void testReloadCore() throws Exception {
+ Random random = random();
+
+ String scope = SolrMetricTestUtils.getRandomScope(random, true);
+ SolrInfoMBean.Category category = SolrMetricTestUtils.getRandomCategory(random, true);
+ Map<String, Counter> metrics = SolrMetricTestUtils.getRandomMetrics(random, true);
+ SolrMetricProducer producer = SolrMetricTestUtils.getProducerOf(category, scope, metrics);
+ metricManager.registerMetricProducer(scope, producer);
+ //waitForListener();
+
+ Set<ObjectInstance> objects = mBeanServer.queryMBeans(null, null);
+ assertEquals(metrics.size(), objects.stream().
+ filter(o -> o.getObjectName().getKeyProperty("scope") != null &&
+ o.getObjectName().getKeyProperty("scope").equals(scope)).count());
+
+ h.getCoreContainer().reload(h.getCore().getName());
+ metricManager.registerMetricProducer(scope, producer);
+
+ objects = mBeanServer.queryMBeans(null, null);
+ assertEquals(metrics.size(), objects.stream().
+ filter(o -> o.getObjectName().getKeyProperty("scope") != null &&
+ o.getObjectName().getKeyProperty("scope").equals(scope)).count());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/licenses/metrics-jetty-LICENSE-ASL.txt
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-jetty-LICENSE-ASL.txt b/solr/licenses/metrics-jetty-LICENSE-ASL.txt
new file mode 100644
index 0000000..ccb320c
--- /dev/null
+++ b/solr/licenses/metrics-jetty-LICENSE-ASL.txt
@@ -0,0 +1,203 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2010-2012 Coda Hale and Yammer, Inc.
+
+ Licensed 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.
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/licenses/metrics-jetty-NOTICE.txt
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-jetty-NOTICE.txt b/solr/licenses/metrics-jetty-NOTICE.txt
new file mode 100644
index 0000000..b4c6298
--- /dev/null
+++ b/solr/licenses/metrics-jetty-NOTICE.txt
@@ -0,0 +1,12 @@
+Metrics
+Copyright 2010-2013 Coda Hale and Yammer, Inc.
+
+This product includes software developed by Coda Hale and Yammer, Inc.
+
+This product includes code derived from the JSR-166 project (ThreadLocalRandom, Striped64,
+LongAdder), which was released with the following comments:
+
+ Written by Doug Lea with assistance from members of JCP JSR-166
+ Expert Group and released to the public domain, as explained at
+ http://creativecommons.org/publicdomain/zero/1.0/
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/licenses/metrics-jetty9-3.1.2.jar.sha1
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-jetty9-3.1.2.jar.sha1 b/solr/licenses/metrics-jetty9-3.1.2.jar.sha1
new file mode 100644
index 0000000..0722b0b
--- /dev/null
+++ b/solr/licenses/metrics-jetty9-3.1.2.jar.sha1
@@ -0,0 +1 @@
+7f2fe1039424ca687bea5d09ec0bfa372bf7d062
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/db1339ff/solr/licenses/metrics-json-3.1.2.jar.sha1
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-json-3.1.2.jar.sha1 b/solr/licenses/metrics-json-3.1.2.jar.sha1
new file mode 100644
index 0000000..93168e9
--- /dev/null
+++ b/solr/licenses/metrics-json-3.1.2.jar.sha1
@@ -0,0 +1 @@
+88d9e57e1ef6431109d4030c717cf5f927900fd9