diff --git a/NOTICE.txt b/NOTICE.txt index 3c55a5e0295..ad7c25aaad6 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1270,6 +1270,217 @@ Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-l limitations under the License. +-------------------------------------------------------------------------------- +Dependency : github.com/elastic/elastic-agent-system-metrics +Version: v0.4.4 +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-system-metrics@v0.4.4/LICENSE.txt: + + 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 [yyyy] [name of copyright owner] + + 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. + + -------------------------------------------------------------------------------- Dependency : github.com/elastic/go-licenser Version: v0.4.0 @@ -2009,6 +2220,43 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +Dependency : github.com/gorilla/mux +Version: v1.8.0 +Licence type (autodetected): BSD-3-Clause +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/gorilla/mux@v1.8.0/LICENSE: + +Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + -------------------------------------------------------------------------------- Dependency : github.com/hashicorp/go-multierror Version: v1.1.1 @@ -3996,12 +4244,12 @@ Contents of probable licence file $GOMODCACHE/go.elastic.co/apm@v1.15.0/LICENSE: -------------------------------------------------------------------------------- -Dependency : go.elastic.co/apm/module/apmgrpc +Dependency : go.elastic.co/apm/module/apmgorilla Version: v1.15.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/go.elastic.co/apm/module/apmgrpc@v1.15.0/LICENSE: +Contents of probable licence file $GOMODCACHE/go.elastic.co/apm/module/apmgorilla@v1.15.0/LICENSE: Apache License Version 2.0, January 2004 @@ -4207,13 +4455,12 @@ Contents of probable licence file $GOMODCACHE/go.elastic.co/apm/module/apmgrpc@v -------------------------------------------------------------------------------- -Dependency : go.elastic.co/ecszap -Version: v1.0.1 +Dependency : go.elastic.co/apm/module/apmgrpc +Version: v1.15.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/go.elastic.co/ecszap@v1.0.1/LICENSE: - +Contents of probable licence file $GOMODCACHE/go.elastic.co/apm/module/apmgrpc@v1.15.0/LICENSE: Apache License Version 2.0, January 2004 @@ -4403,7 +4650,219 @@ Contents of probable licence file $GOMODCACHE/go.elastic.co/ecszap@v1.0.1/LICENS same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2020 Elastic and contributors + Copyright 2018 Elasticsearch BV + + 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. + + +-------------------------------------------------------------------------------- +Dependency : go.elastic.co/ecszap +Version: v1.0.1 +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/go.elastic.co/ecszap@v1.0.1/LICENSE: + + + 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 2020 Elastic and contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -7491,6 +7950,217 @@ Contents of probable licence file $GOMODCACHE/github.com/docker/go-connections@v limitations under the License. +-------------------------------------------------------------------------------- +Dependency : github.com/elastic/go-structform +Version: v0.0.9 +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/elastic/go-structform@v0.0.9/LICENSE: + + 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 2012–2018 Elastic + + 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. + + -------------------------------------------------------------------------------- Dependency : github.com/elastic/go-windows Version: v1.0.1 @@ -7703,6 +8373,217 @@ Contents of probable licence file $GOMODCACHE/github.com/elastic/go-windows@v1.0 limitations under the License. +-------------------------------------------------------------------------------- +Dependency : github.com/elastic/gosigar +Version: v0.14.2 +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/elastic/gosigar@v0.14.2/LICENSE: + + 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 [yyyy] [name of copyright owner] + +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. + + -------------------------------------------------------------------------------- Dependency : github.com/elazarl/goproxy Version: v0.0.0-20180725130230-947c36da3153 @@ -9321,43 +10202,6 @@ Contents of probable licence file $GOMODCACHE/github.com/googleapis/gnostic@v0.5 --------------------------------------------------------------------------------- -Dependency : github.com/gorilla/mux -Version: v1.8.0 -Licence type (autodetected): BSD-3-Clause --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/github.com/gorilla/mux@v1.8.0/LICENSE: - -Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------------------- Dependency : github.com/grpc-ecosystem/go-grpc-middleware Version: v1.3.0 diff --git a/go.mod b/go.mod index 0aa3bfaa8cd..148cee40adc 100644 --- a/go.mod +++ b/go.mod @@ -14,12 +14,14 @@ require ( github.com/elastic/elastic-agent-autodiscover v0.0.0-20220404145827-89887023c1ab github.com/elastic/elastic-agent-client/v7 v7.0.0-20220804181728-b0328d2fe484 github.com/elastic/elastic-agent-libs v0.2.6 + github.com/elastic/elastic-agent-system-metrics v0.4.4 github.com/elastic/go-licenser v0.4.0 github.com/elastic/go-sysinfo v1.7.1 github.com/elastic/go-ucfg v0.8.5 github.com/gofrs/flock v0.8.1 github.com/gofrs/uuid v4.2.0+incompatible github.com/google/go-cmp v0.5.6 + github.com/gorilla/mux v1.8.0 github.com/hashicorp/go-multierror v1.1.1 github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 @@ -38,6 +40,7 @@ require ( github.com/spf13/cobra v1.3.0 github.com/stretchr/testify v1.7.0 github.com/tsg/go-daemon v0.0.0-20200207173439-e704b93fd89b + go.elastic.co/apm/module/apmgorilla v1.15.0 go.elastic.co/ecszap v1.0.1 go.elastic.co/go-licence-detector v0.5.0 go.uber.org/zap v1.21.0 @@ -69,7 +72,9 @@ require ( github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/docker v20.10.12+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect + github.com/elastic/go-structform v0.0.9 // indirect github.com/elastic/go-windows v1.0.1 // indirect + github.com/elastic/gosigar v0.14.2 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/fatih/color v1.13.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect diff --git a/go.sum b/go.sum index bc17c5e307b..47d8d474785 100644 --- a/go.sum +++ b/go.sum @@ -383,12 +383,16 @@ github.com/elastic/elastic-agent-client/v7 v7.0.0-20220804181728-b0328d2fe484/go github.com/elastic/elastic-agent-libs v0.0.0-20220303160015-5b4e674da3dd/go.mod h1://82M1l73IHx0wDbS2Tzkq6Fx9fkmytS1KgkIyzvNTM= github.com/elastic/elastic-agent-libs v0.2.6 h1:DpcUcCVYZ7lNtHLUlyT1u/GtGAh49wpL15DTH7+8O5o= github.com/elastic/elastic-agent-libs v0.2.6/go.mod h1:chO3rtcLyGlKi9S0iGVZhYCzDfdDsAQYBc+ui588AFE= +github.com/elastic/elastic-agent-system-metrics v0.4.4 h1:Br3S+TlBhijrLysOvbHscFhgQ00X/trDT5VEnOau0E0= +github.com/elastic/elastic-agent-system-metrics v0.4.4/go.mod h1:tF/f9Off38nfzTZHIVQ++FkXrDm9keFhFpJ+3pQ00iI= github.com/elastic/elastic-package v0.32.1/go.mod h1:l1fEnF52XRBL6a5h6uAemtdViz2bjtjUtgdQcuRhEAY= github.com/elastic/go-elasticsearch/v7 v7.16.0/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4= github.com/elastic/go-elasticsearch/v8 v8.0.0-20210317102009-a9d74cec0186/go.mod h1:xe9a/L2aeOgFKKgrO3ibQTnMdpAeL0GC+5/HpGScSa4= github.com/elastic/go-licenser v0.3.1/go.mod h1:D8eNQk70FOCVBl3smCGQt/lv7meBeQno2eI1S5apiHQ= github.com/elastic/go-licenser v0.4.0 h1:jLq6A5SilDS/Iz1ABRkO6BHy91B9jBora8FwGRsDqUI= github.com/elastic/go-licenser v0.4.0/go.mod h1:V56wHMpmdURfibNBggaSBfqgPxyT1Tldns1i87iTEvU= +github.com/elastic/go-structform v0.0.9 h1:HpcS7xljL4kSyUfDJ8cXTJC6rU5ChL1wYb6cx3HLD+o= +github.com/elastic/go-structform v0.0.9/go.mod h1:CZWf9aIRYY5SuKSmOhtXScE5uQiLZNqAFnwKR4OrIM4= github.com/elastic/go-sysinfo v1.1.1/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0= github.com/elastic/go-sysinfo v1.7.1 h1:Wx4DSARcKLllpKT2TnFVdSUJOsybqMYCNQZq1/wO+s0= github.com/elastic/go-sysinfo v1.7.1/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0= @@ -398,6 +402,8 @@ github.com/elastic/go-ucfg v0.8.5/go.mod h1:4E8mPOLSUV9hQ7sgLEJ4bvt0KhMuDJa8joDT github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU= github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0= github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss= +github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= +github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/elastic/package-spec v1.3.0/go.mod h1:KzGTSDqCkdhmL1IFpOH2ZQNSSE9JEhNtndxU3ZrQilA= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= @@ -634,8 +640,10 @@ github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2c github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= @@ -1189,6 +1197,8 @@ go.elastic.co/apm v1.13.0/go.mod h1:dylGv2HKR0tiCV+wliJz1KHtDyuD8SPe69oV7VyK6WY= go.elastic.co/apm v1.15.0 h1:uPk2g/whK7c7XiZyz/YCUnAUBNPiyNeE3ARX3G6Gx7Q= go.elastic.co/apm v1.15.0/go.mod h1:dylGv2HKR0tiCV+wliJz1KHtDyuD8SPe69oV7VyK6WY= go.elastic.co/apm/module/apmelasticsearch v1.10.0/go.mod h1:lwoaGDfZzfb9e6TXd3h8/KNmLAONOas7o5NLVNmv8Xk= +go.elastic.co/apm/module/apmgorilla v1.15.0 h1:1yTAksffgaFXYEIwlLRiQnxLfy3p3RtpDw8HDupIJfY= +go.elastic.co/apm/module/apmgorilla v1.15.0/go.mod h1:+23mZudYvZ9VgxCQjseLo9EF5gkKEr0KSQBupw+rzP8= go.elastic.co/apm/module/apmgrpc v1.15.0 h1:Z7h58uuMJUoYXK6INFunlcGEXZQ18QKAhPh6NFYDNHE= go.elastic.co/apm/module/apmgrpc v1.15.0/go.mod h1:IEbTGJzY5Xx737PkHDT3bbzh9syovK+IfAlckJsUgPE= go.elastic.co/apm/module/apmhttp v1.10.0/go.mod h1:Y4timwcJ8sQWbWpcw3Y7Mat1OssNpGhpwyfUnpqIDew= @@ -1429,6 +1439,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/internal/pkg/agent/application/application.go b/internal/pkg/agent/application/application.go index c5076535825..d3edb21888e 100644 --- a/internal/pkg/agent/application/application.go +++ b/internal/pkg/agent/application/application.go @@ -11,6 +11,7 @@ import ( "github.com/elastic/elastic-agent/internal/pkg/agent/application/coordinator" "github.com/elastic/elastic-agent/internal/pkg/agent/application/info" + "github.com/elastic/elastic-agent/internal/pkg/agent/application/monitoring" "github.com/elastic/elastic-agent/internal/pkg/agent/application/paths" "github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade" "github.com/elastic/elastic-agent/internal/pkg/agent/configuration" @@ -64,8 +65,9 @@ func New( } upgrader := upgrade.NewUpgrader(log, cfg.Settings.DownloadConfig, agentInfo) + monitor := monitoring.New(cfg.Settings.V1MonitoringEnabled, cfg.Settings.DownloadConfig.OS(), cfg.Settings.MonitoringConfig, agentInfo) - runtime, err := runtime.NewManager(log, cfg.Settings.GRPC.String(), agentInfo, tracer) + runtime, err := runtime.NewManager(log, cfg.Settings.GRPC.String(), agentInfo, tracer, monitor) if err != nil { return nil, fmt.Errorf("failed to initialize runtime manager: %w", err) } @@ -114,7 +116,7 @@ func New( return nil, errors.New(err, "failed to initialize composable controller") } - coord := coordinator.New(log, agentInfo, specs, reexec, upgrader, runtime, configMgr, composable, caps, compModifiers...) + coord := coordinator.New(log, agentInfo, specs, reexec, upgrader, runtime, configMgr, composable, caps, monitor, compModifiers...) if managed != nil { // the coordinator requires the config manager as well as in managed-mode the config manager requires the // coordinator, so it must be set here once the coordinator is created diff --git a/internal/pkg/agent/application/coordinator/coordinator.go b/internal/pkg/agent/application/coordinator/coordinator.go index e49198da65f..bc79482e80b 100644 --- a/internal/pkg/agent/application/coordinator/coordinator.go +++ b/internal/pkg/agent/application/coordinator/coordinator.go @@ -53,6 +53,18 @@ type UpgradeManager interface { Upgrade(ctx context.Context, version string, sourceURI string, action *fleetapi.ActionUpgrade) (_ reexec.ShutdownCallbackFn, err error) } +// MonitorManager provides an interface to perform the monitoring action for the agent. +type MonitorManager interface { + // Enabled when configured to collect metrics/logs. + Enabled() bool + + // Reload reloads the configuration for the upgrade manager. + Reload(rawConfig *config.Config) error + + // InjectMonitoring injects monitoring configuration into resolved ast tree. + MonitoringConfig(map[string]interface{}, map[string]string) (map[string]interface{}, error) +} + // Runner provides interface to run a manager and receive running errors. type Runner interface { // Run runs the manager. @@ -147,6 +159,7 @@ type Coordinator struct { reexecMgr ReExecManager upgradeMgr UpgradeManager + monitorMgr MonitorManager runtimeMgr RuntimeManager runtimeMgrErr error @@ -162,7 +175,7 @@ type Coordinator struct { } // New creates a new coordinator. -func New(logger *logger.Logger, agentInfo *info.AgentInfo, specs component.RuntimeSpecs, reexecMgr ReExecManager, upgradeMgr UpgradeManager, runtimeMgr RuntimeManager, configMgr ConfigManager, varsMgr VarsManager, caps capabilities.Capability, modifiers ...ComponentsModifier) *Coordinator { +func New(logger *logger.Logger, agentInfo *info.AgentInfo, specs component.RuntimeSpecs, reexecMgr ReExecManager, upgradeMgr UpgradeManager, runtimeMgr RuntimeManager, configMgr ConfigManager, varsMgr VarsManager, caps capabilities.Capability, monitorMgr MonitorManager, modifiers ...ComponentsModifier) *Coordinator { return &Coordinator{ logger: logger, agentInfo: agentInfo, @@ -177,6 +190,7 @@ func New(logger *logger.Logger, agentInfo *info.AgentInfo, specs component.Runti state: coordinatorState{ state: agentclient.Starting, }, + monitorMgr: monitorMgr, } } @@ -565,6 +579,10 @@ func (c *Coordinator) processConfig(ctx context.Context, cfg *config.Config) (er return fmt.Errorf("failed to reload upgrade manager configuration: %w", err) } + if err := c.monitorMgr.Reload(cfg); err != nil { + return fmt.Errorf("failed to reload upgrade manager configuration: %w", err) + } + c.state.config = cfg c.state.ast = rawAst @@ -630,7 +648,13 @@ func (c *Coordinator) compute() (map[string]interface{}, []component.Component, if err != nil { return nil, nil, fmt.Errorf("failed to convert ast to map[string]interface{}: %w", err) } - comps, err := c.specs.ToComponents(cfg) + + var configInjector component.GenerateMonitoringCfgFn + if c.monitorMgr.Enabled() { + configInjector = c.monitorMgr.MonitoringConfig + } + + comps, err := c.specs.ToComponents(cfg, configInjector) if err != nil { return nil, nil, fmt.Errorf("failed to render components: %w", err) } diff --git a/internal/pkg/agent/application/monitoring/handler.go b/internal/pkg/agent/application/monitoring/handler.go new file mode 100644 index 00000000000..6bec3eb37f2 --- /dev/null +++ b/internal/pkg/agent/application/monitoring/handler.go @@ -0,0 +1,70 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package monitoring + +import ( + "encoding/json" + "fmt" + "net/http" +) + +const errTypeUnexpected = "UNEXPECTED" + +type apiError interface { + Status() int +} + +func createHandler(fn func(w http.ResponseWriter, r *http.Request) error) *apiHandler { + return &apiHandler{ + innerFn: fn, + } +} + +type apiHandler struct { + innerFn func(w http.ResponseWriter, r *http.Request) error +} + +// ServeHTTP sets status code based on err returned +func (h *apiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + err := h.innerFn(w, r) + if err != nil { + switch e := err.(type) { // nolint:errorlint // Will need refactor. + case apiError: + w.WriteHeader(e.Status()) + default: + w.WriteHeader(http.StatusInternalServerError) + + } + + writeResponse(w, unexpectedErrorWithReason(err.Error())) + } +} + +func writeResponse(w http.ResponseWriter, c interface{}) { + bytes, err := json.Marshal(c) + if err != nil { + // json marshal failed + fmt.Fprintf(w, "Not valid json: %v", err) + return + } + + fmt.Fprint(w, string(bytes)) + +} + +type errResponse struct { + // Type is a type of error + Type string `json:"type"` + + // Reason is a detailed error message + Reason string `json:"reason"` +} + +func unexpectedErrorWithReason(reason string, args ...interface{}) errResponse { + return errResponse{ + Type: errTypeUnexpected, + Reason: fmt.Sprintf(reason, args...), + } +} diff --git a/internal/pkg/agent/application/monitoring/server.go b/internal/pkg/agent/application/monitoring/server.go new file mode 100644 index 00000000000..ef5a26df9d2 --- /dev/null +++ b/internal/pkg/agent/application/monitoring/server.go @@ -0,0 +1,86 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package monitoring + +import ( + "net/http" + "os" + "path/filepath" + "runtime" + "strings" + + "github.com/gorilla/mux" + "go.elastic.co/apm" + "go.elastic.co/apm/module/apmgorilla" + + "github.com/elastic/elastic-agent-libs/api" + "github.com/elastic/elastic-agent-libs/config" + "github.com/elastic/elastic-agent-libs/monitoring" + "github.com/elastic/elastic-agent/pkg/core/logger" +) + +// New creates a new server exposing metrics and process information. +func NewServer( + log *logger.Logger, + endpointConfig api.Config, + ns func(string) *monitoring.Namespace, + tracer *apm.Tracer, +) (*api.Server, error) { + if err := createAgentMonitoringDrop(endpointConfig.Host); err != nil { + // log but ignore + log.Errorf("failed to create monitoring drop: %v", err) + } + + cfg, err := config.NewConfigFrom(endpointConfig) + if err != nil { + return nil, err + } + + return exposeMetricsEndpoint(log, cfg, ns, tracer) +} + +func exposeMetricsEndpoint( + log *logger.Logger, + config *config.C, + ns func(string) *monitoring.Namespace, + tracer *apm.Tracer, +) (*api.Server, error) { + r := mux.NewRouter() + if tracer != nil { + r.Use(apmgorilla.Middleware(apmgorilla.WithTracer(tracer))) + } + statsHandler := statsHandler(ns("stats")) + r.Handle("/stats", createHandler(statsHandler)) + + mux := http.NewServeMux() + mux.Handle("/", r) + + return api.New(log, mux, config) +} + +func createAgentMonitoringDrop(drop string) error { + if drop == "" || runtime.GOOS == "windows" { + return nil + } + + path := strings.TrimPrefix(drop, "unix://") + if strings.HasSuffix(path, ".sock") { + path = filepath.Dir(path) + } + + _, err := os.Stat(path) + if err != nil { + if !os.IsNotExist(err) { + return err + } + + // create + if err := os.MkdirAll(path, 0775); err != nil { + return err + } + } + + return os.Chown(path, os.Geteuid(), os.Getegid()) +} diff --git a/internal/pkg/agent/application/monitoring/stats.go b/internal/pkg/agent/application/monitoring/stats.go new file mode 100644 index 00000000000..c395e224214 --- /dev/null +++ b/internal/pkg/agent/application/monitoring/stats.go @@ -0,0 +1,36 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package monitoring + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/elastic/elastic-agent-libs/monitoring" +) + +func statsHandler(ns *monitoring.Namespace) func(http.ResponseWriter, *http.Request) error { + return func(w http.ResponseWriter, r *http.Request) error { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + + data := monitoring.CollectStructSnapshot( + ns.GetRegistry(), + monitoring.Full, + false, + ) + + bytes, err := json.Marshal(data) + var content string + if err != nil { + content = fmt.Sprintf("Not valid json: %v", err) + } else { + content = string(bytes) + } + fmt.Fprint(w, content) + + return nil + } +} diff --git a/internal/pkg/agent/application/monitoring/v1_monitor.go b/internal/pkg/agent/application/monitoring/v1_monitor.go new file mode 100644 index 00000000000..1d8f2750afd --- /dev/null +++ b/internal/pkg/agent/application/monitoring/v1_monitor.go @@ -0,0 +1,913 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package monitoring + +import ( + "crypto/sha256" + "fmt" + "net/url" + "os" + "path/filepath" + "runtime" + "strings" + "unicode" + + "github.com/elastic/elastic-agent/internal/pkg/agent/application/info" + "github.com/elastic/elastic-agent/internal/pkg/agent/application/paths" + "github.com/elastic/elastic-agent/internal/pkg/agent/errors" + "github.com/elastic/elastic-agent/internal/pkg/config" + monitoringCfg "github.com/elastic/elastic-agent/internal/pkg/core/monitoring/config" +) + +const ( + // args: data path, pipeline name, application name + logFileFormat = "%s/logs/%s" + // args: data path, install path, pipeline name, application name + logFileFormatWin = "%s\\logs\\%s" + + // args: pipeline name, application name + mbEndpointFileFormatWin = `npipe:///%s` + + // args: pipeline name, application name + agentMbEndpointFileFormatWin = `npipe:///elastic-agent` + // agentMbEndpointHTTP is used with cloud and exposes metrics on http endpoint + agentMbEndpointHTTP = "http://%s:%d" + httpPlusPrefix = "http+" + httpPrefix = "http" + fileSchemePrefix = "file" + unixSchemePrefix = "unix" + + defaultOutputName = "default" + outputsKey = "outputs" + inputsKey = "inputs" + idKey = "id" + agentKey = "agent" + monitoringKey = "monitoring" + useOutputKey = "use_output" + monitoringOutput = "monitoring" + defaultMonitoringNamespace = "default" + agentName = "elastic-agent" + + windowsOS = "windows" +) + +var ( + supportedComponents = []string{"filebeat", "metricbeat", "apm-server", "auditbeat", "cloudbeat", "endpoint-security", "fleet-server", "heartbeat", "osquerybeat", "packetbeat"} + supportedBeatsComponents = []string{"filebeat", "metricbeat", "auditbeat", "cloudbeat", "heartbeat", "osquerybeat", "packetbeat"} +) + +// Beats monitor is providing V1 monitoring support. +type BeatsMonitor struct { + enabled bool // feature flag disabling whole v1 monitoring story + config *monitoringConfig + operatingSystem string + agentInfo *info.AgentInfo +} + +type monitoringConfig struct { + C *monitoringCfg.MonitoringConfig `config:"agent.monitoring"` +} + +// New creates a new BeatsMonitor instance. +func New(enabled bool, operatingSystem string, cfg *monitoringCfg.MonitoringConfig, agentInfo *info.AgentInfo) *BeatsMonitor { + return &BeatsMonitor{ + enabled: enabled, + config: &monitoringConfig{ + C: cfg, + }, + operatingSystem: operatingSystem, + agentInfo: agentInfo, + } +} + +// Enabled returns true if monitoring is enabled and at least one of logs and metrics should be collected. +func (b *BeatsMonitor) Enabled() bool { + return b.enabled && b.config.C.Enabled && (b.config.C.MonitorLogs || b.config.C.MonitorMetrics) +} + +// Reload refreshes monitoring configuration. +func (b *BeatsMonitor) Reload(rawConfig *config.Config) error { + if !b.Enabled() { + return nil + } + + if err := rawConfig.Unpack(&b.config); err != nil { + return errors.New(err, "failed to unpack monitoring config during reload") + } + return nil +} + +// MonitoringConfig adds monitoring inputs to a configuration based on retrieved list of components to run. +func (b *BeatsMonitor) MonitoringConfig(policy map[string]interface{}, componentIDToBinary map[string]string) (map[string]interface{}, error) { + if !b.Enabled() { + return nil, nil + } + + monitoringOutputName := defaultOutputName + if agentCfg, found := policy[agentKey]; found { + agentCfgMap, ok := agentCfg.(map[string]interface{}) + if ok { + if monitoringCfg, found := agentCfgMap[monitoringKey]; found { + monitoringMap, ok := monitoringCfg.(map[string]interface{}) + if ok { + if use, found := monitoringMap[useOutputKey]; found { + if useStr, ok := use.(string); ok { + monitoringOutputName = useStr + } + } + } + } + } + } + + cfg := make(map[string]interface{}) + + if err := b.injectMonitoringOutput(policy, cfg, monitoringOutputName); err != nil { + return nil, errors.New(err, "failed to inject monitoring output") + } + + // initializes inputs collection so injectors don't have to deal with it + b.initInputs(cfg) + + if b.config.C.MonitorLogs { + if err := b.injectLogsInput(cfg, componentIDToBinary, monitoringOutput); err != nil { + return nil, errors.New(err, "failed to inject monitoring output") + } + } + + if b.config.C.MonitorMetrics { + if err := b.injectMetricsInput(cfg, componentIDToBinary, monitoringOutput); err != nil { + return nil, errors.New(err, "failed to inject monitoring output") + } + } + return cfg, nil +} + +// EnrichArgs enriches arguments provided to application, in order to enable +// monitoring +func (b *BeatsMonitor) EnrichArgs(unit, binary string, args []string) []string { + if !b.enabled { + // even if monitoring is disabled enrich args. + // the only way to skip it is by disabling monitoring by feature flag + return args + } + + // only beats understands these flags + if !isSupportedBeatsBinary(binary) { + return args + } + + appendix := make([]string, 0, 20) + endpoint := endpointPath(unit, b.operatingSystem) + if endpoint != "" { + appendix = append(appendix, + "-E", "http.enabled=true", + "-E", "http.host="+endpoint, + ) + if b.config.C.Pprof != nil && b.config.C.Pprof.Enabled { + appendix = append(appendix, + "-E", "http.pprof.enabled=true", + ) + } + if b.config.C.HTTP.Buffer != nil && b.config.C.HTTP.Buffer.Enabled { + appendix = append(appendix, + "-E", "http.buffer.enabled=true", + ) + } + } + + loggingPath := loggingPath(unit, b.operatingSystem) + if loggingPath != "" { + appendix = append(appendix, + "-E", "logging.files.path="+filepath.Dir(loggingPath), + "-E", "logging.files.name="+filepath.Base(loggingPath), + "-E", "logging.files.keepfiles=7", + "-E", "logging.files.permission=0640", + "-E", "logging.files.interval=1h", + ) + + if !b.config.C.LogMetrics { + appendix = append(appendix, + "-E", "logging.metrics.enabled=false", + ) + } + } + + return append(args, appendix...) +} + +// Prepare executes steps in order for monitoring to work correctly +func (b *BeatsMonitor) Prepare() error { + if !b.Enabled() { + return nil + } + drops := make([]string, 0, 2) + if b.config.C.MonitorLogs { + logsDrop := loggingPath("unit", b.operatingSystem) + drops = append(drops, filepath.Dir(logsDrop)) + } + + if b.config.C.MonitorMetrics { + metricsDrop := monitoringDrop(endpointPath("unit", b.operatingSystem)) + drops = append(drops, metricsDrop) + } + + for _, drop := range drops { + if drop == "" { + continue + } + + // skip if already exists + if _, err := os.Stat(drop); err != nil { + if !os.IsNotExist(err) { + return err + } + + // create + if err := os.MkdirAll(drop, 0775); err != nil { + return errors.New(err, fmt.Sprintf("failed to create directory %q", drop)) + } + + uid, gid := os.Geteuid(), os.Getegid() + if err := changeOwner(drop, uid, gid); err != nil { + return errors.New(err, fmt.Sprintf("failed to change owner of directory %q", drop)) + } + } + } + + return nil +} + +// Cleanup removes +func (b *BeatsMonitor) Cleanup(unit string) error { + if !b.Enabled() { + return nil + } + + endpoint := monitoringFile(unit, b.operatingSystem) + if endpoint == "" { + return nil + } + + return os.RemoveAll(endpoint) +} + +func (b *BeatsMonitor) initInputs(cfg map[string]interface{}) { + _, found := cfg[inputsKey] + if found { + return + } + + inputsCollection := make([]interface{}, 0) + cfg[inputsKey] = inputsCollection +} + +func (b *BeatsMonitor) injectMonitoringOutput(source, dest map[string]interface{}, monitoringOutputName string) error { + outputsNode, found := source[outputsKey] + if !found { + return fmt.Errorf("outputs not part of the config") + } + + outputs, ok := outputsNode.(map[string]interface{}) + if !ok { + return fmt.Errorf("outputs not a map") + } + + outputNode, found := outputs[monitoringOutputName] + if !found { + return fmt.Errorf("output %q used for monitoring not found", monitoringOutputName) + } + + monitoringOutputs := map[string]interface{}{ + monitoringOutput: outputNode, + } + + dest[outputsKey] = monitoringOutputs + + return nil +} + +func (b *BeatsMonitor) injectLogsInput(cfg map[string]interface{}, componentIDToBinary map[string]string, monitoringOutput string) error { + monitoringNamespace := b.monitoringNamespace() + //fixedAgentName := strings.ReplaceAll(agentName, "-", "_") + logsDrop := filepath.Dir(loggingPath("unit", b.operatingSystem)) + + streams := []interface{}{ + map[string]interface{}{ + idKey: "logs-monitoring-agent", + "data_stream": map[string]interface{}{ + "type": "logs", + "dataset": "elastic_agent", + "namespace": monitoringNamespace, + }, + "paths": []interface{}{ + filepath.Join(logsDrop, agentName+"-*.ndjson"), + filepath.Join(logsDrop, agentName+"-watcher-*.ndjson"), + }, + "index": fmt.Sprintf("logs-elastic_agent-%s", monitoringNamespace), + "close": map[string]interface{}{ + "on_state_change": map[string]interface{}{ + "inactive": "5m", + }, + }, + "parsers": []interface{}{ + map[string]interface{}{ + "ndjson": map[string]interface{}{ + "overwrite_keys": true, + "message_key": "message", + }, + }, + }, + "processors": []interface{}{ + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "data_stream", + "fields": map[string]interface{}{ + "type": "logs", + "dataset": "elastic_agent", + "namespace": monitoringNamespace, + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "event", + "fields": map[string]interface{}{ + "dataset": "elastic_agent", + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "elastic_agent", + "fields": map[string]interface{}{ + "id": b.agentInfo.AgentID(), + "version": b.agentInfo.Version(), + "snapshot": b.agentInfo.Snapshot(), + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "agent", + "fields": map[string]interface{}{ + "id": b.agentInfo.AgentID(), + }, + }, + }, + map[string]interface{}{ + "drop_fields": map[string]interface{}{ + "fields": []interface{}{ + "ecs.version", //coming from logger, already added by libbeat + }, + "ignore_missing": true, + }, + }}, + }, + } + for unit, binaryName := range componentIDToBinary { + if !isSupportedBinary(binaryName) { + continue + } + + fixedBinaryName := strings.ReplaceAll(binaryName, "-", "_") + name := strings.ReplaceAll(unit, "-", "_") // conform with index naming policy + logFile := loggingPath(unit, b.operatingSystem) + streams = append(streams, map[string]interface{}{ + idKey: "logs-monitoring-" + name, + "data_stream": map[string]interface{}{ + "type": "logs", + "dataset": fmt.Sprintf("elastic_agent.%s", fixedBinaryName), + "namespace": monitoringNamespace, + }, + "index": fmt.Sprintf("logs-elastic_agent.%s-%s", fixedBinaryName, monitoringNamespace), + "paths": []interface{}{logFile, logFile + "*"}, + "close": map[string]interface{}{ + "on_state_change": map[string]interface{}{ + "inactive": "5m", + }, + }, + "parsers": []interface{}{ + map[string]interface{}{ + "ndjson": map[string]interface{}{ + "overwrite_keys": true, + "message_key": "message", + }, + }, + }, + "processors": []interface{}{ + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "data_stream", + "fields": map[string]interface{}{ + "type": "logs", + "dataset": fmt.Sprintf("elastic_agent.%s", fixedBinaryName), + "namespace": monitoringNamespace, + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "event", + "fields": map[string]interface{}{ + "dataset": fmt.Sprintf("elastic_agent.%s", fixedBinaryName), + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "elastic_agent", + "fields": map[string]interface{}{ + "id": b.agentInfo.AgentID(), + "version": b.agentInfo.Version(), + "snapshot": b.agentInfo.Snapshot(), + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "agent", + "fields": map[string]interface{}{ + "id": b.agentInfo.AgentID(), + }, + }, + }, + map[string]interface{}{ + "drop_fields": map[string]interface{}{ + "fields": []interface{}{ + "ecs.version", //coming from logger, already added by libbeat + }, + "ignore_missing": true, + }, + }, + }, + }) + } + + inputs := []interface{}{ + map[string]interface{}{ + idKey: "logs-monitoring-agent", + "name": "logs-monitoring-agent", + "type": "filestream", + useOutputKey: monitoringOutput, + "data_stream": map[string]interface{}{ + "namespace": monitoringNamespace, + }, + "streams": streams, + }, + } + inputsNode, found := cfg[inputsKey] + if !found { + return fmt.Errorf("no inputs in config") + } + + inputsCfg, ok := inputsNode.([]interface{}) + if !ok { + return fmt.Errorf("inputs is not an array") + } + + inputsCfg = append(inputsCfg, inputs...) + cfg[inputsKey] = inputsCfg + return nil +} + +func (b *BeatsMonitor) monitoringNamespace() string { + if ns := b.config.C.Namespace; ns != "" { + return ns + } + return defaultMonitoringNamespace +} +func (b *BeatsMonitor) injectMetricsInput(cfg map[string]interface{}, componentIDToBinary map[string]string, monitoringOutputName string) error { + monitoringNamespace := b.monitoringNamespace() + fixedAgentName := strings.ReplaceAll(agentName, "-", "_") + beatsStreams := make([]interface{}, 0, len(componentIDToBinary)) + streams := []interface{}{ + map[string]interface{}{ + idKey: "metrics-monitoring-agent", + "data_stream": map[string]interface{}{ + "type": "metrics", + "dataset": fmt.Sprintf("elastic_agent.%s", fixedAgentName), + "namespace": monitoringNamespace, + }, + "metricsets": []interface{}{"json"}, + "path": "/stats", + "hosts": []interface{}{HttpPlusAgentMonitoringEndpoint(b.operatingSystem, b.config.C)}, + "namespace": "agent", + "period": "10s", + "index": fmt.Sprintf("metrics-elastic_agent.%s-%s", fixedAgentName, monitoringNamespace), + "processors": []interface{}{ + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "data_stream", + "fields": map[string]interface{}{ + "type": "metrics", + "dataset": fmt.Sprintf("elastic_agent.%s", fixedAgentName), + "namespace": monitoringNamespace, + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "event", + "fields": map[string]interface{}{ + "dataset": fmt.Sprintf("elastic_agent.%s", fixedAgentName), + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "elastic_agent", + "fields": map[string]interface{}{ + "id": b.agentInfo.AgentID(), + "version": b.agentInfo.Version(), + "snapshot": b.agentInfo.Snapshot(), + "process": "elastic-agent", + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "agent", + "fields": map[string]interface{}{ + "id": b.agentInfo.AgentID(), + }, + }, + }, + map[string]interface{}{ + "copy_fields": map[string]interface{}{ + "fields": httpCopyRules(), + "ignore_missing": true, + "fail_on_error": false, + }, + }, + map[string]interface{}{ + "drop_fields": map[string]interface{}{ + "fields": []interface{}{ + "http", + }, + "ignore_missing": true, + }, + }, + }, + }, + } + for unit, binaryName := range componentIDToBinary { + if !isSupportedBinary(binaryName) { + continue + } + + endpoints := []interface{}{prefixedEndpoint(endpointPath(unit, b.operatingSystem))} + name := strings.ReplaceAll(unit, "-", "_") // conform with index naming policy + + if isSupportedBeatsBinary(binaryName) { + beatsStreams = append(beatsStreams, map[string]interface{}{ + idKey: "metrics-monitoring-" + name, + "data_stream": map[string]interface{}{ + "type": "metrics", + "dataset": fmt.Sprintf("elastic_agent.%s", name), + "namespace": monitoringNamespace, + }, + "metricsets": []interface{}{"stats", "state"}, + "hosts": endpoints, + "period": "10s", + "index": fmt.Sprintf("metrics-elastic_agent.%s-%s", fixedAgentName, monitoringNamespace), + "processors": []interface{}{ + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "data_stream", + "fields": map[string]interface{}{ + "type": "metrics", + "dataset": fmt.Sprintf("elastic_agent.%s", name), + "namespace": monitoringNamespace, + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "event", + "fields": map[string]interface{}{ + "dataset": fmt.Sprintf("elastic_agent.%s", name), + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "elastic_agent", + "fields": map[string]interface{}{ + "id": b.agentInfo.AgentID(), + "version": b.agentInfo.Version(), + "snapshot": b.agentInfo.Snapshot(), + "process": binaryName, + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "agent", + "fields": map[string]interface{}{ + "id": b.agentInfo.AgentID(), + }, + }, + }, + }, + }) + } + + streams = append(streams, map[string]interface{}{ + idKey: "metrics-monitoring-" + name + "-1", + "data_stream": map[string]interface{}{ + "type": "metrics", + "dataset": fmt.Sprintf("elastic_agent.%s", fixedAgentName), + "namespace": monitoringNamespace, + }, + "metricsets": []interface{}{"json"}, + "hosts": endpoints, + "path": "/stats", + "namespace": "agent", + "period": "10s", + "index": fmt.Sprintf("metrics-elastic_agent.%s-%s", fixedAgentName, monitoringNamespace), + "processors": []interface{}{ + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "event", + "fields": map[string]interface{}{ + "dataset": fmt.Sprintf("elastic_agent.%s", fixedAgentName), + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "elastic_agent", + "fields": map[string]interface{}{ + "id": b.agentInfo.AgentID(), + "version": b.agentInfo.Version(), + "snapshot": b.agentInfo.Snapshot(), + "process": name, + }, + }, + }, + map[string]interface{}{ + "add_fields": map[string]interface{}{ + "target": "agent", + "fields": map[string]interface{}{ + "id": b.agentInfo.AgentID(), + }, + }, + }, + map[string]interface{}{ + "copy_fields": map[string]interface{}{ + "fields": httpCopyRules(), + "ignore_missing": true, + "fail_on_error": false, + }, + }, + map[string]interface{}{ + "drop_fields": map[string]interface{}{ + "fields": []interface{}{ + "http", + }, + "ignore_missing": true, + }, + }, + }, + }) + } + + inputs := []interface{}{ + map[string]interface{}{ + idKey: "metrics-monitoring-beats", + "name": "metrics-monitoring-beats", + "type": "beat/metrics", + useOutputKey: monitoringOutput, + "data_stream": map[string]interface{}{ + "namespace": monitoringNamespace, + }, + "streams": beatsStreams, + }, + map[string]interface{}{ + idKey: "metrics-monitoring-agent", + "name": "metrics-monitoring-agent", + "type": "http/metrics", + useOutputKey: monitoringOutput, + "data_stream": map[string]interface{}{ + "namespace": monitoringNamespace, + }, + "streams": streams, + }, + } + + inputsNode, found := cfg[inputsKey] + if !found { + return fmt.Errorf("no inputs in config") + } + + inputsCfg, ok := inputsNode.([]interface{}) + if !ok { + return fmt.Errorf("inputs is not an array") + } + + inputsCfg = append(inputsCfg, inputs...) + cfg[inputsKey] = inputsCfg + return nil +} + +func loggingPath(id, operatingSystem string) string { + id = strings.ReplaceAll(id, string(filepath.Separator), "-") + if operatingSystem == windowsOS { + return fmt.Sprintf(logFileFormatWin, paths.Home(), id) + } + + return fmt.Sprintf(logFileFormat, paths.Home(), id) +} + +func endpointPath(id, operatingSystem string) (endpointPath string) { + id = strings.ReplaceAll(id, string(filepath.Separator), "-") + if operatingSystem == windowsOS { + return fmt.Sprintf(mbEndpointFileFormatWin, id) + } + // unix socket path must be less than 104 characters + path := fmt.Sprintf("unix://%s.sock", filepath.Join(paths.TempDir(), id)) + if len(path) < 104 { + return path + } + // place in global /tmp (or /var/tmp on Darwin) to ensure that its small enough to fit; current path is way to long + // for it to be used, but needs to be unique per Agent (in the case that multiple are running) + return fmt.Sprintf(`unix:///tmp/elastic-agent/%x.sock`, sha256.Sum256([]byte(path))) +} + +func prefixedEndpoint(endpoint string) string { + if endpoint == "" || strings.HasPrefix(endpoint, httpPlusPrefix) || strings.HasPrefix(endpoint, httpPrefix) { + return endpoint + } + + return httpPlusPrefix + endpoint +} + +func monitoringFile(id, operatingSystem string) string { + endpoint := endpointPath(id, operatingSystem) + if endpoint == "" { + return "" + } + if isNpipe(endpoint) { + return "" + } + + if isWindowsPath(endpoint) { + return endpoint + } + + u, _ := url.Parse(endpoint) + if u == nil || (u.Scheme != "" && u.Scheme != fileSchemePrefix && u.Scheme != unixSchemePrefix) { + return "" + } + + if u.Scheme == fileSchemePrefix { + return strings.TrimPrefix(endpoint, "file://") + } + + if u.Scheme == unixSchemePrefix { + return strings.TrimPrefix(endpoint, "unix://") + } + return endpoint +} + +func isNpipe(path string) bool { + return strings.HasPrefix(path, "npipe") || strings.HasPrefix(path, `\\.\pipe\`) +} + +func isWindowsPath(path string) bool { + if len(path) < 4 { + return false + } + return unicode.IsLetter(rune(path[0])) && path[1] == ':' +} + +func changeOwner(path string, uid, gid int) error { + if runtime.GOOS == windowsOS { + // on windows it always returns the syscall.EWINDOWS error, wrapped in *PathError + return nil + } + + return os.Chown(path, uid, gid) +} + +// HttpPlusAgentMonitoringEndpoint provides an agent monitoring endpoint path with a `http+` prefix. +func HttpPlusAgentMonitoringEndpoint(operatingSystem string, cfg *monitoringCfg.MonitoringConfig) string { + return prefixedEndpoint(AgentMonitoringEndpoint(operatingSystem, cfg)) +} + +// AgentMonitoringEndpoint provides an agent monitoring endpoint path. +func AgentMonitoringEndpoint(operatingSystem string, cfg *monitoringCfg.MonitoringConfig) string { + if cfg != nil && cfg.Enabled { + return fmt.Sprintf(agentMbEndpointHTTP, cfg.HTTP.Host, cfg.HTTP.Port) + } + + if operatingSystem == windowsOS { + return agentMbEndpointFileFormatWin + } + // unix socket path must be less than 104 characters + path := fmt.Sprintf("unix://%s.sock", filepath.Join(paths.TempDir(), agentName)) + if len(path) < 104 { + return path + } + // place in global /tmp to ensure that its small enough to fit; current path is way to long + // for it to be used, but needs to be unique per Agent (in the case that multiple are running) + return fmt.Sprintf(`unix:///tmp/elastic-agent/%x.sock`, sha256.Sum256([]byte(path))) +} + +func httpCopyRules() []interface{} { + fromToMap := []interface{}{ + // I should be able to see the CPU Usage on the running machine. Am using too much CPU? + map[string]interface{}{ + "from": "http.agent.beat.cpu", + "to": "system.process.cpu", + }, + + // I should be able to see the Memory usage of Elastic Agent. Is the Elastic Agent using too much memory? + map[string]interface{}{ + "from": "http.agent.beat.memstats.memory_sys", + "to": "system.process.memory.size", + }, + + // I should be able to see fd usage. Am I keep too many files open? + map[string]interface{}{ + "from": "http.agent.beat.handles", + "to": "system.process.fd", + }, + + // Cgroup reporting + map[string]interface{}{ + "from": "http.agent.beat.cgroup", + "to": "system.process.cgroup", + }, + + // apm-server specific + map[string]interface{}{ + "from": "http.agent.apm-server", + "to": "apm-server", + }, + } + + return fromToMap +} + +func isSupportedBinary(binaryName string) bool { + for _, supportedBinary := range supportedComponents { + if strings.EqualFold(supportedBinary, binaryName) { + return true + } + } + return false +} + +func isSupportedBeatsBinary(binaryName string) bool { + for _, supportedBinary := range supportedBeatsComponents { + if strings.EqualFold(supportedBinary, binaryName) { + return true + } + } + return false +} + +func monitoringDrop(path string) (drop string) { + defer func() { + if drop != "" { + // Dir call changes separator to the one used in OS + // '/var/lib' -> '\var\lib\' on windows + baseLen := len(filepath.Dir(drop)) + drop = drop[:baseLen] + } + }() + + if strings.Contains(path, "localhost") { + return "" + } + + path = strings.TrimPrefix(path, httpPlusPrefix) + + // npipe is virtual without a drop + if isNpipe(path) { + return "" + } + + if isWindowsPath(path) { + return path + } + + u, _ := url.Parse(path) + if u == nil || (u.Scheme != "" && u.Scheme != fileSchemePrefix && u.Scheme != unixSchemePrefix) { + return "" + } + + if u.Scheme == fileSchemePrefix { + return strings.TrimPrefix(path, "file://") + } + + if u.Scheme == unixSchemePrefix { + return strings.TrimPrefix(path, "unix://") + } + + return path +} diff --git a/internal/pkg/agent/cmd/inspect.go b/internal/pkg/agent/cmd/inspect.go index 77e917c9c3c..6d9b884aea4 100644 --- a/internal/pkg/agent/cmd/inspect.go +++ b/internal/pkg/agent/cmd/inspect.go @@ -17,7 +17,10 @@ import ( "github.com/elastic/elastic-agent-libs/logp" "github.com/elastic/elastic-agent-libs/service" + "github.com/elastic/elastic-agent/internal/pkg/agent/application/info" + "github.com/elastic/elastic-agent/internal/pkg/agent/application/monitoring" "github.com/elastic/elastic-agent/internal/pkg/agent/application/paths" + "github.com/elastic/elastic-agent/internal/pkg/agent/configuration" "github.com/elastic/elastic-agent/internal/pkg/agent/errors" "github.com/elastic/elastic-agent/internal/pkg/agent/transpiler" "github.com/elastic/elastic-agent/internal/pkg/agent/vars" @@ -45,6 +48,7 @@ wait that amount of time before using the variables for the configuration. Run: func(c *cobra.Command, args []string) { var opts inspectConfigOpts opts.variables, _ = c.Flags().GetBool("variables") + opts.includeMonitoring, _ = c.Flags().GetBool("monitoring") opts.variablesWait, _ = c.Flags().GetDuration("variables-wait") ctx, cancel := context.WithCancel(context.Background()) @@ -57,6 +61,7 @@ wait that amount of time before using the variables for the configuration. } cmd.Flags().Bool("variables", false, "render configuration with variables substituted") + cmd.Flags().Bool("monitoring", false, "includes monitoring configuration") cmd.Flags().Duration("variables-wait", time.Duration(0), "wait this amount of time for variables before performing substitution") cmd.AddCommand(newInspectComponentsCommandWithArgs(s, streams)) @@ -115,8 +120,9 @@ variables for the configuration. } type inspectConfigOpts struct { - variables bool - variablesWait time.Duration + variables bool + includeMonitoring bool + variablesWait time.Duration } func inspectConfig(ctx context.Context, cfgPath string, opts inspectConfigOpts, streams *cli.IOStreams) error { @@ -135,13 +141,53 @@ func inspectConfig(ctx context.Context, cfgPath string, opts inspectConfigOpts, return err } - if !opts.variables { + if !opts.variables && !opts.includeMonitoring { return printConfig(fullCfg, l, streams) } cfg, err := getConfigWithVariables(ctx, l, cfgPath, opts.variablesWait) if err != nil { return err } + + if opts.includeMonitoring { + // Load the requirements before trying to load the configuration. These should always load + // even if the configuration is wrong. + platform, err := component.LoadPlatformDetail() + if err != nil { + return fmt.Errorf("failed to gather system information: %w", err) + } + specs, err := component.LoadRuntimeSpecs(paths.Components(), platform) + if err != nil { + return fmt.Errorf("failed to detect inputs and outputs: %w", err) + } + + monitorFn, err := getMonitoringFn(cfg) + if err != nil { + return fmt.Errorf("failed to get monitoring: %w", err) + } + _, binaryMapping, err := specs.PolicyToComponents(cfg) + if err != nil { + return fmt.Errorf("failed to get binary mappings: %w", err) + } + monitorCfg, err := monitorFn(cfg, binaryMapping) + if err != nil { + return fmt.Errorf("failed to get monitoring config: %w", err) + } + + if monitorCfg != nil { + rawCfg := config.MustNewConfigFrom(cfg) + + if err := rawCfg.Merge(monitorCfg); err != nil { + return fmt.Errorf("failed to merge monitoring config: %w", err) + } + + cfg, err = rawCfg.ToMapStr() + if err != nil { + return fmt.Errorf("failed to convert monitoring config: %w", err) + } + } + } + return printMapStringConfig(cfg, streams) } @@ -212,8 +258,13 @@ func inspectComponents(ctx context.Context, cfgPath string, opts inspectComponen return err } + monitorFn, err := getMonitoringFn(m) + if err != nil { + return fmt.Errorf("failed to get monitoring: %w", err) + } + // Compute the components from the computed configuration. - comps, err := specs.ToComponents(m) + comps, err := specs.ToComponents(m, monitorFn) if err != nil { return fmt.Errorf("failed to render components: %w", err) } @@ -271,6 +322,26 @@ func inspectComponents(ctx context.Context, cfgPath string, opts inspectComponen return printComponents(comps, streams) } +func getMonitoringFn(cfg map[string]interface{}) (component.GenerateMonitoringCfgFn, error) { + config, err := config.NewConfigFrom(cfg) + if err != nil { + return nil, err + } + + agentCfg := configuration.DefaultConfiguration() + if err := config.Unpack(agentCfg); err != nil { + return nil, err + } + + agentInfo, err := info.NewAgentInfoWithLog("error", false) + if err != nil { + return nil, fmt.Errorf("could not load agent info: %w", err) + } + + monitor := monitoring.New(agentCfg.Settings.V1MonitoringEnabled, agentCfg.Settings.DownloadConfig.OS(), agentCfg.Settings.MonitoringConfig, agentInfo) + return monitor.MonitoringConfig, nil +} + func getConfigWithVariables(ctx context.Context, l *logger.Logger, cfgPath string, timeout time.Duration) (map[string]interface{}, error) { caps, err := capabilities.Load(paths.AgentCapabilitiesPath(), l) if err != nil { diff --git a/internal/pkg/agent/cmd/run.go b/internal/pkg/agent/cmd/run.go index ad8690d90ee..e6f9ec8d0f7 100644 --- a/internal/pkg/agent/cmd/run.go +++ b/internal/pkg/agent/cmd/run.go @@ -19,10 +19,15 @@ import ( apmtransport "go.elastic.co/apm/transport" "gopkg.in/yaml.v2" + monitoringLib "github.com/elastic/elastic-agent-libs/monitoring" + + "github.com/elastic/elastic-agent-libs/api" "github.com/elastic/elastic-agent-libs/service" + "github.com/elastic/elastic-agent-system-metrics/report" "github.com/elastic/elastic-agent/internal/pkg/agent/application" "github.com/elastic/elastic-agent/internal/pkg/agent/application/filelock" "github.com/elastic/elastic-agent/internal/pkg/agent/application/info" + "github.com/elastic/elastic-agent/internal/pkg/agent/application/monitoring" "github.com/elastic/elastic-agent/internal/pkg/agent/application/paths" "github.com/elastic/elastic-agent/internal/pkg/agent/application/reexec" "github.com/elastic/elastic-agent/internal/pkg/agent/application/secret" @@ -38,6 +43,7 @@ import ( "github.com/elastic/elastic-agent/internal/pkg/release" "github.com/elastic/elastic-agent/pkg/component" "github.com/elastic/elastic-agent/pkg/core/logger" + "github.com/elastic/elastic-agent/version" ) const ( @@ -164,6 +170,14 @@ func run(override cfgOverrider, modifiers ...component.PlatformModifier) error { return err } + serverStopFn, err := setupMetrics(logger, cfg.Settings.DownloadConfig.OS(), cfg.Settings.MonitoringConfig, tracer) + if err != nil { + return err + } + defer func() { + _ = serverStopFn() + }() + diagHooks := diagnostics.GlobalHooks() diagHooks = append(diagHooks, coord.DiagnosticHooks()...) control := server.New(logger.Named("control"), agentInfo, coord, tracer, diagHooks) @@ -327,7 +341,7 @@ func tryDelayEnroll(ctx context.Context, logger *logger.Logger, cfg *configurati enrollPath := paths.AgentEnrollFile() if _, err := os.Stat(enrollPath); err != nil { // no enrollment file exists or failed to stat it; nothing to do - return cfg, nil //nolint:nilerr // there is nothing to do + return cfg, nil } contents, err := ioutil.ReadFile(enrollPath) if err != nil { @@ -432,3 +446,29 @@ func initTracer(agentName, version string, mcfg *monitoringCfg.MonitoringConfig) Transport: ts, }) } + +func setupMetrics( + logger *logger.Logger, + operatingSystem string, + cfg *monitoringCfg.MonitoringConfig, + tracer *apm.Tracer, +) (func() error, error) { + if err := report.SetupMetrics(logger, agentName, version.GetDefaultVersion()); err != nil { + return nil, err + } + + // start server for stats + endpointConfig := api.Config{ + Enabled: true, + Host: monitoring.AgentMonitoringEndpoint(operatingSystem, cfg), + } + + s, err := monitoring.NewServer(logger, endpointConfig, monitoringLib.GetNamespace, tracer) + if err != nil { + return nil, errors.New(err, "could not start the HTTP server for the API") + } + s.Start() + + // return server stopper + return s.Stop, nil +} diff --git a/internal/pkg/agent/configuration/settings.go b/internal/pkg/agent/configuration/settings.go index 0a211101c4d..3b509270344 100644 --- a/internal/pkg/agent/configuration/settings.go +++ b/internal/pkg/agent/configuration/settings.go @@ -21,18 +21,20 @@ type SettingsConfig struct { LoggingConfig *logger.Config `yaml:"logging,omitempty" config:"logging,omitempty" json:"logging,omitempty"` // standalone config - Reload *ReloadConfig `config:"reload" yaml:"reload" json:"reload"` - Path string `config:"path" yaml:"path" json:"path"` + Reload *ReloadConfig `config:"reload" yaml:"reload" json:"reload"` + Path string `config:"path" yaml:"path" json:"path"` + V1MonitoringEnabled bool `config:"v1_monitoring_enabled" yaml:"v1_monitoring_enabled" json:"v1_monitoring_enabled"` } // DefaultSettingsConfig creates a config with pre-set default values. func DefaultSettingsConfig() *SettingsConfig { return &SettingsConfig{ - ProcessConfig: process.DefaultConfig(), - DownloadConfig: artifact.DefaultConfig(), - LoggingConfig: logger.DefaultLoggingConfig(), - MonitoringConfig: monitoringCfg.DefaultConfig(), - GRPC: DefaultGRPCConfig(), - Reload: DefaultReloadConfig(), + ProcessConfig: process.DefaultConfig(), + DownloadConfig: artifact.DefaultConfig(), + LoggingConfig: logger.DefaultLoggingConfig(), + MonitoringConfig: monitoringCfg.DefaultConfig(), + GRPC: DefaultGRPCConfig(), + Reload: DefaultReloadConfig(), + V1MonitoringEnabled: true, } } diff --git a/internal/pkg/agent/install/uninstall.go b/internal/pkg/agent/install/uninstall.go index df5c11d747c..fd99c3bbb82 100644 --- a/internal/pkg/agent/install/uninstall.go +++ b/internal/pkg/agent/install/uninstall.go @@ -167,7 +167,7 @@ func serviceComponentsFromConfig(specs component.RuntimeSpecs, cfg *config.Confi if err != nil { return nil, errors.New("failed to create a map from config", err) } - allComps, err := specs.ToComponents(mm) + allComps, err := specs.ToComponents(mm, nil) if err != nil { return nil, fmt.Errorf("failed to render components: %w", err) } diff --git a/internal/pkg/agent/vars/vars.go b/internal/pkg/agent/vars/vars.go index 7f0aff1c329..b685583895f 100644 --- a/internal/pkg/agent/vars/vars.go +++ b/internal/pkg/agent/vars/vars.go @@ -10,11 +10,12 @@ import ( "fmt" "time" + "golang.org/x/sync/errgroup" + "github.com/elastic/elastic-agent/internal/pkg/agent/transpiler" "github.com/elastic/elastic-agent/internal/pkg/composable" "github.com/elastic/elastic-agent/internal/pkg/config" "github.com/elastic/elastic-agent/pkg/core/logger" - "golang.org/x/sync/errgroup" ) func WaitForVariables(ctx context.Context, l *logger.Logger, cfg *config.Config, wait time.Duration) ([]*transpiler.Vars, error) { diff --git a/internal/pkg/core/monitoring/config/config.go b/internal/pkg/core/monitoring/config/config.go index cbaee09c9e2..bf5edd9716f 100644 --- a/internal/pkg/core/monitoring/config/config.go +++ b/internal/pkg/core/monitoring/config/config.go @@ -52,6 +52,7 @@ func DefaultConfig() *MonitoringConfig { MonitorTraces: false, HTTP: &MonitoringHTTPConfig{ Enabled: false, + Host: "localhost", Port: defaultPort, }, Namespace: defaultNamespace, diff --git a/pkg/component/component.go b/pkg/component/component.go index 20969e9a11d..f77b27d6fcf 100644 --- a/pkg/component/component.go +++ b/pkg/component/component.go @@ -17,6 +17,8 @@ import ( "github.com/elastic/elastic-agent/pkg/utils" ) +type GenerateMonitoringCfgFn func(map[string]interface{}, map[string]string) (map[string]interface{}, error) + const ( // defaultUnitLogLevel is the default log level that a unit will get if one is not defined. defaultUnitLogLevel = client.UnitLogLevelInfo @@ -79,19 +81,45 @@ type Component struct { } // ToComponents returns the components that should be running based on the policy and the current runtime specification. -func (r *RuntimeSpecs) ToComponents(policy map[string]interface{}) ([]Component, error) { - outputsMap, err := toIntermediate(policy) +func (r *RuntimeSpecs) ToComponents(policy map[string]interface{}, monitoringInjector GenerateMonitoringCfgFn) ([]Component, error) { + components, binaryMapping, err := r.PolicyToComponents(policy) if err != nil { return nil, err } + + if monitoringInjector != nil { + monitoringCfg, err := monitoringInjector(policy, binaryMapping) + if err != nil { + return nil, fmt.Errorf("failed to inject monitoring: %w", err) + } + + if monitoringCfg != nil { + // monitoring is enabled + monitoringComps, _, err := r.PolicyToComponents(monitoringCfg) + if err != nil { + return nil, fmt.Errorf("failed to generate monitoring components: %w", err) + } + + components = append(components, monitoringComps...) + } + } + + return components, nil +} + +func (r *RuntimeSpecs) PolicyToComponents(policy map[string]interface{}) ([]Component, map[string]string, error) { + outputsMap, err := toIntermediate(policy) + if err != nil { + return nil, nil, err + } if outputsMap == nil { - return nil, nil + return nil, nil, nil } // set the runtime variables that are available in the input specification runtime checks hasRoot, err := utils.HasRoot() if err != nil { - return nil, err + return nil, nil, err } vars, err := transpiler.NewVars(map[string]interface{}{ "runtime": map[string]interface{}{ @@ -109,10 +137,11 @@ func (r *RuntimeSpecs) ToComponents(policy map[string]interface{}) ([]Component, }, }, nil) if err != nil { - return nil, err + return nil, nil, err } var components []Component + componentIdsInputMap := make(map[string]string) for outputName, output := range outputsMap { if !output.enabled { // skip; not enabled @@ -179,10 +208,12 @@ func (r *RuntimeSpecs) ToComponents(policy map[string]interface{}) ([]Component, Spec: inputSpec, Units: units, }) + componentIdsInputMap[componentID] = inputSpec.BinaryName } } } - return components, nil + + return components, componentIdsInputMap, nil } // toIntermediate takes the policy and returns it into an intermediate representation that is easier to map into a set diff --git a/pkg/component/component_test.go b/pkg/component/component_test.go index f43dfc244c6..0d9e97d4c94 100644 --- a/pkg/component/component_test.go +++ b/pkg/component/component_test.go @@ -3,7 +3,6 @@ // you may not use this file except in compliance with the Elastic License. //nolint:dupl // duplicate code is in test cases - package component import ( @@ -915,7 +914,7 @@ func TestToComponents(t *testing.T) { runtime, err := LoadRuntimeSpecs(filepath.Join("..", "..", "specs"), scenario.Platform, SkipBinaryCheck()) require.NoError(t, err) - result, err := runtime.ToComponents(scenario.Policy) + result, err := runtime.ToComponents(scenario.Policy, nil) if scenario.Err != "" { assert.Equal(t, scenario.Err, err.Error()) } else { diff --git a/pkg/component/runtime/command.go b/pkg/component/runtime/command.go index 8c1722d657f..2cabe906b1f 100644 --- a/pkg/component/runtime/command.go +++ b/pkg/component/runtime/command.go @@ -35,6 +35,12 @@ const ( envAgentComponentInputType = "AGENT_COMPONENT_INPUT_TYPE" ) +type MonitoringManager interface { + EnrichArgs(string, string, []string) []string + Prepare() error + Cleanup(string) error +} + type procState struct { proc *process.Info state *os.ProcessState @@ -43,6 +49,7 @@ type procState struct { // CommandRuntime provides the command runtime for running a component as a subprocess. type CommandRuntime struct { current component.Component + monitor MonitoringManager ch chan ComponentState actionCh chan actionMode @@ -58,7 +65,7 @@ type CommandRuntime struct { } // NewCommandRuntime creates a new command runtime for the provided component. -func NewCommandRuntime(comp component.Component) (ComponentRuntime, error) { +func NewCommandRuntime(comp component.Component, monitor MonitoringManager) (ComponentRuntime, error) { if comp.Spec.Spec.Command == nil { return nil, errors.New("must have command defined in specification") } @@ -70,6 +77,7 @@ func NewCommandRuntime(comp component.Component) (ComponentRuntime, error) { compCh: make(chan component.Component), actionState: actionStop, state: newComponentState(&comp), + monitor: monitor, }, nil } @@ -279,7 +287,18 @@ func (c *CommandRuntime) start(comm Communicator) error { if err != nil { return fmt.Errorf("execution of component prevented: %w", err) } - proc, err := process.Start(path, uid, gid, cmdSpec.Args, env, attachOutErr, dirPath(workDir)) + + if err := c.monitor.Prepare(); err != nil { + return err + } + args := c.monitor.EnrichArgs(c.current.ID, c.current.Spec.BinaryName, cmdSpec.Args) + + // differentiate data paths + dataPath := filepath.Join(paths.Home(), "run", c.current.ID) + _ = os.MkdirAll(dataPath, 0755) + args = append(args, "-E", "path.data="+dataPath) + + proc, err := process.Start(path, uid, gid, args, env, attachOutErr, dirPath(workDir)) if err != nil { return err } @@ -303,6 +322,10 @@ func (c *CommandRuntime) stop(ctx context.Context) error { } return nil } + + // cleanup reserved resources related to monitoring + defer c.monitor.Cleanup(c.current.ID) //nolint:errcheck // this is ok + cmdSpec := c.current.Spec.Spec.Command go func(info *process.Info, timeout time.Duration) { t := time.NewTimer(timeout) diff --git a/pkg/component/runtime/manager.go b/pkg/component/runtime/manager.go index b475ddef4ca..d713a9a10c4 100644 --- a/pkg/component/runtime/manager.go +++ b/pkg/component/runtime/manager.go @@ -73,6 +73,7 @@ type Manager struct { listenAddr string agentInfo *info.AgentInfo tracer *apm.Tracer + monitor MonitoringManager netMx sync.RWMutex listener net.Listener @@ -95,7 +96,7 @@ type Manager struct { } // NewManager creates a new manager. -func NewManager(logger *logger.Logger, listenAddr string, agentInfo *info.AgentInfo, tracer *apm.Tracer) (*Manager, error) { +func NewManager(logger *logger.Logger, listenAddr string, agentInfo *info.AgentInfo, tracer *apm.Tracer, monitor MonitoringManager) (*Manager, error) { ca, err := authority.NewCA() if err != nil { return nil, err @@ -110,6 +111,7 @@ func NewManager(logger *logger.Logger, listenAddr string, agentInfo *info.AgentI current: make(map[string]*componentRuntimeState), subscriptions: make(map[string][]*Subscription), errCh: make(chan error), + monitor: monitor, } return m, nil } @@ -619,7 +621,7 @@ func (m *Manager) update(components []component.Component, teardown bool) error } else { // new component; create its runtime logger := m.logger.Named(fmt.Sprintf("component.runtime.%s", comp.ID)) - state, err := newComponentRuntimeState(m, logger, comp) + state, err := newComponentRuntimeState(m, logger, m.monitor, comp) if err != nil { return fmt.Errorf("failed to create new component %s: %w", comp.ID, err) } diff --git a/pkg/component/runtime/manager_test.go b/pkg/component/runtime/manager_test.go index 1475e6fd094..b71a24c35e0 100644 --- a/pkg/component/runtime/manager_test.go +++ b/pkg/component/runtime/manager_test.go @@ -3,7 +3,6 @@ // you may not use this file except in compliance with the Elastic License. //nolint:dupl // duplicate code is in test cases - package runtime import ( @@ -29,7 +28,8 @@ import ( ) const ( - exeExt = ".exe" + exeExt = ".exe" + errActionUndefined = "action undefined" ) var ( @@ -50,7 +50,7 @@ func TestManager_SimpleComponentErr(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -152,7 +152,7 @@ func TestManager_FakeInput_StartStop(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -277,7 +277,7 @@ func TestManager_FakeInput_BadUnitToGood(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -448,7 +448,7 @@ func TestManager_FakeInput_GoodUnitToBad(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -603,7 +603,7 @@ func TestManager_FakeInput_Configure(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -729,7 +729,7 @@ func TestManager_FakeInput_RemoveUnit(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -887,7 +887,7 @@ func TestManager_FakeInput_ActionState(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -1017,7 +1017,7 @@ func TestManager_FakeInput_Restarts(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -1156,7 +1156,7 @@ func TestManager_FakeInput_RestartsOnMissedCheckins(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -1277,7 +1277,7 @@ func TestManager_FakeInput_InvalidAction(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -1340,7 +1340,7 @@ func TestManager_FakeInput_InvalidAction(t *testing.T) { actionCancel() if err == nil { subErrCh <- fmt.Errorf("should have returned an error") - } else if err.Error() != "action undefined" { + } else if err.Error() != errActionUndefined { subErrCh <- fmt.Errorf("should have returned error: action undefined") } else { subErrCh <- nil @@ -1401,7 +1401,7 @@ func TestManager_FakeInput_MultiComponent(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -1613,7 +1613,7 @@ func TestManager_FakeInput_LogLevel(t *testing.T) { defer cancel() ai, _ := info.NewAgentInfo(true) - m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer) + m, err := NewManager(newErrorLogger(t), "localhost:0", ai, apmtest.DiscardTracer, newTestMonitoringMgr()) require.NoError(t, err) errCh := make(chan error) go func() { @@ -1691,7 +1691,7 @@ func TestManager_FakeInput_LogLevel(t *testing.T) { actionCancel() if err == nil { subErrCh <- fmt.Errorf("should have returned an error") - } else if err.Error() != "action undefined" { + } else if err.Error() != errActionUndefined { subErrCh <- fmt.Errorf("should have returned error: action undefined") } else { subErrCh <- nil @@ -1830,3 +1830,11 @@ func testBinary(t *testing.T) string { } return binaryPath } + +type testMonitoringManager struct{} + +func newTestMonitoringMgr() *testMonitoringManager { return &testMonitoringManager{} } + +func (*testMonitoringManager) EnrichArgs(_ string, _ string, args []string) []string { return args } +func (*testMonitoringManager) Prepare() error { return nil } +func (*testMonitoringManager) Cleanup(string) error { return nil } diff --git a/pkg/component/runtime/runtime.go b/pkg/component/runtime/runtime.go index 43731645b5f..58c7d1ed153 100644 --- a/pkg/component/runtime/runtime.go +++ b/pkg/component/runtime/runtime.go @@ -54,11 +54,11 @@ type ComponentRuntime interface { } // NewComponentRuntime creates the proper runtime based on the input specification for the component. -func NewComponentRuntime(comp component.Component) (ComponentRuntime, error) { +func NewComponentRuntime(comp component.Component, monitor MonitoringManager) (ComponentRuntime, error) { if comp.Err != nil { return NewFailedRuntime(comp) } else if comp.Spec.Spec.Command != nil { - return NewCommandRuntime(comp) + return NewCommandRuntime(comp, monitor) } else if comp.Spec.Spec.Service != nil { return nil, errors.New("service component runtime not implemented") } @@ -82,12 +82,12 @@ type componentRuntimeState struct { actions map[string]func(*proto.ActionResponse) } -func newComponentRuntimeState(m *Manager, logger *logger.Logger, comp component.Component) (*componentRuntimeState, error) { +func newComponentRuntimeState(m *Manager, logger *logger.Logger, monitor MonitoringManager, comp component.Component) (*componentRuntimeState, error) { comm, err := newRuntimeComm(logger, m.getListenAddr(), m.ca, m.agentInfo) if err != nil { return nil, err } - runtime, err := NewComponentRuntime(comp) + runtime, err := NewComponentRuntime(comp, monitor) if err != nil { return nil, err } diff --git a/specs/metricbeat.spec.yml b/specs/metricbeat.spec.yml index a744cdb535f..b160a4f29e7 100644 --- a/specs/metricbeat.spec.yml +++ b/specs/metricbeat.spec.yml @@ -155,3 +155,9 @@ inputs: outputs: *outputs command: args: *args + - name: http/metrics + description: "HTTP metrics" + platforms: *platforms + outputs: *outputs + command: + args: *args diff --git a/version/version.go b/version/version.go index f5101a34efa..60029093c35 100644 --- a/version/version.go +++ b/version/version.go @@ -4,4 +4,4 @@ package version -const defaultBeatVersion = "8.5.0" +const defaultBeatVersion = "8.6.0"