54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Solr Datasource for Grafana
2 | ===========================
3 |
4 | This plugin for [Grafana](http://grafana.org) provides an advanced datasource for querying Solr server >= 4. This datasource also provides support for the Solr version bundled with [Cloudera CDH 5.X](https://www.cloudera.com).
5 |
6 | This project is open source pursuant to the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).
7 | It is copyright (C) 2018 by PUE Team.
8 |
9 | Installation
10 | ------------
11 |
12 | The easiest way to install this plugin is to clone or unzip this repository on the grafana plugins folder. For example:
13 |
14 | ```bash
15 | cd /var/lib/grafana/plugins
16 | git clone https://github.com/pueteam/datasource-plugin-solr
17 | ```
18 |
19 | Then restart grafana to reload the plugins folder.
20 |
21 | Configuration
22 | -------------
23 |
24 | 1. Add a new datasource and choose "Solr" as the type.
25 |
26 | 2. Fill in the "Url" and other server parameters. If you run Solr in a kerberized cluster, you'll need LDAP authentication enabled, and provide the credentials here.
27 |
28 | 3. Optionally, add the collection to use. This is required if you plan to use templates.
29 |
30 | 4. Click "Test Connection" to verify that you entered the information correctly.
31 |
32 | 5. Cick "Save".
33 |
34 | Queries
35 | -------
36 |
37 | First, select the query type. You can choose between `standard` and `group`. The `standard` query is the default.
38 |
39 | - **Standard Queries**: The `standard` queries will execute regular queries against Solr. You'll need to fill the `Collection`, the `Timestamp` field, the `Fields` list (space or comma separated) and the `Query` in the Solr format `*:*`.
40 |
41 | - **Group Queries**: The `group` type allows you to group results by `Group By Field` parameter. You'll also need to fill the `Group Value Field` and this parameter should be **numeric**. You can also limit the `Max Group Rows` results.
42 |
43 | Template Support
44 | ----------------
45 |
46 | This plugin supports Templates/Variables to be used, for example, in the `Query` parameter. You'll need to specify the `Collection` parameter in the `Datasource` parameters.
47 |
48 | ```bash
49 | CR:$CR AND city:$city
50 | ```
51 |
52 | Autocompletion Support
53 | ----------------------
54 |
55 | This plugin supports auto completion for the Query Parameters.
56 |
57 | Annotation Support
58 | ------------------
59 |
60 | This plugin also supports Annotations. You'll need to provide:
61 |
62 | - Collection
63 | - Query
64 | - Tags
65 | - Title
66 | - Text
67 | - Time
68 |
69 | Development
70 | -----------
71 |
72 | To compile, run the following commands:
73 |
74 | ```bash
75 | npm install
76 | grunt
77 | ```
78 |
79 | To install in your Grafana server locally, either point Grafana at the repository directory by
80 | editing `grafana.ini` to contain:
81 |
82 | ```bash
83 | [plugin.solr]
84 | path = /path/to/some/directory/datasource-plugin-solr
85 | ```
86 |
87 | Or symlink the repository directory into the Grafana server's plugin directory:
88 |
89 | ```bash
90 | cd /path/to/grafana/data/plugins
91 | ln -s /path/to/some/directory/datasource-plugin-solr .
92 | ```
93 |
94 | Then restart the Grafana server.
95 |
96 | Contributors
97 | ------------
98 |
99 | - Sergio Rodriguez de Guzman
100 |
--------------------------------------------------------------------------------
/dist/README.md:
--------------------------------------------------------------------------------
1 | Solr Datasource for Grafana
2 | ===========================
3 |
4 | This plugin for [Grafana](http://grafana.org) provides an advanced datasource for querying Solr server >= 4. This datasource also provides support for the Solr version bundled with [Cloudera CDH 5.X](https://www.cloudera.com).
5 |
6 | This project is open source pursuant to the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).
7 | It is copyright (C) 2018 by PUE Team.
8 |
9 | Installation
10 | ------------
11 |
12 | The easiest way to install this plugin is to clone or unzip this repository on the grafana plugins folder. For example:
13 |
14 | ```bash
15 | cd /var/lib/grafana/plugins
16 | git clone https://github.com/pueteam/datasource-plugin-solr
17 | ```
18 |
19 | Then restart grafana to reload the plugins folder.
20 |
21 | Configuration
22 | -------------
23 |
24 | 1. Add a new datasource and choose "Solr" as the type.
25 |
26 | 2. Fill in the "Url" and other server parameters. If you run Solr in a kerberized cluster, you'll need LDAP authentication enabled, and provide the credentials here.
27 |
28 | 3. Optionally, add the collection to use. This is required if you plan to use templates.
29 |
30 | 4. Click "Test Connection" to verify that you entered the information correctly.
31 |
32 | 5. Cick "Save".
33 |
34 | Queries
35 | -------
36 |
37 | First, select the query type. You can choose between `standard` and `group`. The `standard` query is the default.
38 |
39 | - **Standard Queries**: The `standard` queries will execute regular queries against Solr. You'll need to fill the `Collection`, the `Timestamp` field, the `Fields` list (space or comma separated) and the `Query` in the Solr format `*:*`.
40 |
41 | - **Group Queries**: The `group` type allows you to group results by `Group By Field` parameter. You'll also need to fill the `Group Value Field` and this parameter should be **numeric**. You can also limit the `Max Group Rows` results.
42 |
43 | Template Support
44 | ----------------
45 |
46 | This plugin supports Templates/Variables to be used, for example, in the `Query` parameter. You'll need to specify the `Collection` parameter in the `Datasource` parameters.
47 |
48 | ```bash
49 | CR:$CR AND city:$city
50 | ```
51 |
52 | Autocompletion Support
53 | ----------------------
54 |
55 | This plugin supports auto completion for the Query Parameters.
56 |
57 | Annotation Support
58 | ------------------
59 |
60 | This plugin also supports Annotations. You'll need to provide:
61 |
62 | - Collection
63 | - Query
64 | - Tags
65 | - Title
66 | - Text
67 | - Time
68 |
69 | Development
70 | -----------
71 |
72 | To compile, run the following commands:
73 |
74 | ```bash
75 | npm install
76 | grunt
77 | ```
78 |
79 | To install in your Grafana server locally, either point Grafana at the repository directory by
80 | editing `grafana.ini` to contain:
81 |
82 | ```bash
83 | [plugin.solr]
84 | path = /path/to/some/directory/datasource-plugin-solr
85 | ```
86 |
87 | Or symlink the repository directory into the Grafana server's plugin directory:
88 |
89 | ```bash
90 | cd /path/to/grafana/data/plugins
91 | ln -s /path/to/some/directory/datasource-plugin-solr .
92 | ```
93 |
94 | Then restart the Grafana server.
95 |
96 | Contributors
97 | ------------
98 |
99 | - Sergio Rodriguez de Guzman
100 |
--------------------------------------------------------------------------------
/dist/query_ctrl.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["../src/query_ctrl.js"],"names":["QueryCtrl","SolrQueryCtrl","$scope","$injector","scope","target","type","time","fields","groupEnabled","groupValueField","groupByField","groupLimit","collection","datasource","solrCollection","solrCloudMode","query","listCollections","listFields","rawQuery","panelCtrl","refresh","templateUrl"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeEA,e,kBAAAA,S;;;;;;;;;;;;;;;;;;;;;+BAGWC,a;;;AACX;AACA,+BAAYC,MAAZ,EAAoBC,SAApB,EAA+B;AAAA;;AAAA,oIACvBD,MADuB,EACfC,SADe;;AAG7B;;;;;AAKA,gBAAKC,KAAL,GAAaF,MAAb;AACA,gBAAKG,MAAL,CAAYA,MAAZ,GAAqB,MAAKA,MAAL,CAAYA,MAAZ,IAAsB,KAA3C;AACA,gBAAKA,MAAL,CAAYC,IAAZ,GAAmB,MAAKD,MAAL,CAAYC,IAAZ,IAAoB,WAAvC;AACA,gBAAKD,MAAL,CAAYE,IAAZ,GAAmB,MAAKF,MAAL,CAAYE,IAAZ,IAAoB,EAAvC;AACA,gBAAKF,MAAL,CAAYG,MAAZ,GAAqB,MAAKH,MAAL,CAAYG,MAAZ,IAAsB,EAA3C;AACA,gBAAKH,MAAL,CAAYI,YAAZ,GAA2B,MAAKJ,MAAL,CAAYI,YAAZ,IAA4B,UAAvD;AACA,gBAAKJ,MAAL,CAAYK,eAAZ,GAA8B,MAAKL,MAAL,CAAYK,eAAZ,IAA+B,EAA7D;AACA,gBAAKL,MAAL,CAAYM,YAAZ,GAA2B,MAAKN,MAAL,CAAYM,YAAZ,IAA4B,EAAvD;AACA,gBAAKN,MAAL,CAAYO,UAAZ,GAAyB,MAAKP,MAAL,CAAYO,UAAZ,IAA0B,MAAnD;AACA,gBAAKP,MAAL,CAAYQ,UAAZ,GAAyB,MAAKR,MAAL,CAAYQ,UAAZ,IAA0B,MAAKC,UAAL,CAAgBC,cAA1C,IAA4D,EAArF;AACA,gBAAKV,MAAL,CAAYW,aAAZ,GAA4B,MAAKX,MAAL,CAAYW,aAAZ,IAA6B,MAAKF,UAAL,CAAgBE,aAA7C,IAA8D,IAA1F;AAlB6B;AAmB9B;;;;qCACUC,K,EAAO;AAChB,mBAAO,KAAKH,UAAL,CAAgBI,eAAhB,CAAgCD,SAAS,EAAzC,CAAP;AACD;;;yCAEcA,K,EAAO;AACpB,mBAAO,KAAKH,UAAL,CAAgBI,eAAhB,CAAgCD,SAAS,EAAzC,CAAP;AACD;;;qCAEUA,K,EAAOJ,U,EAAY;AAC5B,mBAAO,KAAKC,UAAL,CAAgBK,UAAhB,CAA2BF,SAAS,EAApC,EAAwCJ,UAAxC,CAAP;AACD;;;6CAEkB;AACjB,iBAAKR,MAAL,CAAYe,QAAZ,GAAuB,CAAC,KAAKf,MAAL,CAAYe,QAApC;AACD;;;6CAEkB;AACjB,iBAAKC,SAAL,CAAeC,OAAf,GADiB,CACS;AAC3B;;;;QAxCgCtB,S;;;;AA2CnCC,oBAAcsB,WAAd,GAA4B,4BAA5B","file":"query_ctrl.js","sourcesContent":["// Copyright 2018 PUE.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport {\n QueryCtrl\n} from 'app/plugins/sdk';\n\nexport class SolrQueryCtrl extends QueryCtrl {\n /** @ngInject **/\n constructor($scope, $injector) {\n super($scope, $injector);\n\n /*\n if (this.target) {\n this.target.target = this.target.target || '';\n }\n */\n this.scope = $scope;\n this.target.target = this.target.target || '*:*';\n this.target.type = this.target.type || 'timeserie';\n this.target.time = this.target.time || '';\n this.target.fields = this.target.fields || '';\n this.target.groupEnabled = this.target.groupEnabled || 'standard';\n this.target.groupValueField = this.target.groupValueField || '';\n this.target.groupByField = this.target.groupByField || '';\n this.target.groupLimit = this.target.groupLimit || 100000;\n this.target.collection = this.target.collection || this.datasource.solrCollection || '';\n this.target.solrCloudMode = this.target.solrCloudMode || this.datasource.solrCloudMode || true;\n }\n getOptions(query) {\n return this.datasource.listCollections(query || '');\n }\n\n listCollection(query) {\n return this.datasource.listCollections(query || '');\n }\n\n listFields(query, collection) {\n return this.datasource.listFields(query || '', collection);\n }\n\n toggleEditorMode() {\n this.target.rawQuery = !this.target.rawQuery;\n }\n\n onChangeInternal() {\n this.panelCtrl.refresh(); // Asks the panel to refresh data.\n }\n}\n\nSolrQueryCtrl.templateUrl = 'partials/query.editor.html';"]}
--------------------------------------------------------------------------------
/src/images/solr.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/images/solr.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/query_ctrl.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | System.register(['app/plugins/sdk'], function (_export, _context) {
4 | "use strict";
5 |
6 | var QueryCtrl, _createClass, SolrQueryCtrl;
7 |
8 | function _classCallCheck(instance, Constructor) {
9 | if (!(instance instanceof Constructor)) {
10 | throw new TypeError("Cannot call a class as a function");
11 | }
12 | }
13 |
14 | function _possibleConstructorReturn(self, call) {
15 | if (!self) {
16 | throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
17 | }
18 |
19 | return call && (typeof call === "object" || typeof call === "function") ? call : self;
20 | }
21 |
22 | function _inherits(subClass, superClass) {
23 | if (typeof superClass !== "function" && superClass !== null) {
24 | throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
25 | }
26 |
27 | subClass.prototype = Object.create(superClass && superClass.prototype, {
28 | constructor: {
29 | value: subClass,
30 | enumerable: false,
31 | writable: true,
32 | configurable: true
33 | }
34 | });
35 | if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
36 | }
37 |
38 | return {
39 | setters: [function (_appPluginsSdk) {
40 | QueryCtrl = _appPluginsSdk.QueryCtrl;
41 | }],
42 | execute: function () {
43 | _createClass = function () {
44 | function defineProperties(target, props) {
45 | for (var i = 0; i < props.length; i++) {
46 | var descriptor = props[i];
47 | descriptor.enumerable = descriptor.enumerable || false;
48 | descriptor.configurable = true;
49 | if ("value" in descriptor) descriptor.writable = true;
50 | Object.defineProperty(target, descriptor.key, descriptor);
51 | }
52 | }
53 |
54 | return function (Constructor, protoProps, staticProps) {
55 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
56 | if (staticProps) defineProperties(Constructor, staticProps);
57 | return Constructor;
58 | };
59 | }();
60 |
61 | _export('SolrQueryCtrl', SolrQueryCtrl = function (_QueryCtrl) {
62 | _inherits(SolrQueryCtrl, _QueryCtrl);
63 |
64 | /** @ngInject **/
65 | function SolrQueryCtrl($scope, $injector) {
66 | _classCallCheck(this, SolrQueryCtrl);
67 |
68 | var _this = _possibleConstructorReturn(this, (SolrQueryCtrl.__proto__ || Object.getPrototypeOf(SolrQueryCtrl)).call(this, $scope, $injector));
69 |
70 | /*
71 | if (this.target) {
72 | this.target.target = this.target.target || '';
73 | }
74 | */
75 | _this.scope = $scope;
76 | _this.target.target = _this.target.target || '*:*';
77 | _this.target.type = _this.target.type || 'timeserie';
78 | _this.target.time = _this.target.time || '';
79 | _this.target.fields = _this.target.fields || '';
80 | _this.target.groupEnabled = _this.target.groupEnabled || 'standard';
81 | _this.target.groupValueField = _this.target.groupValueField || '';
82 | _this.target.groupByField = _this.target.groupByField || '';
83 | _this.target.groupLimit = _this.target.groupLimit || 100000;
84 | _this.target.collection = _this.target.collection || _this.datasource.solrCollection || '';
85 | _this.target.solrCloudMode = _this.target.solrCloudMode || _this.datasource.solrCloudMode || true;
86 | return _this;
87 | }
88 |
89 | _createClass(SolrQueryCtrl, [{
90 | key: 'getOptions',
91 | value: function getOptions(query) {
92 | return this.datasource.listCollections(query || '');
93 | }
94 | }, {
95 | key: 'listCollection',
96 | value: function listCollection(query) {
97 | return this.datasource.listCollections(query || '');
98 | }
99 | }, {
100 | key: 'listFields',
101 | value: function listFields(query, collection) {
102 | return this.datasource.listFields(query || '', collection);
103 | }
104 | }, {
105 | key: 'toggleEditorMode',
106 | value: function toggleEditorMode() {
107 | this.target.rawQuery = !this.target.rawQuery;
108 | }
109 | }, {
110 | key: 'onChangeInternal',
111 | value: function onChangeInternal() {
112 | this.panelCtrl.refresh(); // Asks the panel to refresh data.
113 | }
114 | }]);
115 |
116 | return SolrQueryCtrl;
117 | }(QueryCtrl));
118 |
119 | _export('SolrQueryCtrl', SolrQueryCtrl);
120 |
121 | SolrQueryCtrl.templateUrl = 'partials/query.editor.html';
122 | }
123 | };
124 | });
125 | //# sourceMappingURL=query_ctrl.js.map
126 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/src/datasource.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 PUE.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import _ from 'lodash';
16 | import * as $ from 'jquery';
17 | import moment from 'moment';
18 | import * as dateMath from 'app/core/utils/datemath';
19 |
20 | /** @ngInject */
21 | export class SolrDatasource {
22 | constructor(instanceSettings, $q, backendSrv, templateSrv) {
23 | this.url = instanceSettings.url;
24 | if (this.url.endsWith('/')) {
25 | this.url = this.url.substr(0, this.url.length - 1);
26 | }
27 | this.basicAuth = instanceSettings.basicAuth;
28 | this.withCredentials = instanceSettings.withCredentials;
29 | this.name = instanceSettings.name;
30 | //this.collection = instanceSettings.jsonData.collection;
31 | this.$q = $q;
32 | this.templateSrv = templateSrv;
33 | this.backendSrv = backendSrv;
34 | this.solrCollection = instanceSettings.jsonData.solrCollection;
35 | this.solrCloudMode = instanceSettings.jsonData.solrCloudMode;
36 |
37 | // Helper to make API requests to Solr. To avoid CORS issues, the requests may be proxied
38 | // through Grafana's backend via `backendSrv.datasourceRequest`.
39 | this._request = function (options) {
40 | options.url = this.url + options.url;
41 | options.method = options.method || 'GET';
42 | options.inspect = {
43 | 'type': 'solr'
44 | };
45 |
46 | if (this.basicAuth) {
47 | options.withCredentials = true;
48 | options.headers = {
49 | "Authorization": this.basicAuth
50 | };
51 | }
52 |
53 | return backendSrv.datasourceRequest(options);
54 | };
55 | }
56 |
57 | // Test the connection to Solr by querying collection response.
58 | testDatasource() {
59 | return this.doRequest({
60 | url: this.url + '/',
61 | method: 'GET',
62 | }).then(response => {
63 | if (response.status === 200) {
64 | return {
65 | status: "success",
66 | message: "Data source is working",
67 | title: "Success"
68 | };
69 | } else {
70 | return {
71 | status: "error",
72 | message: "Data source is NOT working",
73 | title: "Error"
74 | };
75 | }
76 | });
77 | }
78 |
79 | // Query for metric targets within the specified time range.
80 | // Returns the promise of a result dictionary.
81 | query(queryOptions) {
82 | //console.log('QUERY: ' + JSON.stringify(queryOptions));
83 | var self = this;
84 |
85 | var targetPromises = _(queryOptions.targets)
86 | .filter(function (target) {
87 | return target.target && !target.hide;
88 | })
89 | .map(function (target) {
90 | if (!target.collection || !target.time) {
91 | return [];
92 | }
93 | if (target.groupEnabled === 'group' && !target.groupByField) {
94 | return [];
95 | }
96 | //var url = '/api/v' + self.apiVersion + '/timeseries';
97 | //fq=time:[2018-01-24T02:59:10.000Z TO 2018-01-24T14:59:10.000Z]
98 | var url = '/solr/' + target.collection + '/select';
99 | //var rows = queryOptions.maxDataPoints || '100000';
100 | var rows = 100000;
101 | var q = self.templateSrv.replace(target.target, queryOptions.scopedVars);
102 | q = self.queryBuilder(q);
103 | var query = {
104 | wt: 'json',
105 | //query: templateSrv.replace(target.target, queryOptions.scopedVars),
106 | fq: target.time + ':[' + queryOptions.range.from.toJSON() + ' TO ' + queryOptions.range.to.toJSON() + ']',
107 | q: q,
108 | fl: target.time + ',' + target.fields,
109 | rows: rows,
110 | sort: target.time + ' desc'
111 | //from: queryOptions.range.from.toJSON(),
112 | //to: queryOptions.range.to.toJSON(),
113 | };
114 | if (target.groupEnabled === 'group') {
115 | query.group = true;
116 | query['group.field'] = target.groupByField;
117 | self.groupByField = target.groupByField;
118 | query['group.limit'] = target.groupLimit;
119 | }
120 |
121 | self.time = target.time;
122 |
123 | var requestOptions;
124 |
125 | requestOptions = {
126 | method: 'GET',
127 | url: url,
128 | params: query
129 | };
130 |
131 | return self._request(requestOptions).then(_.bind(self.convertResponse, self));
132 | })
133 | .value();
134 |
135 | return this.$q.all(targetPromises).then(function (convertedResponses) {
136 | var result = {
137 | data: _.map(convertedResponses, function (convertedResponse) {
138 | return convertedResponse.data;
139 | })
140 | };
141 | result.data = _.flatten(result.data);
142 | //console.log('RESULT: ' + JSON.stringify(result));
143 | return result;
144 | });
145 | }
146 |
147 | queryBuilder(query) {
148 | return query.replace(/{/g, '(').replace(/}/g, ')').replace(/,/g, ' OR ');
149 | }
150 |
151 | getOptions(query) {
152 | return [];
153 | }
154 |
155 | listCollections(query) {
156 | // solr/admin/collections?action=LIST&wt=json
157 | if (!this.solrCloudMode) {
158 | return [];
159 | }
160 | var url = this.url + '/solr/admin/collections?action=LIST&wt=json';
161 | var requestOptions;
162 |
163 | requestOptions = {
164 | method: 'GET',
165 | url: url
166 | };
167 |
168 | return this.doRequest(requestOptions).then(this.mapToTextValue);
169 | }
170 |
171 | listFields(query, collection) {
172 | // solr/admin/collections?action=LIST&wt=json
173 | if (!collection) {
174 | return [];
175 | }
176 | var url = this.url + '/solr/' + collection + '/select?q=*:*&wt=csv&rows=1';
177 | var requestOptions;
178 |
179 | requestOptions = {
180 | method: 'GET',
181 | url: url
182 | };
183 |
184 | return this.doRequest(requestOptions).then(this.mapToTextValue);
185 | }
186 |
187 | metricFindQuery(query) {
188 | //q=*:*&facet=true&facet.field=CR&facet.field=product_type&facet.field=provincia&wt=json&rows=0
189 | if (!this.solrCollection) {
190 | return [];
191 | }
192 | var facetFields = query;
193 | var url = this.url + '/solr/' + this.solrCollection + '/select?q=*:*&facet=true&facet.field=' + facetFields + '&wt=json&rows=0';
194 |
195 | return this.doRequest({
196 | url: url,
197 | method: 'GET',
198 | }).then(this.mapToTextValue);
199 | }
200 |
201 | mapToTextValue(result) {
202 | if (result.data.collections) {
203 | return result.data.collections.map(function (collection) {
204 | return {
205 | text: collection,
206 | value: collection
207 | };
208 | });
209 | }
210 | if (result.data.facet_counts) {
211 | var ar = [];
212 | for (var key in result.data.facet_counts.facet_fields) {
213 | if (result.data.facet_counts.facet_fields.hasOwnProperty(key)) {
214 | var array = result.data.facet_counts.facet_fields[key];
215 | for (var i = 0; i < array.length; i += 2) { // take every second element
216 | ar.push({
217 | text: array[i],
218 | expandable: false
219 | });
220 | }
221 | }
222 | }
223 | return ar;
224 | }
225 | if (result.data) {
226 | return result.data.split('\n')[0].split(',').map(function (field) {
227 | return {
228 | text: field,
229 | value: field
230 | };
231 | });
232 | }
233 | }
234 |
235 | convertResponseUngrouped(response) {
236 | var data = response.data;
237 | var seriesList = [];
238 | var series = {};
239 | var self = this;
240 | _(data.response.docs).forEach(function (item) {
241 | for (var property in item) {
242 | if (item.hasOwnProperty(property) && property != self.time) {
243 | // do stuff
244 | if (typeof (series[property]) === 'undefined') {
245 | series[property] = [];
246 | }
247 | var ts = moment.utc(item[self.time]).unix() * 1000;
248 | series[property].push([item[property] || 0, ts]);
249 | }
250 | }
251 | });
252 | for (var property in series) {
253 | seriesList.push({
254 | target: property,
255 | datapoints: series[property].reverse()
256 | });
257 | }
258 | return {
259 | data: seriesList
260 | };
261 | }
262 |
263 | convertResponseGrouped(response) {
264 | var data = response.data;
265 | var groupBy = data.responseHeader.params['group.field'];
266 | var seriesList = [];
267 | // Recover the timestamp variable used for filtering
268 | var time = response.data.responseHeader.params.fl.split(',')[0];
269 | _(data.grouped[groupBy].groups).forEach(function (item) {
270 | var target = item.groupValue || 'N/A';
271 | var datapoints = [];
272 | for (var i = 0; i < item.doclist.docs.length; i++) {
273 | for (var property in item.doclist.docs[i]) {
274 | if (item.doclist.docs[i].hasOwnProperty(property) && property != time) {
275 | var t = moment.utc(item.doclist.docs[i][time]).unix() * 1000;
276 | datapoints.push([item.doclist.docs[i][property], t]);
277 | }
278 | }
279 | }
280 | seriesList.push({
281 | target: target,
282 | datapoints: datapoints.reverse()
283 | });
284 | });
285 | return {
286 | data: seriesList
287 | };
288 | }
289 |
290 | convertResponse(response) {
291 |
292 | var data = response.data;
293 |
294 | if (!data) {
295 | return [];
296 | }
297 |
298 | if (data.response) {
299 | return this.convertResponseUngrouped(response);
300 | }
301 |
302 | if (data.grouped) {
303 | return this.convertResponseGrouped(response);
304 | }
305 |
306 | return [];
307 | }
308 |
309 | annotationQuery(options) {
310 | const annotation = options.annotation;
311 | const baseQuery = this.templateSrv.replace(annotation.query, {}, "glob") || "*:*";
312 | const timeField = annotation.timeField || "timestamp_dt";
313 | const collection = annotation.collection || "annotations";
314 | const tagsField = annotation.tagsField || "tags";
315 | const titleField = annotation.titleField || "desc";
316 | const textField = annotation.textField || null;
317 | const start = options.range.from.toISOString();
318 | const end = options.range.to.toISOString();
319 | const query = {
320 | q: `${baseQuery} AND ${timeField}:[${start} TO ${end}]`,
321 | limit: 10,
322 | wt: 'json',
323 | defType: 'edismax'
324 | };
325 |
326 | var url = this.url + '/solr/' + collection + '/select';
327 |
328 | var requestOptions;
329 |
330 | requestOptions = {
331 | method: 'GET',
332 | url: url,
333 | params: query
334 | };
335 |
336 | return this.doRequest(requestOptions).then((result) => {
337 | return _.map(result.data.response.docs, (doc) => {
338 | return {
339 | annotation: annotation,
340 | time: moment(doc[timeField]).valueOf(),
341 | title: doc[titleField],
342 | tags: doc[tagsField],
343 | text: doc[textField]
344 | };
345 | });
346 | });
347 | }
348 |
349 | doRequest(options) {
350 | options.withCredentials = this.withCredentials;
351 | options.headers = this.headers;
352 | if (this.basicAuth) {
353 | options.withCredentials = true;
354 | options.headers = {
355 | "Authorization": this.basicAuth
356 | };
357 | }
358 |
359 | return this.backendSrv.datasourceRequest(options);
360 | }
361 | }
362 |
--------------------------------------------------------------------------------
/dist/datasource.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | System.register(['lodash', 'jquery', 'moment', 'app/core/utils/datemath'], function (_export, _context) {
4 | "use strict";
5 |
6 | var _, $, moment, dateMath, _createClass, SolrDatasource;
7 |
8 | function _classCallCheck(instance, Constructor) {
9 | if (!(instance instanceof Constructor)) {
10 | throw new TypeError("Cannot call a class as a function");
11 | }
12 | }
13 |
14 | return {
15 | setters: [function (_lodash) {
16 | _ = _lodash.default;
17 | }, function (_jquery) {
18 | $ = _jquery;
19 | }, function (_moment) {
20 | moment = _moment.default;
21 | }, function (_appCoreUtilsDatemath) {
22 | dateMath = _appCoreUtilsDatemath;
23 | }],
24 | execute: function () {
25 | _createClass = function () {
26 | function defineProperties(target, props) {
27 | for (var i = 0; i < props.length; i++) {
28 | var descriptor = props[i];
29 | descriptor.enumerable = descriptor.enumerable || false;
30 | descriptor.configurable = true;
31 | if ("value" in descriptor) descriptor.writable = true;
32 | Object.defineProperty(target, descriptor.key, descriptor);
33 | }
34 | }
35 |
36 | return function (Constructor, protoProps, staticProps) {
37 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
38 | if (staticProps) defineProperties(Constructor, staticProps);
39 | return Constructor;
40 | };
41 | }();
42 |
43 | _export('SolrDatasource', SolrDatasource = function () {
44 | function SolrDatasource(instanceSettings, $q, backendSrv, templateSrv) {
45 | _classCallCheck(this, SolrDatasource);
46 |
47 | this.url = instanceSettings.url;
48 | if (this.url.endsWith('/')) {
49 | this.url = this.url.substr(0, this.url.length - 1);
50 | }
51 | this.basicAuth = instanceSettings.basicAuth;
52 | this.withCredentials = instanceSettings.withCredentials;
53 | this.name = instanceSettings.name;
54 | //this.collection = instanceSettings.jsonData.collection;
55 | this.$q = $q;
56 | this.templateSrv = templateSrv;
57 | this.backendSrv = backendSrv;
58 | this.solrCollection = instanceSettings.jsonData.solrCollection;
59 | this.solrCloudMode = instanceSettings.jsonData.solrCloudMode;
60 |
61 | // Helper to make API requests to Solr. To avoid CORS issues, the requests may be proxied
62 | // through Grafana's backend via `backendSrv.datasourceRequest`.
63 | this._request = function (options) {
64 | options.url = this.url + options.url;
65 | options.method = options.method || 'GET';
66 | options.inspect = {
67 | 'type': 'solr'
68 | };
69 |
70 | if (this.basicAuth) {
71 | options.withCredentials = true;
72 | options.headers = {
73 | "Authorization": this.basicAuth
74 | };
75 | }
76 |
77 | return backendSrv.datasourceRequest(options);
78 | };
79 | }
80 |
81 | // Test the connection to Solr by querying collection response.
82 |
83 |
84 | _createClass(SolrDatasource, [{
85 | key: 'testDatasource',
86 | value: function testDatasource() {
87 | return this.doRequest({
88 | url: this.url + '/',
89 | method: 'GET'
90 | }).then(function (response) {
91 | if (response.status === 200) {
92 | return {
93 | status: "success",
94 | message: "Data source is working",
95 | title: "Success"
96 | };
97 | } else {
98 | return {
99 | status: "error",
100 | message: "Data source is NOT working",
101 | title: "Error"
102 | };
103 | }
104 | });
105 | }
106 | }, {
107 | key: 'query',
108 | value: function query(queryOptions) {
109 | //console.log('QUERY: ' + JSON.stringify(queryOptions));
110 | var self = this;
111 |
112 | var targetPromises = _(queryOptions.targets).filter(function (target) {
113 | return target.target && !target.hide;
114 | }).map(function (target) {
115 | if (!target.collection || !target.time) {
116 | return [];
117 | }
118 | if (target.groupEnabled === 'group' && !target.groupByField) {
119 | return [];
120 | }
121 | //var url = '/api/v' + self.apiVersion + '/timeseries';
122 | //fq=time:[2018-01-24T02:59:10.000Z TO 2018-01-24T14:59:10.000Z]
123 | var url = '/solr/' + target.collection + '/select?wt=json';
124 | //var rows = queryOptions.maxDataPoints || '100000';
125 | var rows = 100000;
126 | var q = self.templateSrv.replace(target.target, queryOptions.scopedVars);
127 | q = self.queryBuilder(q);
128 | var query = {
129 | //query: templateSrv.replace(target.target, queryOptions.scopedVars),
130 | fq: target.time + ':[' + queryOptions.range.from.toJSON() + ' TO ' + queryOptions.range.to.toJSON() + ']',
131 | q: q,
132 | fl: target.time + ',' + target.fields,
133 | rows: rows,
134 | sort: target.time + ' desc'
135 | //from: queryOptions.range.from.toJSON(),
136 | //to: queryOptions.range.to.toJSON(),
137 | };
138 | if (target.groupEnabled === 'group') {
139 | query.group = true;
140 | query['group.field'] = target.groupByField;
141 | self.groupByField = target.groupByField;
142 | query['group.limit'] = target.groupLimit;
143 | }
144 |
145 | self.time = target.time;
146 |
147 | var requestOptions;
148 |
149 | requestOptions = {
150 | method: 'GET',
151 | url: url,
152 | params: query
153 | };
154 |
155 | return self._request(requestOptions).then(_.bind(self.convertResponse, self));
156 | }).value();
157 |
158 | return this.$q.all(targetPromises).then(function (convertedResponses) {
159 | var result = {
160 | data: _.map(convertedResponses, function (convertedResponse) {
161 | return convertedResponse.data;
162 | })
163 | };
164 | result.data = _.flatten(result.data);
165 | //console.log('RESULT: ' + JSON.stringify(result));
166 | return result;
167 | });
168 | }
169 | }, {
170 | key: 'queryBuilder',
171 | value: function queryBuilder(query) {
172 | return query.replace(/{/g, '(').replace(/}/g, ')').replace(/,/g, ' OR ');
173 | }
174 | }, {
175 | key: 'getOptions',
176 | value: function getOptions(query) {
177 | return [];
178 | }
179 | }, {
180 | key: 'listCollections',
181 | value: function listCollections(query) {
182 | // solr/admin/collections?action=LIST&wt=json
183 | if (!this.solrCloudMode) {
184 | return [];
185 | }
186 | var url = this.url + '/solr/admin/collections?action=LIST&wt=json';
187 | var requestOptions;
188 |
189 | requestOptions = {
190 | method: 'GET',
191 | url: url
192 | };
193 |
194 | return this.doRequest(requestOptions).then(this.mapToTextValue);
195 | }
196 | }, {
197 | key: 'listFields',
198 | value: function listFields(query, collection) {
199 | // solr/admin/collections?action=LIST&wt=json
200 | if (!collection) {
201 | return [];
202 | }
203 | var url = this.url + '/solr/' + collection + '/select?q=*:*&wt=csv&rows=1';
204 | var requestOptions;
205 |
206 | requestOptions = {
207 | method: 'GET',
208 | url: url
209 | };
210 |
211 | return this.doRequest(requestOptions).then(this.mapToTextValue);
212 | }
213 | }, {
214 | key: 'metricFindQuery',
215 | value: function metricFindQuery(query) {
216 | //q=*:*&facet=true&facet.field=CR&facet.field=product_type&facet.field=provincia&wt=json&rows=0
217 | if (!this.solrCollection) {
218 | return [];
219 | }
220 | var facetFields = query;
221 | var url = this.url + '/solr/' + this.solrCollection + '/select?q=*:*&facet=true&facet.field=' + facetFields + '&wt=json&rows=0';
222 |
223 | return this.doRequest({
224 | url: url,
225 | method: 'GET'
226 | }).then(this.mapToTextValue);
227 | }
228 | }, {
229 | key: 'mapToTextValue',
230 | value: function mapToTextValue(result) {
231 | if (result.data.collections) {
232 | return result.data.collections.map(function (collection) {
233 | return {
234 | text: collection,
235 | value: collection
236 | };
237 | });
238 | }
239 | if (result.data.facet_counts) {
240 | var ar = [];
241 | for (var key in result.data.facet_counts.facet_fields) {
242 | if (result.data.facet_counts.facet_fields.hasOwnProperty(key)) {
243 | var array = result.data.facet_counts.facet_fields[key];
244 | for (var i = 0; i < array.length; i += 2) {
245 | // take every second element
246 | ar.push({
247 | text: array[i],
248 | expandable: false
249 | });
250 | }
251 | }
252 | }
253 | return ar;
254 | }
255 | if (result.data) {
256 | return result.data.split('\n')[0].split(',').map(function (field) {
257 | return {
258 | text: field,
259 | value: field
260 | };
261 | });
262 | }
263 | }
264 | }, {
265 | key: 'convertResponseUngrouped',
266 | value: function convertResponseUngrouped(response) {
267 | var data = response.data;
268 | var seriesList = [];
269 | var series = {};
270 | var self = this;
271 | _(data.response.docs).forEach(function (item) {
272 | for (var property in item) {
273 | if (item.hasOwnProperty(property) && property != self.time) {
274 | // do stuff
275 | if (typeof series[property] === 'undefined') {
276 | series[property] = [];
277 | }
278 | var ts = moment.utc(item[self.time]).unix() * 1000;
279 | series[property].push([item[property] || 0, ts]);
280 | }
281 | }
282 | });
283 | for (var property in series) {
284 | seriesList.push({
285 | target: property,
286 | datapoints: series[property].reverse()
287 | });
288 | }
289 | return {
290 | data: seriesList
291 | };
292 | }
293 | }, {
294 | key: 'convertResponseGrouped',
295 | value: function convertResponseGrouped(response) {
296 | var data = response.data;
297 | var groupBy = data.responseHeader.params['group.field'];
298 | var seriesList = [];
299 | // Recover the timestamp variable used for filtering
300 | var time = response.data.responseHeader.params.fl.split(',')[0];
301 | _(data.grouped[groupBy].groups).forEach(function (item) {
302 | var target = item.groupValue || 'N/A';
303 | var datapoints = [];
304 | for (var i = 0; i < item.doclist.docs.length; i++) {
305 | for (var property in item.doclist.docs[i]) {
306 | if (item.doclist.docs[i].hasOwnProperty(property) && property != time) {
307 | var t = moment.utc(item.doclist.docs[i][time]).unix() * 1000;
308 | datapoints.push([item.doclist.docs[i][property], t]);
309 | }
310 | }
311 | }
312 | seriesList.push({
313 | target: target,
314 | datapoints: datapoints.reverse()
315 | });
316 | });
317 | return {
318 | data: seriesList
319 | };
320 | }
321 | }, {
322 | key: 'convertResponse',
323 | value: function convertResponse(response) {
324 |
325 | var data = response.data;
326 |
327 | if (!data) {
328 | return [];
329 | }
330 |
331 | if (data.response) {
332 | return this.convertResponseUngrouped(response);
333 | }
334 |
335 | if (data.grouped) {
336 | return this.convertResponseGrouped(response);
337 | }
338 |
339 | return [];
340 | }
341 | }, {
342 | key: 'annotationQuery',
343 | value: function annotationQuery(options) {
344 | var annotation = options.annotation;
345 | var baseQuery = this.templateSrv.replace(annotation.query, {}, "glob") || "*:*";
346 | var timeField = annotation.timeField || "timestamp_dt";
347 | var collection = annotation.collection || "annotations";
348 | var tagsField = annotation.tagsField || "tags";
349 | var titleField = annotation.titleField || "desc";
350 | var textField = annotation.textField || null;
351 | var start = options.range.from.toISOString();
352 | var end = options.range.to.toISOString();
353 | var query = {
354 | q: baseQuery + ' AND ' + timeField + ':[' + start + ' TO ' + end + ']',
355 | limit: 10
356 | };
357 |
358 | var url = this.url + '/solr/' + collection + '/select?wt=json&defType=edismax';
359 |
360 | var requestOptions;
361 |
362 | requestOptions = {
363 | method: 'GET',
364 | url: url,
365 | params: query
366 | };
367 |
368 | return this.doRequest(requestOptions).then(function (result) {
369 | return _.map(result.data.response.docs, function (doc) {
370 | return {
371 | annotation: annotation,
372 | time: moment(doc[timeField]).valueOf(),
373 | title: doc[titleField],
374 | tags: doc[tagsField],
375 | text: doc[textField]
376 | };
377 | });
378 | });
379 | }
380 | }, {
381 | key: 'doRequest',
382 | value: function doRequest(options) {
383 | options.withCredentials = this.withCredentials;
384 | options.headers = this.headers;
385 | if (this.basicAuth) {
386 | options.withCredentials = true;
387 | options.headers = {
388 | "Authorization": this.basicAuth
389 | };
390 | }
391 |
392 | return this.backendSrv.datasourceRequest(options);
393 | }
394 | }]);
395 |
396 | return SolrDatasource;
397 | }());
398 |
399 | _export('SolrDatasource', SolrDatasource);
400 | }
401 | };
402 | });
403 | //# sourceMappingURL=datasource.js.map
404 |
--------------------------------------------------------------------------------
/dist/datasource.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["../src/datasource.js"],"names":["_","$","moment","dateMath","SolrDatasource","instanceSettings","$q","backendSrv","templateSrv","url","endsWith","substr","length","basicAuth","withCredentials","name","solrCollection","jsonData","solrCloudMode","_request","options","method","inspect","headers","datasourceRequest","doRequest","then","response","status","message","title","queryOptions","self","targetPromises","targets","filter","target","hide","map","collection","time","groupEnabled","groupByField","rows","q","replace","scopedVars","queryBuilder","query","fq","range","from","toJSON","to","fl","fields","sort","group","groupLimit","requestOptions","params","bind","convertResponse","value","all","convertedResponses","result","data","convertedResponse","flatten","mapToTextValue","facetFields","collections","text","facet_counts","ar","key","facet_fields","hasOwnProperty","array","i","push","expandable","split","field","seriesList","series","docs","forEach","item","property","ts","utc","unix","datapoints","reverse","groupBy","responseHeader","grouped","groups","groupValue","doclist","t","convertResponseUngrouped","convertResponseGrouped","annotation","baseQuery","timeField","tagsField","titleField","textField","start","toISOString","end","limit","doc","valueOf","tags"],"mappings":"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","file":"datasource.js","sourcesContent":["// Copyright 2018 PUE.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport _ from 'lodash';\nimport * as $ from 'jquery';\nimport moment from 'moment';\nimport * as dateMath from 'app/core/utils/datemath';\n\n/** @ngInject */\nexport class SolrDatasource {\n constructor(instanceSettings, $q, backendSrv, templateSrv) {\n this.url = instanceSettings.url;\n if (this.url.endsWith('/')) {\n this.url = this.url.substr(0, this.url.length - 1);\n }\n this.basicAuth = instanceSettings.basicAuth;\n this.withCredentials = instanceSettings.withCredentials;\n this.name = instanceSettings.name;\n //this.collection = instanceSettings.jsonData.collection;\n this.$q = $q;\n this.templateSrv = templateSrv;\n this.backendSrv = backendSrv;\n this.solrCollection = instanceSettings.jsonData.solrCollection;\n this.solrCloudMode = instanceSettings.jsonData.solrCloudMode;\n\n // Helper to make API requests to Solr. To avoid CORS issues, the requests may be proxied\n // through Grafana's backend via `backendSrv.datasourceRequest`.\n this._request = function (options) {\n options.url = this.url + options.url;\n options.method = options.method || 'GET';\n options.inspect = {\n 'type': 'solr'\n };\n\n if (this.basicAuth) {\n options.withCredentials = true;\n options.headers = {\n \"Authorization\": this.basicAuth\n };\n }\n\n return backendSrv.datasourceRequest(options);\n };\n }\n\n // Test the connection to Solr by querying collection response.\n testDatasource() {\n return this.doRequest({\n url: this.url + '/',\n method: 'GET',\n }).then(response => {\n if (response.status === 200) {\n return {\n status: \"success\",\n message: \"Data source is working\",\n title: \"Success\"\n };\n } else {\n return {\n status: \"error\",\n message: \"Data source is NOT working\",\n title: \"Error\"\n };\n }\n });\n }\n\n // Query for metric targets within the specified time range.\n // Returns the promise of a result dictionary.\n query(queryOptions) {\n //console.log('QUERY: ' + JSON.stringify(queryOptions));\n var self = this;\n\n var targetPromises = _(queryOptions.targets)\n .filter(function (target) {\n return target.target && !target.hide;\n })\n .map(function (target) {\n if (!target.collection || !target.time) {\n return [];\n }\n if (target.groupEnabled === 'group' && !target.groupByField) {\n return [];\n }\n //var url = '/api/v' + self.apiVersion + '/timeseries';\n //fq=time:[2018-01-24T02:59:10.000Z TO 2018-01-24T14:59:10.000Z]\n var url = '/solr/' + target.collection + '/select?wt=json';\n //var rows = queryOptions.maxDataPoints || '100000';\n var rows = 100000;\n var q = self.templateSrv.replace(target.target, queryOptions.scopedVars);\n q = self.queryBuilder(q);\n var query = {\n //query: templateSrv.replace(target.target, queryOptions.scopedVars),\n fq: target.time + ':[' + queryOptions.range.from.toJSON() + ' TO ' + queryOptions.range.to.toJSON() + ']',\n q: q,\n fl: target.time + ',' + target.fields,\n rows: rows,\n sort: target.time + ' desc'\n //from: queryOptions.range.from.toJSON(),\n //to: queryOptions.range.to.toJSON(),\n };\n if (target.groupEnabled === 'group') {\n query.group = true;\n query['group.field'] = target.groupByField;\n self.groupByField = target.groupByField;\n query['group.limit'] = target.groupLimit;\n }\n\n self.time = target.time;\n\n var requestOptions;\n\n requestOptions = {\n method: 'GET',\n url: url,\n params: query\n };\n\n return self._request(requestOptions).then(_.bind(self.convertResponse, self));\n })\n .value();\n\n return this.$q.all(targetPromises).then(function (convertedResponses) {\n var result = {\n data: _.map(convertedResponses, function (convertedResponse) {\n return convertedResponse.data;\n })\n };\n result.data = _.flatten(result.data);\n //console.log('RESULT: ' + JSON.stringify(result));\n return result;\n });\n }\n\n queryBuilder(query) {\n return query.replace(/{/g, '(').replace(/}/g, ')').replace(/,/g, ' OR ');\n }\n\n getOptions(query) {\n return [];\n }\n\n listCollections(query) {\n // solr/admin/collections?action=LIST&wt=json\n if (!this.solrCloudMode) {\n return [];\n }\n var url = this.url + '/solr/admin/collections?action=LIST&wt=json';\n var requestOptions;\n\n requestOptions = {\n method: 'GET',\n url: url\n };\n\n return this.doRequest(requestOptions).then(this.mapToTextValue);\n }\n\n listFields(query, collection) {\n // solr/admin/collections?action=LIST&wt=json\n if (!collection) {\n return [];\n }\n var url = this.url + '/solr/' + collection + '/select?q=*:*&wt=csv&rows=1';\n var requestOptions;\n\n requestOptions = {\n method: 'GET',\n url: url\n };\n\n return this.doRequest(requestOptions).then(this.mapToTextValue);\n }\n\n metricFindQuery(query) {\n //q=*:*&facet=true&facet.field=CR&facet.field=product_type&facet.field=provincia&wt=json&rows=0\n if (!this.solrCollection) {\n return [];\n }\n var facetFields = query;\n var url = this.url + '/solr/' + this.solrCollection + '/select?q=*:*&facet=true&facet.field=' + facetFields + '&wt=json&rows=0';\n\n return this.doRequest({\n url: url,\n method: 'GET',\n }).then(this.mapToTextValue);\n }\n\n mapToTextValue(result) {\n if (result.data.collections) {\n return result.data.collections.map(function (collection) {\n return {\n text: collection,\n value: collection\n };\n });\n }\n if (result.data.facet_counts) {\n var ar = [];\n for (var key in result.data.facet_counts.facet_fields) {\n if (result.data.facet_counts.facet_fields.hasOwnProperty(key)) {\n var array = result.data.facet_counts.facet_fields[key];\n for (var i = 0; i < array.length; i += 2) { // take every second element\n ar.push({\n text: array[i],\n expandable: false\n });\n }\n }\n }\n return ar;\n }\n if (result.data) {\n return result.data.split('\\n')[0].split(',').map(function (field) {\n return {\n text: field,\n value: field\n };\n });\n }\n }\n\n convertResponseUngrouped(response) {\n var data = response.data;\n var seriesList = [];\n var series = {};\n var self = this;\n _(data.response.docs).forEach(function (item) {\n for (var property in item) {\n if (item.hasOwnProperty(property) && property != self.time) {\n // do stuff\n if (typeof (series[property]) === 'undefined') {\n series[property] = [];\n }\n var ts = moment.utc(item[self.time]).unix() * 1000;\n series[property].push([item[property] || 0, ts]);\n }\n }\n });\n for (var property in series) {\n seriesList.push({\n target: property,\n datapoints: series[property].reverse()\n });\n }\n return {\n data: seriesList\n };\n }\n\n convertResponseGrouped(response) {\n var data = response.data;\n var groupBy = data.responseHeader.params['group.field'];\n var seriesList = [];\n // Recover the timestamp variable used for filtering\n var time = response.data.responseHeader.params.fl.split(',')[0];\n _(data.grouped[groupBy].groups).forEach(function (item) {\n var target = item.groupValue || 'N/A';\n var datapoints = [];\n for (var i = 0; i < item.doclist.docs.length; i++) {\n for (var property in item.doclist.docs[i]) {\n if (item.doclist.docs[i].hasOwnProperty(property) && property != time) {\n var t = moment.utc(item.doclist.docs[i][time]).unix() * 1000;\n datapoints.push([item.doclist.docs[i][property], t]);\n }\n }\n }\n seriesList.push({\n target: target,\n datapoints: datapoints.reverse()\n });\n });\n return {\n data: seriesList\n };\n }\n\n convertResponse(response) {\n\n var data = response.data;\n\n if (!data) {\n return [];\n }\n\n if (data.response) {\n return this.convertResponseUngrouped(response);\n }\n\n if (data.grouped) {\n return this.convertResponseGrouped(response);\n }\n\n return [];\n }\n\n annotationQuery(options) {\n const annotation = options.annotation;\n const baseQuery = this.templateSrv.replace(annotation.query, {}, \"glob\") || \"*:*\";\n const timeField = annotation.timeField || \"timestamp_dt\";\n const collection = annotation.collection || \"annotations\";\n const tagsField = annotation.tagsField || \"tags\";\n const titleField = annotation.titleField || \"desc\";\n const textField = annotation.textField || null;\n const start = options.range.from.toISOString();\n const end = options.range.to.toISOString();\n const query = {\n q: `${baseQuery} AND ${timeField}:[${start} TO ${end}]`,\n limit: 10\n };\n\n var url = this.url + '/solr/' + collection + '/select?wt=json&defType=edismax';\n\n var requestOptions;\n\n requestOptions = {\n method: 'GET',\n url: url,\n params: query\n };\n\n return this.doRequest(requestOptions).then((result) => {\n return _.map(result.data.response.docs, (doc) => {\n return {\n annotation: annotation,\n time: moment(doc[timeField]).valueOf(),\n title: doc[titleField],\n tags: doc[tagsField],\n text: doc[textField]\n };\n });\n });\n }\n\n doRequest(options) {\n options.withCredentials = this.withCredentials;\n options.headers = this.headers;\n if (this.basicAuth) {\n options.withCredentials = true;\n options.headers = {\n \"Authorization\": this.basicAuth\n };\n }\n\n return this.backendSrv.datasourceRequest(options);\n }\n}"]}
--------------------------------------------------------------------------------