diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2019-10-13 08:36:33 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2019-10-13 08:36:33 +0000 |
commit | a30a849b78fa4fe8552141b7b2802d1af1b18c09 (patch) | |
tree | fab3c8bf29bf2d565595d4fa6a9413916ff02fee | |
parent | Adding upstream version 1.17.1. (diff) | |
download | netdata-a30a849b78fa4fe8552141b7b2802d1af1b18c09.tar.xz netdata-a30a849b78fa4fe8552141b7b2802d1af1b18c09.zip |
Adding upstream version 1.18.0.upstream/1.18.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
174 files changed, 11296 insertions, 2787 deletions
diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..50d4af0c4 --- /dev/null +++ b/.clang-format @@ -0,0 +1,118 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# clang-format configuration file. Intended for clang-format >= 4. +# +# For more information, see: +# +# Documentation/process/clang-format.rst +# https://clang.llvm.org/docs/ClangFormat.html +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +#AlignEscapedNewlines: Left # Unknown to clang-format-4.0 +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + #AfterExternBlock: false # Unknown to clang-format-5.0 + BeforeCatch: false + BeforeElse: false + IndentBraces: false + #SplitEmptyFunction: true # Unknown to clang-format-4.0 + #SplitEmptyRecord: true # Unknown to clang-format-4.0 + #SplitEmptyNamespace: true # Unknown to clang-format-4.0 +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0 +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0 +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +#CompactNamespaces: false # Unknown to clang-format-4.0 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +#FixNamespaceComments: false # Unknown to clang-format-4.0 + +#IncludeBlocks: Preserve # Unknown to clang-format-5.0 +IncludeCategories: + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: true +#IndentPPDirectives: None # Unknown to clang-format-5.0 +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: Inner +#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0 +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true + +# Taken from git's rules +#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +#SortUsingDeclarations: false # Unknown to clang-format-4.0 +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0 +#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0 +SpaceBeforeParens: ControlStatements +#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0 +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp03 +TabWidth: 4 +UseTab: Never +... diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 35070e49d..107d42135 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,14 +5,14 @@ * @ktsaou @cakrit @cosmix # Ownership by directory structure -.travis/ @cakrit @cosmix -.github/ @cakrit @cosmix +.travis/ @cakrit @cosmix @knatsakis +.github/ @cakrit @cosmix @knatsakis backends/ @thiagoftsm @vlvkobal backends/graphite/ @thiagoftsm @vlvkobal backends/json/ @thiagoftsm @vlvkobal backends/opentsdb/ @thiagoftsm @vlvkobal backends/prometheus/ @vlvkobal @thiagoftsm -build/ @cakrit @cosmix +build/ @cakrit @cosmix @knatsakis collectors/ @vlvkobal @mfundul @cakrit @cosmix collectors/charts.d.plugin/ @cakrit @cosmix collectors/freebsd.plugin/ @vlvkobal @thiagoftsm @cakrit @cosmix @@ -30,9 +30,7 @@ health/ @thiagoftsm @vlvkobal @cakrit @cosmix health/health.d/ @thiagoftsm @vlvkobal @cakrit @cosmix health/notifications/ @Ferroin @thiagoftsm @cakrit @cosmix libnetdata/ @thiagofsm @mfundul @cakrit @cosmix -packaging/ @cakrit @cosmix -packaging/installer/ @cakrit @cosmix -packaging/makeself/ @cakrit @cosmix +packaging/ @cakrit @cosmix @knatsakis registry/ @VLegakis @cakrit @cosmix streaming/ @thiagoftsm @vlvkobal @cakrit @cosmix web/ @thiagoftsm @mfundul @vlvkobal @cakrit @cosmix @@ -40,19 +38,19 @@ web/gui/ @VLegakis @cakrit @cosmix # Ownership by filetype (overwrites ownership by directory) *.md @cakrit @cosmix @joelhans -*.am @cakrit @cosmix +*.am @cakrit @cosmix @knatsakis # Ownership of specific files -.gitignore @cakrit @cosmix -.travis.yml @cakrit @cosmix -.lgtm.yml @cakrit @cosmix -.eslintrc @cakrit @cosmix -.eslintignore @cakrit @cosmix -.csslintrc @cakrit @cosmix -.codeclimate.yml @cakrit @cosmix -.codacy.yml @cakrit @cosmix -netdata.spec.in @cakrit @cosmix -netdata-installer.sh @cakrit @cosmix +.gitignore @cakrit @cosmix @knatsakis +.travis.yml @cakrit @cosmix @knatsakis +.lgtm.yml @cakrit @cosmix @knatsakis +.eslintrc @cakrit @cosmix @knatsakis +.eslintignore @cakrit @cosmix @knatsakis +.csslintrc @cakrit @cosmix @knatsakis +.codeclimate.yml @cakrit @cosmix @knatsakis +.codacy.yml @cakrit @cosmix @knatsakis +netdata.spec.in @cakrit @cosmix @knatsakis +netdata-installer.sh @cakrit @cosmix @knatsakis netlify.toml @cakrit @cosmix package.json @VLegakis packaging/version @netdatabot diff --git a/.gitignore b/.gitignore index 1222d46ea..afb0c67bd 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,9 @@ xenstat.plugin perf.plugin !perf.plugin/ +slabinfo.plugin +!slabinfo.plugin/ + cgroup-network !cgroup-network/ @@ -167,6 +170,7 @@ sitespeed-result/ tests/acls/acl.sh tests/urls/request.sh tests/alarm_repetition/alarm.sh +tests/template_dimension/template_dim.sh # tests and temp files python.d/python-modules-installer.sh diff --git a/.squash.yml b/.squash.yml new file mode 100644 index 000000000..58e591034 --- /dev/null +++ b/.squash.yml @@ -0,0 +1,7 @@ +deployments: + netdata: + auto_deploy_on_commits: true + filename: ./packaging/docker/Dockerfile + context_path: ./ + port_forwarding: 80:19999 + run_options: -v /proc:/host/proc:ro -v /sys:/host/sys:ro -v /var/run/docker.sock:/var/run/docker.sock:ro --cap-add SYS_PTRACE --security-opt apparmor=unconfined diff --git a/.travis.yml b/.travis.yml index 8d9cea2ca..efe1fb601 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,9 +27,13 @@ install: - export LATEST_RELEASE_DATE="$(git log -1 --format=%aD "${LATEST_RELEASE_VERSION}" | cat)" - if [[ "${TRAVIS_COMMIT_MESSAGE}" = *"[Build latest]"* ]]; then export BUILD_VERSION="$(cat packaging/version | cut -d'-' -f1,2 | sed -e 's/-/./g').latest"; fi; - export DEPLOY_REPO="netdata" # Default production packaging repository + - export PACKAGING_USER="netdata" # Standard package cloud account - if [[ "${TRAVIS_COMMIT_MESSAGE}" = *"[Build latest]"* ]]; then export DEPLOY_REPO="netdata-edge"; fi; - - export PACKAGING_USER="$(echo ${TRAVIS_REPO_SLUG} | cut -d'/' -f1)" - export PACKAGE_CLOUD_RETENTION_DAYS=30 + - if [ ! "${TRAVIS_REPO_SLUG}" = "netdata/netdata" ]; then export DEPLOY_REPO="netdata-devel"; fi; + # These are release-related artifacts and have to be evaluated before we start doing conditional checks inside stages + - source ".travis/tagger.sh" + - export GIT_TAG="$(git tag --points-at)" @@ -52,13 +56,12 @@ stages: # Nightly operations - name: Nightly operations - #if: branch = master AND type = cron - if: branch =fix-coverity-toolkit + if: branch = master AND type = cron - name: Nightly release if: branch = master AND type = cron # Scheduled releases - - name: Packaging for release + - name: Support activities on main branch if: branch = master AND type != pull_request AND type != cron - name: Publish for release @@ -240,22 +243,23 @@ jobs: - - stage: Packaging for release + - stage: Support activities on main branch + name: Run labeler on github issues + script: .travis/labeler.sh # labeler should be replaced with GitHub Actions when they hit GA - name: Generate changelog and TAG the release (only on special commit msg) - before_script: post_message "TRAVIS_MESSAGE" "Packaging step for release initiated" "${NOTIF_CHANNEL}" + - name: Generate changelog for release (only on special and tagged commit msg) + before_script: post_message "TRAVIS_MESSAGE" "Support activities on main branch initiated" "${NOTIF_CHANNEL}" script: - echo "GIT Branch:" && git branch - echo "Last commit:" && git log -1 - echo "GIT Describe:" && git describe - echo "packaging/version:" && cat packaging/version + - if [[ -z "${GIT_TAG}" ]]; then echo "Running set tag for release" && set_tag_for_release; fi; - .travis/generate_changelog_and_tag_release.sh - after_failure: post_message "TRAVIS_MESSAGE" "<!here> Packaging for release failed" + after_failure: post_message "TRAVIS_MESSAGE" "<!here> Changelog generation and tag of release, failed" git: depth: false - - - name: Run labeler on github issues - script: .travis/labeler.sh # labeler should be replaced with GitHub Actions when they hit GA + if: commit_message =~ /\[netdata (release candidate|(major|minor|patch) release)\]/ AND tag !~ /(-rc)/ OR (env(GIT_TAG) IS present AND NOT env(GIT_TAG) IS blank) @@ -411,19 +415,19 @@ jobs: - if [ -n "${BUILDER_NAME}" ]; then rm -rf /home/${BUILDER_NAME}/* && echo "Cleared /home/${BUILDER_NAME} directory" || echo "Failed to clean /home/${BUILDER_NAME} directory"; fi; - if [ -d "${PACKAGES_DIRECTORY}" ]; then rm -rf "${PACKAGES_DIRECTORY}"; fi; - name: "Build & Publish RPM package for Enterprise Linux 7" + name: "Build & Publish RPM package for Enterprise Linux 6" <<: *RPM_TEMPLATE if: commit_message =~ /\[Package (amd64|arm64|i386) RPM( Enterprise Linux)?\]/ env: - - BUILDER_NAME="builder" BUILD_DISTRO="centos" BUILD_RELEASE="7" BUILD_STRING="el/7" + - BUILDER_NAME="builder" BUILD_DISTRO="centos" BUILD_RELEASE="6" BUILD_STRING="el/6" - PACKAGE_TYPE="rpm" REPO_TOOL="yum" - ALLOW_SOFT_FAILURE_HERE=true - - name: "Build & Publish RPM package for Enterprise Linux 6" + - name: "Build & Publish RPM package for Enterprise Linux 7" <<: *RPM_TEMPLATE - if: commit_message =~ /\[Package (amd64|arm64|i386) RPM( Enterprise Linux)?\]/ + if: commit_message =~ /\[Package (amd64|arm64) RPM( Enterprise Linux)?\]/ env: - - BUILDER_NAME="builder" BUILD_DISTRO="centos" BUILD_RELEASE="6" BUILD_STRING="el/6" + - BUILDER_NAME="builder" BUILD_DISTRO="centos" BUILD_RELEASE="7" BUILD_STRING="el/7" - PACKAGE_TYPE="rpm" REPO_TOOL="yum" - ALLOW_SOFT_FAILURE_HERE=true @@ -521,8 +525,7 @@ jobs: - name: Trigger .RPM and .DEB package generation before_script: post_message "TRAVIS_MESSAGE" "Starting RPM and DEB package generation for release" "${NOTIF_CHANNEL}" script: - - if [[ -z "${GIT_TAG}" ]] || [[ ! "${GIT_TAG}" = "$(git tag --points-at)" ]]; then post_message "TRAVIS_MESSAGE" "<!here> I Did not find a valid GIT_TAG to proceed with stable packaging" "${NOTIF_CHANNEL}" && exit 1; fi; - - if [[ -n "${GIT_TAG}" ]] && [[ "${GIT_TAG}" = "$(git tag --points-at)" ]]; then .travis/trigger_package_generation.sh; fi; + - .travis/trigger_package_generation.sh after_failure: post_message "TRAVIS_MESSAGE" "<!here> Stable release package generation produced errors" "${NOTIF_CHANNEL}" git: depth: false diff --git a/.travis/generate_changelog_for_release.sh b/.travis/create_changelog.sh index d7066aa9b..8d4c12ee1 100755 --- a/.travis/generate_changelog_for_release.sh +++ b/.travis/create_changelog.sh @@ -1,16 +1,24 @@ -#!/bin/bash - +#!/usr/bin/env bash +# +# Copyright: SPDX-License-Identifier: GPL-3.0-or-later +# +# Author : Pavlos Emm. Katsoulakis (paul@netdata.cloud) set -e -if [ ! -f .gitignore ]; then - echo "Run as ./travis/$(basename "$0") from top level directory of git repository" - exit 1 +# If we are not in netdata git repo, at the top level directory, fail +TOP_LEVEL=$(basename "$(git rev-parse --show-toplevel)") +CWD=$(git rev-parse --show-cdup || echo "") +if [ -n "$CWD" ] || [ ! "${TOP_LEVEL}" == "netdata" ]; then + echo "Run as .travis/$(basename "$0") from top level directory of netdata git repository" + echo "Changelog creation aborted" + exit 1 fi ORGANIZATION=$(echo "$TRAVIS_REPO_SLUG" | awk -F '/' '{print $1}') PROJECT=$(echo "$TRAVIS_REPO_SLUG" | awk -F '/' '{print $2}') GIT_MAIL=${GIT_MAIL:-"bot@netdata.cloud"} GIT_USER=${GIT_USER:-"netdatabot"} + if [ -z ${GIT_TAG+x} ]; then OPTS="" else @@ -18,20 +26,21 @@ else fi if [ ! "${TRAVIS_REPO_SLUG}" == "netdata/netdata" ]; then - echo "Beta mode on ${TRAVIS_REPO_SLUG}, nothing else to do" + echo "Beta mode on ${TRAVIS_REPO_SLUG}, nothing else to do here" exit 0 fi echo "--- Creating changelog ---" git checkout master git pull -#docker run -it --rm -v "$(pwd)":/usr/local/src/your-app ferrarimarco/github-changelog-generator:1.14.3 \ + docker run -it -v "$(pwd)":/project markmandel/github-changelog-generator:latest \ --user "${ORGANIZATION}" \ --project "${PROJECT}" \ --token "${GITHUB_TOKEN}" \ --since-tag "v1.10.0" \ - --no-issues \ --unreleased-label "**Next release**" \ + --no-issues \ --exclude-labels "stale,duplicate,question,invalid,wontfix,discussion,no changelog" \ - --no-compare-link ${OPTS} + --max-issues 500 \ + --bug-labels IGNOREBUGS ${OPTS} diff --git a/.travis/generate_changelog_and_tag_release.sh b/.travis/generate_changelog_and_tag_release.sh index 4613ab14b..bf5555b4c 100755 --- a/.travis/generate_changelog_and_tag_release.sh +++ b/.travis/generate_changelog_and_tag_release.sh @@ -30,14 +30,11 @@ if [ ! -f .gitignore ]; then exit 1 fi -echo "--- Executing Tagging facility to determine TAG ---" -source .travis/tagger.sh - -echo "--- Changelog generator and tagger script starting ---" -# If tagger script hasn't produced a TAG, there is nothing to do so bail out happy +echo "--- Changelog generator script starting ---" +# If we dont have a produced TAG there is nothing to do, so bail out happy if [ -z "${GIT_TAG}" ]; then - echo "GIT_TAG is empty, nothing to do for now (Value: $GIT_TAG)" - exit 0 + echo "GIT_TAG is empty, that is not suppose to happen (Value: $GIT_TAG)" + exit 1 fi if [ ! "${TRAVIS_REPO_SLUG}" == "netdata/netdata" ]; then @@ -55,9 +52,9 @@ echo "---- UPDATE VERSION FILE ----" echo "$GIT_TAG" >packaging/version git add packaging/version -#echo "---- GENERATE CHANGELOG -----" -#./.travis/generate_changelog_for_release.sh -#git add CHANGELOG.md +echo "---- Create CHANGELOG -----" +./.travis/create_changelog.sh +git add CHANGELOG.md echo "---- COMMIT AND PUSH CHANGES ----" git commit -m "[ci skip] release $GIT_TAG" --author "${GIT_USER} <${GIT_MAIL}>" diff --git a/.travis/generate_changelog_for_nightlies.sh b/.travis/generate_changelog_for_nightlies.sh index b90862880..59173af3f 100755 --- a/.travis/generate_changelog_for_nightlies.sh +++ b/.travis/generate_changelog_for_nightlies.sh @@ -1,6 +1,6 @@ -#!/bin/bash +#!/usr/bin/env bash # -# Changelog generation scriptlet. +# Changelog generation scriptlet, for nightlies # # Copyright: SPDX-License-Identifier: GPL-3.0-or-later # @@ -20,38 +20,18 @@ fi LAST_TAG="$1" COMMITS_SINCE_RELEASE="$2" NEW_VERSION="${LAST_TAG}-$((COMMITS_SINCE_RELEASE + 1))-nightly" -ORG=$(echo "$TRAVIS_REPO_SLUG" | cut -d '/' -f1) -PROJECT=$(echo "$TRAVIS_REPO_SLUG" | cut -d '/' -f 2) GIT_MAIL=${GIT_MAIL:-"bot@netdata.cloud"} GIT_USER=${GIT_USER:-"netdatabot"} PUSH_URL=$(git config --get remote.origin.url | sed -e 's/^https:\/\///') FAIL=0 -if [ -z ${GIT_TAG+x} ]; then - OPTS="" -else - OPTS="--future-release ${GIT_TAG}" -fi -echo "We got $COMMITS_SINCE_RELEASE changes since $LAST_TAG, re-generating changelog" if [ ! "${TRAVIS_REPO_SLUG}" == "netdata/netdata" ]; then echo "Beta mode on ${TRAVIS_REPO_SLUG}, nothing else to do here" exit 0 fi -git checkout master -git pull - -echo "Running project markmandel for github changelog generation" -#docker run -it --rm -v "$(pwd)":/usr/local/src/your-app ferrarimarco/github-changelog-generator:1.14.3 \ -docker run -it -v "$(pwd)":/project markmandel/github-changelog-generator:latest \ - --user "${ORG}" \ - --project "${PROJECT}" \ - --token "${GITHUB_TOKEN}" \ - --since-tag "v1.10.0" \ - --unreleased-label "**Next release**" \ - --no-issues \ - --exclude-labels "stale,duplicate,question,invalid,wontfix,discussion,no changelog" \ - --no-compare-link ${OPTS} +echo "Running changelog creation mechanism" +.travis/create_changelog.sh echo "Changelog created! Adding packaging/version(${NEW_VERSION}) and CHANGELOG.md to the repository" echo "${NEW_VERSION}" > packaging/version diff --git a/.travis/nightlies.sh b/.travis/nightlies.sh index 13a813d75..e60ee2797 100755 --- a/.travis/nightlies.sh +++ b/.travis/nightlies.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This is the nightly changelog generation script # It is responsible for two major activities: @@ -29,7 +29,7 @@ PREVIOUS_NIGHTLY_COUNT="$(rev <packaging/version | cut -d- -f 2 | rev)" # If no commits since release, just stop if [ "${COMMITS_SINCE_RELEASE}" == "${PREVIOUS_NIGHTLY_COUNT}" ]; then - echo "No changes since last nighthly release" + echo "No changes since last nighthly release, nothing else to do" exit 0 fi @@ -39,6 +39,7 @@ if [ ! "${TRAVIS_REPO_SLUG}" == "netdata/netdata" ]; then fi echo "--- Running Changelog generation ---" +echo "We got $COMMITS_SINCE_RELEASE changes since $LAST_TAG, re-generating changelog" NIGHTLIES_CHANGELOG_FAILED=0 .travis/generate_changelog_for_nightlies.sh "${LAST_TAG}" "${COMMITS_SINCE_RELEASE}" || NIGHTLIES_CHANGELOG_FAILED=1 diff --git a/.travis/package_management/build.sh b/.travis/package_management/build.sh index a5217715f..bafaecc5a 100644 --- a/.travis/package_management/build.sh +++ b/.travis/package_management/build.sh @@ -24,9 +24,9 @@ ln -sf contrib/debian debian echo "Executing dpkg-buildpackage" # pre/post options are after 1.18.8, is simpler to just check help for their existence than parsing version if dpkg-buildpackage --help | grep "\-\-post\-clean" 2> /dev/null > /dev/null; then - dpkg-buildpackage --post-clean --pre-clean --build=binary + dpkg-buildpackage --post-clean --pre-clean --build=binary -us -uc else - dpkg-buildpackage -b + dpkg-buildpackage -b -us -uc fi echo "DEB build script completed!" diff --git a/.travis/package_management/build_judy.sh b/.travis/package_management/build_judy.sh new file mode 100755 index 000000000..202ea0449 --- /dev/null +++ b/.travis/package_management/build_judy.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# +# Build Judy from source, you need to run this script as root. +# +# Copyright: SPDX-License-Identifier: GPL-3.0-or-later +# +# Author : Pavlos Emm. Katsoulakis (paul@netdata.cloud) +set -e +JUDY_VER="1.0.5" +JUDY_DIR="/opt/judy-${JUDY_VER}" + +# If we are not in netdata git repo, at the top level directory, fail +TOP_LEVEL=$(basename "$(git rev-parse --show-toplevel)") +CWD=$(git rev-parse --show-cdup) +if [ -n "$CWD" ] || [ ! "${TOP_LEVEL}" == "netdata" ]; then + echo "Run as .travis/package_management/$(basename "$0") from top level directory of netdata git repository" + echo "Build Judy package from source code failed" + exit 1 +fi + +echo "Fetching judy source tarball" +wget -O /opt/judy.tar.gz http://downloads.sourceforge.net/project/judy/judy/Judy-${JUDY_VER}/Judy-${JUDY_VER}.tar.gz + +echo "Entering /opt directory and extracting tarball" +cd /opt && tar -xf judy.tar.gz && rm judy.tar.gz + +echo "Entering ${JUDY_DIR}" +cd "${JUDY_DIR}" + +echo "Running configure" +CFLAGS="-O2 -s" CXXFLAGS="-O2 -s" ./configure + +echo "Compiling and installing" +make && make install + +echo "Done, enjoy Judy!" diff --git a/.travis/package_management/build_libuv.sh b/.travis/package_management/build_libuv.sh new file mode 100755 index 000000000..c30eede64 --- /dev/null +++ b/.travis/package_management/build_libuv.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# +# Build libuv from source, you need to run this script as root. +# +# Copyright: SPDX-License-Identifier: GPL-3.0-or-later +# +# Author : Pavlos Emm. Katsoulakis <paul@netdata.cloud> +set -e +LIBUV_VERSION="v1.32.0" +# Their folder is libuv-1.32.0 while the tarball version is v1.32.0, so fix that until they fix it... +LIBUV_DIR="/opt/libuv-${LIBUV_VERSION/v/}" + +# If we are not in netdata git repo, at the top level directory, fail +TOP_LEVEL=$(basename "$(git rev-parse --show-toplevel)") +CWD=$(git rev-parse --show-cdup) +if [ -n "$CWD" ] || [ ! "${TOP_LEVEL}" == "netdata" ]; then + echo "Run as .travis/package_management/$(basename "$0") from top level directory of netdata git repository" + echo "Build libuv package from source code failed" + exit 1 +fi + +echo "Fetching libuv from github" +wget -O /opt/libuv.tar.gz "https://github.com/libuv/libuv/archive/${LIBUV_VERSION}.tar.gz" + +echo "Entering /opt and extracting source" +cd /opt && tar -xf libuv.tar.gz && rm libuv.tar.gz + +echo "Entering ${LIBUV_DIR}" +cd "${LIBUV_DIR}" + +echo "Compiling and installing" +sh autogen.sh +./configure +make && make check && make install + +echo "Done, enjoy libuv!" diff --git a/.travis/package_management/common.py b/.travis/package_management/common.py index a72fe4837..8a5106971 100755 --- a/.travis/package_management/common.py +++ b/.travis/package_management/common.py @@ -7,6 +7,9 @@ import lxc import subprocess import os +import sys +import tempfile +import shutil def fetch_version(orig_build_version): tag = None @@ -53,10 +56,10 @@ def run_command(container, command): if command_result != 0: raise Exception("Command failed with exit code %d" % command_result) -def run_command_in_host(cmd): - print("Issue command in host: %s" % str(cmd)) +def run_command_in_host(cmd, cwd=None): + print("Issue command in host: %s, cwd:%s" % (str(cmd), str(cwd))) - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) o, e = proc.communicate() print('Output: ' + o.decode('ascii')) print('Error: ' + e.decode('ascii')) @@ -133,31 +136,41 @@ def prepare_version_source(dest_archive, pkg_friendly_version, tag=None): print(".0 Preparing local implementation tarball for version %s" % pkg_friendly_version) tar_file = os.environ['LXC_CONTAINER_ROOT'] + dest_archive + print(".0 Copy repo to prepare it for tarball generation") + tmp_src = tempfile.mkdtemp(prefix='netdata-source-') + run_command_in_host(['cp', '-r', '.', tmp_src]) + if tag is not None: print(".1 Checking out tag %s" % tag) - run_command_in_host(['git', 'fetch', '--all']) + run_command_in_host(['git', 'fetch', '--all'], tmp_src) # TODO: Keep in mind that tricky 'v' there, needs to be removed once we clear our versioning scheme - run_command_in_host(['git', 'checkout', 'v%s' % pkg_friendly_version]) + run_command_in_host(['git', 'checkout', 'v%s' % pkg_friendly_version], tmp_src) print(".2 Tagging the code with version: %s" % pkg_friendly_version) - run_command_in_host(['git', 'tag', '-a', pkg_friendly_version, '-m', 'Tagging while packaging on %s' % os.environ["CONTAINER_NAME"]]) + run_command_in_host(['git', 'tag', '-a', pkg_friendly_version, '-m', 'Tagging while packaging on %s' % os.environ["CONTAINER_NAME"]], tmp_src) print(".3 Run autoreconf -ivf") - run_command_in_host(['autoreconf', '-ivf']) + run_command_in_host(['autoreconf', '-ivf'], tmp_src) print(".4 Run configure") - run_command_in_host(['./configure', '--prefix=/usr', '--sysconfdir=/etc', '--localstatedir=/var', '--libdir=/usr/lib', '--libexecdir=/usr/libexec', '--with-math', '--with-zlib', '--with-user=netdata']) + run_command_in_host(['./configure', '--prefix=/usr', '--sysconfdir=/etc', '--localstatedir=/var', '--libdir=/usr/lib', '--libexecdir=/usr/libexec', '--with-math', '--with-zlib', '--with-user=netdata'], tmp_src) print(".5 Run make dist") - run_command_in_host(['make', 'dist']) + run_command_in_host(['make', 'dist'], tmp_src) print(".6 Copy generated tarbal to desired path") - if os.path.exists('netdata-%s.tar.gz' % pkg_friendly_version): - run_command_in_host(['sudo', 'cp', 'netdata-%s.tar.gz' % pkg_friendly_version, tar_file]) + generated_tarball = '%s/netdata-%s.tar.gz' % (tmp_src, pkg_friendly_version) + + if os.path.exists(generated_tarball): + run_command_in_host(['sudo', 'cp', generated_tarball, tar_file]) print(".7 Fixing permissions on tarball") run_command_in_host(['sudo', 'chmod', '777', tar_file]) + + print(".8 Bring over netdata.spec, Remove temp directory"); + run_command_in_host(['cp', '%s/netdata.spec' % tmp_src, 'netdata.spec']) + shutil.rmtree(tmp_src) else: - print("I could not find (%s) on the disk, stopping the build. Kindly check the logs and try again" % 'netdata-%s.tar.gz' % pkg_friendly_version) + print("I could not find (%s) on the disk, stopping the build. Kindly check the logs and try again" % generated_tarball) sys.exit(1) diff --git a/.travis/package_management/trigger_deb_lxc_build.py b/.travis/package_management/trigger_deb_lxc_build.py index 46b64e6a9..464a7715f 100755 --- a/.travis/package_management/trigger_deb_lxc_build.py +++ b/.travis/package_management/trigger_deb_lxc_build.py @@ -57,8 +57,13 @@ print("Checking version consistency") since_version = os.environ["LATEST_RELEASE_VERSION"] if str(since_version).replace('v', '') == str(new_version) and str(new_version).count('.') == 2: s = since_version.split('.') - prev = str(int(s[1]) - 1) - since_version = s[0] + '.' + prev + s[2] + if int(s[2]) > 0: + patch_prev = str(int(s[2]) - 1) + since_version = s[0] + '.' + s[1] + '.' + patch_prev + else: + prev = str(int(s[1]) - 1) + since_version = s[0] + '.' + prev + '.' + s[2] + print("We seem to be building a new stable release, reduce by one since_version option. New since_version:%s" % since_version) print("Fixing changelog tags") diff --git a/.travis/tagger.sh b/.travis/tagger.sh index adac35b48..a775a826f 100755 --- a/.travis/tagger.sh +++ b/.travis/tagger.sh @@ -1,6 +1,4 @@ -#!/bin/bash -# -# Original script is available at https://github.com/paulfantom/travis-helper/blob/master/releasing/releaser.sh +# #BASH library # # Tags are generated by searching for a keyword in last commit message. Keywords are: # - [patch] or [fix] to bump patch number @@ -12,8 +10,6 @@ # - GITHUB_TOKEN variable set with GitHub token. Access level: repo.public_repo # - git-semver python package (pip install git-semver) # -# Note: Exported variables needed by .travis/draft_release.sh -# # Original script is available at https://github.com/paulfantom/travis-helper/blob/master/releasing/releaser.sh # # Copyright: SPDX-License-Identifier: GPL-3.0-or-later @@ -21,24 +17,11 @@ # Author : Pawel Krupa (paulfantom) # Author : Pavlos Emm. Katsoulakis (paul@netdata.cloud) -set -e - - -# If we are not in netdata git repo, at the top level directory, fail -TOP_LEVEL=$(basename "$(git rev-parse --show-toplevel)") -CWD=$(git rev-parse --show-cdup || echo "") -if [ -n "${CWD}" ] || [ ! "${TOP_LEVEL}" == "netdata" ]; then - echo "Run as .travis/$(basename "$0") from top level directory of netdata git repository" - echo "Changelog generation process aborted" - exit 1 -fi - - # Figure out what will be new release candidate tag based only on previous ones. # This assumes that RELEASES are in format of "v0.1.2" and prereleases (RCs) are using "v0.1.2-rc0" function set_tag_release_candidate() { LAST_TAG=$(git semver) - echo "Last tag found is: ${LAST_TAG}" + echo "${0}: Last tag found is: ${LAST_TAG}" if [[ $LAST_TAG =~ -rc* ]]; then VERSION=$(echo "$LAST_TAG" | cut -d'-' -f 1) @@ -47,31 +30,32 @@ function set_tag_release_candidate() { else VERSION="$(git semver --next-minor)" RC=0 - echo "Warning: Will set version to ${VERSION} (Last tag: ${LAST_TAG}) while tagged for release candidate generation" + echo "${0}: Warning: Will set version to ${VERSION} (Last tag: ${LAST_TAG}) while tagged for release candidate generation" fi + GIT_TAG="v${VERSION}-rc${RC}" + echo "${0}: Generated a new tag, set to: (${GIT_TAG})" } -echo "Determining TAG" - -# Check if current commit is tagged or not -GIT_TAG=$(git tag --points-at) - -if [ -z "${GIT_TAG}" ]; then - git semver - # Figure out next tag based on commit message - echo "Last commit message: ${TRAVIS_COMMIT_MESSAGE}" - case "${TRAVIS_COMMIT_MESSAGE}" in - *"[netdata patch release]"*) GIT_TAG="v$(git semver --next-patch)" ;; - *"[netdata minor release]"*) GIT_TAG="v$(git semver --next-minor)" ;; - *"[netdata major release]"*) GIT_TAG="v$(git semver --next-major)" ;; - *"[netdata release candidate]"*) set_tag_release_candidate ;; - *) - echo "Keyword not detected. Exiting..." - exit 0 - ;; - esac -fi - -echo "Setting up GIT_TAG to ${GIT_TAG}" -export GIT_TAG +function set_tag_for_release() { + echo "${0}: Checking for tag existence" + if [ -z "${GIT_TAG}" ]; then + echo "${0}: No tag was found, generating a new tag" + git semver + + echo "${0}: Last commit message: ${TRAVIS_COMMIT_MESSAGE}" + + # Figure out next tag based on commit message + case "${TRAVIS_COMMIT_MESSAGE}" in + *"[netdata patch release]"*) GIT_TAG="v$(git semver --next-patch)" ;; + *"[netdata minor release]"*) GIT_TAG="v$(git semver --next-minor)" ;; + *"[netdata major release]"*) GIT_TAG="v$(git semver --next-major)" ;; + *"[netdata release candidate]"*) set_tag_release_candidate ;; + *) + echo "${0}: Keyword not detected. Nothing to set for GIT_TAG" + ;; + esac + else + echo "${0}: We seem to already have a GIT_TAG set to (${GIT_TAG})" + fi +} diff --git a/.travis/trigger_package_generation.sh b/.travis/trigger_package_generation.sh index aee69be5f..713679c16 100755 --- a/.travis/trigger_package_generation.sh +++ b/.travis/trigger_package_generation.sh @@ -45,7 +45,19 @@ push_change echo "---- Waiting for ${WAIT_TIME} seconds before triggering next process ----" sleep "${WAIT_TIME}" +commit_change "i386" "DEB" +push_change + +echo "---- Waiting for ${WAIT_TIME} seconds before triggering next process ----" +sleep "${WAIT_TIME}" + commit_change "amd64" "RPM" push_change +echo "---- Waiting for ${WAIT_TIME} seconds before triggering next process ----" +sleep "${WAIT_TIME}" + +commit_change "i386" "RPM" +push_change + echo "---- Done! ----" diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f288f603..d2c1e8a08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,110 @@ # Changelog -## [**Next release**](https://github.com/netdata/netdata/tree/HEAD) +## [v1.18.0](https://github.com/netdata/netdata/tree/v1.18.0) (2019-10-10) + +[Full Changelog](https://github.com/netdata/netdata/compare/v1.17.1...v1.18.0) + +**Merged pull requests:** + +- netdata: Add knatsakis as codeowner, wherever paulkatsoulakis was [\#7036](https://github.com/netdata/netdata/pull/7036) ([knatsakis](https://github.com/knatsakis)) +- rabbitmq: survive lack of vhosts [\#7019](https://github.com/netdata/netdata/pull/7019) ([ilyam8](https://github.com/ilyam8)) +- Fix crash on FreeBSD due to do\_dev\_cpu\_temperature stack corruption [\#7014](https://github.com/netdata/netdata/pull/7014) ([samm-git](https://github.com/samm-git)) +- Fix handling of illegal metric timestamps in database engine [\#7008](https://github.com/netdata/netdata/pull/7008) ([mfundul](https://github.com/mfundul)) +- Fix a resource leak [\#7007](https://github.com/netdata/netdata/pull/7007) ([vlvkobal](https://github.com/vlvkobal)) +- Remove hard cap from page cache size to eliminate deadlocks. [\#7006](https://github.com/netdata/netdata/pull/7006) ([mfundul](https://github.com/mfundul)) +- Add Portuguese \(Brazil\) as a language option [\#7004](https://github.com/netdata/netdata/pull/7004) ([cakrit](https://github.com/cakrit)) +- fix issue \#7002 [\#7003](https://github.com/netdata/netdata/pull/7003) ([OneCodeMonkey](https://github.com/OneCodeMonkey)) +- Increase dbengine default cache size [\#6997](https://github.com/netdata/netdata/pull/6997) ([mfundul](https://github.com/mfundul)) +- Checklinks fix [\#6994](https://github.com/netdata/netdata/pull/6994) ([cakrit](https://github.com/cakrit)) +- Remove warning from Coverity [\#6992](https://github.com/netdata/netdata/pull/6992) ([thiagoftsm](https://github.com/thiagoftsm)) +- netdata/installer: allow netdata service install, when docker runs systemd [\#6987](https://github.com/netdata/netdata/pull/6987) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Fixing broken links found via linkchecker [\#6983](https://github.com/netdata/netdata/pull/6983) ([joelhans](https://github.com/joelhans)) +- Fix dbengine consistency [\#6979](https://github.com/netdata/netdata/pull/6979) ([mfundul](https://github.com/mfundul)) +- Make dbengine the default memory mode [\#6977](https://github.com/netdata/netdata/pull/6977) ([mfundul](https://github.com/mfundul)) +- rabbitmq: collect vhosts msg metrics from `/api/vhosts` [\#6976](https://github.com/netdata/netdata/pull/6976) ([ilyam8](https://github.com/ilyam8)) +- Fix coverity erro \(CID 349552\) double lock [\#6970](https://github.com/netdata/netdata/pull/6970) ([thiagoftsm](https://github.com/thiagoftsm)) +- web api: include family into allmetrics json response [\#6966](https://github.com/netdata/netdata/pull/6966) ([ilyam8](https://github.com/ilyam8)) +- elasticsearch: collect metrics from \_cat/indices [\#6965](https://github.com/netdata/netdata/pull/6965) ([ilyam8](https://github.com/ilyam8)) +- Reduce overhead during write io [\#6964](https://github.com/netdata/netdata/pull/6964) ([mfundul](https://github.com/mfundul)) +- mysql: collect galera cluster metrics [\#6962](https://github.com/netdata/netdata/pull/6962) ([ilyam8](https://github.com/ilyam8)) +- Clarification on configuring notification recipients [\#6961](https://github.com/netdata/netdata/pull/6961) ([cakrit](https://github.com/cakrit)) +- netdata/packaging: Make spec file more consistent with version dependencies, plus some documentation nits [\#6948](https://github.com/netdata/netdata/pull/6948) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Fix a memory leak [\#6945](https://github.com/netdata/netdata/pull/6945) ([vlvkobal](https://github.com/vlvkobal)) +- Fix Remark Lint for READMEs in Database [\#6942](https://github.com/netdata/netdata/pull/6942) ([prhomhyse](https://github.com/prhomhyse)) +- Coverity 20190924 [\#6941](https://github.com/netdata/netdata/pull/6941) ([thiagoftsm](https://github.com/thiagoftsm)) +- Restore original alignment behaviour of RRDR [\#6938](https://github.com/netdata/netdata/pull/6938) ([mfundul](https://github.com/mfundul)) +- minor - check for curl to not get wrong error message [\#6931](https://github.com/netdata/netdata/pull/6931) ([underhood](https://github.com/underhood)) +- netdata/packaging: fix broken links on web files, for deb [\#6930](https://github.com/netdata/netdata/pull/6930) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- installer: include go.d.plugin version v0.10.0 [\#6929](https://github.com/netdata/netdata/pull/6929) ([ilyam8](https://github.com/ilyam8)) +- python.d: fix log warnings in start\_job [\#6928](https://github.com/netdata/netdata/pull/6928) ([ilyam8](https://github.com/ilyam8)) +- zookeeper and hdfs: alarms and dashboard\_info [\#6927](https://github.com/netdata/netdata/pull/6927) ([ilyam8](https://github.com/ilyam8)) +- netdata.spec.in: Do not build CUPS plugin subpackage on CentOS 6 and CentOS 7 [\#6926](https://github.com/netdata/netdata/pull/6926) ([knatsakis](https://github.com/knatsakis)) +- Fix remark lint for Contrib [\#6921](https://github.com/netdata/netdata/pull/6921) ([prhomhyse](https://github.com/prhomhyse)) +- Fix remark warnings for Daemon README [\#6920](https://github.com/netdata/netdata/pull/6920) ([prhomhyse](https://github.com/prhomhyse)) +- Fix Remark Lint Warnings for Backends [\#6917](https://github.com/netdata/netdata/pull/6917) ([prhomhyse](https://github.com/prhomhyse)) +- Suggest using /run or /var/run for the unix socket [\#6916](https://github.com/netdata/netdata/pull/6916) ([cakrit](https://github.com/cakrit)) +- Improve documentation for the SNMP collector [\#6915](https://github.com/netdata/netdata/pull/6915) ([cakrit](https://github.com/cakrit)) +- netdata/ci: nits and fixes around package release workflow [\#6914](https://github.com/netdata/netdata/pull/6914) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Detect deadlock in dbengine page cache [\#6911](https://github.com/netdata/netdata/pull/6911) ([mfundul](https://github.com/mfundul)) +- Correct read length of silencers file [\#6909](https://github.com/netdata/netdata/pull/6909) ([cakrit](https://github.com/cakrit)) +- netdata/ci: fix branch check [\#6905](https://github.com/netdata/netdata/pull/6905) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- \#3925 implementation [\#6903](https://github.com/netdata/netdata/pull/6903) ([underhood](https://github.com/underhood)) +- netdata/packaging: remove rhel7 - i386, until its settled from bug \#6849 [\#6902](https://github.com/netdata/netdata/pull/6902) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Improve changelog generation and add it back to the pipeline [\#6900](https://github.com/netdata/netdata/pull/6900) ([cakrit](https://github.com/cakrit)) +- \[collector/slabinfo\] Fix pagesize not defined in non-x86 arches [\#6897](https://github.com/netdata/netdata/pull/6897) ([Saruspete](https://github.com/Saruspete)) +- Permit x-auth-token in Access-Control-Allow-Headers [\#6894](https://github.com/netdata/netdata/pull/6894) ([cakrit](https://github.com/cakrit)) +- netdata/packaging: fix kickstart-static64 argument parsing [\#6892](https://github.com/netdata/netdata/pull/6892) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Change the log level for chart updates [\#6887](https://github.com/netdata/netdata/pull/6887) ([vlvkobal](https://github.com/vlvkobal)) +- Resolve all Kubernetes container names [\#6885](https://github.com/netdata/netdata/pull/6885) ([cakrit](https://github.com/cakrit)) +- Update docs for offline install [\#6884](https://github.com/netdata/netdata/pull/6884) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Remove Dollar sign from Bash code in documentation and fix remark-lint warnings [\#6880](https://github.com/netdata/netdata/pull/6880) ([prhomhyse](https://github.com/prhomhyse)) +- Markdown syntax fixes for MDX parser [\#6877](https://github.com/netdata/netdata/pull/6877) ([joelhans](https://github.com/joelhans)) +- fix LGTM warnings [\#6875](https://github.com/netdata/netdata/pull/6875) ([jacekkolasa](https://github.com/jacekkolasa)) +- Update python.d module checklist to match the current paths and build system. [\#6874](https://github.com/netdata/netdata/pull/6874) ([Ferroin](https://github.com/Ferroin)) +- installer: include go.d.plugin version v0.9.0 [\#6872](https://github.com/netdata/netdata/pull/6872) ([ilyam8](https://github.com/ilyam8)) +- Instructions for simple SMTP transport [\#6870](https://github.com/netdata/netdata/pull/6870) ([cakrit](https://github.com/cakrit)) +- Add example for prometheus archiving source parameter [\#6869](https://github.com/netdata/netdata/pull/6869) ([cakrit](https://github.com/cakrit)) +- dont redirect when redirectURI is the same [\#6868](https://github.com/netdata/netdata/pull/6868) ([jacekkolasa](https://github.com/jacekkolasa)) +- /var/lib/netdata/registry was being left behind after purge [\#6867](https://github.com/netdata/netdata/pull/6867) ([davent](https://github.com/davent)) +- python.d.plugin: no job config build fix [\#6856](https://github.com/netdata/netdata/pull/6856) ([ilyam8](https://github.com/ilyam8)) +- Resolve broken links in The standard web dashboard doc [\#6854](https://github.com/netdata/netdata/pull/6854) ([prhomhyse](https://github.com/prhomhyse)) +- netdata/packaging: Bring on board two scripts that build libuv and judy from source [\#6850](https://github.com/netdata/netdata/pull/6850) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- netdata/packaging: nits and fixes for packaging [\#6842](https://github.com/netdata/netdata/pull/6842) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- netdata/packaging: nit - missed trailing slash [\#6840](https://github.com/netdata/netdata/pull/6840) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- netdata/packaging: Ensure that we do not mess with CI tooling, when building stable [\#6838](https://github.com/netdata/netdata/pull/6838) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- netdata/packaging: we didnt fix changelog handling, fixes and nits now [\#6837](https://github.com/netdata/netdata/pull/6837) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Add news of 1.17.1 to README [\#6836](https://github.com/netdata/netdata/pull/6836) ([cakrit](https://github.com/cakrit)) +- netdata/packaging: no need to overengineer with these checks [\#6834](https://github.com/netdata/netdata/pull/6834) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Buffer overflow [\#6817](https://github.com/netdata/netdata/pull/6817) ([amoss](https://github.com/amoss)) +- Docs: Overhaul of Getting started guide [\#6811](https://github.com/netdata/netdata/pull/6811) ([joelhans](https://github.com/joelhans)) +- NPM Packages version update [\#6801](https://github.com/netdata/netdata/pull/6801) ([prhomhyse](https://github.com/prhomhyse)) +- Collector slabinfo [\#6800](https://github.com/netdata/netdata/pull/6800) ([Saruspete](https://github.com/Saruspete)) +- Fix some errors reported by Coverity [\#6797](https://github.com/netdata/netdata/pull/6797) ([thiagoftsm](https://github.com/thiagoftsm)) +- Allow hostnames in Access Control Lists [\#6796](https://github.com/netdata/netdata/pull/6796) ([amoss](https://github.com/amoss)) +- update grep to be more specific [\#6794](https://github.com/netdata/netdata/pull/6794) ([n0coast](https://github.com/n0coast)) +- Common pattern for web and alarms together with two bug fixes [\#6783](https://github.com/netdata/netdata/pull/6783) ([thiagoftsm](https://github.com/thiagoftsm)) +- Changes to launching the python.d plugin aggregator. [\#6781](https://github.com/netdata/netdata/pull/6781) ([amoss](https://github.com/amoss)) +- vcsa collector: charts descritpion and alarms [\#6772](https://github.com/netdata/netdata/pull/6772) ([ilyam8](https://github.com/ilyam8)) +- netdata/packaging: Introduce separate CUPS package for debian distributions [\#6724](https://github.com/netdata/netdata/pull/6724) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- netdata/packaging: Split CUPS plugin to separate package \(RPM\) [\#6700](https://github.com/netdata/netdata/pull/6700) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- netdata/installer: Add support for offline installs using kickstart or kickstart-static64 [\#6693](https://github.com/netdata/netdata/pull/6693) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Add clang-format. Update Contribution guidelines. [\#6677](https://github.com/netdata/netdata/pull/6677) ([cosmix](https://github.com/cosmix)) +- changed naming for redirect\_uri param [\#6663](https://github.com/netdata/netdata/pull/6663) ([jacekkolasa](https://github.com/jacekkolasa)) +- Fixes netdata group deletion on linux for uninstall script [\#6645](https://github.com/netdata/netdata/pull/6645) ([mbarper](https://github.com/mbarper)) +- Gearman plugin for Netdata [\#6567](https://github.com/netdata/netdata/pull/6567) ([agronick](https://github.com/agronick)) +- Create a template for all dimensions [\#6560](https://github.com/netdata/netdata/pull/6560) ([thiagoftsm](https://github.com/thiagoftsm)) +- Center the chart on timeframe when an alarm is raised [\#6391](https://github.com/netdata/netdata/pull/6391) ([thiagoftsm](https://github.com/thiagoftsm)) +- Cppcheck fixes [\#6386](https://github.com/netdata/netdata/pull/6386) ([ac000](https://github.com/ac000)) + +## [v1.17.1](https://github.com/netdata/netdata/tree/v1.17.1) (2019-09-12) + +[Full Changelog](https://github.com/netdata/netdata/compare/v1.17.0...v1.17.1) **Merged pull requests:** - netdata/packaging: fix ubuntu/xenial runtime dependencies [\#6825](https://github.com/netdata/netdata/pull/6825) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - netdata/ci: Force last good version of git-semver, they broke it [\#6820](https://github.com/netdata/netdata/pull/6820) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Stress test insertions into dbengine and bugfixes [\#6814](https://github.com/netdata/netdata/pull/6814) ([mfundul](https://github.com/mfundul)) - netdata/ci: Fix author on triggering commits for packaging [\#6813](https://github.com/netdata/netdata/pull/6813) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - netdata/packaging: remove fedora/28, is no longer available [\#6808](https://github.com/netdata/netdata/pull/6808) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - netdata/ci: second batch of fixes for coverity scan script and others [\#6804](https://github.com/netdata/netdata/pull/6804) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) @@ -16,20 +115,17 @@ - netdata/packaging: Trigger stable package generation upon release process [\#6766](https://github.com/netdata/netdata/pull/6766) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - update cache hashes for js and css [\#6756](https://github.com/netdata/netdata/pull/6756) ([jacekkolasa](https://github.com/jacekkolasa)) - \[libnetdata/thread\] Set thread name from tag [\#6745](https://github.com/netdata/netdata/pull/6745) ([Saruspete](https://github.com/Saruspete)) +- sidebar-info update - DB engine [\#6744](https://github.com/netdata/netdata/pull/6744) ([jacekkolasa](https://github.com/jacekkolasa)) - pythond respect prev running jobs and refactor [\#6661](https://github.com/netdata/netdata/pull/6661) ([ilyam8](https://github.com/ilyam8)) - Stop configure.ac from linking against dbengine and https libraries w… [\#6658](https://github.com/netdata/netdata/pull/6658) ([mfundul](https://github.com/mfundul)) - Add high level explanation of dashboard contents [\#6648](https://github.com/netdata/netdata/pull/6648) ([joelhans](https://github.com/joelhans)) - Fix clear notification missing [\#6638](https://github.com/netdata/netdata/pull/6638) ([thiagoftsm](https://github.com/thiagoftsm)) - dash.html [\#6603](https://github.com/netdata/netdata/pull/6603) ([tnyeanderson](https://github.com/tnyeanderson)) - HTTP response message [\#6595](https://github.com/netdata/netdata/pull/6595) ([thiagoftsm](https://github.com/thiagoftsm)) -- Expand dashboard auto-scaling and convertible units [\#5920](https://github.com/netdata/netdata/pull/5920) ([qingkunl](https://github.com/qingkunl)) ## [v1.17.0](https://github.com/netdata/netdata/tree/v1.17.0) (2019-09-03) -**Fixed bugs:** - -- netdata/installer: fix static64 installer always overwriting configuration [\#6710](https://github.com/netdata/netdata/pull/6710) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging: put go.d version in one place [\#6557](https://github.com/netdata/netdata/pull/6557) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.16.1...v1.17.0) **Merged pull requests:** @@ -45,6 +141,7 @@ - Netdata-installer warning removed [\#6715](https://github.com/netdata/netdata/pull/6715) ([thiagoftsm](https://github.com/thiagoftsm)) - Remove of unecessary NULL web server [\#6714](https://github.com/netdata/netdata/pull/6714) ([thiagoftsm](https://github.com/thiagoftsm)) - History tips [\#6711](https://github.com/netdata/netdata/pull/6711) ([jacekkolasa](https://github.com/jacekkolasa)) +- netdata/installer: fix static64 installer always overwriting configuration [\#6710](https://github.com/netdata/netdata/pull/6710) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - exact path to netdata.conf in .gitignore [\#6709](https://github.com/netdata/netdata/pull/6709) ([sunflowerbofh](https://github.com/sunflowerbofh)) - Tabulatin on health/health.c [\#6691](https://github.com/netdata/netdata/pull/6691) ([thiagoftsm](https://github.com/thiagoftsm)) - netdata/packaging: Align libdir in all configure commands [\#6682](https://github.com/netdata/netdata/pull/6682) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) @@ -86,6 +183,7 @@ - netdata/packaging: Bare OS validations [\#6574](https://github.com/netdata/netdata/pull/6574) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - vsphere collector: charts description and alarms [\#6572](https://github.com/netdata/netdata/pull/6572) ([ilyam8](https://github.com/ilyam8)) - Documentation style guide & build instructions [\#6563](https://github.com/netdata/netdata/pull/6563) ([joelhans](https://github.com/joelhans)) +- netdata/packaging: put go.d version in one place [\#6557](https://github.com/netdata/netdata/pull/6557) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - Add alarm status counter api call [\#6554](https://github.com/netdata/netdata/pull/6554) ([alpes214](https://github.com/alpes214)) - netdata/packaging: Documentation on distribution support matrix and functionality availability [\#6552](https://github.com/netdata/netdata/pull/6552) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - mongodb: ssl connection [\#6546](https://github.com/netdata/netdata/pull/6546) ([ilyam8](https://github.com/ilyam8)) @@ -93,22 +191,16 @@ - Netdata Cloud documentation [\#6476](https://github.com/netdata/netdata/pull/6476) ([joelhans](https://github.com/joelhans)) - Variable Granularity support for data collection [\#6430](https://github.com/netdata/netdata/pull/6430) ([mfundul](https://github.com/mfundul)) - \(re-open\) ZRAM info collector module \(proc.plugin\) [\#6424](https://github.com/netdata/netdata/pull/6424) ([RaZeR-RBI](https://github.com/RaZeR-RBI)) -- Update plugin\_nfacct.c [\#6098](https://github.com/netdata/netdata/pull/6098) ([fun04wr0ng](https://github.com/fun04wr0ng)) ## [v1.16.1](https://github.com/netdata/netdata/tree/v1.16.1) (2019-07-31) -**Fixed bugs:** - -- netdata/packaging: Move tarball checksum information into lib dir of netdata [\#6555](https://github.com/netdata/netdata/pull/6555) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging: Adopt netdata-updater to run properly for static64 installations. [\#6520](https://github.com/netdata/netdata/pull/6520) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging: Do not deliver edit-config as part of the distribution tarball [\#6507](https://github.com/netdata/netdata/pull/6507) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Stop anonymous stats from writing log in /tmp [\#6491](https://github.com/netdata/netdata/pull/6491) ([cakrit](https://github.com/cakrit)) -- netdata/packaging: Fix RPM packaging workflow issues, plus draft changes for .DEB packaging [\#6415](https://github.com/netdata/netdata/pull/6415) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.16.0...v1.16.1) **Merged pull requests:** - Handle disconnected sockets in unbound collector. [\#6561](https://github.com/netdata/netdata/pull/6561) ([Ferroin](https://github.com/Ferroin)) - netdata/packaging: Notify us when CHANGELOG.md gets too old [\#6556](https://github.com/netdata/netdata/pull/6556) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- netdata/packaging: Move tarball checksum information into lib dir of netdata [\#6555](https://github.com/netdata/netdata/pull/6555) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - Add configurable default locations for trusted CA certificates [\#6549](https://github.com/netdata/netdata/pull/6549) ([thiagoftsm](https://github.com/thiagoftsm)) - smartd\_log: use `del\_dimension` instead of `hide\_dimension` to delete inactive disks [\#6547](https://github.com/netdata/netdata/pull/6547) ([ilyam8](https://github.com/ilyam8)) - redirect after clicking Nodes \> SignIn [\#6544](https://github.com/netdata/netdata/pull/6544) ([jacekkolasa](https://github.com/jacekkolasa)) @@ -118,10 +210,13 @@ - Docs: Remove text about nightly version [\#6534](https://github.com/netdata/netdata/pull/6534) ([joelhans](https://github.com/joelhans)) - Documentation navigation fix [\#6533](https://github.com/netdata/netdata/pull/6533) ([joelhans](https://github.com/joelhans)) - .travis.yml: Fix some yamllint errors [\#6526](https://github.com/netdata/netdata/pull/6526) ([knatsakis](https://github.com/knatsakis)) +- netdata/packaging: Adopt netdata-updater to run properly for static64 installations. [\#6520](https://github.com/netdata/netdata/pull/6520) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - mongodb: change `password` to `pass` in the module config [\#6518](https://github.com/netdata/netdata/pull/6518) ([ilyam8](https://github.com/ilyam8)) +- netdata/packaging: Do not deliver edit-config as part of the distribution tarball [\#6507](https://github.com/netdata/netdata/pull/6507) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - Fixed broken left navbar links in translated docs [\#6505](https://github.com/netdata/netdata/pull/6505) ([cakrit](https://github.com/cakrit)) - Update CLA with intention to keep netdata FOSS [\#6504](https://github.com/netdata/netdata/pull/6504) ([cakrit](https://github.com/cakrit)) - netdata/docs: Add @joelhans as co-owner on documentation [\#6501](https://github.com/netdata/netdata/pull/6501) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +- Stop anonymous stats from writing log in /tmp [\#6491](https://github.com/netdata/netdata/pull/6491) ([cakrit](https://github.com/cakrit)) - Add support for plain text only emails [\#6485](https://github.com/netdata/netdata/pull/6485) ([leo-lb](https://github.com/leo-lb)) - netdata/packaging: Enable built-in support for prometheus remote write in packaging [\#6480](https://github.com/netdata/netdata/pull/6480) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - Fix the snappy library check [\#6479](https://github.com/netdata/netdata/pull/6479) ([vlvkobal](https://github.com/vlvkobal)) @@ -150,6 +245,7 @@ - netdata/packaging/doc: Update documentation dependencies [\#6421](https://github.com/netdata/netdata/pull/6421) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - Add global configuration option for zero metrics [\#6419](https://github.com/netdata/netdata/pull/6419) ([vlvkobal](https://github.com/vlvkobal)) - Updated logos in the infographic and remaining favicons [\#6417](https://github.com/netdata/netdata/pull/6417) ([cakrit](https://github.com/cakrit)) +- netdata/packaging: Fix RPM packaging workflow issues, plus draft changes for .DEB packaging [\#6415](https://github.com/netdata/netdata/pull/6415) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - SSL vs. TLS consistency and clarification in documentation [\#6414](https://github.com/netdata/netdata/pull/6414) ([joelhans](https://github.com/joelhans)) - Add more codeowners to the core [\#6413](https://github.com/netdata/netdata/pull/6413) ([vlvkobal](https://github.com/vlvkobal)) - Add news of v1.16.0 to main README [\#6411](https://github.com/netdata/netdata/pull/6411) ([cakrit](https://github.com/cakrit)) @@ -160,23 +256,10 @@ - Change default installation to stable in documentation [\#6388](https://github.com/netdata/netdata/pull/6388) ([joelhans](https://github.com/joelhans)) - Daemon fix double kills of collection threads on shutdown [\#6387](https://github.com/netdata/netdata/pull/6387) ([emmrk](https://github.com/emmrk)) - Add apps grouping debug messages [\#6375](https://github.com/netdata/netdata/pull/6375) ([vlvkobal](https://github.com/vlvkobal)) -- Reimplemented mypopen\(\) function family [\#6339](https://github.com/netdata/netdata/pull/6339) ([mfundul](https://github.com/mfundul)) -- ZRAM info collector module \(proc.plugin\) [\#6276](https://github.com/netdata/netdata/pull/6276) ([RaZeR-RBI](https://github.com/RaZeR-RBI)) -- Url parser refactoring [\#6247](https://github.com/netdata/netdata/pull/6247) ([thiagoftsm](https://github.com/thiagoftsm)) ## [v1.16.0](https://github.com/netdata/netdata/tree/v1.16.0) (2019-07-08) -**Fixed bugs:** - -- netdata/packaging/docker: Fix docker documentation and a fix to avoid failures [\#6344](https://github.com/netdata/netdata/pull/6344) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Fix devuan support for initd [\#6275](https://github.com/netdata/netdata/pull/6275) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/docker: Fix docker socket utilization, first pass [\#6233](https://github.com/netdata/netdata/pull/6233) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/daemon: Eliminate a couple of warnings, plus tabs removal [\#6222](https://github.com/netdata/netdata/pull/6222) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/ci: Add lifecycle checks to bare operating system installations [\#6209](https://github.com/netdata/netdata/pull/6209) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/daemon: SSL fix - broken compilation case when ssl library not present! [\#6201](https://github.com/netdata/netdata/pull/6201) ([thiagoftsm](https://github.com/thiagoftsm)) -- netdata/packaging/installer: Fix updater issue on empty config value [\#6182](https://github.com/netdata/netdata/pull/6182) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/installer: nits and fixes [\#6121](https://github.com/netdata/netdata/pull/6121) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata: Fix labels usage, quotes are not needed [\#6091](https://github.com/netdata/netdata/pull/6091) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.15.0...v1.16.0) **Merged pull requests:** @@ -194,865 +277,58 @@ - Add more debug messages for pluginsd pipe errors [\#6373](https://github.com/netdata/netdata/pull/6373) ([vlvkobal](https://github.com/vlvkobal)) - Improve documentation about file descriptors and systemd configuration. [\#6372](https://github.com/netdata/netdata/pull/6372) ([mfundul](https://github.com/mfundul)) - netdata/packaging: Netdata binary packages generation - spec file refinement, support for nightlies \(RPM\) [\#6369](https://github.com/netdata/netdata/pull/6369) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- apps.plugin: detect openldap server processes by default on Debian [\#6364](https://github.com/netdata/netdata/pull/6364) ([nodiscc](https://github.com/nodiscc)) -- Easily disable alarms, by persisting the silencers configuration [\#6360](https://github.com/netdata/netdata/pull/6360) ([thiagoftsm](https://github.com/thiagoftsm)) -- Redirect old site to new site at www.netdata.cloud [\#6359](https://github.com/netdata/netdata/pull/6359) ([cakrit](https://github.com/cakrit)) -- Better checks for nfacct headers [\#6351](https://github.com/netdata/netdata/pull/6351) ([vlvkobal](https://github.com/vlvkobal)) -- Tomcat status invalid XML fix [\#6345](https://github.com/netdata/netdata/pull/6345) ([Danamir](https://github.com/Danamir)) -- pihole: alarms delay fix [\#6342](https://github.com/netdata/netdata/pull/6342) ([ilyam8](https://github.com/ilyam8)) -- monit: obsolete service in runtime [\#6340](https://github.com/netdata/netdata/pull/6340) ([ilyam8](https://github.com/ilyam8)) -- adaptec\_raid: logical device regex fix [\#6338](https://github.com/netdata/netdata/pull/6338) ([ilyam8](https://github.com/ilyam8)) -- Better context name to client context [\#6336](https://github.com/netdata/netdata/pull/6336) ([thiagoftsm](https://github.com/thiagoftsm)) -- installer: include go.d.plugin version v0.7.0 [\#6328](https://github.com/netdata/netdata/pull/6328) ([ilyam8](https://github.com/ilyam8)) -- pihole: add to the dashboard\_info [\#6325](https://github.com/netdata/netdata/pull/6325) ([ilyam8](https://github.com/ilyam8)) -- pihole collector: add alarms [\#6320](https://github.com/netdata/netdata/pull/6320) ([ilyam8](https://github.com/ilyam8)) -- dnsmasq\_dhcp: dhcp-range utilization alarm [\#6319](https://github.com/netdata/netdata/pull/6319) ([ilyam8](https://github.com/ilyam8)) -- Update the documentation on charts with zero metrics [\#6314](https://github.com/netdata/netdata/pull/6314) ([vlvkobal](https://github.com/vlvkobal)) -- fix elasticsearch plugin [\#6311](https://github.com/netdata/netdata/pull/6311) ([Wing924](https://github.com/Wing924)) -- Repeating alarm notifications [\#6309](https://github.com/netdata/netdata/pull/6309) ([thiagoftsm](https://github.com/thiagoftsm)) -- Chart name streaming [\#6304](https://github.com/netdata/netdata/pull/6304) ([vlvkobal](https://github.com/vlvkobal)) -- Handle file descriptors running out [\#6303](https://github.com/netdata/netdata/pull/6303) ([mfundul](https://github.com/mfundul)) -- Add note regarding libexecdir [\#6301](https://github.com/netdata/netdata/pull/6301) ([cakrit](https://github.com/cakrit)) -- stale bot limits update [\#6297](https://github.com/netdata/netdata/pull/6297) ([ilyam8](https://github.com/ilyam8)) -- \[freeipmi\] Remove id in sensor name when already unique [\#6296](https://github.com/netdata/netdata/pull/6296) ([Saruspete](https://github.com/Saruspete)) -- Agent Frontend footer hidden [\#6294](https://github.com/netdata/netdata/pull/6294) ([thiagoftsm](https://github.com/thiagoftsm)) -- doc: remove single/multi-threaded web server configuration [\#6291](https://github.com/netdata/netdata/pull/6291) ([nodiscc](https://github.com/nodiscc)) -- Add a riak plugin [\#6286](https://github.com/netdata/netdata/pull/6286) ([jchristgit](https://github.com/jchristgit)) -- netdata/packaging: Separate beta messages from production messages [\#6282](https://github.com/netdata/netdata/pull/6282) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Add more info on the stream.conf health enabled by default = auto option [\#6281](https://github.com/netdata/netdata/pull/6281) ([cakrit](https://github.com/cakrit)) -- Add comments about AWS SDK for C++ installation [\#6277](https://github.com/netdata/netdata/pull/6277) ([vlvkobal](https://github.com/vlvkobal)) -- Easily disable alarms, by persisting the silencers configuration [\#6274](https://github.com/netdata/netdata/pull/6274) ([thiagoftsm](https://github.com/thiagoftsm)) -- netdata/packaging: During install, many file not found were raised [\#6272](https://github.com/netdata/netdata/pull/6272) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/documentation: Its Redhat, then came the others [\#6271](https://github.com/netdata/netdata/pull/6271) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging: Adjust CI notification logic [\#6268](https://github.com/netdata/netdata/pull/6268) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Update README.md [\#6264](https://github.com/netdata/netdata/pull/6264) ([mfundul](https://github.com/mfundul)) -- UrlService: add min required version check [\#6263](https://github.com/netdata/netdata/pull/6263) ([ilyam8](https://github.com/ilyam8)) -- Fix variable namespace in memory health check [\#6261](https://github.com/netdata/netdata/pull/6261) ([octomike](https://github.com/octomike)) -- Fix typo in nfacct.plugin [\#6260](https://github.com/netdata/netdata/pull/6260) ([vlvkobal](https://github.com/vlvkobal)) -- netdata/packaging: Fix netdata/netdata docker image failure, when users passing PGID that already exists on the system [\#6259](https://github.com/netdata/netdata/pull/6259) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- PR to fix issue \#6238 [\#6242](https://github.com/netdata/netdata/pull/6242) ([thiagoftsm](https://github.com/thiagoftsm)) -- Update CODEOWNERS [\#6241](https://github.com/netdata/netdata/pull/6241) ([cakrit](https://github.com/cakrit)) -- Force page alignment per dimension of chart. [\#6240](https://github.com/netdata/netdata/pull/6240) ([mfundul](https://github.com/mfundul)) -- dns\_query\_time py module: saving dns request in 'r', checking response for answer, recording '-… [\#6237](https://github.com/netdata/netdata/pull/6237) ([n0coast](https://github.com/n0coast)) -- netdata/packaging: Add more distribution validations [\#6235](https://github.com/netdata/netdata/pull/6235) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Remove CNCF logo and TOC presentation reference [\#6234](https://github.com/netdata/netdata/pull/6234) ([dankohn](https://github.com/dankohn)) -- URL\_parser fixing allmetrics! [\#6231](https://github.com/netdata/netdata/pull/6231) ([thiagoftsm](https://github.com/thiagoftsm)) -- Perf plugin [\#6225](https://github.com/netdata/netdata/pull/6225) ([vlvkobal](https://github.com/vlvkobal)) -- netdata/packaging: Introducing automatic binary packages generation and delivery for RPM types \(Phase 1\) [\#6223](https://github.com/netdata/netdata/pull/6223) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Backend and SSL! [\#6220](https://github.com/netdata/netdata/pull/6220) ([thiagoftsm](https://github.com/thiagoftsm)) -- SSL\_fix\_format Fix wrong format used with SSL! [\#6219](https://github.com/netdata/netdata/pull/6219) ([thiagoftsm](https://github.com/thiagoftsm)) -- installer: include go.d.plugin version v0.6.1 [\#6217](https://github.com/netdata/netdata/pull/6217) ([ilyam8](https://github.com/ilyam8)) -- Fill chart gaps efficiently. [\#6216](https://github.com/netdata/netdata/pull/6216) ([mfundul](https://github.com/mfundul)) -- Add code style guidance to CONTRIBUTING [\#6212](https://github.com/netdata/netdata/pull/6212) ([cakrit](https://github.com/cakrit)) -- Simplify health cmdapi tester - no setup/cleanup needed [\#6210](https://github.com/netdata/netdata/pull/6210) ([cakrit](https://github.com/cakrit)) -- Visibility fix in anonymous-statistics.md [\#6208](https://github.com/netdata/netdata/pull/6208) ([cakrit](https://github.com/cakrit)) -- smartd documentation improvements [\#6207](https://github.com/netdata/netdata/pull/6207) ([cakrit](https://github.com/cakrit)) -- Add note to make smartd directory [\#6203](https://github.com/netdata/netdata/pull/6203) ([Steve8291](https://github.com/Steve8291)) -- Fix page cache descriptor race condition [\#6202](https://github.com/netdata/netdata/pull/6202) ([mfundul](https://github.com/mfundul)) -- Turn tv.html links to https [\#6198](https://github.com/netdata/netdata/pull/6198) ([cakrit](https://github.com/cakrit)) -- wmi collector: `fa-server` icon [\#6197](https://github.com/netdata/netdata/pull/6197) ([ilyam8](https://github.com/ilyam8)) -- Change print level from error to info [\#6195](https://github.com/netdata/netdata/pull/6195) ([mfundul](https://github.com/mfundul)) -- health: change x509check\_last\_collected\_secs alarm every to 60s [\#6194](https://github.com/netdata/netdata/pull/6194) ([ilyam8](https://github.com/ilyam8)) -- Documentation: Correct example list for python.d SimpleService [\#6189](https://github.com/netdata/netdata/pull/6189) ([kvisle](https://github.com/kvisle)) -- Terminate email header lines with \r\n [\#6187](https://github.com/netdata/netdata/pull/6187) ([toofar](https://github.com/toofar)) -- Make custom notification's instructions clearer [\#6181](https://github.com/netdata/netdata/pull/6181) ([cakrit](https://github.com/cakrit)) -- web log pattern fix [\#6180](https://github.com/netdata/netdata/pull/6180) ([ilyam8](https://github.com/ilyam8)) -- Correct date used in pushbullet notifications [\#6179](https://github.com/netdata/netdata/pull/6179) ([cakrit](https://github.com/cakrit)) -- Support falling back to buffered I/O when direct I/O is unavailable [\#6174](https://github.com/netdata/netdata/pull/6174) ([mfundul](https://github.com/mfundul)) -- Add empty page detection in DB engine [\#6173](https://github.com/netdata/netdata/pull/6173) ([mfundul](https://github.com/mfundul)) -- Increase the cpu\_limit chart precision in cgroup plugin [\#6172](https://github.com/netdata/netdata/pull/6172) ([vlvkobal](https://github.com/vlvkobal)) -- varnish v4 compatibility fix [\#6168](https://github.com/netdata/netdata/pull/6168) ([ilyam8](https://github.com/ilyam8)) -- Update security policy [\#6166](https://github.com/netdata/netdata/pull/6166) ([cakrit](https://github.com/cakrit)) -- Fix mdstat disks chart [\#6164](https://github.com/netdata/netdata/pull/6164) ([vlvkobal](https://github.com/vlvkobal)) -- Properly add security policy [\#6163](https://github.com/netdata/netdata/pull/6163) ([cakrit](https://github.com/cakrit)) -- Fix typo in README [\#6146](https://github.com/netdata/netdata/pull/6146) ([cakrit](https://github.com/cakrit)) -- Documentation fixes [\#6144](https://github.com/netdata/netdata/pull/6144) ([cakrit](https://github.com/cakrit)) -- x509check: add last\_collected alarm [\#6139](https://github.com/netdata/netdata/pull/6139) ([ilyam8](https://github.com/ilyam8)) -- web\_log: remove trailing space from nginx\_ext2 pattern [\#6138](https://github.com/netdata/netdata/pull/6138) ([ilyam8](https://github.com/ilyam8)) -- Change 'netdata' to 'Netdata' in /docs/ and /README.md [\#6137](https://github.com/netdata/netdata/pull/6137) ([apardyl](https://github.com/apardyl)) -- DB engine optimize RAM usage [\#6134](https://github.com/netdata/netdata/pull/6134) ([mfundul](https://github.com/mfundul)) -- Optimize calls that gather system info [\#6128](https://github.com/netdata/netdata/pull/6128) ([cakrit](https://github.com/cakrit)) -- Fix telemetry config in netdata-installer [\#6127](https://github.com/netdata/netdata/pull/6127) ([cakrit](https://github.com/cakrit)) -- Pass correct info to run funct. [\#6126](https://github.com/netdata/netdata/pull/6126) ([Steve8291](https://github.com/Steve8291)) -- Add modules to charts.d.conf [\#6120](https://github.com/netdata/netdata/pull/6120) ([Steve8291](https://github.com/Steve8291)) -- add userstats charts for mysql [\#6118](https://github.com/netdata/netdata/pull/6118) ([kam1kaze](https://github.com/kam1kaze)) -- Active processes number alert [\#6116](https://github.com/netdata/netdata/pull/6116) ([apardyl](https://github.com/apardyl)) -- add mysql deadlocks chart [\#6115](https://github.com/netdata/netdata/pull/6115) ([kam1kaze](https://github.com/kam1kaze)) -- Remove system\_info copying [\#6113](https://github.com/netdata/netdata/pull/6113) ([vlvkobal](https://github.com/vlvkobal)) -- Fix incorrect module name: energi [\#6112](https://github.com/netdata/netdata/pull/6112) ([Steve8291](https://github.com/Steve8291)) -- Update README.md [\#6111](https://github.com/netdata/netdata/pull/6111) ([mfundul](https://github.com/mfundul)) -- installer: include go.d.plugin version v0.6.0 [\#6097](https://github.com/netdata/netdata/pull/6097) ([ilyam8](https://github.com/ilyam8)) -- Move call to send\_statistics later, to get more events from docker [\#6096](https://github.com/netdata/netdata/pull/6096) ([cakrit](https://github.com/cakrit)) -- Fix path \#6085 [\#6093](https://github.com/netdata/netdata/pull/6093) ([gmosx](https://github.com/gmosx)) -- Fix minor typos [\#6090](https://github.com/netdata/netdata/pull/6090) ([Steve8291](https://github.com/Steve8291)) -- Create missing /etc/netdata/custom-plugins.d [\#6089](https://github.com/netdata/netdata/pull/6089) ([Steve8291](https://github.com/Steve8291)) -- Corrected links to web\_log.conf [\#6087](https://github.com/netdata/netdata/pull/6087) ([cakrit](https://github.com/cakrit)) -- Mention anonymous statistics in additional places in the docs [\#6084](https://github.com/netdata/netdata/pull/6084) ([cakrit](https://github.com/cakrit)) -- Add "custom-plugins.d" to fix error in log file [\#6080](https://github.com/netdata/netdata/pull/6080) ([Steve8291](https://github.com/Steve8291)) -- New URL parser [\#6070](https://github.com/netdata/netdata/pull/6070) ([thiagoftsm](https://github.com/thiagoftsm)) -- wmi alarms [\#6068](https://github.com/netdata/netdata/pull/6068) ([ilyam8](https://github.com/ilyam8)) -- Add perforce server process monitoring [\#6064](https://github.com/netdata/netdata/pull/6064) ([akwan](https://github.com/akwan)) -- Prometheus remote write backend [\#6062](https://github.com/netdata/netdata/pull/6062) ([vlvkobal](https://github.com/vlvkobal)) -- SSL implementation for Netdata [\#5956](https://github.com/netdata/netdata/pull/5956) ([thiagoftsm](https://github.com/thiagoftsm)) -- NEW: local remark-lint checks and autofix support [\#5898](https://github.com/netdata/netdata/pull/5898) ([andvgal](https://github.com/andvgal)) -- use github templating mechanisms to classify issues when they are created [\#5776](https://github.com/netdata/netdata/pull/5776) ([paulfantom](https://github.com/paulfantom)) ## [v1.15.0](https://github.com/netdata/netdata/tree/v1.15.0) (2019-05-22) -**Fixed bugs:** - -- netdata/packaging: Fix kickstart/kickstart-static64 formatting bugs [\#6048](https://github.com/netdata/netdata/pull/6048) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging: install/uninstall fixes for macOS case [\#6045](https://github.com/netdata/netdata/pull/6045) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging: Adjust auto-updater installation logic [\#6035](https://github.com/netdata/netdata/pull/6035) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging: Fix broken netdata docker image for dbengine-enabled code [\#6020](https://github.com/netdata/netdata/pull/6020) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Fix segmentation fault [\#6011](https://github.com/netdata/netdata/pull/6011) ([vlvkobal](https://github.com/vlvkobal)) -- netdata/packaging: Fix failing CI nightly process [\#6007](https://github.com/netdata/netdata/pull/6007) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) - -**Merged pull requests:** - -- Shorten netdata version and correctly send OS\_VERSION\_ID [\#6082](https://github.com/netdata/netdata/pull/6082) ([cakrit](https://github.com/cakrit)) -- Fix build errors [\#6081](https://github.com/netdata/netdata/pull/6081) ([mfundul](https://github.com/mfundul)) -- Fix race condition in DB engine API [\#6079](https://github.com/netdata/netdata/pull/6079) ([mfundul](https://github.com/mfundul)) -- Fix creating chart directories when not necessary with memory mode dbengine [\#6078](https://github.com/netdata/netdata/pull/6078) ([mfundul](https://github.com/mfundul)) -- Add more metrics to the prometheus bats tests [\#6074](https://github.com/netdata/netdata/pull/6074) ([cakrit](https://github.com/cakrit)) -- Add 1.15 to news section of main README [\#6065](https://github.com/netdata/netdata/pull/6065) ([cakrit](https://github.com/cakrit)) -- Fix delete datafile error [\#6057](https://github.com/netdata/netdata/pull/6057) ([mfundul](https://github.com/mfundul)) -- Update swagger with definition of api/v1/alarm\_variables [\#6055](https://github.com/netdata/netdata/pull/6055) ([cakrit](https://github.com/cakrit)) -- Reiterate the proper way to persist configurations in the Configuration guid [\#6052](https://github.com/netdata/netdata/pull/6052) ([cakrit](https://github.com/cakrit)) -- netdata/daemon/backends: Fix AWS Kinesis link error [\#6047](https://github.com/netdata/netdata/pull/6047) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging: Fix makeself packaging [\#6041](https://github.com/netdata/netdata/pull/6041) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Fix timestamps being reversed for backends [\#6040](https://github.com/netdata/netdata/pull/6040) ([mfundul](https://github.com/mfundul)) -- Improve paragraphs in HTML docs [\#6032](https://github.com/netdata/netdata/pull/6032) ([cakrit](https://github.com/cakrit)) -- Reduce HTML documentation font size [\#6030](https://github.com/netdata/netdata/pull/6030) ([cakrit](https://github.com/cakrit)) -- Add database engine doc to the menu [\#6029](https://github.com/netdata/netdata/pull/6029) ([cakrit](https://github.com/cakrit)) -- Minor improvements for Nodes integration [\#6028](https://github.com/netdata/netdata/pull/6028) ([gmosx](https://github.com/gmosx)) -- installer: include go.d.plugin version v0.5.0 [\#6025](https://github.com/netdata/netdata/pull/6025) ([ilyam8](https://github.com/ilyam8)) -- netdata/packaging: Fine tune documentation on how to test docker images [\#6024](https://github.com/netdata/netdata/pull/6024) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Add prowl to list of methods checked for enablement of notifications [\#6022](https://github.com/netdata/netdata/pull/6022) ([cakrit](https://github.com/cakrit)) -- Correct instructions on Slack webhooks [\#6016](https://github.com/netdata/netdata/pull/6016) ([cakrit](https://github.com/cakrit)) -- netdata/packaging: Make docker image bring onboard the required packages for the new DB [\#6014](https://github.com/netdata/netdata/pull/6014) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Fix Coverity defects [\#6008](https://github.com/netdata/netdata/pull/6008) ([vlvkobal](https://github.com/vlvkobal)) -- Do not cache alarms and info api calls. Extend no-cache headers. [\#5999](https://github.com/netdata/netdata/pull/5999) ([cakrit](https://github.com/cakrit)) -- UserService self.\_get\_raw\_data except fix [\#5997](https://github.com/netdata/netdata/pull/5997) ([ilyam8](https://github.com/ilyam8)) -- Add system info streaming [\#5996](https://github.com/netdata/netdata/pull/5996) ([vlvkobal](https://github.com/vlvkobal)) -- Provide sample implementation for custom notifications [\#5992](https://github.com/netdata/netdata/pull/5992) ([cakrit](https://github.com/cakrit)) -- \(Docs\) fix pfsense instructions [\#5982](https://github.com/netdata/netdata/pull/5982) ([Fohdeesha](https://github.com/Fohdeesha)) -- fix typo in the mysql graph [\#5980](https://github.com/netdata/netdata/pull/5980) ([kam1kaze](https://github.com/kam1kaze)) -- Change HTTP version to HTTP method [\#5974](https://github.com/netdata/netdata/pull/5974) ([SahAssar](https://github.com/SahAssar)) -- Add "text-only" chart renderer [\#5971](https://github.com/netdata/netdata/pull/5971) ([Daniel15](https://github.com/Daniel15)) -- Update Node app\_group [\#5962](https://github.com/netdata/netdata/pull/5962) ([jonfairbanks](https://github.com/jonfairbanks)) -- Fix coverity warnings [\#5952](https://github.com/netdata/netdata/pull/5952) ([cakrit](https://github.com/cakrit)) -- Add support for Mac OS X Name and Version [\#5949](https://github.com/netdata/netdata/pull/5949) ([cakrit](https://github.com/cakrit)) -- netdata/packaging: Do not install netdata service when within docker [\#5947](https://github.com/netdata/netdata/pull/5947) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- nvidia\_smi: power chart algorithm,mul,div fix [\#5940](https://github.com/netdata/netdata/pull/5940) ([ilyam8](https://github.com/ilyam8)) -- netdata/packaging/ci: Make timeout usage more cross-distro compliant [\#5938](https://github.com/netdata/netdata/pull/5938) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Fixing a typo in documentation [\#5936](https://github.com/netdata/netdata/pull/5936) ([smonff](https://github.com/smonff)) -- mongodb: various KeyError fixes [\#5931](https://github.com/netdata/netdata/pull/5931) ([ilyam8](https://github.com/ilyam8)) -- netdata/packaging/ci: minor improvements [\#5928](https://github.com/netdata/netdata/pull/5928) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- smartd\_log: attrs 3, 194 fix [\#5923](https://github.com/netdata/netdata/pull/5923) ([ilyam8](https://github.com/ilyam8)) -- Fix lifecycle script [\#5918](https://github.com/netdata/netdata/pull/5918) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/docker: fix docker permissions and other things [\#5917](https://github.com/netdata/netdata/pull/5917) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Add AWS Kinesis backend [\#5914](https://github.com/netdata/netdata/pull/5914) ([vlvkobal](https://github.com/vlvkobal)) -- SocketService: set socket operation timeout before connecting [\#5911](https://github.com/netdata/netdata/pull/5911) ([ilyam8](https://github.com/ilyam8)) -- Support for aggregate node view [\#5902](https://github.com/netdata/netdata/pull/5902) ([gmosx](https://github.com/gmosx)) -- netdata/packaging/ci: Create manual nightly deployment tool [\#5899](https://github.com/netdata/netdata/pull/5899) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Implement unified cgroup cpu limit [\#5895](https://github.com/netdata/netdata/pull/5895) ([skrzyp1](https://github.com/skrzyp1)) -- NEW: Energi Core daemon monitoring, suits other Bitcoin forks [\#5894](https://github.com/netdata/netdata/pull/5894) ([andvgal](https://github.com/andvgal)) -- NEW: allow additional name argument passing to urllib3 request in UrlService [\#5893](https://github.com/netdata/netdata/pull/5893) ([andvgal](https://github.com/andvgal)) -- Initial script for API load testing [\#5892](https://github.com/netdata/netdata/pull/5892) ([cakrit](https://github.com/cakrit)) -- info API minor enhancements [\#5891](https://github.com/netdata/netdata/pull/5891) ([cakrit](https://github.com/cakrit)) -- Extend netdata info API call [\#5889](https://github.com/netdata/netdata/pull/5889) ([cakrit](https://github.com/cakrit)) -- Add ioping plugin [\#5725](https://github.com/netdata/netdata/pull/5725) ([vlvkobal](https://github.com/vlvkobal)) -- Database engine [\#5282](https://github.com/netdata/netdata/pull/5282) ([mfundul](https://github.com/mfundul)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.14.0...v1.15.0) ## [v1.14.0](https://github.com/netdata/netdata/tree/v1.14.0) (2019-04-18) -**Fixed bugs:** - -- netdata/packaging/ci: Do not trigger deployment if certain conditions are not met [\#5816](https://github.com/netdata/netdata/pull/5816) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/installer: HoS situation - Fix broken install-or-update script [\#5806](https://github.com/netdata/netdata/pull/5806) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging: Fix non compatible function declaration [\#5789](https://github.com/netdata/netdata/pull/5789) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Make netdata.spec more futureproof [\#5766](https://github.com/netdata/netdata/pull/5766) ([nichivo](https://github.com/nichivo)) - -**Merged pull requests:** - -- Pipeline redesign master [\#5885](https://github.com/netdata/netdata/pull/5885) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Fix segmentation fault in streaming [\#5882](https://github.com/netdata/netdata/pull/5882) ([vlvkobal](https://github.com/vlvkobal)) -- netdata/packaging/ci: Use proper notifier in slack message [\#5866](https://github.com/netdata/netdata/pull/5866) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/installer: Dont use --always in git describe. [\#5860](https://github.com/netdata/netdata/pull/5860) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Openldap tls support rebased [\#5859](https://github.com/netdata/netdata/pull/5859) ([ekartsonakis](https://github.com/ekartsonakis)) -- netdata/packaging/installer: correlate permissions amongst plugins to 0750 [\#5856](https://github.com/netdata/netdata/pull/5856) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/web/gui/dashboard: do not remove the dashboard upon make clean [\#5853](https://github.com/netdata/netdata/pull/5853) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- installer: include go.d.plugin version v0.4.0 [\#5849](https://github.com/netdata/netdata/pull/5849) ([ilyam8](https://github.com/ilyam8)) -- netdata/collectors/cgroups.plugin: When jq not available, prompt the user he may have to install jq [\#5848](https://github.com/netdata/netdata/pull/5848) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- python.d.plugin: py2 fix crash on macos [\#5838](https://github.com/netdata/netdata/pull/5838) ([ilyam8](https://github.com/ilyam8)) -- python.d.plugin: autodetection retry fix [\#5837](https://github.com/netdata/netdata/pull/5837) ([ilyam8](https://github.com/ilyam8)) -- phpfpm collector: add last\_collected\_secs health check [\#5836](https://github.com/netdata/netdata/pull/5836) ([ilyam8](https://github.com/ilyam8)) -- elasticsearch: update config file [\#5834](https://github.com/netdata/netdata/pull/5834) ([ilyam8](https://github.com/ilyam8)) -- couchdb: \_fetch\_data TypeError fix [\#5833](https://github.com/netdata/netdata/pull/5833) ([ilyam8](https://github.com/ilyam8)) -- Return responses even in memory mode none [\#5819](https://github.com/netdata/netdata/pull/5819) ([cakrit](https://github.com/cakrit)) -- netdata/packaging/installer: Update README [\#5811](https://github.com/netdata/netdata/pull/5811) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- python.d.plugin zombie fix [\#5797](https://github.com/netdata/netdata/pull/5797) ([ilyam8](https://github.com/ilyam8)) -- Add memory free and per process memory usage to nvidia\_smi [\#5796](https://github.com/netdata/netdata/pull/5796) ([huww98](https://github.com/huww98)) -- python.d.plugin: allow delete dimension in runtime [\#5795](https://github.com/netdata/netdata/pull/5795) ([ilyam8](https://github.com/ilyam8)) -- Support configurable syslog facilities [\#5792](https://github.com/netdata/netdata/pull/5792) ([thiagoftsm](https://github.com/thiagoftsm)) -- netdata/packaging/docker: Change password [\#5790](https://github.com/netdata/netdata/pull/5790) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/updater: fix updater [\#5785](https://github.com/netdata/netdata/pull/5785) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/ci: fix travis syntax [\#5780](https://github.com/netdata/netdata/pull/5780) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Add preferred disk id pattern [\#5779](https://github.com/netdata/netdata/pull/5779) ([vlvkobal](https://github.com/vlvkobal)) -- netdata/packaging/ci: Add kickstart execution integrity tests [\#5778](https://github.com/netdata/netdata/pull/5778) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata: Add another global owner [\#5777](https://github.com/netdata/netdata/pull/5777) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/kickstart: fix kickstart [\#5771](https://github.com/netdata/netdata/pull/5771) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Fix smstools3 error handling [\#5770](https://github.com/netdata/netdata/pull/5770) ([cakrit](https://github.com/cakrit)) -- netdata/packaging: Remove .tar.gz on distclean [\#5763](https://github.com/netdata/netdata/pull/5763) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/installer: fix sha256sum failure on freeBSD [\#5760](https://github.com/netdata/netdata/pull/5760) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- postgres module: connect via uri [\#5758](https://github.com/netdata/netdata/pull/5758) ([ilyam8](https://github.com/ilyam8)) -- Fix unix socket access on FreeBSD [\#5756](https://github.com/netdata/netdata/pull/5756) ([vlvkobal](https://github.com/vlvkobal)) -- libapache2-mod-proxy-html was a transitional package for apache2-bin [\#5753](https://github.com/netdata/netdata/pull/5753) ([piiiggg](https://github.com/piiiggg)) -- Fix the Polyverse reinstall that caused APK broken state [\#5751](https://github.com/netdata/netdata/pull/5751) ([archisgore](https://github.com/archisgore)) -- fix go.d.plugin config.tar.gz checksum [\#5750](https://github.com/netdata/netdata/pull/5750) ([ilyam8](https://github.com/ilyam8)) -- Correct typo in ceph README [\#5742](https://github.com/netdata/netdata/pull/5742) ([cakrit](https://github.com/cakrit)) -- Fix some misspells in docs and code [\#5549](https://github.com/netdata/netdata/pull/5549) ([JoeWrightss](https://github.com/JoeWrightss)) -- Added RocketChat default recipient for roles [\#5545](https://github.com/netdata/netdata/pull/5545) ([tctovsli](https://github.com/tctovsli)) -- Add simonnagl as CODEOWNER for cups.plugin [\#5453](https://github.com/netdata/netdata/pull/5453) ([simonnagl](https://github.com/simonnagl)) -- unified cgroup support [\#5407](https://github.com/netdata/netdata/pull/5407) ([skrzyp1](https://github.com/skrzyp1)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.14.0-rc0...v1.14.0) ## [v1.14.0-rc0](https://github.com/netdata/netdata/tree/v1.14.0-rc0) (2019-03-30) -**Merged pull requests:** - -- netdata/packaging/ci: small improvements in logging [\#5746](https://github.com/netdata/netdata/pull/5746) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/makeself: no comment [\#5743](https://github.com/netdata/netdata/pull/5743) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- installer: include go.d.plugin version v0.3.1 [\#5740](https://github.com/netdata/netdata/pull/5740) ([ilyam8](https://github.com/ilyam8)) -- access: fix codeowners [\#5739](https://github.com/netdata/netdata/pull/5739) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/installer: netdata-installer.sh script \(and subscripts\) refactoring wrap-up [\#5736](https://github.com/netdata/netdata/pull/5736) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Spelling fix for streaming readme.md [\#5734](https://github.com/netdata/netdata/pull/5734) ([vinyasmusic](https://github.com/vinyasmusic)) -- Fix dist build [\#5728](https://github.com/netdata/netdata/pull/5728) ([vlvkobal](https://github.com/vlvkobal)) -- add some kubelet alarms [\#5724](https://github.com/netdata/netdata/pull/5724) ([ilyam8](https://github.com/ilyam8)) -- Update fping version [\#5719](https://github.com/netdata/netdata/pull/5719) ([vlvkobal](https://github.com/vlvkobal)) -- add some kubernetes to apps\_groups.conf [\#5714](https://github.com/netdata/netdata/pull/5714) ([ilyam8](https://github.com/ilyam8)) -- netdata/packaging/ci: nits [\#5709](https://github.com/netdata/netdata/pull/5709) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/ci: Make Travis CI more strict on nightlies run [\#5708](https://github.com/netdata/netdata/pull/5708) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- NEW: authdb option for MongoDB collector [\#5707](https://github.com/netdata/netdata/pull/5707) ([andvgal](https://github.com/andvgal)) -- Send custom docs [\#5703](https://github.com/netdata/netdata/pull/5703) ([cakrit](https://github.com/cakrit)) -- add 'containers priority' option to cgroups plugin [\#5700](https://github.com/netdata/netdata/pull/5700) ([ilyam8](https://github.com/ilyam8)) -- Remove temp log file if no update needed [\#5695](https://github.com/netdata/netdata/pull/5695) ([cakrit](https://github.com/cakrit)) -- add a description how to achieve vhost access logs with nginx in web\_log [\#5694](https://github.com/netdata/netdata/pull/5694) ([hsegnitz](https://github.com/hsegnitz)) -- netdata/packaging/docker/publish: Fix docker publishing [\#5692](https://github.com/netdata/netdata/pull/5692) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- netdata/packaging/docker: Fix build - typo on array iteration [\#5691](https://github.com/netdata/netdata/pull/5691) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Integrity testing: Check published kickstart files integrity [\#5689](https://github.com/netdata/netdata/pull/5689) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- do not show the modal on demo sites [\#5686](https://github.com/netdata/netdata/pull/5686) ([ktsaou](https://github.com/ktsaou)) -- netdata/packaging/uninstaller: Update uninstall document [\#5678](https://github.com/netdata/netdata/pull/5678) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- fix incorrect use of isnormal\(\) [\#5677](https://github.com/netdata/netdata/pull/5677) ([ktsaou](https://github.com/ktsaou)) -- py stuff: change l2isbad to ilyam8 [\#5676](https://github.com/netdata/netdata/pull/5676) ([ilyam8](https://github.com/ilyam8)) -- bring uninstaller back [\#5675](https://github.com/netdata/netdata/pull/5675) ([paulfantom](https://github.com/paulfantom)) -- Fix py2-psycopg2 right after upgrade [\#5667](https://github.com/netdata/netdata/pull/5667) ([archisgore](https://github.com/archisgore)) -- Add SMS Server Tools 3 SMS notifications [\#5662](https://github.com/netdata/netdata/pull/5662) ([cakrit](https://github.com/cakrit)) -- postgres add ssl connection support [\#5661](https://github.com/netdata/netdata/pull/5661) ([ilyam8](https://github.com/ilyam8)) -- Add xenstat plugin [\#5660](https://github.com/netdata/netdata/pull/5660) ([vlvkobal](https://github.com/vlvkobal)) -- Remove obsolete python modules [\#5659](https://github.com/netdata/netdata/pull/5659) ([ilyam8](https://github.com/ilyam8)) -- Fix path to pidfile in FreeBSD rc.d file [\#5657](https://github.com/netdata/netdata/pull/5657) ([honzahommer](https://github.com/honzahommer)) -- netdata/build: A small house keeping around coverity scan \(no functional or process change\) [\#5656](https://github.com/netdata/netdata/pull/5656) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Load gtm only if anonymous\_statistics are enabled [\#5651](https://github.com/netdata/netdata/pull/5651) ([cakrit](https://github.com/cakrit)) -- Fix slack notifications footer and set cloud redirect URL to http [\#5650](https://github.com/netdata/netdata/pull/5650) ([cakrit](https://github.com/cakrit)) -- x509check alarm fix [\#5645](https://github.com/netdata/netdata/pull/5645) ([ilyam8](https://github.com/ilyam8)) -- Split docker build script into build and publish - attempt small cleanups along the way [\#5591](https://github.com/netdata/netdata/pull/5591) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- fix command not found error when run script under root user. [\#5581](https://github.com/netdata/netdata/pull/5581) ([vinsia](https://github.com/vinsia)) -- Patch netdata-installer.sh to avoid unwanted errors during stock config cleanup [\#5571](https://github.com/netdata/netdata/pull/5571) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Make sign-in functionality more visible [\#5569](https://github.com/netdata/netdata/pull/5569) ([gmosx](https://github.com/gmosx)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.13.0...v1.14.0-rc0) ## [v1.13.0](https://github.com/netdata/netdata/tree/v1.13.0) (2019-03-14) -**Merged pull requests:** - -- installer: include go.d.plugin version v0.2.0 [\#5638](https://github.com/netdata/netdata/pull/5638) ([paulfantom](https://github.com/paulfantom)) -- Beanstalk fix [\#5633](https://github.com/netdata/netdata/pull/5633) ([ilyam8](https://github.com/ilyam8)) -- Add link to k8s helm chart in installation [\#5627](https://github.com/netdata/netdata/pull/5627) ([cakrit](https://github.com/cakrit)) -- Remove ssl check module [\#5626](https://github.com/netdata/netdata/pull/5626) ([ilyam8](https://github.com/ilyam8)) -- Fix Postgres connect, incorrect port value [\#5618](https://github.com/netdata/netdata/pull/5618) ([Jaxmetalmax](https://github.com/Jaxmetalmax)) -- postgres connect fix [\#5617](https://github.com/netdata/netdata/pull/5617) ([ilyam8](https://github.com/ilyam8)) -- Fix a bug in cgroups renaming [\#5612](https://github.com/netdata/netdata/pull/5612) ([vlvkobal](https://github.com/vlvkobal)) -- mysql module add ssl connection support [\#5610](https://github.com/netdata/netdata/pull/5610) ([ilyam8](https://github.com/ilyam8)) -- Fix memory leaks [\#5604](https://github.com/netdata/netdata/pull/5604) ([vlvkobal](https://github.com/vlvkobal)) -- python loaders cleanup [\#5602](https://github.com/netdata/netdata/pull/5602) ([ilyam8](https://github.com/ilyam8)) -- Update custom dashboards documentation [\#5600](https://github.com/netdata/netdata/pull/5600) ([cakrit](https://github.com/cakrit)) -- spigotmc fix UnicodeDecodeError [\#5598](https://github.com/netdata/netdata/pull/5598) ([ilyam8](https://github.com/ilyam8)) -- SimpleService cleanup: do not inherit from OldVersionCompatibility [\#5594](https://github.com/netdata/netdata/pull/5594) ([ilyam8](https://github.com/ilyam8)) -- spigotmc: py2 compatibility fix [\#5593](https://github.com/netdata/netdata/pull/5593) ([ilyam8](https://github.com/ilyam8)) -- Use total\_\* memory counters for cgroups [\#5592](https://github.com/netdata/netdata/pull/5592) ([vlvkobal](https://github.com/vlvkobal)) -- remove paulfantom code ownership and TODO notices [\#5579](https://github.com/netdata/netdata/pull/5579) ([paulfantom](https://github.com/paulfantom)) -- When running from within a k8s pod, use the k8s API to get the cgroup name [\#5576](https://github.com/netdata/netdata/pull/5576) ([cakrit](https://github.com/cakrit)) -- Wait for logs to be opened before calling anonymous statistics [\#5573](https://github.com/netdata/netdata/pull/5573) ([cakrit](https://github.com/cakrit)) -- Fix nonobsolete dimension deletion [\#5563](https://github.com/netdata/netdata/pull/5563) ([vlvkobal](https://github.com/vlvkobal)) -- Fix incorrect icon for streaming master \#5560 [\#5561](https://github.com/netdata/netdata/pull/5561) ([gmosx](https://github.com/gmosx)) -- Delay renaming for docker containers [\#5557](https://github.com/netdata/netdata/pull/5557) ([vlvkobal](https://github.com/vlvkobal)) -- Correct PLUGINS\_DIR flag in CMakeLists.txt [\#5555](https://github.com/netdata/netdata/pull/5555) ([cakrit](https://github.com/cakrit)) -- python.d.plugin: use separate process for initial module checking [\#5552](https://github.com/netdata/netdata/pull/5552) ([ilyam8](https://github.com/ilyam8)) -- Pass agent id to authorization pages [\#5551](https://github.com/netdata/netdata/pull/5551) ([gmosx](https://github.com/gmosx)) -- Have the debug option set the freeipmi debug flags [\#5548](https://github.com/netdata/netdata/pull/5548) ([cakrit](https://github.com/cakrit)) -- Fix typo [\#5546](https://github.com/netdata/netdata/pull/5546) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Add news for 1.12.1 and 1.12.2 to main readme [\#5544](https://github.com/netdata/netdata/pull/5544) ([cakrit](https://github.com/cakrit)) -- Don't send zeroes for empty groups [\#5540](https://github.com/netdata/netdata/pull/5540) ([vlvkobal](https://github.com/vlvkobal)) -- Correct go.d.plugin sha256sum check [\#5539](https://github.com/netdata/netdata/pull/5539) ([cakrit](https://github.com/cakrit)) -- Registry delete should allow deleting the host we are looking at [\#5537](https://github.com/netdata/netdata/pull/5537) ([cakrit](https://github.com/cakrit)) -- Minor fixes around plugin\_directories initialization [\#5536](https://github.com/netdata/netdata/pull/5536) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Support legacy Prometheus metric names for source average [\#5531](https://github.com/netdata/netdata/pull/5531) ([cakrit](https://github.com/cakrit)) -- Update unbound module documenttion with troubleshooting section. [\#5528](https://github.com/netdata/netdata/pull/5528) ([Ferroin](https://github.com/Ferroin)) -- Add IPC shared memory charts [\#5522](https://github.com/netdata/netdata/pull/5522) ([vlvkobal](https://github.com/vlvkobal)) -- Prevent data corruption upon GUID duplication between master and slave netdata instances [\#5511](https://github.com/netdata/netdata/pull/5511) ([paulkatsoulakis](https://github.com/paulkatsoulakis)) -- Convert SpigotMC module to use regexes for parsing. [\#5507](https://github.com/netdata/netdata/pull/5507) ([Ferroin](https://github.com/Ferroin)) -- Add zero minimum in linux power supply module [\#5395](https://github.com/netdata/netdata/pull/5395) ([vlvkobal](https://github.com/vlvkobal)) -- sslcheck module: \(remote\) SSL certificate expiry time check [\#5365](https://github.com/netdata/netdata/pull/5365) ([ghost](https://github.com/ghost)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.12.2...v1.13.0) ## [v1.12.2](https://github.com/netdata/netdata/tree/v1.12.2) (2019-02-28) -**Merged pull requests:** - -- Show streamed servers even for users that are not signed in! \#5482 [\#5519](https://github.com/netdata/netdata/pull/5519) ([gmosx](https://github.com/gmosx)) -- python.d.plugin add heartbeat [\#5503](https://github.com/netdata/netdata/pull/5503) ([ilyam8](https://github.com/ilyam8)) -- prevent merging changes to kickstart.sh when checksum in docs is wrong [\#5498](https://github.com/netdata/netdata/pull/5498) ([paulfantom](https://github.com/paulfantom)) -- Update kickstart md5sums in README [\#5496](https://github.com/netdata/netdata/pull/5496) ([cakrit](https://github.com/cakrit)) -- Fix SIGSEGV crash during shutdown of tc plugin. [\#5495](https://github.com/netdata/netdata/pull/5495) ([mfundul](https://github.com/mfundul)) -- introduce stable installation channel [\#5487](https://github.com/netdata/netdata/pull/5487) ([paulfantom](https://github.com/paulfantom)) -- Make curl silent and show errors only if it fails [\#5485](https://github.com/netdata/netdata/pull/5485) ([mullnerz](https://github.com/mullnerz)) -- Fix curl timeout [\#5476](https://github.com/netdata/netdata/pull/5476) ([elfgoh](https://github.com/elfgoh)) -- Correct kickstart md5sums [\#5473](https://github.com/netdata/netdata/pull/5473) ([cakrit](https://github.com/cakrit)) -- Correct docs: apps plugin is not an internal collector [\#5472](https://github.com/netdata/netdata/pull/5472) ([cakrit](https://github.com/cakrit)) -- Added rocketchat to method-list [\#5471](https://github.com/netdata/netdata/pull/5471) ([tctovsli](https://github.com/tctovsli)) -- Increase timeout for download of go.d.plugin [\#5468](https://github.com/netdata/netdata/pull/5468) ([elfgoh](https://github.com/elfgoh)) -- docker: use base images build by us [\#5465](https://github.com/netdata/netdata/pull/5465) ([paulfantom](https://github.com/paulfantom)) -- oracledb py module [\#5421](https://github.com/netdata/netdata/pull/5421) ([ilyam8](https://github.com/ilyam8)) -- Fix CMake warning for nfacct plugin [\#5379](https://github.com/netdata/netdata/pull/5379) ([vlvkobal](https://github.com/vlvkobal)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.12.1...v1.12.2) ## [v1.12.1](https://github.com/netdata/netdata/tree/v1.12.1) (2019-02-21) -**Fixed bugs:** - -- Don't send host/port in to anonymous stats in fatal of STREAM\_RECEIVER [\#5378](https://github.com/netdata/netdata/pull/5378) ([cakrit](https://github.com/cakrit)) - -**Merged pull requests:** - -- Fix timer crash during exit [\#5464](https://github.com/netdata/netdata/pull/5464) ([mfundul](https://github.com/mfundul)) -- Mention installer option `--disable-go` [\#5461](https://github.com/netdata/netdata/pull/5461) ([cakrit](https://github.com/cakrit)) -- revert \#5457 and test if files exist after installation [\#5460](https://github.com/netdata/netdata/pull/5460) ([paulfantom](https://github.com/paulfantom)) -- Update icon in demosites.html [\#5458](https://github.com/netdata/netdata/pull/5458) ([cakrit](https://github.com/cakrit)) -- Installer - Handle cases when go.d plugin can't be downloaded [\#5457](https://github.com/netdata/netdata/pull/5457) ([cakrit](https://github.com/cakrit)) -- Update md5sums on README.md [\#5456](https://github.com/netdata/netdata/pull/5456) ([cakrit](https://github.com/cakrit)) -- Fix SEGV by removing free of vars of charts that do not exist [\#5455](https://github.com/netdata/netdata/pull/5455) ([cakrit](https://github.com/cakrit)) -- cups.plugin: remove flag -cupsimage [\#5448](https://github.com/netdata/netdata/pull/5448) ([simonnagl](https://github.com/simonnagl)) -- Prevent invalid Linux power supply alarms during startup [\#5447](https://github.com/netdata/netdata/pull/5447) ([cakrit](https://github.com/cakrit)) -- Use go.d.plugin in version v0.1.0 [\#5446](https://github.com/netdata/netdata/pull/5446) ([paulfantom](https://github.com/paulfantom)) -- Correct duplicate flag enum in health.h [\#5441](https://github.com/netdata/netdata/pull/5441) ([cakrit](https://github.com/cakrit)) -- Remove extra 'v' from Server response header [\#5440](https://github.com/netdata/netdata/pull/5440) ([cakrit](https://github.com/cakrit)) -- Fix curl download [\#5439](https://github.com/netdata/netdata/pull/5439) ([Hufschmidt](https://github.com/Hufschmidt)) -- Update README.md - add news for 1.12 [\#5437](https://github.com/netdata/netdata/pull/5437) ([cakrit](https://github.com/cakrit)) -- apcupsd - Treat ONBATT the same as ONLINE [\#5435](https://github.com/netdata/netdata/pull/5435) ([cakrit](https://github.com/cakrit)) -- Add tor to the default app groups [\#5434](https://github.com/netdata/netdata/pull/5434) ([jamezrin](https://github.com/jamezrin)) -- fix \#5430 - LogService.\_get\_raw\_data under python3 fails on undecodable data [\#5431](https://github.com/netdata/netdata/pull/5431) ([apardyl](https://github.com/apardyl)) -- Correct version check in UI [\#5429](https://github.com/netdata/netdata/pull/5429) ([cakrit](https://github.com/cakrit)) -- spec: fixed template issue for netdata source. [\#5427](https://github.com/netdata/netdata/pull/5427) ([k0ste](https://github.com/k0ste)) -- cpuidle handle newlines in names [\#5425](https://github.com/netdata/netdata/pull/5425) ([cakrit](https://github.com/cakrit)) -- Improve configure.ac mnl and netfilter\_acc checks for static builds [\#5424](https://github.com/netdata/netdata/pull/5424) ([mfundul](https://github.com/mfundul)) -- remove redudant pipes for cgroup-network netnsid [\#5417](https://github.com/netdata/netdata/pull/5417) ([ktsaou](https://github.com/ktsaou)) -- Fix clock\_gettime\(\) failures with the CLOCK\_BOOTTIME argument [\#5415](https://github.com/netdata/netdata/pull/5415) ([mfundul](https://github.com/mfundul)) -- Uninstall instruction improvements [\#5414](https://github.com/netdata/netdata/pull/5414) ([cakrit](https://github.com/cakrit)) -- use netnsid for detecting cgroup networks; [\#5413](https://github.com/netdata/netdata/pull/5413) ([ktsaou](https://github.com/ktsaou)) -- python module sensors fix [\#5406](https://github.com/netdata/netdata/pull/5406) ([ilyam8](https://github.com/ilyam8)) -- Refactored static kickstart script [\#5397](https://github.com/netdata/netdata/pull/5397) ([paulfantom](https://github.com/paulfantom)) -- Fix ceph.chart.py for Python3 [\#5396](https://github.com/netdata/netdata/pull/5396) ([GaetanF](https://github.com/GaetanF)) -- Fix Coverity defects [\#5394](https://github.com/netdata/netdata/pull/5394) ([vlvkobal](https://github.com/vlvkobal)) -- Update CODEOWNERS [\#5389](https://github.com/netdata/netdata/pull/5389) ([cakrit](https://github.com/cakrit)) -- Add driver-type option to the freeipmi plugin [\#5384](https://github.com/netdata/netdata/pull/5384) ([cakrit](https://github.com/cakrit)) -- Add documentation for network interfaces [\#5381](https://github.com/netdata/netdata/pull/5381) ([vlvkobal](https://github.com/vlvkobal)) -- Correct Installation link in updating doc [\#5380](https://github.com/netdata/netdata/pull/5380) ([cakrit](https://github.com/cakrit)) -- Add support of tera-byte size for Linux bcache. [\#5373](https://github.com/netdata/netdata/pull/5373) ([kamcpp](https://github.com/kamcpp)) -- Render MyNetdata menu after fetching hosts info \#5370 [\#5371](https://github.com/netdata/netdata/pull/5371) ([gmosx](https://github.com/gmosx)) -- Added missing BuildRequires for autoconf, automake [\#5363](https://github.com/netdata/netdata/pull/5363) ([johnhomelan](https://github.com/johnhomelan)) -- Split nfacct plugin into separate process [\#5361](https://github.com/netdata/netdata/pull/5361) ([vlvkobal](https://github.com/vlvkobal)) -- fix: wget log spam in headless mode \(fixes \#5356\) [\#5359](https://github.com/netdata/netdata/pull/5359) ([mkg20001](https://github.com/mkg20001)) -- Fix replacement of whitespace for versions retrieved from github [\#5355](https://github.com/netdata/netdata/pull/5355) ([cakrit](https://github.com/cakrit)) -- fix warning condition for mem.available [\#5353](https://github.com/netdata/netdata/pull/5353) ([cakrit](https://github.com/cakrit)) -- cups.plugin: Support older versions [\#5350](https://github.com/netdata/netdata/pull/5350) ([simonnagl](https://github.com/simonnagl)) -- fix AC\_CHECK\_LIB to work correctly with cups library [\#5349](https://github.com/netdata/netdata/pull/5349) ([mfundul](https://github.com/mfundul)) -- Add link to writing a new module in example readme [\#5348](https://github.com/netdata/netdata/pull/5348) ([cakrit](https://github.com/cakrit)) -- Provide more precise uninstall instructions [\#5347](https://github.com/netdata/netdata/pull/5347) ([cakrit](https://github.com/cakrit)) -- Localization support in HTML docs, simplification of checklinks.sh [\#5342](https://github.com/netdata/netdata/pull/5342) ([cakrit](https://github.com/cakrit)) -- Fix cgroups Codacy issue [\#5340](https://github.com/netdata/netdata/pull/5340) ([vlvkobal](https://github.com/vlvkobal)) -- Fix FreeBSD plugin Codacy issues [\#5338](https://github.com/netdata/netdata/pull/5338) ([vlvkobal](https://github.com/vlvkobal)) -- cleanup updater script and no `/opt` usage [\#5218](https://github.com/netdata/netdata/pull/5218) ([paulfantom](https://github.com/paulfantom)) -- Add go.d documentation [\#5215](https://github.com/netdata/netdata/pull/5215) ([cakrit](https://github.com/cakrit)) -- Add cgroup cpu and memory limits and alarms [\#5172](https://github.com/netdata/netdata/pull/5172) ([vlvkobal](https://github.com/vlvkobal)) -- Add message queue statistics [\#5115](https://github.com/netdata/netdata/pull/5115) ([vlvkobal](https://github.com/vlvkobal)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.12.0...v1.12.1) ## [v1.12.0](https://github.com/netdata/netdata/tree/v1.12.0) (2019-02-06) -**Merged pull requests:** - -- Fix Codacy issues for FreeBSD plugin [\#5334](https://github.com/netdata/netdata/pull/5334) ([vlvkobal](https://github.com/vlvkobal)) -- portcheck: remove unused var [\#5332](https://github.com/netdata/netdata/pull/5332) ([ilyam8](https://github.com/ilyam8)) -- fix some python codacy errors [\#5331](https://github.com/netdata/netdata/pull/5331) ([ilyam8](https://github.com/ilyam8)) -- Remove codacy warnings from sma\_webbox [\#5330](https://github.com/netdata/netdata/pull/5330) ([cakrit](https://github.com/cakrit)) -- Allow user to override the default behavior for read-only mounts [\#5327](https://github.com/netdata/netdata/pull/5327) ([vlvkobal](https://github.com/vlvkobal)) -- Remove deprecated API call [\#5326](https://github.com/netdata/netdata/pull/5326) ([Aisbergg](https://github.com/Aisbergg)) -- fix compilation of cups.plugin; fixes \#5324 [\#5325](https://github.com/netdata/netdata/pull/5325) ([ktsaou](https://github.com/ktsaou)) -- Clarify that uninstaller.sh needs to be downloaded [\#5315](https://github.com/netdata/netdata/pull/5315) ([cakrit](https://github.com/cakrit)) -- Remove registrypath from alarm-notify [\#5302](https://github.com/netdata/netdata/pull/5302) ([cakrit](https://github.com/cakrit)) -- Minor updates to anonymous statistics [\#5295](https://github.com/netdata/netdata/pull/5295) ([cakrit](https://github.com/cakrit)) -- kickstart: noexec detection [\#5293](https://github.com/netdata/netdata/pull/5293) ([paulfantom](https://github.com/paulfantom)) -- Correct info on what kickstart.sh does [\#5292](https://github.com/netdata/netdata/pull/5292) ([cakrit](https://github.com/cakrit)) -- Add errno to fatal event for statistics [\#5291](https://github.com/netdata/netdata/pull/5291) ([cakrit](https://github.com/cakrit)) -- updated cncf landscape url [\#5288](https://github.com/netdata/netdata/pull/5288) ([ktsaou](https://github.com/ktsaou)) -- Add back the symlink netdata-latest.gz.run [\#5286](https://github.com/netdata/netdata/pull/5286) ([cakrit](https://github.com/cakrit)) -- Additional UI fixes [\#5284](https://github.com/netdata/netdata/pull/5284) ([gmosx](https://github.com/gmosx)) -- GUI Update check - use version instead of commit [\#5283](https://github.com/netdata/netdata/pull/5283) ([cakrit](https://github.com/cakrit)) -- Correct auto-updater to netdata-updater [\#5281](https://github.com/netdata/netdata/pull/5281) ([cakrit](https://github.com/cakrit)) -- netdata update instructions after recent changes [\#5277](https://github.com/netdata/netdata/pull/5277) ([cakrit](https://github.com/cakrit)) -- Fix incorrect parsing of ACLs [\#5275](https://github.com/netdata/netdata/pull/5275) ([cakrit](https://github.com/cakrit)) -- Improve apps grouping config and docs [\#5269](https://github.com/netdata/netdata/pull/5269) ([vlvkobal](https://github.com/vlvkobal)) -- Always run make clean before make [\#5265](https://github.com/netdata/netdata/pull/5265) ([cakrit](https://github.com/cakrit)) -- varnish module: add instance\_name option [\#5264](https://github.com/netdata/netdata/pull/5264) ([ilyam8](https://github.com/ilyam8)) -- Bug fix for 5261 [\#5263](https://github.com/netdata/netdata/pull/5263) ([cakrit](https://github.com/cakrit)) -- ceph module bugfix: fix invalid json response [\#5260](https://github.com/netdata/netdata/pull/5260) ([ilyam8](https://github.com/ilyam8)) -- Fix typo in docs/configuration-guide.md [\#5259](https://github.com/netdata/netdata/pull/5259) ([u32i64](https://github.com/u32i64)) -- SUSE addition [\#5258](https://github.com/netdata/netdata/pull/5258) ([dannysauer](https://github.com/dannysauer)) -- Check version.txt in correct directory and fix link to docs [\#5256](https://github.com/netdata/netdata/pull/5256) ([cakrit](https://github.com/cakrit)) -- Mysql charts fix [\#5250](https://github.com/netdata/netdata/pull/5250) ([ilyam8](https://github.com/ilyam8)) -- plugins.d doc: Remove empty similar headline [\#5245](https://github.com/netdata/netdata/pull/5245) ([simonnagl](https://github.com/simonnagl)) -- Pass correct options to the configure command [\#5244](https://github.com/netdata/netdata/pull/5244) ([cakrit](https://github.com/cakrit)) -- Update kickstart.sh md5sum in docs [\#5242](https://github.com/netdata/netdata/pull/5242) ([cakrit](https://github.com/cakrit)) -- Fix check for install-required-packages.sh [\#5241](https://github.com/netdata/netdata/pull/5241) ([cakrit](https://github.com/cakrit)) -- Fix nightly builds and cron autoupdater [\#5232](https://github.com/netdata/netdata/pull/5232) ([paulfantom](https://github.com/paulfantom)) -- Remove v before the version [\#5223](https://github.com/netdata/netdata/pull/5223) ([cakrit](https://github.com/cakrit)) -- Instruct users to use edit-config [\#5222](https://github.com/netdata/netdata/pull/5222) ([cakrit](https://github.com/cakrit)) -- Improvements to QoS \(tc\) documentation [\#5221](https://github.com/netdata/netdata/pull/5221) ([cakrit](https://github.com/cakrit)) -- python dockerd module: check version [\#5217](https://github.com/netdata/netdata/pull/5217) ([ilyam8](https://github.com/ilyam8)) -- Bug fix for netdata behind authenticated proxies [\#5216](https://github.com/netdata/netdata/pull/5216) ([cakrit](https://github.com/cakrit)) -- add go.d.plugin to apps\_groups.conf [\#5214](https://github.com/netdata/netdata/pull/5214) ([ilyam8](https://github.com/ilyam8)) -- Don't show zero charts for ZFS filesystem [\#5211](https://github.com/netdata/netdata/pull/5211) ([vlvkobal](https://github.com/vlvkobal)) -- install go.d.plugin [\#5199](https://github.com/netdata/netdata/pull/5199) ([paulfantom](https://github.com/paulfantom)) -- Correct link to Rest API [\#5193](https://github.com/netdata/netdata/pull/5193) ([cakrit](https://github.com/cakrit)) -- CUPS plugin [\#5188](https://github.com/netdata/netdata/pull/5188) ([simonnagl](https://github.com/simonnagl)) -- alarm-notify: Add Prowl integration for iOS users. [\#5132](https://github.com/netdata/netdata/pull/5132) ([Ferroin](https://github.com/Ferroin)) -- Anonymous statistics [\#5113](https://github.com/netdata/netdata/pull/5113) ([cakrit](https://github.com/cakrit)) -- Update info on plugins in performance doc [\#5101](https://github.com/netdata/netdata/pull/5101) ([cakrit](https://github.com/cakrit)) -- Cloud Sign-In [\#5095](https://github.com/netdata/netdata/pull/5095) ([gmosx](https://github.com/gmosx)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.12.0-rc3...v1.12.0) ## [v1.12.0-rc3](https://github.com/netdata/netdata/tree/v1.12.0-rc3) (2019-01-17) -**Fixed bugs:** - -- Fix for unix sockets after addition of port ACLs [\#5184](https://github.com/netdata/netdata/pull/5184) ([cakrit](https://github.com/cakrit)) - -**Merged pull requests:** - -- update bug\_report.md [\#5205](https://github.com/netdata/netdata/pull/5205) ([ilyam8](https://github.com/ilyam8)) -- add missing modules to python.d.conf [\#5194](https://github.com/netdata/netdata/pull/5194) ([ilyam8](https://github.com/ilyam8)) -- remove double 'afraid to' in CONTRIBUTING.md [\#5189](https://github.com/netdata/netdata/pull/5189) ([arkamar](https://github.com/arkamar)) -- Use tarballs from GCS in kickstart.sh [\#5185](https://github.com/netdata/netdata/pull/5185) ([paulfantom](https://github.com/paulfantom)) -- fix for fireqos classname not showing [\#5176](https://github.com/netdata/netdata/pull/5176) ([psychomelet](https://github.com/psychomelet)) -- GCS-based updater [\#5174](https://github.com/netdata/netdata/pull/5174) ([paulfantom](https://github.com/paulfantom)) -- Updated Polyverse reinstall commands in Dockerfile [\#5173](https://github.com/netdata/netdata/pull/5173) ([archisgore](https://github.com/archisgore)) -- Change how the ip address and port are logged in socket.c [\#5166](https://github.com/netdata/netdata/pull/5166) ([krinfels](https://github.com/krinfels)) -- Correct SNMP module name in plugin error handling [\#5153](https://github.com/netdata/netdata/pull/5153) ([pablerass](https://github.com/pablerass)) -- Fix cached memory calculation [\#5151](https://github.com/netdata/netdata/pull/5151) ([vlvkobal](https://github.com/vlvkobal)) -- Fix typo in plugins.d/README.md [\#5150](https://github.com/netdata/netdata/pull/5150) ([arkamar](https://github.com/arkamar)) -- "Network Traffic \(system.net\)" is always zero on FreeBSD virtual machines if hypervisor uses VirtIO NIC [\#5149](https://github.com/netdata/netdata/pull/5149) ([vladmovchan](https://github.com/vladmovchan)) -- rabbitmq: api/nodes requests fix [\#5142](https://github.com/netdata/netdata/pull/5142) ([ilyam8](https://github.com/ilyam8)) -- go\_expavar fix: don't check for duplicate expvars [\#5141](https://github.com/netdata/netdata/pull/5141) ([ilyam8](https://github.com/ilyam8)) -- hddtemp fix: don't use disk model as dim name [\#5140](https://github.com/netdata/netdata/pull/5140) ([ilyam8](https://github.com/ilyam8)) -- add option to opt-out from telemetry program [\#5138](https://github.com/netdata/netdata/pull/5138) ([paulfantom](https://github.com/paulfantom)) -- Scramble packages in docker images with polymorphic linux [\#5137](https://github.com/netdata/netdata/pull/5137) ([paulfantom](https://github.com/paulfantom)) -- change ownership of .gitignore [\#5131](https://github.com/netdata/netdata/pull/5131) ([paulfantom](https://github.com/paulfantom)) -- Update Charts.md [\#5124](https://github.com/netdata/netdata/pull/5124) ([mfundul](https://github.com/mfundul)) -- self-contained uninstaller [\#5121](https://github.com/netdata/netdata/pull/5121) ([paulfantom](https://github.com/paulfantom)) -- force git describe to always create a version [\#5119](https://github.com/netdata/netdata/pull/5119) ([paulfantom](https://github.com/paulfantom)) -- Clarify backend modes of operation [\#5116](https://github.com/netdata/netdata/pull/5116) ([cakrit](https://github.com/cakrit)) -- web-site content; why-netdata content [\#5097](https://github.com/netdata/netdata/pull/5097) ([ktsaou](https://github.com/ktsaou)) -- Add variables to alarm-notify.sh [\#5096](https://github.com/netdata/netdata/pull/5096) ([cakrit](https://github.com/cakrit)) -- do not report stale metrics to prometheus [\#5084](https://github.com/netdata/netdata/pull/5084) ([ktsaou](https://github.com/ktsaou)) -- Unify versioning [\#5051](https://github.com/netdata/netdata/pull/5051) ([paulfantom](https://github.com/paulfantom)) -- Port ACLs, Management API and Health commands [\#4969](https://github.com/netdata/netdata/pull/4969) ([cakrit](https://github.com/cakrit)) -- Generate a configure script for RPM build \(\#4570\) [\#4571](https://github.com/netdata/netdata/pull/4571) ([ananace](https://github.com/ananace)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.12.0-rc2...v1.12.0-rc3) ## [v1.12.0-rc2](https://github.com/netdata/netdata/tree/v1.12.0-rc2) (2019-01-03) -**Merged pull requests:** - -- postgres : fix WAL query [\#5105](https://github.com/netdata/netdata/pull/5105) ([anayrat](https://github.com/anayrat)) -- Correct memory usage statement in memory=none [\#5100](https://github.com/netdata/netdata/pull/5100) ([cakrit](https://github.com/cakrit)) -- fix permissions for log files when building rpms [\#5099](https://github.com/netdata/netdata/pull/5099) ([paulfantom](https://github.com/paulfantom)) -- fix web site install link [\#5092](https://github.com/netdata/netdata/pull/5092) ([ktsaou](https://github.com/ktsaou)) -- Removed c3, morris and raphael JS libraries \(\#5086\) [\#5088](https://github.com/netdata/netdata/pull/5088) ([gmosx](https://github.com/gmosx)) -- Improve instructions on how to view the slave UI [\#5083](https://github.com/netdata/netdata/pull/5083) ([cakrit](https://github.com/cakrit)) -- UrlService dont respect Retry-After header by default [\#5082](https://github.com/netdata/netdata/pull/5082) ([ilyam8](https://github.com/ilyam8)) -- smartd\_log: skip non-CSVs early [\#5081](https://github.com/netdata/netdata/pull/5081) ([kevlar1818](https://github.com/kevlar1818)) -- Dashboard grammar change [\#5080](https://github.com/netdata/netdata/pull/5080) ([Xalaxis](https://github.com/Xalaxis)) -- Add systemd pattern list parameter to the documentation [\#5077](https://github.com/netdata/netdata/pull/5077) ([vlvkobal](https://github.com/vlvkobal)) -- Fix update instructions URL in frontend [\#5076](https://github.com/netdata/netdata/pull/5076) ([jorisvervuurt](https://github.com/jorisvervuurt)) -- Add how to add new alarm [\#5069](https://github.com/netdata/netdata/pull/5069) ([cakrit](https://github.com/cakrit)) -- Fix cpuidle statistics in containers [\#5065](https://github.com/netdata/netdata/pull/5065) ([vlvkobal](https://github.com/vlvkobal)) -- Fix coverity issues [\#5061](https://github.com/netdata/netdata/pull/5061) ([vlvkobal](https://github.com/vlvkobal)) -- Disable cpuidle module if schedstat file is missing [\#5059](https://github.com/netdata/netdata/pull/5059) ([vlvkobal](https://github.com/vlvkobal)) -- Fixed typo [\#5054](https://github.com/netdata/netdata/pull/5054) ([samnela](https://github.com/samnela)) -- New option clear\_alarm\_always [\#5050](https://github.com/netdata/netdata/pull/5050) ([dex4er](https://github.com/dex4er)) -- fix IEC units in bash modules [\#5049](https://github.com/netdata/netdata/pull/5049) ([paulfantom](https://github.com/paulfantom)) -- Gracefully ignore the offset if the value is not a number [\#5040](https://github.com/netdata/netdata/pull/5040) ([cakrit](https://github.com/cakrit)) -- Fix process statistics collection for FreeBSD in apps.plugin [\#5038](https://github.com/netdata/netdata/pull/5038) ([vlvkobal](https://github.com/vlvkobal)) -- Apcupsd add check for UPS online [\#5037](https://github.com/netdata/netdata/pull/5037) ([cakrit](https://github.com/cakrit)) -- Add warning for offset in Counter64 metrics [\#5032](https://github.com/netdata/netdata/pull/5032) ([cakrit](https://github.com/cakrit)) -- Add other web servers to proxy instructions [\#5027](https://github.com/netdata/netdata/pull/5027) ([cakrit](https://github.com/cakrit)) -- copy updater script instead of linking it [\#5010](https://github.com/netdata/netdata/pull/5010) ([paulfantom](https://github.com/paulfantom)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.12.0-rc1...v1.12.0-rc2) ## [v1.12.0-rc1](https://github.com/netdata/netdata/tree/v1.12.0-rc1) (2018-12-19) -**Merged pull requests:** - -- Non-interactive uninstaller [\#5021](https://github.com/netdata/netdata/pull/5021) ([paulfantom](https://github.com/paulfantom)) -- Kavenegar returns 200 [\#5020](https://github.com/netdata/netdata/pull/5020) ([salehi](https://github.com/salehi)) -- Fix missing method\_name: kavenegar [\#5019](https://github.com/netdata/netdata/pull/5019) ([salehi](https://github.com/salehi)) -- remove cross-directory dependency in build system [\#5012](https://github.com/netdata/netdata/pull/5012) ([paulfantom](https://github.com/paulfantom)) -- Move installer dir under packaging [\#5009](https://github.com/netdata/netdata/pull/5009) ([paulfantom](https://github.com/paulfantom)) -- Show a warning if JavaScript is disabled \#2422 [\#4999](https://github.com/netdata/netdata/pull/4999) ([gmosx](https://github.com/gmosx)) -- \[python\] make units compliant with IEC standard [\#4995](https://github.com/netdata/netdata/pull/4995) ([ilyam8](https://github.com/ilyam8)) -- Integrate patches from freeipmi and set paramters [\#4993](https://github.com/netdata/netdata/pull/4993) ([Preisschild](https://github.com/Preisschild)) -- Fix crash in mdstat module [\#4992](https://github.com/netdata/netdata/pull/4992) ([vlvkobal](https://github.com/vlvkobal)) -- Update cgroup-name.sh.in [\#4991](https://github.com/netdata/netdata/pull/4991) ([n0coast](https://github.com/n0coast)) -- postgres timeouts [\#4988](https://github.com/netdata/netdata/pull/4988) ([ilyam8](https://github.com/ilyam8)) -- Make units compliant with IEC standard [\#4985](https://github.com/netdata/netdata/pull/4985) ([vlvkobal](https://github.com/vlvkobal)) -- Typo: `stab\_status` -\> `stub\_status` [\#4984](https://github.com/netdata/netdata/pull/4984) ([petecooper](https://github.com/petecooper)) -- Pass cloud\_base\_url from daemon to web/gui through hello endpoint \#4980 [\#4982](https://github.com/netdata/netdata/pull/4982) ([gmosx](https://github.com/gmosx)) -- Fix to \#4968, custom recipients were not working properly [\#4978](https://github.com/netdata/netdata/pull/4978) ([cakrit](https://github.com/cakrit)) -- Fix mdstat parsing [\#4977](https://github.com/netdata/netdata/pull/4977) ([vlvkobal](https://github.com/vlvkobal)) -- GCS access key shouldn't be encrypted [\#4976](https://github.com/netdata/netdata/pull/4976) ([paulfantom](https://github.com/paulfantom)) -- Fix accidentally changed file permissions [\#4974](https://github.com/netdata/netdata/pull/4974) ([vlvkobal](https://github.com/vlvkobal)) -- fix month 'Dec' being detected as IPv6 address in ovpn python.d plugin [\#4970](https://github.com/netdata/netdata/pull/4970) ([vpnable](https://github.com/vpnable)) -- Add support for Factorio server monitoring [\#4966](https://github.com/netdata/netdata/pull/4966) ([jonfairbanks](https://github.com/jonfairbanks)) -- Add mdstat to CMake configuration [\#4965](https://github.com/netdata/netdata/pull/4965) ([vlvkobal](https://github.com/vlvkobal)) -- Move power supply python module to proc plugin [\#4960](https://github.com/netdata/netdata/pull/4960) ([vlvkobal](https://github.com/vlvkobal)) -- dovecot readme update [\#4959](https://github.com/netdata/netdata/pull/4959) ([ilyam8](https://github.com/ilyam8)) -- Add cakrit to health codeowners [\#4953](https://github.com/netdata/netdata/pull/4953) ([cakrit](https://github.com/cakrit)) -- Prevent netdata-updater.sh from sending cron report for git stash entries [\#4952](https://github.com/netdata/netdata/pull/4952) ([cakrit](https://github.com/cakrit)) -- Temporary workaround for \#4945 [\#4951](https://github.com/netdata/netdata/pull/4951) ([cakrit](https://github.com/cakrit)) -- allow label modification [\#4949](https://github.com/netdata/netdata/pull/4949) ([paulfantom](https://github.com/paulfantom)) -- Fix link in streaming hosts list [\#4948](https://github.com/netdata/netdata/pull/4948) ([adherzog](https://github.com/adherzog)) -- Show demosite/host in GA for demo sites [\#4947](https://github.com/netdata/netdata/pull/4947) ([cakrit](https://github.com/cakrit)) -- Update GA in demosites.html [\#4946](https://github.com/netdata/netdata/pull/4946) ([cakrit](https://github.com/cakrit)) -- postgres fix: detect servers version and use the right query [\#4944](https://github.com/netdata/netdata/pull/4944) ([ilyam8](https://github.com/ilyam8)) -- Add support for providing FQDN in alarm notifications. [\#4943](https://github.com/netdata/netdata/pull/4943) ([Ferroin](https://github.com/Ferroin)) -- Add header to SMA webbox readme [\#4942](https://github.com/netdata/netdata/pull/4942) ([cakrit](https://github.com/cakrit)) -- Add doc before path to GA in static site [\#4940](https://github.com/netdata/netdata/pull/4940) ([cakrit](https://github.com/cakrit)) -- Add a Google Analytics tag to every markdown [\#4938](https://github.com/netdata/netdata/pull/4938) ([cakrit](https://github.com/cakrit)) -- Update README.md [\#4937](https://github.com/netdata/netdata/pull/4937) ([cakrit](https://github.com/cakrit)) -- python.d.plugin update [\#4936](https://github.com/netdata/netdata/pull/4936) ([ilyam8](https://github.com/ilyam8)) -- Update Performance.md [\#4935](https://github.com/netdata/netdata/pull/4935) ([cakrit](https://github.com/cakrit)) -- cleaner labeler code [\#4933](https://github.com/netdata/netdata/pull/4933) ([paulfantom](https://github.com/paulfantom)) -- use proper request types and urls to update labels [\#4931](https://github.com/netdata/netdata/pull/4931) ([paulfantom](https://github.com/paulfantom)) -- update code owners [\#4930](https://github.com/netdata/netdata/pull/4930) ([paulfantom](https://github.com/paulfantom)) -- Removed vlvkobal as a codeowner of web/gui [\#4929](https://github.com/netdata/netdata/pull/4929) ([gmosx](https://github.com/gmosx)) -- Add support for nonredundant arrays [\#4923](https://github.com/netdata/netdata/pull/4923) ([vlvkobal](https://github.com/vlvkobal)) -- Config docs improvements [\#4918](https://github.com/netdata/netdata/pull/4918) ([cakrit](https://github.com/cakrit)) -- Introduced IEC-compliant unit abbreviations \#4711 [\#4912](https://github.com/netdata/netdata/pull/4912) ([gmosx](https://github.com/gmosx)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.12.0-rc0...v1.12.0-rc1) ## [v1.12.0-rc0](https://github.com/netdata/netdata/tree/v1.12.0-rc0) (2018-12-06) -**Merged pull requests:** - -- run shfmt on CI scripts [\#4928](https://github.com/netdata/netdata/pull/4928) ([paulfantom](https://github.com/paulfantom)) -- use relative path for logo [\#4927](https://github.com/netdata/netdata/pull/4927) ([ktsaou](https://github.com/ktsaou)) -- fix symbolic link file detection in etc [\#4926](https://github.com/netdata/netdata/pull/4926) ([ktsaou](https://github.com/ktsaou)) -- send all git log msg to fd3 [\#4922](https://github.com/netdata/netdata/pull/4922) ([paulfantom](https://github.com/paulfantom)) -- RabbitMQ chart for message rates should be "line" [\#4916](https://github.com/netdata/netdata/pull/4916) ([dex4er](https://github.com/dex4er)) -- better labeling [\#4915](https://github.com/netdata/netdata/pull/4915) ([paulfantom](https://github.com/paulfantom)) -- Improve docker installation readme, docs navbar fix [\#4914](https://github.com/netdata/netdata/pull/4914) ([cakrit](https://github.com/cakrit)) -- Use the new logo in the UI [\#4913](https://github.com/netdata/netdata/pull/4913) ([gmosx](https://github.com/gmosx)) -- fix info api method compilation warnings [\#4911](https://github.com/netdata/netdata/pull/4911) ([ktsaou](https://github.com/ktsaou)) -- smartd\_log: ata 194 attr fix [\#4908](https://github.com/netdata/netdata/pull/4908) ([ilyam8](https://github.com/ilyam8)) -- Do not update repositories in CI operating system [\#4907](https://github.com/netdata/netdata/pull/4907) ([paulfantom](https://github.com/paulfantom)) -- Don't use IE11 incompatible for-const \#4710 [\#4906](https://github.com/netdata/netdata/pull/4906) ([gmosx](https://github.com/gmosx)) -- Update python.d readme [\#4905](https://github.com/netdata/netdata/pull/4905) ([cakrit](https://github.com/cakrit)) -- do not use protected variable name in updater script [\#4902](https://github.com/netdata/netdata/pull/4902) ([paulfantom](https://github.com/paulfantom)) -- postgres module: locks count fix [\#4901](https://github.com/netdata/netdata/pull/4901) ([ilyam8](https://github.com/ilyam8)) -- treat DT\_UNKNOWN files as regular files [\#4898](https://github.com/netdata/netdata/pull/4898) ([ktsaou](https://github.com/ktsaou)) -- more health debugging to trace config files [\#4897](https://github.com/netdata/netdata/pull/4897) ([ktsaou](https://github.com/ktsaou)) -- added debug statements when loading health config files [\#4896](https://github.com/netdata/netdata/pull/4896) ([ktsaou](https://github.com/ktsaou)) -- Added info on health configuration and page for Charts [\#4895](https://github.com/netdata/netdata/pull/4895) ([cakrit](https://github.com/cakrit)) -- added more debug outpput to freeipmi [\#4894](https://github.com/netdata/netdata/pull/4894) ([ktsaou](https://github.com/ktsaou)) -- nvidia\_smi: handle `N/A` values [\#4893](https://github.com/netdata/netdata/pull/4893) ([ilyam8](https://github.com/ilyam8)) -- add api/v1/info endpoint to swagger [\#4807](https://github.com/netdata/netdata/pull/4807) ([Wing924](https://github.com/Wing924)) -- Update CONTRIBUTING.md [\#4805](https://github.com/netdata/netdata/pull/4805) ([cakrit](https://github.com/cakrit)) -- Add info from PR 208 [\#4804](https://github.com/netdata/netdata/pull/4804) ([cakrit](https://github.com/cakrit)) -- Anonymize IPs in README.md Google Analytics [\#4803](https://github.com/netdata/netdata/pull/4803) ([cakrit](https://github.com/cakrit)) -- Minor updates in htmldoc [\#4802](https://github.com/netdata/netdata/pull/4802) ([cakrit](https://github.com/cakrit)) -- Add cookie consent javascript to docs [\#4801](https://github.com/netdata/netdata/pull/4801) ([cakrit](https://github.com/cakrit)) -- Improve SYNPROXY documentation [\#4800](https://github.com/netdata/netdata/pull/4800) ([cakrit](https://github.com/cakrit)) -- Add debug instructions for python modules [\#4799](https://github.com/netdata/netdata/pull/4799) ([cakrit](https://github.com/cakrit)) -- Added Legal section to documentation, added missing link for apps.plugin [\#4797](https://github.com/netdata/netdata/pull/4797) ([cakrit](https://github.com/cakrit)) -- auto-label PRs and minor cleanup [\#4795](https://github.com/netdata/netdata/pull/4795) ([paulfantom](https://github.com/paulfantom)) -- automatic labeling of new features [\#4792](https://github.com/netdata/netdata/pull/4792) ([paulfantom](https://github.com/paulfantom)) -- Small content change to the netdata-installer.sh [\#4790](https://github.com/netdata/netdata/pull/4790) ([ei8fdb](https://github.com/ei8fdb)) -- lifecycle test [\#4789](https://github.com/netdata/netdata/pull/4789) ([paulfantom](https://github.com/paulfantom)) -- Documentation TOC bug fix [\#4787](https://github.com/netdata/netdata/pull/4787) ([cakrit](https://github.com/cakrit)) -- netdata-security doc corrections [\#4786](https://github.com/netdata/netdata/pull/4786) ([cakrit](https://github.com/cakrit)) -- Update README.md for release 1.11.1 [\#4777](https://github.com/netdata/netdata/pull/4777) ([taniaab](https://github.com/taniaab)) -- Fix typo in "Github Star" documentation [\#4776](https://github.com/netdata/netdata/pull/4776) ([josemaia](https://github.com/josemaia)) -- Added a few more debugging instructions for notifications [\#4774](https://github.com/netdata/netdata/pull/4774) ([cakrit](https://github.com/cakrit)) -- buildhtml.sh should exit with 1 if anything fails [\#4773](https://github.com/netdata/netdata/pull/4773) ([cakrit](https://github.com/cakrit)) -- fail2ban fix: add 'Restore Ban' action [\#4772](https://github.com/netdata/netdata/pull/4772) ([ilyam8](https://github.com/ilyam8)) -- add api/v1/info endpoint [\#4770](https://github.com/netdata/netdata/pull/4770) ([Wing924](https://github.com/Wing924)) -- Move mdstat python module to proc plugin [\#4768](https://github.com/netdata/netdata/pull/4768) ([vlvkobal](https://github.com/vlvkobal)) -- bugfix: query engine resampling duration [\#4759](https://github.com/netdata/netdata/pull/4759) ([ktsaou](https://github.com/ktsaou)) -- web\_log: add alarm on unmatched lines [\#4757](https://github.com/netdata/netdata/pull/4757) ([ilyam8](https://github.com/ilyam8)) -- sensors: don't ignore 0 RPM funs on start [\#4753](https://github.com/netdata/netdata/pull/4753) ([ilyam8](https://github.com/ilyam8)) -- Use var to make NETDATA variable global [\#4752](https://github.com/netdata/netdata/pull/4752) ([gmosx](https://github.com/gmosx)) -- move build Dockerfiles to external repo [\#4749](https://github.com/netdata/netdata/pull/4749) ([paulfantom](https://github.com/paulfantom)) -- remove rolling version suffix [\#4748](https://github.com/netdata/netdata/pull/4748) ([paulfantom](https://github.com/paulfantom)) -- Docs point to docs.netdata.cloud instead of wiki. Correct padding-bot… [\#4747](https://github.com/netdata/netdata/pull/4747) ([cakrit](https://github.com/cakrit)) -- Make Getting Started just a top level link [\#4740](https://github.com/netdata/netdata/pull/4740) ([cakrit](https://github.com/cakrit)) -- docker: correct invalid syntax [\#4738](https://github.com/netdata/netdata/pull/4738) ([paulfantom](https://github.com/paulfantom)) -- Make the whole title area clickable, closes \#4721 [\#4733](https://github.com/netdata/netdata/pull/4733) ([gmosx](https://github.com/gmosx)) -- Correctly apply B unit conversion [\#4724](https://github.com/netdata/netdata/pull/4724) ([gmosx](https://github.com/gmosx)) -- add more layers to container image [\#4722](https://github.com/netdata/netdata/pull/4722) ([paulfantom](https://github.com/paulfantom)) -- python.d: use real time for calc sinceLast [\#4720](https://github.com/netdata/netdata/pull/4720) ([ilyam8](https://github.com/ilyam8)) -- strictier use of URL separators [\#4716](https://github.com/netdata/netdata/pull/4716) ([ktsaou](https://github.com/ktsaou)) -- Test integrity of dashboard.js [\#4715](https://github.com/netdata/netdata/pull/4715) ([paulfantom](https://github.com/paulfantom)) -- fix\(pagerduty\): Use cURL instead of PagerDuty agent to send alarms. [\#4694](https://github.com/netdata/netdata/pull/4694) ([elisiariocouto](https://github.com/elisiariocouto)) -- lint all shell collectors code [\#4690](https://github.com/netdata/netdata/pull/4690) ([paulfantom](https://github.com/paulfantom)) -- Move cpuidle python module to proc plugin [\#4635](https://github.com/netdata/netdata/pull/4635) ([vlvkobal](https://github.com/vlvkobal)) -- Cleanup docker packaging and contrib [\#4627](https://github.com/netdata/netdata/pull/4627) ([paulfantom](https://github.com/paulfantom)) -- Better updater [\#4558](https://github.com/netdata/netdata/pull/4558) ([paulfantom](https://github.com/paulfantom)) -- Generalize the recipient finding logic and reduce the boilerplate code. [\#3960](https://github.com/netdata/netdata/pull/3960) ([Ferroin](https://github.com/Ferroin)) -- RPM spec and patches for sles 11 [\#3708](https://github.com/netdata/netdata/pull/3708) ([veksh](https://github.com/veksh)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.11.1...v1.12.0-rc0) ## [v1.11.1](https://github.com/netdata/netdata/tree/v1.11.1) (2018-11-22) -**Merged pull requests:** - -- Cleanup of web/gui footer [\#4709](https://github.com/netdata/netdata/pull/4709) ([gmosx](https://github.com/gmosx)) -- added byte unit scaling [\#4707](https://github.com/netdata/netdata/pull/4707) ([AndCycle](https://github.com/AndCycle)) -- Add missing quote to tc-qos-helper.sh.in [\#4703](https://github.com/netdata/netdata/pull/4703) ([drwtsn32x](https://github.com/drwtsn32x)) -- Fix typo and py2 compatibility issue. [\#4697](https://github.com/netdata/netdata/pull/4697) ([Ferroin](https://github.com/Ferroin)) -- Update Doc links for adding charts and alarms in sidebar. Isuue \#4650 [\#4669](https://github.com/netdata/netdata/pull/4669) ([nekkabcire](https://github.com/nekkabcire)) -- Update lm\_sensors and catch specific errors. [\#4667](https://github.com/netdata/netdata/pull/4667) ([Ferroin](https://github.com/Ferroin)) -- Remove left over code [\#4662](https://github.com/netdata/netdata/pull/4662) ([xPaw](https://github.com/xPaw)) -- Fix changelog path, add all README.md files to Debian package doc [\#4657](https://github.com/netdata/netdata/pull/4657) ([runejuhl](https://github.com/runejuhl)) -- properly parse network interface names with colon on them [\#4653](https://github.com/netdata/netdata/pull/4653) ([ktsaou](https://github.com/ktsaou)) -- sensors module fix [\#4651](https://github.com/netdata/netdata/pull/4651) ([ilyam8](https://github.com/ilyam8)) -- Update installer/functions.sh [\#4643](https://github.com/netdata/netdata/pull/4643) ([tsingletonacic](https://github.com/tsingletonacic)) -- Fix documentation in beanstalk.conf. [\#4639](https://github.com/netdata/netdata/pull/4639) ([Ferroin](https://github.com/Ferroin)) -- Minor cleanup of main.js [\#4634](https://github.com/netdata/netdata/pull/4634) ([gmosx](https://github.com/gmosx)) -- Fixed tc-helper plugin broken link [\#4617](https://github.com/netdata/netdata/pull/4617) ([ofirule](https://github.com/ofirule)) -- Another Readme Update [\#4612](https://github.com/netdata/netdata/pull/4612) ([ktsaou](https://github.com/ktsaou)) -- Fix spelling mistake in dashboard\_info.js [\#4601](https://github.com/netdata/netdata/pull/4601) ([hotio](https://github.com/hotio)) -- bug fix: conntrack\_max alarm was accessing invalid variable [\#4595](https://github.com/netdata/netdata/pull/4595) ([ktsaou](https://github.com/ktsaou)) -- fixed max interface speed calculation [\#4594](https://github.com/netdata/netdata/pull/4594) ([ktsaou](https://github.com/ktsaou)) -- Issue 4582 \(Show alternate urls in my-netdata menu\) [\#4590](https://github.com/netdata/netdata/pull/4590) ([gmosx](https://github.com/gmosx)) -- nvidia\_smi: init version added [\#4589](https://github.com/netdata/netdata/pull/4589) ([ilyam8](https://github.com/ilyam8)) -- smartd\_log: py2 compatibility fix [\#4584](https://github.com/netdata/netdata/pull/4584) ([ilyam8](https://github.com/ilyam8)) -- Split js 2 [\#4581](https://github.com/netdata/netdata/pull/4581) ([gmosx](https://github.com/gmosx)) -- Alerta.io notification improvements [\#4576](https://github.com/netdata/netdata/pull/4576) ([satterly](https://github.com/satterly)) -- netdata-openrc: Move check from depends\(\) to start\_pre\(\) [\#4575](https://github.com/netdata/netdata/pull/4575) ([aadityabagga](https://github.com/aadityabagga)) -- Fix badges link that leads to 404. [\#4569](https://github.com/netdata/netdata/pull/4569) ([nekkabcire](https://github.com/nekkabcire)) -- Move cpufreq python module to proc plugin [\#4562](https://github.com/netdata/netdata/pull/4562) ([vlvkobal](https://github.com/vlvkobal)) -- decouple nightly cron jobs from packaging stage [\#4559](https://github.com/netdata/netdata/pull/4559) ([paulfantom](https://github.com/paulfantom)) -- Clarify application configuration and fix broken link [\#4554](https://github.com/netdata/netdata/pull/4554) ([JBaczuk](https://github.com/JBaczuk)) -- edit-config: Better support for custom editors. [\#4551](https://github.com/netdata/netdata/pull/4551) ([Ferroin](https://github.com/Ferroin)) -- add tor python module [\#4546](https://github.com/netdata/netdata/pull/4546) ([ilyam8](https://github.com/ilyam8)) -- incremental overflows should not show zeros values [\#4538](https://github.com/netdata/netdata/pull/4538) ([ktsaou](https://github.com/ktsaou)) -- smartd\_log refactor plus SCSI support [\#4523](https://github.com/netdata/netdata/pull/4523) ([ilyam8](https://github.com/ilyam8)) -- openldap monitoring plugin added [\#4513](https://github.com/netdata/netdata/pull/4513) ([ekartsonakis](https://github.com/ekartsonakis)) -- Refactoring dashboard.js, splitting monolithic file into multiple source files. [\#4496](https://github.com/netdata/netdata/pull/4496) ([gmosx](https://github.com/gmosx)) -- Switch e-mail threading to be enabled by default. [\#3780](https://github.com/netdata/netdata/pull/3780) ([Ferroin](https://github.com/Ferroin)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.11.0...v1.11.1) ## [v1.11.0](https://github.com/netdata/netdata/tree/v1.11.0) (2018-11-02) -**Fixed bugs:** - -- fix docker image tagging problem [\#4250](https://github.com/netdata/netdata/pull/4250) ([paulfantom](https://github.com/paulfantom)) - -**Merged pull requests:** - -- Changed swagger editor url to the correct one [\#4539](https://github.com/netdata/netdata/pull/4539) ([infeeeee](https://github.com/infeeeee)) -- fixed wrong annotations given to google charts [\#4535](https://github.com/netdata/netdata/pull/4535) ([ktsaou](https://github.com/ktsaou)) -- allow debugging memory per module [\#4524](https://github.com/netdata/netdata/pull/4524) ([ktsaou](https://github.com/ktsaou)) -- fixed vulnerabilities identified by red4sec.com [\#4521](https://github.com/netdata/netdata/pull/4521) ([ktsaou](https://github.com/ktsaou)) -- Do not enable unused per core interrupts by default [\#4519](https://github.com/netdata/netdata/pull/4519) ([ktsaou](https://github.com/ktsaou)) -- exclude web/gui/src from codacy checks [\#4515](https://github.com/netdata/netdata/pull/4515) ([paulfantom](https://github.com/paulfantom)) -- do not send duplicate chart names while streaming metrics [\#4508](https://github.com/netdata/netdata/pull/4508) ([ktsaou](https://github.com/ktsaou)) -- fix RPM build [\#4507](https://github.com/netdata/netdata/pull/4507) ([ktsaou](https://github.com/ktsaou)) -- Split the API formatters in modules [\#4504](https://github.com/netdata/netdata/pull/4504) ([ktsaou](https://github.com/ktsaou)) -- fixed rpm build; [\#4503](https://github.com/netdata/netdata/pull/4503) ([ktsaou](https://github.com/ktsaou)) -- Fix\(snmp\): fix parse oidname and santilize dimension name [\#4498](https://github.com/netdata/netdata/pull/4498) ([Ehekatl](https://github.com/Ehekatl)) -- fix query min-max, again... [\#4495](https://github.com/netdata/netdata/pull/4495) ([ktsaou](https://github.com/ktsaou)) -- diskspace plugin should not stat\(\) excluded mountpoints [\#4494](https://github.com/netdata/netdata/pull/4494) ([ktsaou](https://github.com/ktsaou)) -- restored min-max calculation of RRDR [\#4489](https://github.com/netdata/netdata/pull/4489) ([ktsaou](https://github.com/ktsaou)) -- query engine documentation and stats [\#4483](https://github.com/netdata/netdata/pull/4483) ([ktsaou](https://github.com/ktsaou)) -- fix query sum [\#4482](https://github.com/netdata/netdata/pull/4482) ([ktsaou](https://github.com/ktsaou)) -- query code cleanup [\#4480](https://github.com/netdata/netdata/pull/4480) ([ktsaou](https://github.com/ktsaou)) -- Fix checking of grouping time [\#4478](https://github.com/netdata/netdata/pull/4478) ([vlvkobal](https://github.com/vlvkobal)) -- Disable python sudo modules by default [\#4477](https://github.com/netdata/netdata/pull/4477) ([ilyam8](https://github.com/ilyam8)) -- bug-fix: fixed aligned queries that returned no data [\#4472](https://github.com/netdata/netdata/pull/4472) ([ktsaou](https://github.com/ktsaou)) -- Add proxysql to python.d.plugin Makefile.am [\#4466](https://github.com/netdata/netdata/pull/4466) ([alibo](https://github.com/alibo)) -- updated tests for the new hierarchy [\#4464](https://github.com/netdata/netdata/pull/4464) ([ktsaou](https://github.com/ktsaou)) -- Remove duplicated entry and put modules in order in python.d.conf [\#4460](https://github.com/netdata/netdata/pull/4460) ([vladmovchan](https://github.com/vladmovchan)) -- fix permissions for config files in a container [\#4454](https://github.com/netdata/netdata/pull/4454) ([paulfantom](https://github.com/paulfantom)) -- mongodb fix [\#4449](https://github.com/netdata/netdata/pull/4449) ([ilyam8](https://github.com/ilyam8)) -- icecast bugfix [\#4448](https://github.com/netdata/netdata/pull/4448) ([ilyam8](https://github.com/ilyam8)) -- invalidate incorrect rpm spec changelog [\#4445](https://github.com/netdata/netdata/pull/4445) ([paulfantom](https://github.com/paulfantom)) -- modularize the query api [\#4443](https://github.com/netdata/netdata/pull/4443) ([ktsaou](https://github.com/ktsaou)) -- Indicate FreeIPMI support for FreeBSD [\#4440](https://github.com/netdata/netdata/pull/4440) ([openspork](https://github.com/openspork)) -- remove unused variables [\#4437](https://github.com/netdata/netdata/pull/4437) ([paulfantom](https://github.com/paulfantom)) -- Feat: detect NIC speed and alarm on each device for net traffic overflow [\#4430](https://github.com/netdata/netdata/pull/4430) ([Ehekatl](https://github.com/Ehekatl)) -- fix streaming bug [\#4425](https://github.com/netdata/netdata/pull/4425) ([ktsaou](https://github.com/ktsaou)) -- fix systemd detection; [\#4423](https://github.com/netdata/netdata/pull/4423) ([ktsaou](https://github.com/ktsaou)) -- moved stream.conf initialization after log files have been open [\#4422](https://github.com/netdata/netdata/pull/4422) ([ktsaou](https://github.com/ktsaou)) -- Fix cmake build on macos [\#4420](https://github.com/netdata/netdata/pull/4420) ([Ehekatl](https://github.com/Ehekatl)) -- Evaluate $used\_ram\_to\_ignore on FreeBSD [\#4419](https://github.com/netdata/netdata/pull/4419) ([openspork](https://github.com/openspork)) -- fix node.d.plugin; [\#4413](https://github.com/netdata/netdata/pull/4413) ([ktsaou](https://github.com/ktsaou)) -- fix netdata.spec for new directory structure [\#4410](https://github.com/netdata/netdata/pull/4410) ([ktsaou](https://github.com/ktsaou)) -- Added uwsgi plugin [\#4404](https://github.com/netdata/netdata/pull/4404) ([robbert-ef](https://github.com/robbert-ef)) -- Add sendmail into the list of mail servers [\#4402](https://github.com/netdata/netdata/pull/4402) ([vladmovchan](https://github.com/vladmovchan)) -- Fix make dist [\#4401](https://github.com/netdata/netdata/pull/4401) ([ktsaou](https://github.com/ktsaou)) -- fix compilation on FreeBSD; [\#4398](https://github.com/netdata/netdata/pull/4398) ([ktsaou](https://github.com/ktsaou)) -- modularized all source code [\#4391](https://github.com/netdata/netdata/pull/4391) ([ktsaou](https://github.com/ktsaou)) -- Account "Laundry" pages on FreeBSD [\#4390](https://github.com/netdata/netdata/pull/4390) ([vladmovchan](https://github.com/vladmovchan)) -- normalized plugin names on all plugins; [\#4387](https://github.com/netdata/netdata/pull/4387) ([ktsaou](https://github.com/ktsaou)) -- updated swagger info for HTTPS [\#4386](https://github.com/netdata/netdata/pull/4386) ([ktsaou](https://github.com/ktsaou)) -- make future code PEP8 compliant [\#4382](https://github.com/netdata/netdata/pull/4382) ([paulfantom](https://github.com/paulfantom)) -- modularize C source code [\#4372](https://github.com/netdata/netdata/pull/4372) ([ktsaou](https://github.com/ktsaou)) -- fix docker builds [\#4367](https://github.com/netdata/netdata/pull/4367) ([paulfantom](https://github.com/paulfantom)) -- add option to run netdata in the background [\#4364](https://github.com/netdata/netdata/pull/4364) ([pohzipohzi](https://github.com/pohzipohzi)) -- support filtering of charts during streaming; [\#4361](https://github.com/netdata/netdata/pull/4361) ([ktsaou](https://github.com/ktsaou)) -- edit-config should use . instead of source with /bin/sh [\#4360](https://github.com/netdata/netdata/pull/4360) ([ktsaou](https://github.com/ktsaou)) -- send pipes URL encoded [\#4358](https://github.com/netdata/netdata/pull/4358) ([ktsaou](https://github.com/ktsaou)) -- updated configs.signatures [\#4356](https://github.com/netdata/netdata/pull/4356) ([ktsaou](https://github.com/ktsaou)) -- Fix firehol image tagging [\#4355](https://github.com/netdata/netdata/pull/4355) ([paulfantom](https://github.com/paulfantom)) -- Fix apache ipv6 configuration [\#4349](https://github.com/netdata/netdata/pull/4349) ([candrews](https://github.com/candrews)) -- Fix phpfpm ipv6 configuration [\#4348](https://github.com/netdata/netdata/pull/4348) ([candrews](https://github.com/candrews)) -- Add query types to mysql plugin [\#4347](https://github.com/netdata/netdata/pull/4347) ([roedie](https://github.com/roedie)) -- ExecutableService: return \[\] instead of None if no data. [\#4346](https://github.com/netdata/netdata/pull/4346) ([Ferroin](https://github.com/Ferroin)) -- Fix the last few PEP 8 compliance issues. [\#4345](https://github.com/netdata/netdata/pull/4345) ([Ferroin](https://github.com/Ferroin)) -- log flood should not be disabled; [\#4344](https://github.com/netdata/netdata/pull/4344) ([ktsaou](https://github.com/ktsaou)) -- better daemon errors about files; [\#4342](https://github.com/netdata/netdata/pull/4342) ([ktsaou](https://github.com/ktsaou)) -- added edit-config [\#4338](https://github.com/netdata/netdata/pull/4338) ([ktsaou](https://github.com/ktsaou)) -- Fix BIND outgoing stats in a multiview environment [\#4337](https://github.com/netdata/netdata/pull/4337) ([vobruba-martin](https://github.com/vobruba-martin)) -- fixes coverity identified issues [\#4333](https://github.com/netdata/netdata/pull/4333) ([ktsaou](https://github.com/ktsaou)) -- Use newer docker in CI build [\#4332](https://github.com/netdata/netdata/pull/4332) ([paulfantom](https://github.com/paulfantom)) -- fix docker image [\#4330](https://github.com/netdata/netdata/pull/4330) ([paulfantom](https://github.com/paulfantom)) -- Auto-releaser [\#4328](https://github.com/netdata/netdata/pull/4328) ([paulfantom](https://github.com/paulfantom)) -- fix spdx headers [\#4327](https://github.com/netdata/netdata/pull/4327) ([paulfantom](https://github.com/paulfantom)) -- updated LGTM URLs [\#4317](https://github.com/netdata/netdata/pull/4317) ([ktsaou](https://github.com/ktsaou)) -- more code owners [\#4316](https://github.com/netdata/netdata/pull/4316) ([paulfantom](https://github.com/paulfantom)) -- Use docker manifests [\#4315](https://github.com/netdata/netdata/pull/4315) ([paulfantom](https://github.com/paulfantom)) -- install some libs for coverity [\#4314](https://github.com/netdata/netdata/pull/4314) ([paulfantom](https://github.com/paulfantom)) -- cleanup FIXME tags [\#4309](https://github.com/netdata/netdata/pull/4309) ([ktsaou](https://github.com/ktsaou)) -- force symlink of netdata-updater.sh [\#4307](https://github.com/netdata/netdata/pull/4307) ([mrdrogdrog](https://github.com/mrdrogdrog)) -- Build OSX earlier than linux [\#4305](https://github.com/netdata/netdata/pull/4305) ([paulfantom](https://github.com/paulfantom)) -- Fix coverity-scan.sh [\#4304](https://github.com/netdata/netdata/pull/4304) ([paulfantom](https://github.com/paulfantom)) -- Python.d PEP 8 cleanup, modules S-Z [\#4302](https://github.com/netdata/netdata/pull/4302) ([Ferroin](https://github.com/Ferroin)) -- Python.d PEP 8 cleanup, modules P-R [\#4299](https://github.com/netdata/netdata/pull/4299) ([Ferroin](https://github.com/Ferroin)) -- Python.d/postgres.chart.py PEP 8 code cleanup [\#4298](https://github.com/netdata/netdata/pull/4298) ([Ferroin](https://github.com/Ferroin)) -- Python.d PEP 8 cleanup, modules N-O [\#4297](https://github.com/netdata/netdata/pull/4297) ([Ferroin](https://github.com/Ferroin)) -- reproducible build system [\#4294](https://github.com/netdata/netdata/pull/4294) ([paulfantom](https://github.com/paulfantom)) -- update variable after install [\#4292](https://github.com/netdata/netdata/pull/4292) ([paulfantom](https://github.com/paulfantom)) -- give credit where credit is due [\#4291](https://github.com/netdata/netdata/pull/4291) ([paulfantom](https://github.com/paulfantom)) -- fix typo in coverity scan script [\#4290](https://github.com/netdata/netdata/pull/4290) ([paulfantom](https://github.com/paulfantom)) -- Python.d PEP 8 cleanup, modules M [\#4289](https://github.com/netdata/netdata/pull/4289) ([Ferroin](https://github.com/Ferroin)) -- Python.d PEP 8 cleanup, modules I-L [\#4288](https://github.com/netdata/netdata/pull/4288) ([Ferroin](https://github.com/Ferroin)) -- Python.d PEP 8 cleanup, modules D-H [\#4287](https://github.com/netdata/netdata/pull/4287) ([Ferroin](https://github.com/Ferroin)) -- Python.d PEP 8 cleanup, modules A-C [\#4286](https://github.com/netdata/netdata/pull/4286) ([Ferroin](https://github.com/Ferroin)) -- Fix typo in documentation [\#4284](https://github.com/netdata/netdata/pull/4284) ([eduherminio](https://github.com/eduherminio)) -- stock configs in /usr/lib/netdata [\#4283](https://github.com/netdata/netdata/pull/4283) ([ktsaou](https://github.com/ktsaou)) -- use flake8 instead of pylint [\#4282](https://github.com/netdata/netdata/pull/4282) ([paulfantom](https://github.com/paulfantom)) -- tcp syn and accept queue charts and alarms [\#4281](https://github.com/netdata/netdata/pull/4281) ([ktsaou](https://github.com/ktsaou)) -- add code of conduct [\#4280](https://github.com/netdata/netdata/pull/4280) ([paulfantom](https://github.com/paulfantom)) -- megacli plugin: adapter regex update [\#4279](https://github.com/netdata/netdata/pull/4279) ([ilyam8](https://github.com/ilyam8)) -- Allow DOCKER\_HOST env variable to override default docker socket path [\#4277](https://github.com/netdata/netdata/pull/4277) ([xginn8](https://github.com/xginn8)) -- Add other common IoT services to apps\_groups.conf [\#4276](https://github.com/netdata/netdata/pull/4276) ([xginn8](https://github.com/xginn8)) -- fix python warnings identified by LGTM [\#4275](https://github.com/netdata/netdata/pull/4275) ([ilyam8](https://github.com/ilyam8)) -- nightly builds + coverity scan [\#4273](https://github.com/netdata/netdata/pull/4273) ([paulfantom](https://github.com/paulfantom)) -- better lgtm config [\#4272](https://github.com/netdata/netdata/pull/4272) ([paulfantom](https://github.com/paulfantom)) -- Fixup small python-logind typos [\#4271](https://github.com/netdata/netdata/pull/4271) ([xginn8](https://github.com/xginn8)) -- Fix several typos in documentation [\#4270](https://github.com/netdata/netdata/pull/4270) ([Calinou](https://github.com/Calinou)) -- \[WIP\] LGTM tag classification [\#4269](https://github.com/netdata/netdata/pull/4269) ([paulfantom](https://github.com/paulfantom)) -- create stale bot integration [\#4268](https://github.com/netdata/netdata/pull/4268) ([paulfantom](https://github.com/paulfantom)) -- apps.plugin fixes [\#4267](https://github.com/netdata/netdata/pull/4267) ([ktsaou](https://github.com/ktsaou)) -- finetune Code Owners entries [\#4264](https://github.com/netdata/netdata/pull/4264) ([paulfantom](https://github.com/paulfantom)) -- updated readme for netdata org [\#4262](https://github.com/netdata/netdata/pull/4262) ([ktsaou](https://github.com/ktsaou)) -- \[cleanup crusade\] Shellcheck [\#4261](https://github.com/netdata/netdata/pull/4261) ([paulfantom](https://github.com/paulfantom)) -- \[WIP\] release less artifacts [\#4260](https://github.com/netdata/netdata/pull/4260) ([paulfantom](https://github.com/paulfantom)) -- Make method in url service configurable [\#4257](https://github.com/netdata/netdata/pull/4257) ([ccremer](https://github.com/ccremer)) -- Fix typo in documentation [\#4255](https://github.com/netdata/netdata/pull/4255) ([olivierlambert](https://github.com/olivierlambert)) -- coverity should still use firehol/netdata until we find a solution [\#4253](https://github.com/netdata/netdata/pull/4253) ([ktsaou](https://github.com/ktsaou)) -- fix badges in README.md [\#4251](https://github.com/netdata/netdata/pull/4251) ([paulfantom](https://github.com/paulfantom)) -- replaced referenced to firehol github org with netdata github org [\#4249](https://github.com/netdata/netdata/pull/4249) ([ktsaou](https://github.com/ktsaou)) -- Travis and docker setup after migration [\#4247](https://github.com/netdata/netdata/pull/4247) ([paulfantom](https://github.com/paulfantom)) -- collect TcpExtTCPReqQFullDrop; [\#4246](https://github.com/netdata/netdata/pull/4246) ([ktsaou](https://github.com/ktsaou)) -- fixed typo in prometheus\_all\_hosts output [\#4245](https://github.com/netdata/netdata/pull/4245) ([ktsaou](https://github.com/ktsaou)) -- apps.plugin now checks fds for changes, with adaptive caching [\#4243](https://github.com/netdata/netdata/pull/4243) ([ktsaou](https://github.com/ktsaou)) -- Added -NoLog parameter for megacli calls [\#4242](https://github.com/netdata/netdata/pull/4242) ([vobruba-martin](https://github.com/vobruba-martin)) -- updated configs.signatures [\#4240](https://github.com/netdata/netdata/pull/4240) ([ktsaou](https://github.com/ktsaou)) -- command js is not node.js [\#4239](https://github.com/netdata/netdata/pull/4239) ([ktsaou](https://github.com/ktsaou)) -- Fix missing comma in couchdb module. [\#4238](https://github.com/netdata/netdata/pull/4238) ([Ferroin](https://github.com/Ferroin)) -- Fix LGTM complaints in monit module. [\#4237](https://github.com/netdata/netdata/pull/4237) ([Ferroin](https://github.com/Ferroin)) -- daemon cleanup [\#4231](https://github.com/netdata/netdata/pull/4231) ([ktsaou](https://github.com/ktsaou)) -- varnish plugin bugfix [\#4228](https://github.com/netdata/netdata/pull/4228) ([ilyam8](https://github.com/ilyam8)) -- CLA signing using cla-assistant.io [\#4226](https://github.com/netdata/netdata/pull/4226) ([ktsaou](https://github.com/ktsaou)) -- Disable IPFS Pin API [\#4224](https://github.com/netdata/netdata/pull/4224) ([jkpit](https://github.com/jkpit)) -- fixes identified by LGTM [\#4220](https://github.com/netdata/netdata/pull/4220) ([ktsaou](https://github.com/ktsaou)) -- workaround for LGTM false-positives [\#4218](https://github.com/netdata/netdata/pull/4218) ([ktsaou](https://github.com/ktsaou)) -- fixed issues identified by lgtm [\#4216](https://github.com/netdata/netdata/pull/4216) ([ktsaou](https://github.com/ktsaou)) -- fix netdata server URL detection in dashboard.js; [\#4215](https://github.com/netdata/netdata/pull/4215) ([ktsaou](https://github.com/ktsaou)) -- Create lgtm config [\#4213](https://github.com/netdata/netdata/pull/4213) ([paulfantom](https://github.com/paulfantom)) -- more LGTM minor fixes [\#4211](https://github.com/netdata/netdata/pull/4211) ([ktsaou](https://github.com/ktsaou)) -- updated configs.signatures [\#4210](https://github.com/netdata/netdata/pull/4210) ([ktsaou](https://github.com/ktsaou)) -- fixes identified by LGTM [\#4209](https://github.com/netdata/netdata/pull/4209) ([ktsaou](https://github.com/ktsaou)) -- allow empty values in config settings; [\#4208](https://github.com/netdata/netdata/pull/4208) ([ktsaou](https://github.com/ktsaou)) -- added UTC to server timezones list; [\#4207](https://github.com/netdata/netdata/pull/4207) ([ktsaou](https://github.com/ktsaou)) -- redis plugin bugfix [\#4205](https://github.com/netdata/netdata/pull/4205) ([ilyam8](https://github.com/ilyam8)) -- send host variables to prometheus [\#4200](https://github.com/netdata/netdata/pull/4200) ([ktsaou](https://github.com/ktsaou)) -- Update CONTRIBUTORS.md [\#4197](https://github.com/netdata/netdata/pull/4197) ([paulfantom](https://github.com/paulfantom)) -- nginx\_plus: use upstream server IP:port in dimension IDs, not the transient ID [\#4194](https://github.com/netdata/netdata/pull/4194) ([illes](https://github.com/illes)) -- time-duration badges should show "undefined" instead of "never" [\#4193](https://github.com/netdata/netdata/pull/4193) ([ktsaou](https://github.com/ktsaou)) -- Add docker plugin [\#4191](https://github.com/netdata/netdata/pull/4191) ([tuxity](https://github.com/tuxity)) -- Improve packaging checks [\#4188](https://github.com/netdata/netdata/pull/4188) ([philwhineray](https://github.com/philwhineray)) -- elasticsearch: handle json parse error in threads [\#4186](https://github.com/netdata/netdata/pull/4186) ([ilyam8](https://github.com/ilyam8)) -- pythond\_small\_fixes [\#4185](https://github.com/netdata/netdata/pull/4185) ([ilyam8](https://github.com/ilyam8)) -- \[cleanup crusade\] more linting of bash modules [\#4183](https://github.com/netdata/netdata/pull/4183) ([paulfantom](https://github.com/paulfantom)) -- create pid directory, if not present [\#4181](https://github.com/netdata/netdata/pull/4181) ([ktsaou](https://github.com/ktsaou)) -- fix for load alarms [\#4180](https://github.com/netdata/netdata/pull/4180) ([ktsaou](https://github.com/ktsaou)) -- updated configs.signatures [\#4179](https://github.com/netdata/netdata/pull/4179) ([ktsaou](https://github.com/ktsaou)) -- Add permission file check in ceph module [\#4177](https://github.com/netdata/netdata/pull/4177) ([lets00](https://github.com/lets00)) -- \[cleanup crusade\] disable linters on installer scripts [\#4176](https://github.com/netdata/netdata/pull/4176) ([paulfantom](https://github.com/paulfantom)) -- Add alarms for abnormally high load averages. [\#4175](https://github.com/netdata/netdata/pull/4175) ([Ferroin](https://github.com/Ferroin)) -- CI builds in containers [\#4174](https://github.com/netdata/netdata/pull/4174) ([paulfantom](https://github.com/paulfantom)) -- Fix lack of dot [\#4172](https://github.com/netdata/netdata/pull/4172) ([paulfantom](https://github.com/paulfantom)) -- remove condition from netdata.service [\#4170](https://github.com/netdata/netdata/pull/4170) ([ktsaou](https://github.com/ktsaou)) -- \[WIP\] fail2ban: ipv6 support added + module simplification [\#4168](https://github.com/netdata/netdata/pull/4168) ([ilyam8](https://github.com/ilyam8)) -- \[cleanup crusade\] linting shell scripts for docker, tests and python [\#4162](https://github.com/netdata/netdata/pull/4162) ([paulfantom](https://github.com/paulfantom)) -- \[cleanup crusade\] shellcheck in contrib [\#4160](https://github.com/netdata/netdata/pull/4160) ([paulfantom](https://github.com/paulfantom)) -- \[cleanup crusade\] Lint bash scripts on letter A [\#4159](https://github.com/netdata/netdata/pull/4159) ([paulfantom](https://github.com/paulfantom)) -- use pidfile to send HUP to netdata via logrotate; [\#4157](https://github.com/netdata/netdata/pull/4157) ([ktsaou](https://github.com/ktsaou)) -- python plugin monotonic fix [\#4156](https://github.com/netdata/netdata/pull/4156) ([ilyam8](https://github.com/ilyam8)) -- add variable system.cpu.processors for alarms; [\#4155](https://github.com/netdata/netdata/pull/4155) ([ktsaou](https://github.com/ktsaou)) -- netdata.service is now installed in /lib/systemd/system; [\#4151](https://github.com/netdata/netdata/pull/4151) ([ktsaou](https://github.com/ktsaou)) -- name veritas volume disk groups [\#4150](https://github.com/netdata/netdata/pull/4150) ([ktsaou](https://github.com/ktsaou)) -- do not get the address of FILE pointer; [\#4149](https://github.com/netdata/netdata/pull/4149) ([ktsaou](https://github.com/ktsaou)) -- Add some extra error logging to the spigotmc module. [\#4148](https://github.com/netdata/netdata/pull/4148) ([Ferroin](https://github.com/Ferroin)) -- /proc/net/snmp minimum line length for IcmpMsg is 2 words, not 3 [\#4147](https://github.com/netdata/netdata/pull/4147) ([ktsaou](https://github.com/ktsaou)) -- when running under systemd, keep the process scheduling parameters set [\#4143](https://github.com/netdata/netdata/pull/4143) ([ktsaou](https://github.com/ktsaou)) -- \[cleanup crusade\] travis build stages [\#4142](https://github.com/netdata/netdata/pull/4142) ([paulfantom](https://github.com/paulfantom)) -- Add ignore-status option to freeipmi\_plugin [\#4141](https://github.com/netdata/netdata/pull/4141) ([plasticrake](https://github.com/plasticrake)) -- \[cleanup crusade\] move profiling to tests directory [\#4140](https://github.com/netdata/netdata/pull/4140) ([paulfantom](https://github.com/paulfantom)) -- Less verbose bash and curl unpacking [\#4139](https://github.com/netdata/netdata/pull/4139) ([paulfantom](https://github.com/paulfantom)) -- \[project management\] add github CODEOWNERS [\#4137](https://github.com/netdata/netdata/pull/4137) ([paulfantom](https://github.com/paulfantom)) -- \[cleanup crusade\] cleanup licenses [\#4136](https://github.com/netdata/netdata/pull/4136) ([paulfantom](https://github.com/paulfantom)) -- Add ProxySQL python plugin [\#4112](https://github.com/netdata/netdata/pull/4112) ([alibo](https://github.com/alibo)) -- Optimize counting of recusive pins [\#4095](https://github.com/netdata/netdata/pull/4095) ([pjz](https://github.com/pjz)) -- \[nginx\_plus\] fix handling of non-contiguous peer IDs [\#4093](https://github.com/netdata/netdata/pull/4093) ([illes](https://github.com/illes)) -- web\_log Virtual host enhancement and http/https [\#4076](https://github.com/netdata/netdata/pull/4076) ([jgrossiord](https://github.com/jgrossiord)) -- push host tags for graphite; [\#3992](https://github.com/netdata/netdata/pull/3992) ([ktsaou](https://github.com/ktsaou)) -- rethinkdb python plugin [\#3955](https://github.com/netdata/netdata/pull/3955) ([ilyam8](https://github.com/ilyam8)) -- Add a python plugin for monitoring power supplies on Linux. [\#3799](https://github.com/netdata/netdata/pull/3799) ([Ferroin](https://github.com/Ferroin)) +[Full Changelog](https://github.com/netdata/netdata/compare/v1.10.0...v1.11.0) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f2ec3169..75a5427a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -400,6 +400,10 @@ set(PERF_PLUGIN_FILES collectors/perf.plugin/perf_plugin.c ) +set(SLABINFO_PLUGIN_FILES + collectors/slabinfo.plugin/slabinfo.c + ) + set(PROC_PLUGIN_FILES collectors/proc.plugin/ipc.c collectors/proc.plugin/plugin_proc.c @@ -728,6 +732,7 @@ IF(LINUX) SET(ENABLE_PLUGIN_CGROUP_NETWORK True) SET(ENABLE_PLUGIN_APPS True) SET(ENABLE_PLUGIN_PERF True) + SET(ENABLE_PLUGIN_SLABINFO True) ELSEIF(FREEBSD) add_executable(netdata config.h ${NETDATA_FILES} ${FREEBSD_PLUGIN_FILES}) @@ -737,6 +742,7 @@ ELSEIF(FREEBSD) SET(ENABLE_PLUGIN_CGROUP_NETWORK False) SET(ENABLE_PLUGIN_APPS True) SET(ENABLE_PLUGIN_PERF False) + SET(ENABLE_PLUGIN_SLABINFO False) ELSEIF(MACOS) add_executable(netdata config.h ${NETDATA_FILES} ${MACOS_PLUGIN_FILES}) @@ -746,6 +752,7 @@ ELSEIF(MACOS) SET(ENABLE_PLUGIN_CGROUP_NETWORK False) SET(ENABLE_PLUGIN_APPS False) SET(ENABLE_PLUGIN_PERF False) + SET(ENABLE_PLUGIN_SLABINFO False) ENDIF() @@ -844,6 +851,20 @@ ENDIF() # ----------------------------------------------------------------------------- +# slabinfo.plugin + +IF(ENABLE_PLUGIN_SLABINFO) + message(STATUS "slabinfo.plugin: enabled") + add_executable(slabinfo.plugin config.h ${SLABINFO_PLUGIN_FILES}) + target_link_libraries (slabinfo.plugin libnetdata ${NETDATA_COMMON_LIBRARIES}) + target_include_directories(slabinfo.plugin PUBLIC ${NETDATA_COMMON_INCLUDE_DIRS}) + target_compile_options(slabinfo.plugin PUBLIC ${NETDATA_COMMON_CFLAGS}) +ELSE() + message(STATUS "slabinfo.plugin: disabled") +ENDIF() + + +# ----------------------------------------------------------------------------- # cgroup-network IF(ENABLE_PLUGIN_CGROUP_NETWORK) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ab7ddff8d..4e0d49ec8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -138,6 +138,7 @@ For C contributions in particular, we try to respect the [Linux kernel style](ht - We occassionally have multiple statements on a single line (e.g. `if (a) b;`) - Allow max line length of 120 chars - Allow opening brace at the end of a function declaration: `function() {`. +- Allow trailing comments ### Your first pull request diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index c24c011f1..b3f42dd7d 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -14,7 +14,7 @@ Welcome! You've arrived at the documentation for Netdata. Use the links below to </div> <div class="nav-getting-started"> - <a class="nav-button" href="docs/GettingStarted/">Getting started guide</a> + <a class="nav-button" href="docs/getting-started/">Getting started guide</a> <p>The perfect place for Netdata beginners to start. Learn how to access Netdata's dashboard, start and stop the service, basic configuration, and more.</p> </div> diff --git a/Makefile.am b/Makefile.am index 0e515db8d..35d9712cb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -236,6 +236,11 @@ NFACCT_PLUGIN_FILES = \ $(LIBNETDATA_FILES) \ $(NULL) +SLABINFO_PLUGIN_FILES = \ + collectors/slabinfo.plugin/slabinfo.c \ + $(LIBNETDATA_FILES) + $(NULL) + XENSTAT_PLUGIN_FILES = \ collectors/xenstat.plugin/xenstat_plugin.c \ $(LIBNETDATA_FILES) \ @@ -600,6 +605,14 @@ if ENABLE_PLUGIN_PERF $(NULL) endif +if ENABLE_PLUGIN_SLABINFO + plugins_PROGRAMS += slabinfo.plugin + slabinfo_plugin_SOURCES = $(SLABINFO_PLUGIN_FILES) + slabinfo_plugin_LDADD = \ + $(NETDATA_COMMON_LIBS) \ + $(NULL) +endif + if ENABLE_BACKEND_KINESIS netdata_SOURCES += $(KINESIS_BACKEND_FILES) netdata_LDADD += $(OPTIONAL_KINESIS_LIBS) @@ -152,6 +152,18 @@ not just visualize metrics. ## News +`Sep 12th, 2019` - **[Netdata v1.17.1 released!](https://github.com/netdata/netdata/releases)** + +Release v1.17.1 contains 2 bug fixes, 6 improvements, and 2 documentation updates. + +The main reason for the patch release is an essential fix to the repeating alarm notifications we introduced in v1.17.0. If you enabled repeating notifications, Netdata would not then send CLEAR notifications for the selected alarms. + +The release also includes a significant improvement to Netdata's auto-detection capabilities, especially after a system restart. Netdata now remembers which `python.d` plugin jobs were successfully collecting data the last time it was running, and retries to run those jobs for 5 minutes before giving up. As a result, you no longer have to worry if your system starts Netdata before the monitored services have had a chance to start properly. We will complete the same improvement for `go.d` plugins in v1.18.0. + +We also made some improvements to our binary packages and added a [neat sample custom dashboard](https://docs.netdata.cloud/web/gui/custom/#dash-multi-host-dashboard) that can show charts from multiple Netdata agents. + +--- + `Sep 3rd, 2019` - **[Netdata v1.17.0 released!](https://github.com/netdata/netdata/releases)** Release v1.17.0 contains 38 bug fixes, 33 improvements, and 20 documentation updates. diff --git a/SECURITY.md b/SECURITY.md index fdaf8141b..4badf2815 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,7 +10,9 @@ We’re extremely grateful for security researchers and users that report vulnerabilities to Netdata Open Source Community. All reports are thoroughly investigated by a set of community volunteers. -To make a report, please create a post [here](https://groups.google.com/a/netdata.cloud/forum/#!newtopic/security) with the vulnerability details and the details expected for [all Netdata bug reports](.github/ISSUE_TEMPLATE/bug_report.md). +To make a report, please create a post [here](https://groups.google.com/a/netdata.cloud/forum/#!newtopic/security) with +the vulnerability details and the details expected for [all Netdata bug +reports](https://github.com/netdata/netdata/blob/c1f4c6cf503995cd4d896c5821b00d55afcbde87/.github/ISSUE_TEMPLATE/bug_report.md). ### When Should I Report a Vulnerability? diff --git a/backends/README.md b/backends/README.md index f93e60f56..ac0847dca 100644 --- a/backends/README.md +++ b/backends/README.md @@ -1,26 +1,25 @@ # Metrics long term archiving -Netdata supports backends for archiving the metrics, or providing long term dashboards, -using Grafana or other tools, like this: +Netdata supports backends for archiving the metrics, or providing long term dashboards, using Grafana or other tools, +like this: ![image](https://cloud.githubusercontent.com/assets/2662304/20649711/29f182ba-b4ce-11e6-97c8-ab2c0ab59833.png) -Since Netdata collects thousands of metrics per server per second, which would easily congest any backend -server when several Netdata servers are sending data to it, Netdata allows sending metrics at a lower -frequency, by resampling them. +Since Netdata collects thousands of metrics per server per second, which would easily congest any backend server when +several Netdata servers are sending data to it, Netdata allows sending metrics at a lower frequency, by resampling them. -So, although Netdata collects metrics every second, it can send to the backend servers averages or sums every -X seconds (though, it can send them per second if you need it to). +So, although Netdata collects metrics every second, it can send to the backend servers averages or sums every X seconds +(though, it can send them per second if you need it to). ## features 1. Supported backends - - **graphite** (`plaintext interface`, used by **Graphite**, **InfluxDB**, **KairosDB**, - **Blueflood**, **ElasticSearch** via logstash tcp input and the graphite codec, etc) + - **graphite** (`plaintext interface`, used by **Graphite**, **InfluxDB**, **KairosDB**, **Blueflood**, + **ElasticSearch** via logstash tcp input and the graphite codec, etc) - metrics are sent to the backend server as `prefix.hostname.chart.dimension`. `prefix` is - configured below, `hostname` is the hostname of the machine (can also be configured). + metrics are sent to the backend server as `prefix.hostname.chart.dimension`. `prefix` is configured below, + `hostname` is the hostname of the machine (can also be configured). - **opentsdb** (`telnet or HTTP interfaces`, used by **OpenTSDB**, **InfluxDB**, **KairosDB**, etc) @@ -33,12 +32,12 @@ X seconds (though, it can send them per second if you need it to). - **prometheus** is described at [prometheus page](prometheus/) since it pulls data from Netdata. - **prometheus remote write** (a binary snappy-compressed protocol buffer encoding over HTTP used by - **Elasticsearch**, **Gnocchi**, **Graphite**, **InfluxDB**, **Kafka**, **OpenTSDB**, - **PostgreSQL/TimescaleDB**, **Splunk**, **VictoriaMetrics**, - and a lot of other [storage providers](https://prometheus.io/docs/operating/integrations/#remote-endpoints-and-storage)) + **Elasticsearch**, **Gnocchi**, **Graphite**, **InfluxDB**, **Kafka**, **OpenTSDB**, **PostgreSQL/TimescaleDB**, + **Splunk**, **VictoriaMetrics**, and a lot of other [storage + providers](https://prometheus.io/docs/operating/integrations/#remote-endpoints-and-storage)) - metrics are labeled in the format, which is used by Netdata for the [plaintext prometheus protocol](prometheus/). - Notes on using the remote write backend are [here](prometheus/remote_write/). + metrics are labeled in the format, which is used by Netdata for the [plaintext prometheus + protocol](prometheus/). Notes on using the remote write backend are [here](prometheus/remote_write/). - **AWS Kinesis Data Streams** @@ -54,32 +53,37 @@ X seconds (though, it can send them per second if you need it to). 4. Netdata supports three modes of operation for all backends: - - `as-collected` sends to backends the metrics as they are collected, in the units they are collected. - So, counters are sent as counters and gauges are sent as gauges, much like all data collectors do. - For example, to calculate CPU utilization in this format, you need to know how to convert kernel ticks to percentage. + - `as-collected` sends to backends the metrics as they are collected, in the units they are collected. So, + counters are sent as counters and gauges are sent as gauges, much like all data collectors do. For example, to + calculate CPU utilization in this format, you need to know how to convert kernel ticks to percentage. - - `average` sends to backends normalized metrics from the Netdata database. - In this mode, all metrics are sent as gauges, in the units Netdata uses. This abstracts data collection - and simplifies visualization, but you will not be able to copy and paste queries from other sources to convert units. - For example, CPU utilization percentage is calculated by Netdata, so Netdata will convert ticks to percentage and - send the average percentage to the backend. + - `average` sends to backends normalized metrics from the Netdata database. In this mode, all metrics are sent as + gauges, in the units Netdata uses. This abstracts data collection and simplifies visualization, but you will not + be able to copy and paste queries from other sources to convert units. For example, CPU utilization percentage + is calculated by Netdata, so Netdata will convert ticks to percentage and send the average percentage to the + backend. - - `sum` or `volume`: the sum of the interpolated values shown on the Netdata graphs is sent to the backend. - So, if Netdata is configured to send data to the backend every 10 seconds, the sum of the 10 values shown on the + - `sum` or `volume`: the sum of the interpolated values shown on the Netdata graphs is sent to the backend. So, if + Netdata is configured to send data to the backend every 10 seconds, the sum of the 10 values shown on the Netdata charts will be used. -Time-series databases suggest to collect the raw values (`as-collected`). If you plan to invest on building your monitoring around a time-series database and you already know (or you will invest in learning) how to convert units and normalize the metrics in Grafana or other visualization tools, we suggest to use `as-collected`. + Time-series databases suggest to collect the raw values (`as-collected`). If you plan to invest on building your + monitoring around a time-series database and you already know (or you will invest in learning) how to convert units + and normalize the metrics in Grafana or other visualization tools, we suggest to use `as-collected`. -If, on the other hand, you just need long term archiving of Netdata metrics and you plan to mainly work with Netdata, we suggest to use `average`. It decouples visualization from data collection, so it will generally be a lot simpler. Furthermore, if you use `average`, the charts shown in the back-end will match exactly what you see in Netdata, which is not necessarily true for the other modes of operation. + If, on the other hand, you just need long term archiving of Netdata metrics and you plan to mainly work with + Netdata, we suggest to use `average`. It decouples visualization from data collection, so it will generally be a lot + simpler. Furthermore, if you use `average`, the charts shown in the back-end will match exactly what you see in + Netdata, which is not necessarily true for the other modes of operation. 5. This code is smart enough, not to slow down Netdata, independently of the speed of the backend server. ## configuration -In `/etc/netdata/netdata.conf` you should have something like this (if not download the latest version -of `netdata.conf` from your Netdata): +In `/etc/netdata/netdata.conf` you should have something like this (if not download the latest version of `netdata.conf` +from your Netdata): -``` +```conf [backend] enabled = yes | no type = graphite | opentsdb:telnet | opentsdb:http | opentsdb:https | prometheus_remote_write | json | kinesis | mongodb @@ -98,92 +102,87 @@ of `netdata.conf` from your Netdata): - `enabled = yes | no`, enables or disables sending data to a backend -- `type = graphite | opentsdb:telnet | opentsdb:http | opentsdb:https | json | kinesis | mongodb`, selects the backend type +- `type = graphite | opentsdb:telnet | opentsdb:http | opentsdb:https | json | kinesis | mongodb`, selects the backend + type -- `destination = host1 host2 host3 ...`, accepts **a space separated list** of hostnames, - IPs (IPv4 and IPv6) and ports to connect to. - Netdata will use the **first available** to send the metrics. +- `destination = host1 host2 host3 ...`, accepts **a space separated list** of hostnames, IPs (IPv4 and IPv6) and + ports to connect to. Netdata will use the **first available** to send the metrics. The format of each item in this list, is: `[PROTOCOL:]IP[:PORT]`. `PROTOCOL` can be `udp` or `tcp`. `tcp` is the default and only supported by the current backends. - `IP` can be `XX.XX.XX.XX` (IPv4), or `[XX:XX...XX:XX]` (IPv6). - For IPv6 you can to enclose the IP in `[]` to separate it from the port. + `IP` can be `XX.XX.XX.XX` (IPv4), or `[XX:XX...XX:XX]` (IPv6). For IPv6 you can to enclose the IP in `[]` to + separate it from the port. `PORT` can be a number of a service name. If omitted, the default port for the backend will be used (graphite = 2003, opentsdb = 4242). Example IPv4: -``` +```conf destination = 10.11.14.2:4242 10.11.14.3:4242 10.11.14.4:4242 ``` Example IPv6 and IPv4 together: -``` +```conf destination = [ffff:...:0001]:2003 10.11.12.1:2003 ``` - When multiple servers are defined, Netdata will try the next one when the first one fails. This allows - you to load-balance different servers: give your backend servers in different order on each Netdata. + When multiple servers are defined, Netdata will try the next one when the first one fails. This allows you to + load-balance different servers: give your backend servers in different order on each Netdata. - Netdata also ships [`nc-backend.sh`](nc-backend.sh), - a script that can be used as a fallback backend to save the metrics to disk and push them to the - time-series database when it becomes available again. It can also be used to monitor / trace / debug - the metrics Netdata generates. + Netdata also ships [`nc-backend.sh`](nc-backend.sh), a script that can be used as a fallback backend to save the + metrics to disk and push them to the time-series database when it becomes available again. It can also be used to + monitor / trace / debug the metrics Netdata generates. For kinesis backend `destination` should be set to an AWS region (for example, `us-east-1`). The MongoDB backend doesn't use the `destination` option for its configuration. It uses the `mongodb.conf` - [configuration file](mongodb/README.md) instead. + [configuration file](../backends/mongodb/) instead. -- `data source = as collected`, or `data source = average`, or `data source = sum`, selects the kind of - data that will be sent to the backend. +- `data source = as collected`, or `data source = average`, or `data source = sum`, selects the kind of data that will + be sent to the backend. -- `hostname = my-name`, is the hostname to be used for sending data to the backend server. By default - this is `[global].hostname`. +- `hostname = my-name`, is the hostname to be used for sending data to the backend server. By default this is + `[global].hostname`. - `prefix = Netdata`, is the prefix to add to all metrics. -- `update every = 10`, is the number of seconds between sending data to the backend. Netdata will add - some randomness to this number, to prevent stressing the backend server when many Netdata servers send - data to the same backend. This randomness does not affect the quality of the data, only the time they - are sent. - -- `buffer on failures = 10`, is the number of iterations (each iteration is `[backend].update every` seconds) - to buffer data, when the backend is not available. If the backend fails to receive the data after that - many failures, data loss on the backend is expected (Netdata will also log it). - -- `timeout ms = 20000`, is the timeout in milliseconds to wait for the backend server to process the data. - By default this is `2 * update_every * 1000`. - -- `send hosts matching = localhost *` includes one or more space separated patterns, using `*` as wildcard - (any number of times within each pattern). The patterns are checked against the hostname (the localhost - is always checked as `localhost`), allowing us to filter which hosts will be sent to the backend when - this Netdata is a central Netdata aggregating multiple hosts. A pattern starting with `!` gives a - negative match. So to match all hosts named `*db*` except hosts containing `*slave*`, use - `!*slave* *db*` (so, the order is important: the first pattern matching the hostname will be used - positive - or negative). - -- `send charts matching = *` includes one or more space separated patterns, using `*` as wildcard (any - number of times within each pattern). The patterns are checked against both chart id and chart name. - A pattern starting with `!` gives a negative match. So to match all charts named `apps.*` - except charts ending in `*reads`, use `!*reads apps.*` (so, the order is important: the first pattern - matching the chart id or the chart name will be used - positive or negative). - -- `send names instead of ids = yes | no` controls the metric names Netdata should send to backend. - Netdata supports names and IDs for charts and dimensions. Usually IDs are unique identifiers as read - by the system and names are human friendly labels (also unique). Most charts and metrics have the same - ID and name, but in several cases they are different: disks with device-mapper, interrupts, QoS classes, - statsd synthetic charts, etc. - -- `host tags = list of TAG=VALUE` defines tags that should be appended on all metrics for the given host. - These are currently only sent to opentsdb and prometheus. Please use the appropriate format for each - time-series db. For example opentsdb likes them like `TAG1=VALUE1 TAG2=VALUE2`, but prometheus like - `tag1="value1",tag2="value2"`. Host tags are mirrored with database replication (streaming of metrics - between Netdata servers). +- `update every = 10`, is the number of seconds between sending data to the backend. Netdata will add some randomness + to this number, to prevent stressing the backend server when many Netdata servers send data to the same backend. + This randomness does not affect the quality of the data, only the time they are sent. + +- `buffer on failures = 10`, is the number of iterations (each iteration is `[backend].update every` seconds) to + buffer data, when the backend is not available. If the backend fails to receive the data after that many failures, + data loss on the backend is expected (Netdata will also log it). + +- `timeout ms = 20000`, is the timeout in milliseconds to wait for the backend server to process the data. By default + this is `2 * update_every * 1000`. + +- `send hosts matching = localhost *` includes one or more space separated patterns, using `*` as wildcard (any number + of times within each pattern). The patterns are checked against the hostname (the localhost is always checked as + `localhost`), allowing us to filter which hosts will be sent to the backend when this Netdata is a central Netdata + aggregating multiple hosts. A pattern starting with `!` gives a negative match. So to match all hosts named `*db*` + except hosts containing `*slave*`, use `!*slave* *db*` (so, the order is important: the first pattern matching the + hostname will be used - positive or negative). + +- `send charts matching = *` includes one or more space separated patterns, using `*` as wildcard (any number of times + within each pattern). The patterns are checked against both chart id and chart name. A pattern starting with `!` + gives a negative match. So to match all charts named `apps.*` except charts ending in `*reads`, use `!*reads + apps.*` (so, the order is important: the first pattern matching the chart id or the chart name will be used - + positive or negative). + +- `send names instead of ids = yes | no` controls the metric names Netdata should send to backend. Netdata supports + names and IDs for charts and dimensions. Usually IDs are unique identifiers as read by the system and names are + human friendly labels (also unique). Most charts and metrics have the same ID and name, but in several cases they + are different: disks with device-mapper, interrupts, QoS classes, statsd synthetic charts, etc. + +- `host tags = list of TAG=VALUE` defines tags that should be appended on all metrics for the given host. These are + currently only sent to opentsdb and prometheus. Please use the appropriate format for each time-series db. For + example opentsdb likes them like `TAG1=VALUE1 TAG2=VALUE2`, but prometheus like `tag1="value1",tag2="value2"`. Host + tags are mirrored with database replication (streaming of metrics between Netdata servers). ## monitoring operation @@ -194,16 +193,15 @@ Netdata provides 5 charts: 2. **Buffered data size**, the amount of data (in KB) Netdata added the buffer. -3. ~~**Backend latency**, the time the backend server needed to process the data Netdata sent. - If there was a re-connection involved, this includes the connection time.~~ - (this chart has been removed, because it only measures the time Netdata needs to give the data - to the O/S - since the backend servers do not ack the reception, Netdata does not have any means - to measure this properly). +3. ~~**Backend latency**, the time the backend server needed to process the data Netdata sent. If there was a + re-connection involved, this includes the connection time.~~ (this chart has been removed, because it only measures + the time Netdata needs to give the data to the O/S - since the backend servers do not ack the reception, Netdata + does not have any means to measure this properly). 4. **Backend operations**, the number of operations performed by Netdata. -5. **Backend thread CPU usage**, the CPU resources consumed by the Netdata thread, that is responsible - for sending the metrics to the backend server. +5. **Backend thread CPU usage**, the CPU resources consumed by the Netdata thread, that is responsible for sending the + metrics to the backend server. ![image](https://cloud.githubusercontent.com/assets/2662304/20463536/eb196084-af3d-11e6-8ee5-ddbd3b4d8449.png) @@ -216,7 +214,8 @@ Netdata adds 4 alarms: 1. `backend_last_buffering`, number of seconds since the last successful buffering of backend data 2. `backend_metrics_sent`, percentage of metrics sent to the backend server 3. `backend_metrics_lost`, number of metrics lost due to repeating failures to contact the backend server -4. ~~`backend_slow`, the percentage of time between iterations needed by the backend time to process the data sent by Netdata~~ (this was misleading and has been removed). +4. ~~`backend_slow`, the percentage of time between iterations needed by the backend time to process the data sent by + Netdata~~ (this was misleading and has been removed). ![image](https://cloud.githubusercontent.com/assets/2662304/20463779/a46ed1c2-af43-11e6-91a5-07ca4533cac3.png) diff --git a/backends/WALKTHROUGH.md b/backends/WALKTHROUGH.md index 19f4ac0e1..c6461db46 100644 --- a/backends/WALKTHROUGH.md +++ b/backends/WALKTHROUGH.md @@ -2,123 +2,102 @@ ## Intro -In this article I will walk you through the basics of getting Netdata, -Prometheus and Grafana all working together and monitoring your application -servers. This article will be using docker on your local workstation. We will be -working with docker in an ad-hoc way, launching containers that run ‘/bin/bash’ -and attaching a TTY to them. I use docker here in a purely academic fashion and -do not condone running Netdata in a container. I pick this method so individuals -without cloud accounts or access to VMs can try this out and for it’s speed of -deployment. +In this article I will walk you through the basics of getting Netdata, Prometheus and Grafana all working together and +monitoring your application servers. This article will be using docker on your local workstation. We will be working +with docker in an ad-hoc way, launching containers that run ‘/bin/bash’ and attaching a TTY to them. I use docker here +in a purely academic fashion and do not condone running Netdata in a container. I pick this method so individuals +without cloud accounts or access to VMs can try this out and for it’s speed of deployment. ## Why Netdata, Prometheus, and Grafana -Some time ago I was introduced to Netdata by a coworker. We were attempting to -troubleshoot python code which seemed to be bottlenecked. I was instantly -impressed by the amount of metrics Netdata exposes to you. I quickly added -Netdata to my set of go-to tools when troubleshooting systems performance. - -Some time ago, even later, I was introduced to Prometheus. Prometheus is a -monitoring application which flips the normal architecture around and polls -rest endpoints for its metrics. This architectural change greatly simplifies -and decreases the time necessary to begin monitoring your applications. -Compared to current monitoring solutions the time spent on designing the -infrastructure is greatly reduced. Running a single Prometheus server per -application becomes feasible with the help of Grafana. - -Grafana has been the go to graphing tool for… some time now. It’s awesome, -anyone that has used it knows it’s awesome. We can point Grafana at Prometheus -and use Prometheus as a data source. This allows a pretty simple overall -monitoring architecture: Install Netdata on your application servers, point -Prometheus at Netdata, and then point Grafana at Prometheus. - -I’m omitting an important ingredient in this stack in order to keep this tutorial -simple and that is service discovery. My personal preference is to use Consul. -Prometheus can plug into consul and automatically begin to scrape new hosts that -register a Netdata client with Consul. - -At the end of this tutorial you will understand how each technology fits -together to create a modern monitoring stack. This stack will offer you -visibility into your application and systems performance. +Some time ago I was introduced to Netdata by a coworker. We were attempting to troubleshoot python code which seemed to +be bottlenecked. I was instantly impressed by the amount of metrics Netdata exposes to you. I quickly added Netdata to +my set of go-to tools when troubleshooting systems performance. + +Some time ago, even later, I was introduced to Prometheus. Prometheus is a monitoring application which flips the normal +architecture around and polls rest endpoints for its metrics. This architectural change greatly simplifies and decreases +the time necessary to begin monitoring your applications. Compared to current monitoring solutions the time spent on +designing the infrastructure is greatly reduced. Running a single Prometheus server per application becomes feasible +with the help of Grafana. + +Grafana has been the go to graphing tool for… some time now. It’s awesome, anyone that has used it knows it’s awesome. +We can point Grafana at Prometheus and use Prometheus as a data source. This allows a pretty simple overall monitoring +architecture: Install Netdata on your application servers, point Prometheus at Netdata, and then point Grafana at +Prometheus. + +I’m omitting an important ingredient in this stack in order to keep this tutorial simple and that is service discovery. +My personal preference is to use Consul. Prometheus can plug into consul and automatically begin to scrape new hosts +that register a Netdata client with Consul. + +At the end of this tutorial you will understand how each technology fits together to create a modern monitoring stack. +This stack will offer you visibility into your application and systems performance. ## Getting Started - Netdata -To begin let’s create our container which we will install Netdata on. We need -to run a container, forward the necessary port that Netdata listens on, and -attach a tty so we can interact with the bash shell on the container. But -before we do this we want name resolution between the two containers to work. -In order to accomplish this we will create a user-defined network and attach -both containers to this network. The first command we should run is: +To begin let’s create our container which we will install Netdata on. We need to run a container, forward the necessary +port that Netdata listens on, and attach a tty so we can interact with the bash shell on the container. But before we do +this we want name resolution between the two containers to work. In order to accomplish this we will create a +user-defined network and attach both containers to this network. The first command we should run is: ```sh docker network create --driver bridge netdata-tutorial ``` -With this user-defined network created we can now launch our container we will -install Netdata on and point it to this network. +With this user-defined network created we can now launch our container we will install Netdata on and point it to this +network. ```sh docker run -it --name netdata --hostname netdata --network=netdata-tutorial -p 19999:19999 centos:latest '/bin/bash' ``` -This command creates an interactive tty session (-it), gives the container both -a name in relation to the docker daemon and a hostname (this is so you know what -container is which when working in the shells and docker maps hostname -resolution to this container), forwards the local port 19999 to the container’s -port 19999 (-p 19999:19999), sets the command to run (/bin/bash) and then -chooses the base container images (centos:latest). After running this you should -be sitting inside the shell of the container. +This command creates an interactive tty session (-it), gives the container both a name in relation to the docker daemon +and a hostname (this is so you know what container is which when working in the shells and docker maps hostname +resolution to this container), forwards the local port 19999 to the container’s port 19999 (-p 19999:19999), sets the +command to run (/bin/bash) and then chooses the base container images (centos:latest). After running this you should be +sitting inside the shell of the container. -After we have entered the shell we can install Netdata. This process could not -be easier. If you take a look at [this link](../packaging/installer/#installation), the Netdata devs give us -several one-liners to install Netdata. I have not had any issues with these one -liners and their bootstrapping scripts so far (If you guys run into anything do -share). Run the following command in your container. +After we have entered the shell we can install Netdata. This process could not be easier. If you take a look at [this +link](../packaging/installer/#installation), the Netdata devs give us several one-liners to install Netdata. I have not +had any issues with these one liners and their bootstrapping scripts so far (If you guys run into anything do share). +Run the following command in your container. ```sh bash <(curl -Ss https://my-netdata.io/kickstart.sh) --dont-wait ``` -After the install completes you should be able to hit the Netdata dashboard at -<http://localhost:19999/> (replace localhost if you’re doing this on a VM or have -the docker container hosted on a machine not on your local system). If this is -your first time using Netdata I suggest you take a look around. The amount of -time I’ve spent digging through /proc and calculating my own metrics has been -greatly reduced by this tool. Take it all in. +After the install completes you should be able to hit the Netdata dashboard at <http://localhost:19999/> (replace +localhost if you’re doing this on a VM or have the docker container hosted on a machine not on your local system). If +this is your first time using Netdata I suggest you take a look around. The amount of time I’ve spent digging through +/proc and calculating my own metrics has been greatly reduced by this tool. Take it all in. Next I want to draw your attention to a particular endpoint. Navigate to -<http://localhost:19999/api/v1/allmetrics?format=prometheus&help=yes> In your -browser. This is the endpoint which publishes all the metrics in a format which -Prometheus understands. Let’s take a look at one of these metrics. -`netdata_system_cpu_percentage_average{chart="system.cpu",family="cpu",dimension="system"} -0.0831255 1501271696000` This metric is representing several things which I will -go in more details in the section on prometheus. For now understand that this -metric: `netdata_system_cpu_percentage_average` has several labels: [chart, -family, dimension]. This corresponds with the first cpu chart you see on the -Netdata dashboard. +<http://localhost:19999/api/v1/allmetrics?format=prometheus&help=yes> In your browser. This is the endpoint which +publishes all the metrics in a format which Prometheus understands. Let’s take a look at one of these metrics. +`netdata_system_cpu_percentage_average{chart="system.cpu",family="cpu",dimension="system"} 0.0831255 1501271696000` This +metric is representing several things which I will go in more details in the section on prometheus. For now understand +that this metric: `netdata_system_cpu_percentage_average` has several labels: (chart, family, dimension). This +corresponds with the first cpu chart you see on the Netdata dashboard. ![](https://github.com/ldelossa/NetdataTutorial/raw/master/Screen%20Shot%202017-07-28%20at%204.00.45%20PM.png) -This CHART is called ‘system.cpu’, The FAMILY is cpu, and the DIMENSION we are -observing is “system”. You can begin to draw links between the charts in Netdata -to the prometheus metrics format in this manner. +This CHART is called ‘system.cpu’, The FAMILY is cpu, and the DIMENSION we are observing is “system”. You can begin to +draw links between the charts in Netdata to the prometheus metrics format in this manner. ## Prometheus -We will be installing prometheus in a container for purpose of demonstration. -While prometheus does have an official container I would like to walk through -the install process and setup on a fresh container. This will allow anyone +We will be installing prometheus in a container for purpose of demonstration. While prometheus does have an official +container I would like to walk through the install process and setup on a fresh container. This will allow anyone reading to migrate this tutorial to a VM or Server of any sort. -Let’s start another container in the same fashion as we did the Netdata -container. +Let’s start another container in the same fashion as we did the Netdata container. ```sh docker run -it --name prometheus --hostname prometheus --network=netdata-tutorial -p 9090:9090 centos:latest '/bin/bash' ``` -This should drop you into a shell once again. Once there quickly install your favorite editor as we will be editing files later in this tutorial. +This should drop you into a shell once again. Once there quickly install your favorite editor as we will be editing +files later in this tutorial. ```sh yum install vim -y @@ -139,39 +118,33 @@ mkdir /opt/prometheus sudo tar -xvf /tmp/prometheus-*linux-amd64.tar.gz -C /opt/prometheus --strip=1 ``` -This should get prometheus installed into the container. Let’s test that we can run prometheus and connect to it’s web interface. +This should get prometheus installed into the container. Let’s test that we can run prometheus and connect to it’s web +interface. ```sh /opt/prometheus/prometheus ``` -Now attempt to go to <http://localhost:9090/>. You should be presented with the -prometheus homepage. This is a good point to talk about Prometheus’s data model -which can be viewed here: <https://prometheus.io/docs/concepts/data_model/> As -explained we have two key elements in Prometheus metrics. We have the ‘metric’ -and its ‘labels’. Labels allow for granularity between metrics. Let’s use our -previous example to further explain. +Now attempt to go to <http://localhost:9090/>. You should be presented with the prometheus homepage. This is a good +point to talk about Prometheus’s data model which can be viewed here: <https://prometheus.io/docs/concepts/data_model/> +As explained we have two key elements in Prometheus metrics. We have the ‘metric’ and its ‘labels’. Labels allow for +granularity between metrics. Let’s use our previous example to further explain. -``` +```conf netdata_system_cpu_percentage_average{chart="system.cpu",family="cpu",dimension="system"} 0.0831255 1501271696000 ``` -Here our metric is -‘netdata_system_cpu_percentage_average’ and our labels are ‘chart’, ‘family’, -and ‘dimension. The last two values constitute the actual metric value for the -metric type (gauge, counter, etc…). We can begin graphing system metrics with -this information, but first we need to hook up Prometheus to poll Netdata stats. - -Let’s move our attention to Prometheus’s configuration. Prometheus gets it -config from the file located (in our example) at -`/opt/prometheus/prometheus.yml`. I won’t spend an extensive amount of time -going over the configuration values documented here: -<https://prometheus.io/docs/operating/configuration/>. We will be adding a new -“job” under the “scrape_configs”. Let’s make the “scrape_configs” section look -like this (we can use the dns name Netdata due to the custom user-defined -network we created in docker beforehand). - -```yml +Here our metric is ‘netdata_system_cpu_percentage_average’ and our labels are ‘chart’, ‘family’, and ‘dimension. The +last two values constitute the actual metric value for the metric type (gauge, counter, etc…). We can begin graphing +system metrics with this information, but first we need to hook up Prometheus to poll Netdata stats. + +Let’s move our attention to Prometheus’s configuration. Prometheus gets it config from the file located (in our example) +at `/opt/prometheus/prometheus.yml`. I won’t spend an extensive amount of time going over the configuration values +documented here: <https://prometheus.io/docs/operating/configuration/>. We will be adding a new“job” under the +“scrape_configs”. Let’s make the “scrape_configs” section look like this (we can use the dns name Netdata due to the +custom user-defined network we created in docker beforehand). + +```yaml scrape_configs: # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. - job_name: 'prometheus' @@ -192,84 +165,66 @@ scrape_configs: - targets: ['netdata:19999'] ``` -Let’s start prometheus once again by running `/opt/prometheus/prometheus`. If we - -now navigate to prometheus at ‘<http://localhost:9090/targets’> we should see our - -target being successfully scraped. If we now go back to the Prometheus’s -homepage and begin to type ‘netdata\_’ Prometheus should auto complete metrics -it is now scraping. +Let’s start prometheus once again by running `/opt/prometheus/prometheus`. If we now navigate to prometheus at +‘<http://localhost:9090/targets’> we should see our target being successfully scraped. If we now go back to the +Prometheus’s homepage and begin to type ‘netdata\_’ Prometheus should auto complete metrics it is now scraping. ![](https://github.com/ldelossa/NetdataTutorial/raw/master/Screen%20Shot%202017-07-28%20at%205.13.43%20PM.png) -Let’s now start exploring how we can graph some metrics. Back in our NetData -container lets get the CPU spinning with a pointless busy loop. On the shell do -the following: +Let’s now start exploring how we can graph some metrics. Back in our NetData container lets get the CPU spinning with a +pointless busy loop. On the shell do the following: -``` +```sh [root@netdata /]# while true; do echo "HOT HOT HOT CPU"; done ``` -Our NetData cpu graph should be showing some activity. Let’s represent this in -Prometheus. In order to do this let’s keep our metrics page open for reference: -<http://localhost:19999/api/v1/allmetrics?format=prometheus&help=yes> We are -setting out to graph the data in the CPU chart so let’s search for “system.cpu” -in the metrics page above. We come across a section of metrics with the first -comments `# COMMENT homogeneous chart "system.cpu", context "system.cpu", family -"cpu", units "percentage"` Followed by the metrics. This is a good start now let -us drill down to the specific metric we would like to graph. +Our NetData cpu graph should be showing some activity. Let’s represent this in Prometheus. In order to do this let’s +keep our metrics page open for reference: <http://localhost:19999/api/v1/allmetrics?format=prometheus&help=yes> We are +setting out to graph the data in the CPU chart so let’s search for “system.cpu”in the metrics page above. We come across +a section of metrics with the first comments `# COMMENT homogeneous chart "system.cpu", context "system.cpu", family +"cpu", units "percentage"` Followed by the metrics. This is a good start now let us drill down to the specific metric we +would like to graph. -``` +```conf # COMMENT netdata_system_cpu_percentage_average: dimension "system", value is percentage, gauge, dt 1501275951 to 1501275951 inclusive netdata_system_cpu_percentage_average{chart="system.cpu",family="cpu",dimension="system"} 0.0000000 1501275951000 ``` -Here we learn that the metric name we care about is -‘netdata_system_cpu_percentage_average’ so throw this into Prometheus and see -what we get. We should see something similar to this (I shut off my busy loop) +Here we learn that the metric name we care about is‘netdata_system_cpu_percentage_average’ so throw this into Prometheus +and see what we get. We should see something similar to this (I shut off my busy loop) ![](https://github.com/ldelossa/NetdataTutorial/raw/master/Screen%20Shot%202017-07-28%20at%205.47.53%20PM.png) -This is a good step toward what we want. Also make note that Prometheus will tag -on an ‘instance’ label for us which corresponds to our statically defined job in -the configuration file. This allows us to tailor our queries to specific -instances. Now we need to isolate the dimension we want in our query. To do this -let us refine the query slightly. Let’s query the dimension also. Place this -into our query text box. -`netdata_system_cpu_percentage_average{dimension="system"}` We now wind up with -the following graph. +This is a good step toward what we want. Also make note that Prometheus will tag on an ‘instance’ label for us which +corresponds to our statically defined job in the configuration file. This allows us to tailor our queries to specific +instances. Now we need to isolate the dimension we want in our query. To do this let us refine the query slightly. Let’s +query the dimension also. Place this into our query text box. +`netdata_system_cpu_percentage_average{dimension="system"}` We now wind up with the following graph. ![](https://github.com/ldelossa/NetdataTutorial/raw/master/Screen%20Shot%202017-07-28%20at%205.54.40%20PM.png) -Awesome, this is exactly what we wanted. If you haven’t caught on yet we can -emulate entire charts from NetData by using the `chart` dimension. If you’d like -you can combine the ‘chart’ and ‘instance’ dimension to create per-instance -charts. Let’s give this a try: -`netdata_system_cpu_percentage_average{chart="system.cpu", instance="netdata:19999"}` - -This is the basics of using Prometheus to query NetData. I’d advise everyone at -this point to read [this page](../backends/prometheus/#using-netdata-with-prometheus). -The key point here is that NetData can export metrics from its internal DB or -can send metrics “as-collected” by specifying the ‘source=as-collected’ url -parameter like so. -<http://localhost:19999/api/v1/allmetrics?format=prometheus&help=yes&types=yes&source=as-collected> -If you choose to use this method you will need to use Prometheus's set of -functions here: <https://prometheus.io/docs/querying/functions/> to obtain useful -metrics as you are now dealing with raw counters from the system. For example -you will have to use the `irate()` function over a counter to get that metric's -rate per second. If your graphing needs are met by using the metrics returned by -NetData's internal database (not specifying any source= url parameter) then use -that. If you find limitations then consider re-writing your queries using the -raw data and using Prometheus functions to get the desired chart. +Awesome, this is exactly what we wanted. If you haven’t caught on yet we can emulate entire charts from NetData by using +the `chart` dimension. If you’d like you can combine the ‘chart’ and ‘instance’ dimension to create per-instance charts. +Let’s give this a try: `netdata_system_cpu_percentage_average{chart="system.cpu", instance="netdata:19999"}` + +This is the basics of using Prometheus to query NetData. I’d advise everyone at this point to read [this +page](../backends/prometheus/#using-netdata-with-prometheus). The key point here is that NetData can export metrics from +its internal DB or can send metrics “as-collected” by specifying the ‘source=as-collected’ url parameter like so. +<http://localhost:19999/api/v1/allmetrics?format=prometheus&help=yes&types=yes&source=as-collected> If you choose to use +this method you will need to use Prometheus's set of functions here: <https://prometheus.io/docs/querying/functions/> to +obtain useful metrics as you are now dealing with raw counters from the system. For example you will have to use the +`irate()` function over a counter to get that metric's rate per second. If your graphing needs are met by using the +metrics returned by NetData's internal database (not specifying any source= url parameter) then use that. If you find +limitations then consider re-writing your queries using the raw data and using Prometheus functions to get the desired +chart. ## Grafana -Finally we make it to grafana. This is the easiest part in my opinion. This time -we will actually run the official grafana docker container as all configuration -we need to do is done via the GUI. Let’s run the following command: +Finally we make it to grafana. This is the easiest part in my opinion. This time we will actually run the official +grafana docker container as all configuration we need to do is done via the GUI. Let’s run the following command: -``` +```sh docker run -i -p 3000:3000 --network=netdata-tutorial grafana/grafana ``` @@ -277,26 +232,22 @@ This will get grafana running at ‘<http://localhost:3000/’> Let’s go there login using the credentials Admin:Admin. -The first thing we want to do is click ‘Add data source’. Let’s make it look -like the following screenshot +The first thing we want to do is click ‘Add data source’. Let’s make it look like the following screenshot ![](https://github.com/ldelossa/NetdataTutorial/raw/master/Screen%20Shot%202017-07-28%20at%206.36.55%20PM.png) -With this completed let’s graph! Create a new Dashboard by clicking on the top -left Grafana Icon and create a new graph in that dashboard. Fill in the query -like we did above and save. +With this completed let’s graph! Create a new Dashboard by clicking on the top left Grafana Icon and create a new graph +in that dashboard. Fill in the query like we did above and save. ![](https://github.com/ldelossa/NetdataTutorial/raw/master/Screen%20Shot%202017-07-28%20at%206.39.38%20PM.png) ## Conclusion -There you have it, a complete systems monitoring stack which is very easy to -deploy. From here I would begin to understand how Prometheus and a service -discovery mechanism such as Consul can play together nicely. My current prod -deployments automatically register Netdata services into Consul and Prometheus -automatically begins to scrape them. Once achieved you do not have to think -about the monitoring system until Prometheus cannot keep up with your scale. -Once this happens there are options presented in the Prometheus documentation -for solving this. Hope this was helpful, happy monitoring. +There you have it, a complete systems monitoring stack which is very easy to deploy. From here I would begin to +understand how Prometheus and a service discovery mechanism such as Consul can play together nicely. My current prod +deployments automatically register Netdata services into Consul and Prometheus automatically begins to scrape them. Once +achieved you do not have to think about the monitoring system until Prometheus cannot keep up with your scale. Once this +happens there are options presented in the Prometheus documentation for solving this. Hope this was helpful, happy +monitoring. [![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fbackends%2FWALKTHROUGH&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/backends/aws_kinesis/README.md b/backends/aws_kinesis/README.md index a6529f237..051ac9637 100644 --- a/backends/aws_kinesis/README.md +++ b/backends/aws_kinesis/README.md @@ -2,11 +2,17 @@ ## Prerequisites -To use AWS Kinesis as a backend AWS SDK for C++ should be [installed](https://docs.aws.amazon.com/en_us/sdk-for-cpp/v1/developer-guide/setup.html) first. `libcrypto`, `libssl`, and `libcurl` are also required to compile Netdata with Kinesis support enabled. Next, Netdata should be re-installed from the source. The installer will detect that the required libraries are now available. +To use AWS Kinesis as a backend AWS SDK for C++ should be +[installed](https://docs.aws.amazon.com/en_us/sdk-for-cpp/v1/developer-guide/setup.html) first. `libcrypto`, `libssl`, +and `libcurl` are also required to compile Netdata with Kinesis support enabled. Next, Netdata should be re-installed +from the source. The installer will detect that the required libraries are now available. -If the AWS SDK for C++ is being installed from source, it is useful to set `-DBUILD_ONLY="kinesis"`. Otherwise, the building process could take a very long time. Take a note, that the default installation path for the libraries is `/usr/local/lib64`. Many Linux distributions don't include this path as the default one for a library search, so it is advisable to use the following options to `cmake` while building the AWS SDK: +If the AWS SDK for C++ is being installed from source, it is useful to set `-DBUILD_ONLY="kinesis"`. Otherwise, the +building process could take a very long time. Take a note, that the default installation path for the libraries is +`/usr/local/lib64`. Many Linux distributions don't include this path as the default one for a library search, so it is +advisable to use the following options to `cmake` while building the AWS SDK: -``` +```sh cmake -DCMAKE_INSTALL_LIBDIR=/usr/lib -DCMAKE_INSTALL_INCLUDEDIR=/usr/include -DBUILD_SHARED_LIBS=OFF -DBUILD_ONLY=kinesis <aws-sdk-cpp sources> ``` @@ -14,7 +20,7 @@ cmake -DCMAKE_INSTALL_LIBDIR=/usr/lib -DCMAKE_INSTALL_INCLUDEDIR=/usr/include -D To enable data sending to the kinesis backend set the following options in `netdata.conf`: -``` +```conf [backend] enabled = yes type = kinesis @@ -25,7 +31,7 @@ set the `destination` option to an AWS region. In the Netdata configuration directory run `./edit-config aws_kinesis.conf` and set AWS credentials and stream name: -``` +```yaml # AWS credentials aws_access_key_id = your_access_key_id aws_secret_access_key = your_secret_access_key @@ -34,8 +40,9 @@ aws_secret_access_key = your_secret_access_key stream name = your_stream_name ``` -Alternatively, AWS credentials can be set for the *netdata* user using AWS SDK for C++ [standard methods](https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html). +Alternatively, AWS credentials can be set for the `netdata` user using AWS SDK for C++ [standard methods](https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html). -A partition key for every record is computed automatically by Netdata with the purpose to distribute records across available shards evenly. +A partition key for every record is computed automatically by Netdata with the purpose to distribute records across +available shards evenly. [![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fbackends%2Faws_kinesis%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/backends/mongodb/README.md b/backends/mongodb/README.md index 7538fe8be..890afd178 100644 --- a/backends/mongodb/README.md +++ b/backends/mongodb/README.md @@ -2,21 +2,24 @@ ## Prerequisites -To use MongoDB as a backend, `libmongoc` 1.7.0 or higher should be [installed](http://mongoc.org/libmongoc/current/installing.html) first. Next, Netdata should be re-installed from the source. The installer will detect that the required libraries are now available. +To use MongoDB as a backend, `libmongoc` 1.7.0 or higher should be +[installed](http://mongoc.org/libmongoc/current/installing.html) first. Next, Netdata should be re-installed from the +source. The installer will detect that the required libraries are now available. ## Configuration To enable data sending to the MongoDB backend set the following options in `netdata.conf`: -``` +```conf [backend] enabled = yes type = mongodb ``` -In the Netdata configuration directory run `./edit-config mongodb.conf` and set [MongoDB URI](https://docs.mongodb.com/manual/reference/connection-string/), database name, and collection name: +In the Netdata configuration directory run `./edit-config mongodb.conf` and set [MongoDB +URI](https://docs.mongodb.com/manual/reference/connection-string/), database name, and collection name: -``` +```yaml # URI uri = mongodb://<hostname> @@ -27,6 +30,7 @@ database = your_database_name collection = your_collection_name ``` -The default socket timeout depends on the backend update interval. The timeout is 500 ms shorter than the interval (but not less than 1000 ms). You can alter the timeout using the `sockettimeoutms` MongoDB URI option. +The default socket timeout depends on the backend update interval. The timeout is 500 ms shorter than the interval (but +not less than 1000 ms). You can alter the timeout using the `sockettimeoutms` MongoDB URI option. [![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fbackends%2Fmongodb%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/backends/opentsdb/README.md b/backends/opentsdb/README.md index ab1f08bd3..5c04868c1 100644 --- a/backends/opentsdb/README.md +++ b/backends/opentsdb/README.md @@ -1,25 +1,31 @@ # OpenTSDB with HTTP -Netdata can easily communicate with OpenTSDB using HTTP API. To enable this channel, set the following options in your `netdata.conf`: +Netdata can easily communicate with OpenTSDB using HTTP API. To enable this channel, set the following options in your +`netdata.conf`: -``` +```conf [backend] type = opentsdb:http destination = localhost:4242 ``` -In this example, OpenTSDB is running with its default port, which is `4242`. If you run OpenTSDB on a different port, change the `destination = localhost:4242` line accordingly. +In this example, OpenTSDB is running with its default port, which is `4242`. If you run OpenTSDB on a different port, +change the `destination = localhost:4242` line accordingly. ## HTTPS -As of [v1.16.0](https://github.com/netdata/netdata/releases/tag/v1.16.0), Netdata can send metrics to OpenTSDB using TLS/SSL. Unfortunately, OpenTDSB does not support encrypted connections, so you will have to configure a reverse proxy to enable HTTPS communication between Netdata and OpenTSBD. You can set up a reverse proxy with [Nginx](../../docs/Running-behind-nginx.md). +As of [v1.16.0](https://github.com/netdata/netdata/releases/tag/v1.16.0), Netdata can send metrics to OpenTSDB using +TLS/SSL. Unfortunately, OpenTDSB does not support encrypted connections, so you will have to configure a reverse proxy +to enable HTTPS communication between Netdata and OpenTSBD. You can set up a reverse proxy with +[Nginx](../../docs/Running-behind-nginx.md). After your proxy is configured, make the following changes to `netdata.conf`: -``` +```conf [backend] type = opentsdb:https destination = localhost:8082 ``` -In this example, we used the port `8082` for our reverse proxy. If your reverse proxy listens on a different port, change the `destination = localhost:8082` line accordingly. +In this example, we used the port `8082` for our reverse proxy. If your reverse proxy listens on a different port, +change the `destination = localhost:8082` line accordingly. diff --git a/backends/prometheus/README.md b/backends/prometheus/README.md index 0a4be27e3..e234efe94 100644 --- a/backends/prometheus/README.md +++ b/backends/prometheus/README.md @@ -1,15 +1,19 @@ # Using Netdata with Prometheus -> IMPORTANT: the format Netdata sends metrics to prometheus has changed since Netdata v1.7. The new prometheus backend for Netdata supports a lot more features and is aligned to the development of the rest of the Netdata backends. +> IMPORTANT: the format Netdata sends metrics to prometheus has changed since Netdata v1.7. The new prometheus backend +> for Netdata supports a lot more features and is aligned to the development of the rest of the Netdata backends. -Prometheus is a distributed monitoring system which offers a very simple setup along with a robust data model. Recently Netdata added support for Prometheus. I'm going to quickly show you how to install both Netdata and prometheus on the same server. We can then use grafana pointed at Prometheus to obtain long term metrics Netdata offers. I'm assuming we are starting at a fresh ubuntu shell (whether you'd like to follow along in a VM or a cloud instance is up to you). +Prometheus is a distributed monitoring system which offers a very simple setup along with a robust data model. Recently +Netdata added support for Prometheus. I'm going to quickly show you how to install both Netdata and prometheus on the +same server. We can then use grafana pointed at Prometheus to obtain long term metrics Netdata offers. I'm assuming we +are starting at a fresh ubuntu shell (whether you'd like to follow along in a VM or a cloud instance is up to you). ## Installing Netdata and prometheus ### Installing Netdata -There are number of ways to install Netdata according to [Installation](../../packaging/installer/#installation)\ -The suggested way of installing the latest Netdata and keep it upgrade automatically. Using one line installation: +There are number of ways to install Netdata according to [Installation](../../packaging/installer/). The suggested way +of installing the latest Netdata and keep it upgrade automatically. Using one line installation: ```sh bash <(curl -Ss https://my-netdata.io/kickstart.sh) @@ -17,7 +21,7 @@ bash <(curl -Ss https://my-netdata.io/kickstart.sh) At this point we should have Netdata listening on port 19999. Attempt to take your browser here: -``` +```sh http://your.netdata.ip:19999 ``` @@ -25,7 +29,10 @@ _(replace `your.netdata.ip` with the IP or hostname of the server running Netdat ### Installing Prometheus -In order to install prometheus we are going to introduce our own systemd startup script along with an example of prometheus.yaml configuration. Prometheus needs to be pointed to your server at a specific target url for it to scrape Netdata's api. Prometheus is always a pull model meaning Netdata is the passive client within this architecture. Prometheus always initiates the connection with Netdata. +In order to install prometheus we are going to introduce our own systemd startup script along with an example of +prometheus.yaml configuration. Prometheus needs to be pointed to your server at a specific target url for it to scrape +Netdata's api. Prometheus is always a pull model meaning Netdata is the passive client within this architecture. +Prometheus always initiates the connection with Netdata. #### Download Prometheus @@ -113,7 +120,10 @@ scrape_configs: #### Install nodes.yml -The following is completely optional, it will enable Prometheus to generate alerts from some NetData sources. Tweak the values to your own needs. We will use the following `nodes.yml` file below. Save it at `/opt/prometheus/nodes.yml`, and add a _- "nodes.yml"_ entry under the _rule_files:_ section in the example prometheus.yml file above. +The following is completely optional, it will enable Prometheus to generate alerts from some NetData sources. Tweak the +values to your own needs. We will use the following `nodes.yml` file below. Save it at `/opt/prometheus/nodes.yml`, and +add a _- "nodes.yml"_ entry under the _rule_files:_ section in the example prometheus.yml file above. + ```yaml groups: - name: nodes @@ -156,7 +166,7 @@ groups: Save this service file as `/etc/systemd/system/prometheus.service`: -``` +```sh [Unit] Description=Prometheus Server AssertPathExists=/opt/prometheus @@ -183,13 +193,15 @@ sudo systemctl enable prometheus Prometheus should now start and listen on port 9090. Attempt to head there with your browser. -If everything is working correctly when you fetch `http://your.prometheus.ip:9090` you will see a 'Status' tab. Click this and click on 'targets' We should see the Netdata host as a scraped target. +If everything is working correctly when you fetch `http://your.prometheus.ip:9090` you will see a 'Status' tab. Click +this and click on 'targets' We should see the Netdata host as a scraped target. -- - - +--- ## Netdata support for prometheus -> IMPORTANT: the format Netdata sends metrics to prometheus has changed since Netdata v1.6. The new format allows easier queries for metrics and supports both `as collected` and normalized metrics. +> IMPORTANT: the format Netdata sends metrics to prometheus has changed since Netdata v1.6. The new format allows easier +> queries for metrics and supports both `as collected` and normalized metrics. Before explaining the changes, we have to understand the key differences between Netdata and prometheus. @@ -203,7 +215,8 @@ Each chart in Netdata has several properties (common to all its metrics): - `chart_name` - a more human friendly name for `chart_id`, also unique. -- `context` - this is the template of the chart. All disk I/O charts have the same context, all mysql requests charts have the same context, etc. This is used for alarm templates to match all the charts they should be attached to. +- `context` - this is the template of the chart. All disk I/O charts have the same context, all mysql requests charts + have the same context, etc. This is used for alarm templates to match all the charts they should be attached to. - `family` groups a set of charts together. It is used as the submenu of the dashboard. @@ -211,32 +224,52 @@ Each chart in Netdata has several properties (common to all its metrics): #### dimensions -Then each Netdata chart contains metrics called `dimensions`. All the dimensions of a chart have the same units of measurement, and are contextually in the same category (ie. the metrics for disk bandwidth are `read` and `write` and they are both in the same chart). +Then each Netdata chart contains metrics called `dimensions`. All the dimensions of a chart have the same units of +measurement, and are contextually in the same category (ie. the metrics for disk bandwidth are `read` and `write` and +they are both in the same chart). ### Netdata data source Netdata can send metrics to prometheus from 3 data sources: -- `as collected` or `raw` - this data source sends the metrics to prometheus as they are collected. No conversion is done by Netdata. The latest value for each metric is just given to prometheus. This is the most preferred method by prometheus, but it is also the harder to work with. To work with this data source, you will need to understand how to get meaningful values out of them. +- `as collected` or `raw` - this data source sends the metrics to prometheus as they are collected. No conversion is + done by Netdata. The latest value for each metric is just given to prometheus. This is the most preferred method by + prometheus, but it is also the harder to work with. To work with this data source, you will need to understand how + to get meaningful values out of them. - The format of the metrics is: `CONTEXT{chart="CHART",family="FAMILY",dimension="DIMENSION"}`. + The format of the metrics is: `CONTEXT{chart="CHART",family="FAMILY",dimension="DIMENSION"}`. - If the metric is a counter (`incremental` in Netdata lingo), `_total` is appended the context. + If the metric is a counter (`incremental` in Netdata lingo), `_total` is appended the context. - Unlike prometheus, Netdata allows each dimension of a chart to have a different algorithm and conversion constants (`multiplier` and `divisor`). In this case, that the dimensions of a charts are heterogeneous, Netdata will use this format: `CONTEXT_DIMENSION{chart="CHART",family="FAMILY"}` + Unlike prometheus, Netdata allows each dimension of a chart to have a different algorithm and conversion constants + (`multiplier` and `divisor`). In this case, that the dimensions of a charts are heterogeneous, Netdata will use this + format: `CONTEXT_DIMENSION{chart="CHART",family="FAMILY"}` -- `average` - this data source uses the Netdata database to send the metrics to prometheus as they are presented on the Netdata dashboard. So, all the metrics are sent as gauges, at the units they are presented in the Netdata dashboard charts. This is the easiest to work with. +- `average` - this data source uses the Netdata database to send the metrics to prometheus as they are presented on + the Netdata dashboard. So, all the metrics are sent as gauges, at the units they are presented in the Netdata + dashboard charts. This is the easiest to work with. - The format of the metrics is: `CONTEXT_UNITS_average{chart="CHART",family="FAMILY",dimension="DIMENSION"}`. + The format of the metrics is: `CONTEXT_UNITS_average{chart="CHART",family="FAMILY",dimension="DIMENSION"}`. - When this source is used, Netdata keeps track of the last access time for each prometheus server fetching the metrics. This last access time is used at the subsequent queries of the same prometheus server to identify the time-frame the `average` will be calculated. So, no matter how frequently prometheus scrapes Netdata, it will get all the database data. To identify each prometheus server, Netdata uses by default the IP of the client fetching the metrics. If there are multiple prometheus servers fetching data from the same Netdata, using the same IP, each prometheus server can append `server=NAME` to the URL. Netdata will use this `NAME` to uniquely identify the prometheus server. + When this source is used, Netdata keeps track of the last access time for each prometheus server fetching the + metrics. This last access time is used at the subsequent queries of the same prometheus server to identify the + time-frame the `average` will be calculated. + + So, no matter how frequently prometheus scrapes Netdata, it will get all the database data. + To identify each prometheus server, Netdata uses by default the IP of the client fetching the metrics. + + If there are multiple prometheus servers fetching data from the same Netdata, using the same IP, each prometheus + server can append `server=NAME` to the URL. Netdata will use this `NAME` to uniquely identify the prometheus server. - `sum` or `volume`, is like `average` but instead of averaging the values, it sums them. - The format of the metrics is: `CONTEXT_UNITS_sum{chart="CHART",family="FAMILY",dimension="DIMENSION"}`. - All the other operations are the same with `average`. + The format of the metrics is: `CONTEXT_UNITS_sum{chart="CHART",family="FAMILY",dimension="DIMENSION"}`. All the + other operations are the same with `average`. + + To change the data source to `sum` or `as-collected` you need to provide the `source` parameter in the request URL. + e.g.: `http://your.netdata.ip:19999/api/v1/allmetrics?format=prometheus&help=yes&source=as-collected` -Keep in mind that early versions of Netdata were sending the metrics as: `CHART_DIMENSION{}`. + Keep in mind that early versions of Netdata were sending the metrics as: `CHART_DIMENSION{}`. ### Querying Metrics @@ -248,7 +281,9 @@ _(replace `your.netdata.ip` with the ip or hostname of your Netdata server)_ Netdata will respond with all the metrics it sends to prometheus. -If you search that page for `"system.cpu"` you will find all the metrics Netdata is exporting to prometheus for this chart. `system.cpu` is the chart name on the Netdata dashboard (on the Netdata dashboard all charts have a text heading such as : `Total CPU utilization (system.cpu)`. What we are interested here in the chart name: `system.cpu`). +If you search that page for `"system.cpu"` you will find all the metrics Netdata is exporting to prometheus for this +chart. `system.cpu` is the chart name on the Netdata dashboard (on the Netdata dashboard all charts have a text heading +such as : `Total CPU utilization (system.cpu)`. What we are interested here in the chart name: `system.cpu`). Searching for `"system.cpu"` reveals: @@ -278,7 +313,9 @@ netdata_system_cpu_percentage_average{chart="system.cpu",family="cpu",dimension= _(Netdata response for `system.cpu` with source=`average`)_ -In `average` or `sum` data sources, all values are normalized and are reported to prometheus as gauges. Now, use the 'expression' text form in prometheus. Begin to type the metrics we are looking for: `netdata_system_cpu`. You should see that the text form begins to auto-fill as prometheus knows about this metric. +In `average` or `sum` data sources, all values are normalized and are reported to prometheus as gauges. Now, use the +'expression' text form in prometheus. Begin to type the metrics we are looking for: `netdata_system_cpu`. You should see +that the text form begins to auto-fill as prometheus knows about this metric. If the data source was `as collected`, the response would be: @@ -312,7 +349,9 @@ For more information check prometheus documentation. ### Streaming data from upstream hosts -The `format=prometheus` parameter only exports the host's Netdata metrics. If you are using the master/slave functionality of Netdata this ignores any upstream hosts - so you should consider using the below in your **prometheus.yml**: +The `format=prometheus` parameter only exports the host's Netdata metrics. If you are using the master/slave +functionality of Netdata this ignores any upstream hosts - so you should consider using the below in your +**prometheus.yml**: ```yaml metrics_path: '/api/v1/allmetrics' @@ -321,31 +360,38 @@ The `format=prometheus` parameter only exports the host's Netdata metrics. If y honor_labels: true ``` -This will report all upstream host data, and `honor_labels` will make Prometheus take note of the instance names provided. +This will report all upstream host data, and `honor_labels` will make Prometheus take note of the instance names +provided. ### Timestamps -To pass the metrics through prometheus pushgateway, Netdata supports the option `×tamps=no` to send the metrics without timestamps. +To pass the metrics through prometheus pushgateway, Netdata supports the option `×tamps=no` to send the metrics +without timestamps. ## Netdata host variables -Netdata collects various system configuration metrics, like the max number of TCP sockets supported, the max number of files allowed system-wide, various IPC sizes, etc. These metrics are not exposed to prometheus by default. +Netdata collects various system configuration metrics, like the max number of TCP sockets supported, the max number of +files allowed system-wide, various IPC sizes, etc. These metrics are not exposed to prometheus by default. To expose them, append `variables=yes` to the Netdata URL. ### TYPE and HELP -To save bandwidth, and because prometheus does not use them anyway, `# TYPE` and `# HELP` lines are suppressed. If wanted they can be re-enabled via `types=yes` and `help=yes`, e.g. `/api/v1/allmetrics?format=prometheus&types=yes&help=yes` +To save bandwidth, and because prometheus does not use them anyway, `# TYPE` and `# HELP` lines are suppressed. If +wanted they can be re-enabled via `types=yes` and `help=yes`, e.g. +`/api/v1/allmetrics?format=prometheus&types=yes&help=yes` ### Names and IDs -Netdata supports names and IDs for charts and dimensions. Usually IDs are unique identifiers as read by the system and names are human friendly labels (also unique). +Netdata supports names and IDs for charts and dimensions. Usually IDs are unique identifiers as read by the system and +names are human friendly labels (also unique). -Most charts and metrics have the same ID and name, but in several cases they are different: disks with device-mapper, interrupts, QoS classes, statsd synthetic charts, etc. +Most charts and metrics have the same ID and name, but in several cases they are different: disks with device-mapper, +interrupts, QoS classes, statsd synthetic charts, etc. The default is controlled in `netdata.conf`: -``` +```conf [backend] send names instead of ids = yes | no ``` @@ -359,18 +405,21 @@ You can overwrite it from prometheus, by appending to the URL: Netdata can filter the metrics it sends to prometheus with this setting: -``` +```conf [backend] send charts matching = * ``` -This settings accepts a space separated list of patterns to match the **charts** to be sent to prometheus. Each pattern can use `*` as wildcard, any number of times (e.g `*a*b*c*` is valid). Patterns starting with `!` give a negative match (e.g `!*.bad users.* groups.*` will send all the users and groups except `bad` user and `bad` group). The order is important: the first match (positive or negative) left to right, is used. +This settings accepts a space separated list of patterns to match the **charts** to be sent to prometheus. Each pattern +can use `*` as wildcard, any number of times (e.g `*a*b*c*` is valid). Patterns starting with `!` give a negative match +(e.g `!*.bad users.* groups.*` will send all the users and groups except `bad` user and `bad` group). The order is +important: the first match (positive or negative) left to right, is used. ### Changing the prefix of Netdata metrics Netdata sends all metrics prefixed with `netdata_`. You can change this in `netdata.conf`, like this: -``` +```conf [backend] prefix = netdata ``` @@ -379,16 +428,23 @@ It can also be changed from the URL, by appending `&prefix=netdata`. ### Metric Units -The default source `average` adds the unit of measurement to the name of each metric (e.g. `_KiB_persec`). -To hide the units and get the same metric names as with the other sources, append to the URL `&hideunits=yes`. +The default source `average` adds the unit of measurement to the name of each metric (e.g. `_KiB_persec`). To hide the +units and get the same metric names as with the other sources, append to the URL `&hideunits=yes`. -The units were standardized in v1.12, with the effect of changing the metric names. -To get the metric names as they were before v1.12, append to the URL `&oldunits=yes` +The units were standardized in v1.12, with the effect of changing the metric names. To get the metric names as they were +before v1.12, append to the URL `&oldunits=yes` ### Accuracy of `average` and `sum` data sources -When the data source is set to `average` or `sum`, Netdata remembers the last access of each client accessing prometheus metrics and uses this last access time to respond with the `average` or `sum` of all the entries in the database since that. This means that prometheus servers are not losing data when they access Netdata with data source = `average` or `sum`. +When the data source is set to `average` or `sum`, Netdata remembers the last access of each client accessing prometheus +metrics and uses this last access time to respond with the `average` or `sum` of all the entries in the database since +that. This means that prometheus servers are not losing data when they access Netdata with data source = `average` or +`sum`. -To uniquely identify each prometheus server, Netdata uses the IP of the client accessing the metrics. If however the IP is not good enough for identifying a single prometheus server (e.g. when prometheus servers are accessing Netdata through a web proxy, or when multiple prometheus servers are NATed to a single IP), each prometheus may append `&server=NAME` to the URL. This `NAME` is used by Netdata to uniquely identify each prometheus server and keep track of its last access time. +To uniquely identify each prometheus server, Netdata uses the IP of the client accessing the metrics. If however the IP +is not good enough for identifying a single prometheus server (e.g. when prometheus servers are accessing Netdata +through a web proxy, or when multiple prometheus servers are NATed to a single IP), each prometheus may append +`&server=NAME` to the URL. This `NAME` is used by Netdata to uniquely identify each prometheus server and keep track of +its last access time. [![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fbackends%2Fprometheus%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/backends/prometheus/remote_write/README.md b/backends/prometheus/remote_write/README.md index 8af6f4d1d..009ded608 100644 --- a/backends/prometheus/remote_write/README.md +++ b/backends/prometheus/remote_write/README.md @@ -2,26 +2,32 @@ ## Prerequisites -To use the prometheus remote write API with [storage providers](https://prometheus.io/docs/operating/integrations/#remote-endpoints-and-storage) [protobuf](https://developers.google.com/protocol-buffers/) and [snappy](https://github.com/google/snappy) libraries should be installed first. Next, Netdata should be re-installed from the source. The installer will detect that the required libraries and utilities are now available. +To use the prometheus remote write API with [storage +providers](https://prometheus.io/docs/operating/integrations/#remote-endpoints-and-storage) +[protobuf](https://developers.google.com/protocol-buffers/) and [snappy](https://github.com/google/snappy) libraries +should be installed first. Next, Netdata should be re-installed from the source. The installer will detect that the +required libraries and utilities are now available. ## Configuration An additional option in the backend configuration section is available for the remote write backend: -``` +```conf [backend] remote write URL path = /receive ``` -The default value is `/receive`. `remote write URL path` is used to set an endpoint path for the remote write protocol. For example, if your endpoint is `http://example.domain:example_port/storage/read` you should set +The default value is `/receive`. `remote write URL path` is used to set an endpoint path for the remote write protocol. +For example, if your endpoint is `http://example.domain:example_port/storage/read` you should set -``` +```conf [backend] destination = example.domain:example_port remote write URL path = /storage/read ``` -`buffered` and `lost` dimensions in the Netdata Backend Data Size operation monitoring chart estimate uncompressed buffer size on failures. +`buffered` and `lost` dimensions in the Netdata Backend Data Size operation monitoring chart estimate uncompressed +buffer size on failures. ## Notes diff --git a/collectors/Makefile.am b/collectors/Makefile.am index fe62ba01d..eaa1a7b8c 100644 --- a/collectors/Makefile.am +++ b/collectors/Makefile.am @@ -22,6 +22,7 @@ SUBDIRS = \ node.d.plugin \ proc.plugin \ python.d.plugin \ + slabinfo.plugin \ statsd.plugin \ tc.plugin \ $(NULL) diff --git a/collectors/README.md b/collectors/README.md index fe6939f63..6cfeb8d23 100644 --- a/collectors/README.md +++ b/collectors/README.md @@ -42,6 +42,7 @@ To minimize the number of processes spawn for data collection, Netdata also supp |[plugins.d](plugins.d/)|`C`|any|internal|-|implements the **external plugins** API and serves external plugins| |[proc.plugin](proc.plugin/)|`C`|linux|internal|yes|collects resource usage and performance data on Linux systems| |[python.d.plugin](python.d.plugin/)|`python` v2+|any|external|yes|a **plugin orchestrator** for data collection modules written in `python` v2 or v3 (both are supported).| +|[slabinfo.plugin](slabinfo.plugin/)|`C`|linux|external|-|collects kernel SLAB details on Linux systems| |[statsd.plugin](statsd.plugin/)|`C`|any|internal|-|implements a high performance **statsd** server for Netdata| |[tc.plugin](tc.plugin/)|`C`|linux|internal|-|collects traffic QoS metrics (`tc`) of Linux network interfaces| diff --git a/collectors/apps.plugin/apps_groups.conf b/collectors/apps.plugin/apps_groups.conf index ab167ddbb..9e3e8d77c 100644 --- a/collectors/apps.plugin/apps_groups.conf +++ b/collectors/apps.plugin/apps_groups.conf @@ -85,6 +85,7 @@ tc-qos-helper: *tc-qos-helper.sh* fping: fping ioping: ioping go.d.plugin: *go.d.plugin* +slabinfo.plugin: slabinfo.plugin # ----------------------------------------------------------------------------- # authentication/authorization related servers diff --git a/collectors/apps.plugin/apps_plugin.c b/collectors/apps.plugin/apps_plugin.c index 29d38bb41..4dcbd38b7 100644 --- a/collectors/apps.plugin/apps_plugin.c +++ b/collectors/apps.plugin/apps_plugin.c @@ -3521,7 +3521,7 @@ static void send_collected_data_to_netdata(struct target *root, const char *type send_BEGIN(type, "uptime_avg", dt); for (w = root; w ; w = w->next) { if(unlikely(w->exposed && w->processes)) - send_SET(w->name, w->processes?(w->uptime_sum / w->processes):0); + send_SET(w->name, w->uptime_sum / w->processes); } send_END(); diff --git a/collectors/cgroups.plugin/cgroup-name.sh.in b/collectors/cgroups.plugin/cgroup-name.sh.in index 784c06042..f7b765bb6 100755 --- a/collectors/cgroups.plugin/cgroup-name.sh.in +++ b/collectors/cgroups.plugin/cgroup-name.sh.in @@ -86,7 +86,7 @@ function k8s_get_name() { if command -v jq >/dev/null 2>&1; then NAME="$( curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" "https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/pods" | - jq -r '.items[] | "k8s_\(.metadata.namespace)_\(.metadata.name)_\(.metadata.uid)_\(.status.containerStatuses[0].name) \(.status.containerStatuses[0].containerID)"' | + jq -r '.items[] | "k8s_\(.metadata.namespace)_\(.metadata.name)_\(.metadata.uid)_" + (.status.containerStatuses[]? | "\(.name) \(.containerID)")' | grep "$id" | cut -d' ' -f1 )" diff --git a/collectors/cgroups.plugin/cgroup-network.c b/collectors/cgroups.plugin/cgroup-network.c index d4f990061..d01065422 100644 --- a/collectors/cgroups.plugin/cgroup-network.c +++ b/collectors/cgroups.plugin/cgroup-network.c @@ -230,7 +230,6 @@ static struct ns { }; int switch_namespace(const char *prefix, pid_t pid) { - if(!prefix) prefix = ""; #ifdef HAVE_SETNS diff --git a/collectors/charts.d.plugin/apache/README.md b/collectors/charts.d.plugin/apache/README.md index d5c7a80a9..53f02a5b8 100644 --- a/collectors/charts.d.plugin/apache/README.md +++ b/collectors/charts.d.plugin/apache/README.md @@ -26,7 +26,7 @@ It has been tested with apache 2.2 and apache 2.4. The latter also provides conn Apache 2.2 response: ```sh -$ curl "http://127.0.0.1/server-status?auto" +curl "http://127.0.0.1/server-status?auto" Total Accesses: 80057 Total kBytes: 223017 CPULoad: .018287 @@ -42,7 +42,7 @@ Scoreboard: _________________________......................................._W__ Apache 2.4 response: ```sh -$ curl "http://127.0.0.1/server-status?auto" +curl "http://127.0.0.1/server-status?auto" 127.0.0.1 ServerVersion: Apache/2.4.18 (Unix) ServerMPM: event diff --git a/collectors/freebsd.plugin/freebsd_sysctl.c b/collectors/freebsd.plugin/freebsd_sysctl.c index 402813fe0..271547ab3 100644 --- a/collectors/freebsd.plugin/freebsd_sysctl.c +++ b/collectors/freebsd.plugin/freebsd_sysctl.c @@ -470,7 +470,7 @@ int do_dev_cpu_temperature(int update_every, usec_t dt) { pcpu_temperature = reallocz(pcpu_temperature, sizeof(int) * number_of_cpus); mib = reallocz(mib, sizeof(int) * number_of_cpus * 4); if (unlikely(number_of_cpus > old_number_of_cpus)) - memset(&mib[old_number_of_cpus * 4], 0, sizeof(RRDDIM) * (number_of_cpus - old_number_of_cpus)); + memset(&mib[old_number_of_cpus * 4], 0, 4 * (number_of_cpus - old_number_of_cpus)); } for (i = 0; i < number_of_cpus; i++) { if (unlikely(!(mib[i * 4]))) diff --git a/collectors/node.d.plugin/snmp/README.md b/collectors/node.d.plugin/snmp/README.md index 8fd66edb7..c661bac8c 100644 --- a/collectors/node.d.plugin/snmp/README.md +++ b/collectors/node.d.plugin/snmp/README.md @@ -19,7 +19,7 @@ In this example: - the SNMP device is `10.11.12.8`. - the SNMP community is `public`. - we will update the values every 10 seconds (`update_every: 10` under the server `10.11.12.8`). -- we define 2 charts `snmp_switch.bandwidth_port1` and `snmp_switch.bandwidth_port2`, each having 2 dimensions: `in` and `out`. +- we define 2 charts `snmp_switch.bandwidth_port1` and `snmp_switch.bandwidth_port2`, each having 2 dimensions: `in` and `out`. Note that the charts and dimensions must not contain any white space or special characters, other than `.` and `_`. ```json { @@ -96,8 +96,8 @@ In this example: <details markdown="1"><summary><b>Caution: Counter64 metrics do not support `offset` (issue #5028).</b></summary> The SNMP plugin supports Counter64 metrics with the only limitation that the `offset` parameter should not be defined. Due to the way Javascript handles large numbers and the fact that the offset is applied to metrics inside the plugin, the offset will be ignored silently. -</details> -<br> +</details> + If you need to define many charts using incremental OIDs, you can use something like this: ```json @@ -356,8 +356,7 @@ This switch has a very slow SNMP processors. To respond, it needs about 8 second } } } - } - ] + }], } ``` diff --git a/collectors/plugins.d/README.md b/collectors/plugins.d/README.md index 225dfcc99..628e7d5c9 100644 --- a/collectors/plugins.d/README.md +++ b/collectors/plugins.d/README.md @@ -18,6 +18,7 @@ from external processes, thus allowing Netdata to use **external plugins**. |[perf.plugin](../perf.plugin/)|`C`|linux|collects CPU performance metrics using performance monitoring units (PMU).| |[node.d.plugin](../node.d.plugin/)|`node.js`|all|a **plugin orchestrator** for data collection modules written in `node.js`.| |[python.d.plugin](../python.d.plugin/)|`python`|all|a **plugin orchestrator** for data collection modules written in `python` v2 or v3 (both are supported).| +|[slabinfo.plugin](../slabinfo.plugin/)|`C`|linux|collects kernel internal cache objects (SLAB) metrics.| Plugin orchestrators may also be described as **modular plugins**. They are modular since they accept custom made modules to be included. Writing modules for these plugins is easier than accessing the native Netdata API directly. You will find modules already available for each orchestrator under the directory of the particular modular plugin (e.g. under python.d.plugin for the python orchestrator). Each of these modular plugins has each own methods for defining modules. Please check the examples and their documentation. diff --git a/collectors/proc.plugin/proc_mdstat.c b/collectors/proc.plugin/proc_mdstat.c index 5c29d31c7..abfd2ff12 100644 --- a/collectors/proc.plugin/proc_mdstat.c +++ b/collectors/proc.plugin/proc_mdstat.c @@ -197,7 +197,7 @@ int do_proc_mdstat(int update_every, usec_t dt) { }
s++;
}
- if(unlikely(str_total[0] == '\0' || str_inuse[0] == '\0')) {
+ if(unlikely(str_total[0] == '\0' || !str_inuse || str_inuse[0] == '\0')) {
error("Cannot read /proc/mdstat raid health status. Unexpected format.");
continue;
}
diff --git a/collectors/proc.plugin/sys_block_zram.c b/collectors/proc.plugin/sys_block_zram.c index a68a405de..170c72062 100644 --- a/collectors/proc.plugin/sys_block_zram.c +++ b/collectors/proc.plugin/sys_block_zram.c @@ -181,10 +181,14 @@ static inline int read_mm_stat(procfile *ff, MM_STAT *stats) { ff = procfile_readall(ff); if (!ff) return -1; - if (procfile_lines(ff) < 1) + if (procfile_lines(ff) < 1) { + procfile_close(ff); return -1; - if (procfile_linewords(ff, 0) < 7) + } + if (procfile_linewords(ff, 0) < 7) { + procfile_close(ff); return -1; + } stats->orig_data_size = str2ull(procfile_word(ff, 0)); stats->compr_data_size = str2ull(procfile_word(ff, 1)); diff --git a/collectors/proc.plugin/sys_class_power_supply.c b/collectors/proc.plugin/sys_class_power_supply.c index 5e37ad5ab..c558a384d 100644 --- a/collectors/proc.plugin/sys_class_power_supply.c +++ b/collectors/proc.plugin/sys_class_power_supply.c @@ -245,67 +245,75 @@ int do_sys_class_power_supply(int update_every, usec_t dt) { if(unlikely(ps->capacity->fd == -1)) { error("Cannot open file '%s'", ps->capacity->filename); power_supply_free(ps); + ps = NULL; } } - ssize_t r = read(ps->capacity->fd, buffer, 30); - if(unlikely(r < 1)) { - error("Cannot read file '%s'", ps->capacity->filename); - power_supply_free(ps); - } - else { - buffer[r] = '\0'; - ps->capacity->value = str2ull(buffer); - } + if (ps) + { + ssize_t r = read(ps->capacity->fd, buffer, 30); + if(unlikely(r < 1)) { + error("Cannot read file '%s'", ps->capacity->filename); + power_supply_free(ps); + ps = NULL; + } + else { + buffer[r] = '\0'; + ps->capacity->value = str2ull(buffer); - if(unlikely(!keep_fds_open)) { - close(ps->capacity->fd); - ps->capacity->fd = -1; - } - else if(unlikely(lseek(ps->capacity->fd, 0, SEEK_SET) == -1)) { - error("Cannot seek in file '%s'", ps->capacity->filename); - close(ps->capacity->fd); - ps->capacity->fd = -1; + if(unlikely(!keep_fds_open)) { + close(ps->capacity->fd); + ps->capacity->fd = -1; + } + else if(unlikely(lseek(ps->capacity->fd, 0, SEEK_SET) == -1)) { + error("Cannot seek in file '%s'", ps->capacity->filename); + close(ps->capacity->fd); + ps->capacity->fd = -1; + } + } } } // read property files int read_error = 0; struct ps_property *pr; - for(pr = ps->property_root; pr && !read_error; pr = pr->next) { - struct ps_property_dim *pd; - for(pd = pr->property_dim_root; pd; pd = pd->next) { - if(likely(!pd->always_zero)) { - char buffer[30 + 1]; - - if(unlikely(pd->fd == -1)) { - pd->fd = open(pd->filename, O_RDONLY, 0666); + if (ps) + { + for(pr = ps->property_root; pr && !read_error; pr = pr->next) { + struct ps_property_dim *pd; + for(pd = pr->property_dim_root; pd; pd = pd->next) { + if(likely(!pd->always_zero)) { + char buffer[30 + 1]; + if(unlikely(pd->fd == -1)) { - error("Cannot open file '%s'", pd->filename); + pd->fd = open(pd->filename, O_RDONLY, 0666); + if(unlikely(pd->fd == -1)) { + error("Cannot open file '%s'", pd->filename); + read_error = 1; + power_supply_free(ps); + break; + } + } + + ssize_t r = read(pd->fd, buffer, 30); + if(unlikely(r < 1)) { + error("Cannot read file '%s'", pd->filename); read_error = 1; power_supply_free(ps); break; } - } - - ssize_t r = read(pd->fd, buffer, 30); - if(unlikely(r < 1)) { - error("Cannot read file '%s'", pd->filename); - read_error = 1; - power_supply_free(ps); - break; - } - buffer[r] = '\0'; - pd->value = str2ull(buffer); + buffer[r] = '\0'; + pd->value = str2ull(buffer); - if(unlikely(!keep_fds_open)) { - close(pd->fd); - pd->fd = -1; - } - else if(unlikely(lseek(pd->fd, 0, SEEK_SET) == -1)) { - error("Cannot seek in file '%s'", pd->filename); - close(pd->fd); - pd->fd = -1; + if(unlikely(!keep_fds_open)) { + close(pd->fd); + pd->fd = -1; + } + else if(unlikely(lseek(pd->fd, 0, SEEK_SET) == -1)) { + error("Cannot seek in file '%s'", pd->filename); + close(pd->fd); + pd->fd = -1; + } } } } diff --git a/collectors/python.d.plugin/Makefile.am b/collectors/python.d.plugin/Makefile.am index ad72cfaef..7d087fbfd 100644 --- a/collectors/python.d.plugin/Makefile.am +++ b/collectors/python.d.plugin/Makefile.am @@ -54,6 +54,7 @@ include example/Makefile.inc include exim/Makefile.inc include fail2ban/Makefile.inc include freeradius/Makefile.inc +include gearman/Makefile.inc include go_expvar/Makefile.inc include haproxy/Makefile.inc include hddtemp/Makefile.inc diff --git a/collectors/python.d.plugin/README.md b/collectors/python.d.plugin/README.md index d0074a124..f38ab6783 100644 --- a/collectors/python.d.plugin/README.md +++ b/collectors/python.d.plugin/README.md @@ -223,12 +223,12 @@ This is a generic checklist for submitting a new Python plugin for Netdata. It At minimum, to be buildable and testable, the PR needs to include: -- The module itself, following proper naming conventions: `python.d/<module_dir>/<module_name>.chart.py` -- A README.md file for the plugin under `python.d/<module_dir>`. -- The configuration file for the module: `conf.d/python.d/<module_name>.conf`. Python config files are in YAML format, and should include comments describing what options are present. The instructions are also needed in the configuration section of the README.md -- A basic configuration for the plugin in the appropriate global config file: `conf.d/python.d.conf`, which is also in YAML format. Either add a line that reads `# <module_name>: yes` if the module is to be enabled by default, or one that reads `<module_name>: no` if it is to be disabled by default. -- A line for the plugin in `python.d/Makefile.am` under `dist_python_DATA`. -- A line for the plugin configuration file in `conf.d/Makefile.am`, under `dist_pythonconfig_DATA` -- Optionally, chart information in `web/dashboard_info.js`. This generally involves specifying a name and icon for the section, and may include descriptions for the section or individual charts. +- The module itself, following proper naming conventions: `collectors/python.d.plugin/<module_dir>/<module_name>.chart.py` +- A README.md file for the plugin under `collectors/python.d.plugin/<module_dir>`. +- The configuration file for the module: `collectors/python.d.plugin/<module_dir>/<module_name>.conf`. Python config files are in YAML format, and should include comments describing what options are present. The instructions are also needed in the configuration section of the README.md +- A basic configuration for the plugin in the appropriate global config file: `collectors/python.d.plugin/python.d.conf`, which is also in YAML format. Either add a line that reads `# <module_name>: yes` if the module is to be enabled by default, or one that reads `<module_name>: no` if it is to be disabled by default. +- A makefile for the plugin at `collectors/python.d.plugin/<module_dir>/Makefile.inc`. Check an existing plugin for what this should look like. +- A line in `collectors/python.d.plugin/Makefile.am` including the above-mentioned makefile. Place it with the other plugin includes (please keep the includes sorted alphabetically). +- Optionally, chart information in `web/gui/dashboard_info.js`. This generally involves specifying a name and icon for the section, and may include descriptions for the section or individual charts. [![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fpython.d.plugin%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/collectors/python.d.plugin/dnsdist/README.md b/collectors/python.d.plugin/dnsdist/README.md index fecf4a5d8..4310fe28a 100644 --- a/collectors/python.d.plugin/dnsdist/README.md +++ b/collectors/python.d.plugin/dnsdist/README.md @@ -1,8 +1,8 @@ # dnsdist -Module monitor dnsdist performance and health metrics. +This module monitors dnsdist performance and health metrics. -Following charts are drawn: +The module draws the following charts: 1. **Response latency** @@ -45,7 +45,7 @@ Following charts are drawn: - servfail-responses - trunc-failures -## configuration +## Configuration ```yaml localhost: @@ -57,6 +57,4 @@ localhost: X-API-Key: 'dnsdist-api-key' ``` ---- - [![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fpython.d.plugin%2Fdnsdist%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/collectors/python.d.plugin/elasticsearch/README.md b/collectors/python.d.plugin/elasticsearch/README.md index a719a9431..211dfabfa 100644 --- a/collectors/python.d.plugin/elasticsearch/README.md +++ b/collectors/python.d.plugin/elasticsearch/README.md @@ -1,6 +1,6 @@ # elasticsearch -This module monitors Elasticsearch performance and health metrics. +This module monitors [Elasticsearch](https://www.elastic.co/products/elasticsearch) performance and health metrics. It produces: @@ -51,19 +51,28 @@ It produces: - Store statistics - Indices and shards statistics +9. **Indices** charts (per index statistics, disabled by default): + + - Docs count + - Store size + - Num of replicas + - Health status + ## configuration Sample: ```yaml local: - host : 'ipaddress' # Elasticsearch server ip address or hostname - port : 'port' # Port on which elasticsearch listens - cluster_health : True/False # Calls to cluster health elasticsearch API. Enabled by default. - cluster_stats : True/False # Calls to cluster stats elasticsearch API. Enabled by default. + host : 'ipaddress' # Elasticsearch server ip address or hostname. + port : 'port' # Port on which elasticsearch listens. + node_status : yes/no # Get metrics from "/_nodes/_local/stats". Enabled by default. + cluster_health : yes/no # Get metrics from "/_cluster/health". Enabled by default. + cluster_stats : yes/no # Get metrics from "'/_cluster/stats". Enabled by default. + indices_stats : yes/no # Get metrics from "/_cat/indices". Disabled by default. ``` -If no configuration is given, module will fail to run. +If no configuration is given, module will try to connect to `http://127.0.0.1:9200`. --- diff --git a/collectors/python.d.plugin/elasticsearch/elasticsearch.chart.py b/collectors/python.d.plugin/elasticsearch/elasticsearch.chart.py index 20109c64f..8aaa08583 100644 --- a/collectors/python.d.plugin/elasticsearch/elasticsearch.chart.py +++ b/collectors/python.d.plugin/elasticsearch/elasticsearch.chart.py @@ -168,6 +168,10 @@ ORDER = [ 'cluster_stats_store', 'cluster_stats_indices', 'cluster_stats_shards_total', + 'index_docs_count', + 'index_store_size', + 'index_replica', + 'index_health', ] CHARTS = { @@ -196,7 +200,8 @@ CHARTS = { ] }, 'search_latency': { - 'options': [None, 'Query And Fetch Latency', 'milliseconds', 'search performance', 'elastic.search_latency', 'stacked'], + 'options': [None, 'Query And Fetch Latency', 'milliseconds', 'search performance', 'elastic.search_latency', + 'stacked'], 'lines': [ ['query_latency', 'query', 'absolute', 1, 1000], ['fetch_latency', 'fetch', 'absolute', 1, 1000] @@ -397,9 +402,6 @@ CHARTS = { 'lines': [ ['status_green', 'green', 'absolute'], ['status_red', 'red', 'absolute'], - ['status_foo1', None, 'absolute'], - ['status_foo2', None, 'absolute'], - ['status_foo3', None, 'absolute'], ['status_yellow', 'yellow', 'absolute'] ] }, @@ -483,10 +485,61 @@ CHARTS = { 'lines': [ ['http_current_open', 'opened', 'absolute', 1, 1] ] - } + }, + 'index_docs_count': { + 'options': [None, 'Docs Count', 'count', 'indices', 'elastic.index_docs', 'line'], + 'lines': [] + }, + 'index_store_size': { + 'options': [None, 'Store Size', 'bytes', 'indices', 'elastic.index_store_size', 'line'], + 'lines': [] + }, + 'index_replica': { + 'options': [None, 'Replica', 'count', 'indices', 'elastic.index_replica', 'line'], + 'lines': [] + }, + 'index_health': { + 'options': [None, 'Health', 'status', 'indices', 'elastic.index_health', 'line'], + 'lines': [] + }, } +def convert_index_store_size_to_bytes(size): + # can be b, kb, mb, gb + if size.endswith('kb'): + return round(float(size[:-2]) * 1024) + elif size.endswith('mb'): + return round(float(size[:-2]) * 1024 * 1024) + elif size.endswith('gb'): + return round(float(size[:-2]) * 1024 * 1024 * 1024) + elif size.endswith('b'): + return round(float(size[:-1])) + return -1 + + +def convert_index_health(health): + if health == 'green': + return 0 + elif health == 'yellow': + return 1 + elif health == 'read': + return 2 + return -1 + + +def get_survive_any(method): + def w(*args): + try: + method(*args) + except Exception as error: + self, queue, url = args[0], args[1], args[2] + self.error("error during '{0}' : {1}".format(url, error)) + queue.put(dict()) + + return w + + class Service(UrlService): def __init__(self, configuration=None, name=None): UrlService.__init__(self, configuration=configuration, name=name) @@ -501,34 +554,41 @@ class Service(UrlService): ) self.latency = dict() self.methods = list() + self.collected_indices = set() def check(self): - if not all([self.host, - self.port, - isinstance(self.host, str), - isinstance(self.port, (str, int))]): + if not self.host: self.error('Host is not defined in the module configuration file') return False - # Hostname -> ip address try: self.host = gethostbyname(self.host) except gaierror as error: - self.error(str(error)) + self.error(repr(error)) return False - # Create URL for every Elasticsearch API - self.methods = [METHODS(get_data=self._get_node_stats, - url=self.url + '/_nodes/_local/stats', - run=self.configuration.get('node_stats', True)), - METHODS(get_data=self._get_cluster_health, - url=self.url + '/_cluster/health', - run=self.configuration.get('cluster_health', True)), - METHODS(get_data=self._get_cluster_stats, - url=self.url + '/_cluster/stats', - run=self.configuration.get('cluster_stats', True))] - - # Remove disabled API calls from 'avail methods' + self.methods = [ + METHODS( + get_data=self._get_node_stats, + url=self.url + '/_nodes/_local/stats', + run=self.configuration.get('node_stats', True), + ), + METHODS( + get_data=self._get_cluster_health, + url=self.url + '/_cluster/health', + run=self.configuration.get('cluster_health', True) + ), + METHODS( + get_data=self._get_cluster_stats, + url=self.url + '/_cluster/stats', + run=self.configuration.get('cluster_stats', True), + ), + METHODS( + get_data=self._get_indices, + url=self.url + '/_cat/indices?format=json', + run=self.configuration.get('indices_stats', False), + ), + ] return UrlService.check(self) def _get_data(self): @@ -539,8 +599,11 @@ class Service(UrlService): for method in self.methods: if not method.run: continue - th = threading.Thread(target=method.get_data, - args=(queue, method.url)) + th = threading.Thread( + target=method.get_data, + args=(queue, method.url), + ) + th.daemon = True th.start() threads.append(th) @@ -550,88 +613,128 @@ class Service(UrlService): return result or None - def _get_cluster_health(self, queue, url): - """ - Format data received from http request - :return: dict - """ - + def add_index_to_charts(self, idx_name): + for name in ('index_docs_count', 'index_store_size', 'index_replica', 'index_health'): + chart = self.charts[name] + dim = ['{0}_{1}'.format(idx_name, name), idx_name] + chart.add_dimension(dim) + + @get_survive_any + def _get_indices(self, queue, url): + # [ + # { + # "pri.store.size": "650b", + # "health": "yellow", + # "status": "open", + # "index": "twitter", + # "pri": "5", + # "rep": "1", + # "docs.count": "10", + # "docs.deleted": "3", + # "store.size": "650b" + # } + # ] raw_data = self._get_raw_data(url) - if not raw_data: return queue.put(dict()) - data = self.json_reply(raw_data) - - if not data: + indices = self.json_parse(raw_data) + if not indices: return queue.put(dict()) - to_netdata = fetch_data_(raw_data=data, - metrics=HEALTH_STATS) + charts_initialized = len(self.charts) != 0 + data = dict() + for idx in indices: + try: + name = idx['index'] + is_system_index = name.startswith('.') + if is_system_index: + continue + + v = { + '{0}_index_docs_count'.format(name): idx['docs.count'], + '{0}_index_replica'.format(name): idx['rep'], + '{0}_index_health'.format(name): convert_index_health(idx['health']), + } + size = convert_index_store_size_to_bytes(idx['store.size']) + if size != -1: + v['{0}_index_store_size'.format(name)] = size + except KeyError as error: + self.debug("error on parsing index : {0}".format(repr(error))) + continue - to_netdata.update({'status_green': 0, 'status_red': 0, 'status_yellow': 0, - 'status_foo1': 0, 'status_foo2': 0, 'status_foo3': 0}) - current_status = 'status_' + data['status'] - to_netdata[current_status] = 1 + data.update(v) + if name not in self.collected_indices and charts_initialized: + self.collected_indices.add(name) + self.add_index_to_charts(name) - return queue.put(to_netdata) + return queue.put(data) - def _get_cluster_stats(self, queue, url): - """ - Format data received from http request - :return: dict - """ - - raw_data = self._get_raw_data(url) + @get_survive_any + def _get_cluster_health(self, queue, url): + raw = self._get_raw_data(url) + if not raw: + return queue.put(dict()) - if not raw_data: + parsed = self.json_parse(raw) + if not parsed: return queue.put(dict()) - data = self.json_reply(raw_data) + data = fetch_data(raw_data=parsed, metrics=HEALTH_STATS) + dummy = { + 'status_green': 0, + 'status_red': 0, + 'status_yellow': 0, + } + data.update(dummy) + current_status = 'status_' + parsed['status'] + data[current_status] = 1 - if not data: - return queue.put(dict()) + return queue.put(data) - to_netdata = fetch_data_(raw_data=data, - metrics=CLUSTER_STATS) + @get_survive_any + def _get_cluster_stats(self, queue, url): + raw = self._get_raw_data(url) + if not raw: + return queue.put(dict()) - return queue.put(to_netdata) + parsed = self.json_parse(raw) + if not parsed: + return queue.put(dict()) - def _get_node_stats(self, queue, url): - """ - Format data received from http request - :return: dict - """ + data = fetch_data(raw_data=parsed, metrics=CLUSTER_STATS) - raw_data = self._get_raw_data(url) + return queue.put(data) - if not raw_data: + @get_survive_any + def _get_node_stats(self, queue, url): + raw = self._get_raw_data(url) + if not raw: return queue.put(dict()) - data = self.json_reply(raw_data) - - if not data: + parsed = self.json_parse(raw) + if not parsed: return queue.put(dict()) - node = list(data['nodes'].keys())[0] - to_netdata = fetch_data_(raw_data=data['nodes'][node], - metrics=NODE_STATS) + node = list(parsed['nodes'].keys())[0] + data = fetch_data(raw_data=parsed['nodes'][node], metrics=NODE_STATS) # Search, index, flush, fetch performance latency for key in LATENCY: try: - to_netdata[key] = self.find_avg(total=to_netdata[LATENCY[key]['total']], - spent_time=to_netdata[LATENCY[key]['spent_time']], - key=key) + data[key] = self.find_avg( + total=data[LATENCY[key]['total']], + spent_time=data[LATENCY[key]['spent_time']], + key=key) except KeyError: continue - if 'process_open_file_descriptors' in to_netdata and 'process_max_file_descriptors' in to_netdata: - to_netdata['file_descriptors_used'] = round(float(to_netdata['process_open_file_descriptors']) - / to_netdata['process_max_file_descriptors'] * 1000) + if 'process_open_file_descriptors' in data and 'process_max_file_descriptors' in data: + v = float(data['process_open_file_descriptors']) / data['process_max_file_descriptors'] * 1000 + data['file_descriptors_used'] = round(v) - return queue.put(to_netdata) + return queue.put(data) - def json_reply(self, reply): + def json_parse(self, reply): try: return json.loads(reply) except ValueError as err: @@ -640,20 +743,22 @@ class Service(UrlService): def find_avg(self, total, spent_time, key): if key not in self.latency: - self.latency[key] = dict(total=total, - spent_time=spent_time) + self.latency[key] = dict(total=total, spent_time=spent_time) return 0 + if self.latency[key]['total'] != total: - latency = float(spent_time - self.latency[key]['spent_time'])\ - / float(total - self.latency[key]['total']) * 1000 + spent_diff = spent_time - self.latency[key]['spent_time'] + total_diff = total - self.latency[key]['total'] + latency = float(spent_diff) / float(total_diff) * 1000 self.latency[key]['total'] = total self.latency[key]['spent_time'] = spent_time return latency + self.latency[key]['spent_time'] = spent_time return 0 -def fetch_data_(raw_data, metrics): +def fetch_data(raw_data, metrics): data = dict() for metric in metrics: value = raw_data @@ -661,7 +766,7 @@ def fetch_data_(raw_data, metrics): try: for m in metrics_list: value = value[m] - except KeyError: + except (KeyError, TypeError): continue data['_'.join(metrics_list)] = value return data diff --git a/collectors/python.d.plugin/elasticsearch/elasticsearch.conf b/collectors/python.d.plugin/elasticsearch/elasticsearch.conf index 5d8e746f5..4058debac 100644 --- a/collectors/python.d.plugin/elasticsearch/elasticsearch.conf +++ b/collectors/python.d.plugin/elasticsearch/elasticsearch.conf @@ -61,11 +61,12 @@ # # Additionally to the above, elasticsearch plugin also supports the following: # -# host: 'ipaddress' # Server ip address or hostname. -# port: 'port' # Port on which elasticsearch listen. -# scheme: 'scheme' # URL scheme. Default is 'http'. -# cluster_health: False/True # Calls to cluster health elasticsearch API. Enabled by default. -# cluster_stats: False/True # Calls to cluster stats elasticsearch API. Enabled by default. +# host : 'ipaddress' # Elasticsearch server ip address or hostname. +# port : 'port' # Port on which elasticsearch listens. +# node_status : yes/no # Get metrics from "/_nodes/_local/stats". Enabled by default. +# cluster_health : yes/no # Get metrics from "/_cluster/health". Enabled by default. +# cluster_stats : yes/no # Get metrics from "'/_cluster/stats". Enabled by default. +# indices_stats : yes/no # Get metrics from "/_cat/indices". Disabled by default. # # # if the URL is password protected, the following are supported: diff --git a/collectors/python.d.plugin/gearman/Makefile.inc b/collectors/python.d.plugin/gearman/Makefile.inc new file mode 100644 index 000000000..97ce8d201 --- /dev/null +++ b/collectors/python.d.plugin/gearman/Makefile.inc @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# THIS IS NOT A COMPLETE Makefile +# IT IS INCLUDED BY ITS PARENT'S Makefile.am +# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT + +# install these files +dist_python_DATA += gearman/gearman.chart.py +dist_pythonconfig_DATA += gearman/gearman.conf + +# do not install these files, but include them in the distribution +dist_noinst_DATA += gearman/README.md gearman/Makefile.inc diff --git a/collectors/python.d.plugin/gearman/README.md b/collectors/python.d.plugin/gearman/README.md new file mode 100644 index 000000000..cbb4da3e2 --- /dev/null +++ b/collectors/python.d.plugin/gearman/README.md @@ -0,0 +1,39 @@ +# Gearman + +Module monitors Gearman worker statistics. A chart +is shown for each job as well as one showing a summary +of all workers. + +Note: Charts may show as a line graph rather than an area +graph if you load Netdata with no jobs running. To change +this go to "Settings" > "Which dimensions to show?" and +select "All". + +Plugin can obtain data from tcp socket **OR** unix socket. + +**Requirement:** +Socket MUST be readable by netdata user. + +It produces: + + * Workers queued + * Workers idle + * Workers running + +### configuration + +```yaml +localhost: + name : 'local' + host : 'localhost' + port : 4730 + + # TLS information can be provided as well + tls : no + cert : /path/to/cert + key : /path/to/key +``` + +When no configuration file is found, module tries to connect to TCP/IP socket: `localhost:4730`. + +--- diff --git a/collectors/python.d.plugin/gearman/gearman.chart.py b/collectors/python.d.plugin/gearman/gearman.chart.py new file mode 100644 index 000000000..26f3533c4 --- /dev/null +++ b/collectors/python.d.plugin/gearman/gearman.chart.py @@ -0,0 +1,229 @@ +# Description: dovecot netdata python.d module +# Author: Kyle Agronick (agronick) +# SPDX-License-Identifier: GPL-3.0+ + +# Gearman Netdata Plugin + +from bases.FrameworkServices.SocketService import SocketService +from copy import deepcopy + + +CHARTS = { + 'total_workers': { + 'options': [None, 'Total Jobs', 'Jobs', 'Total Jobs', 'gearman.total_jobs', 'line'], + 'lines': [ + ['total_pending', 'Pending', 'absolute'], + ['total_running', 'Running', 'absolute'], + ] + }, +} + + +def job_chart_template(job_name): + return { + 'options': [None, job_name, 'Jobs', 'Activity by Job', 'gearman.single_job', 'stacked'], + 'lines': [ + ['{0}_pending'.format(job_name), 'Pending', 'absolute'], + ['{0}_idle'.format(job_name), 'Idle', 'absolute'], + ['{0}_running'.format(job_name), 'Running', 'absolute'], + ] + } + +def build_result_dict(job): + """ + Get the status for each job + :return: dict + """ + + total, running, available = job['metrics'] + + idle = available - running + pending = total - running + + return { + '{0}_pending'.format(job['job_name']): pending, + '{0}_idle'.format(job['job_name']): idle, + '{0}_running'.format(job['job_name']): running, + } + +def parse_worker_data(job): + job_name = job[0] + job_metrics = job[1:] + + return { + 'job_name': job_name, + 'metrics': job_metrics, + } + + +class GearmanReadException(BaseException): + pass + + +class Service(SocketService): + def __init__(self, configuration=None, name=None): + super(Service, self).__init__(configuration=configuration, name=name) + self.request = "status\n" + self._keep_alive = True + + self.host = self.configuration.get('host', 'localhost') + self.port = self.configuration.get('port', 4730) + + self.tls = self.configuration.get('tls', False) + self.cert = self.configuration.get('cert', None) + self.key = self.configuration.get('key', None) + + self.active_jobs = set() + self.definitions = deepcopy(CHARTS) + self.order = ['total_workers'] + + def _get_data(self): + """ + Format data received from socket + :return: dict + """ + + try: + active_jobs = self.get_active_jobs() + except GearmanReadException: + return None + + found_jobs, job_data = self.process_jobs(active_jobs) + self.remove_stale_jobs(found_jobs) + return job_data + + def get_active_jobs(self): + active_jobs = [] + + for job in self.get_worker_data(): + parsed_job = parse_worker_data(job) + + # Gearman does not clean up old jobs + # We only care about jobs that have + # some relevant data + if not any(parsed_job['metrics']): + continue + + active_jobs.append(parsed_job) + + return active_jobs + + def get_worker_data(self): + """ + Split the data returned from Gearman + into a list of lists + + This returns the same output that you + would get from a gearadmin --status + command. + + Example output returned from + _get_raw_data(): + generic_worker2 78 78 500 + generic_worker3 0 0 760 + generic_worker1 0 0 500 + + :return: list + """ + + try: + raw = self._get_raw_data() + except (ValueError, AttributeError): + raise GearmanReadException() + + if raw is None: + self.debug("Gearman returned no data") + raise GearmanReadException() + + job_lines = raw.splitlines()[:-1] + job_lines = [job.split() for job in sorted(job_lines)] + + for line in job_lines: + line[1:] = map(int, line[1:]) + + return job_lines + + def process_jobs(self, active_jobs): + + output = { + 'total_pending': 0, + 'total_idle': 0, + 'total_running': 0, + } + found_jobs = set() + + for parsed_job in active_jobs: + + job_name = self.add_job(parsed_job) + found_jobs.add(job_name) + job_data = build_result_dict(parsed_job) + + for sum_value in ('pending', 'running', 'idle'): + output['total_{0}'.format(sum_value)] += job_data['{0}_{1}'.format(job_name, sum_value)] + + output.update(job_data) + + return found_jobs, output + + def remove_stale_jobs(self, active_job_list): + """ + Removes jobs that have no workers, pending jobs, + or running jobs + :param active_job_list: The latest list of active jobs + :type active_job_list: iterable + :return: None + """ + + for to_remove in self.active_jobs - active_job_list: + self.remove_job(to_remove) + + def add_job(self, parsed_job): + """ + Adds a job to the list of active jobs + :param parsed_job: A parsed job dict + :type parsed_job: dict + :return: None + """ + + def add_chart(job_name): + """ + Adds a new job chart + :param job_name: The name of the job to add + :type job_name: string + :return: None + """ + + job_key = 'job_{0}'.format(job_name) + template = job_chart_template(job_name) + new_chart = self.charts.add_chart([job_key] + template['options']) + for dimension in template['lines']: + new_chart.add_dimension(dimension) + + if parsed_job['job_name'] not in self.active_jobs: + add_chart(parsed_job['job_name']) + self.active_jobs.add(parsed_job['job_name']) + + return parsed_job['job_name'] + + def remove_job(self, job_name): + """ + Removes a job to the list of active jobs + :param job_name: The name of the job to remove + :type job_name: string + :return: None + """ + + def remove_chart(job_name): + """ + Removes a job chart + :param job_name: The name of the job to remove + :type job_name: string + :return: None + """ + + job_key = 'job_{0}'.format(job_name) + self.charts[job_key].obsolete() + del self.charts[job_key] + + remove_chart(job_name) + self.active_jobs.remove(job_name) diff --git a/collectors/python.d.plugin/gearman/gearman.conf b/collectors/python.d.plugin/gearman/gearman.conf new file mode 100644 index 000000000..c41fd9ffd --- /dev/null +++ b/collectors/python.d.plugin/gearman/gearman.conf @@ -0,0 +1,72 @@ +# netdata python.d.plugin configuration for gearman +# +# This file is in YaML format. Generally the format is: +# +# name: value +# +# There are 2 sections: +# - global variables +# - one or more JOBS +# +# JOBS allow you to collect values from multiple sources. +# Each source will have its own set of charts. +# +# JOB parameters have to be indented (using spaces only, example below). + +# ---------------------------------------------------------------------- +# Global Variables +# These variables set the defaults for all JOBs, however each JOB +# may define its own, overriding the defaults. + +# update_every sets the default data collection frequency. +# If unset, the python.d.plugin default is used. +# update_every: 1 + +# priority controls the order of charts at the netdata dashboard. +# Lower numbers move the charts towards the top of the page. +# If unset, the default for python.d.plugin is used. +# priority: 60000 + +# penalty indicates whether to apply penalty to update_every in case of failures. +# Penalty will increase every 5 failed updates in a row. Maximum penalty is 10 minutes. +# penalty: yes + +# autodetection_retry sets the job re-check interval in seconds. +# The job is not deleted if check fails. +# Attempts to start the job are made once every autodetection_retry. +# This feature is disabled by default. +# autodetection_retry: 0 + +# ---------------------------------------------------------------------- +# JOBS (data collection sources) +# +# The default JOBS share the same *name*. JOBS with the same name +# are mutually exclusive. Only one of them will be allowed running at +# any time. This allows autodetection to try several alternatives and +# pick the one that works. +# +# Any number of jobs is supported. +# +# All python.d.plugin JOBS (for all its modules) support a set of +# predefined parameters. These are: +# +# job_name: +# name: myname # the JOB's name as it will appear at the +# # dashboard (by default is the job_name) +# # JOBs sharing a name are mutually exclusive +# update_every: 1 # the JOB's data collection frequency +# priority: 60000 # the JOB's order on the dashboard +# penalty: yes # the JOB's penalty +# autodetection_retry: 0 # the JOB's re-check interval in seconds +# +# Additionally to the above, gearman also supports the following: +# +# hostname: localhost # The host running the Gearman server +# port: 4730 # Port of the Gearman server +# ---------------------------------------------------------------------- +# AUTO-DETECTION JOB + +localhost: + name : 'local' + host : 'localhost' + port : 4730
\ No newline at end of file diff --git a/collectors/python.d.plugin/mysql/README.md b/collectors/python.d.plugin/mysql/README.md index 45f842d42..037153220 100644 --- a/collectors/python.d.plugin/mysql/README.md +++ b/collectors/python.d.plugin/mysql/README.md @@ -241,12 +241,12 @@ It will produce following charts (if data is available): - sql - io -42. **Replicated Writesets** in writesets/s +42. **Galera Replicated Writesets** in writesets/s - rx - tx -43. **Replicated Bytes** in KiB/s +43. **Galera Replicated Bytes** in KiB/s - rx - tx @@ -256,16 +256,48 @@ It will produce following charts (if data is available): - rx - tx -45. **Replication Conflicts** in transactions +45. **Galera Replication Conflicts** in transactions - bf aborts - cert fails -46. **Flow Control** in ms +46. **Galera Flow Control** in ms - paused -47. **Users CPU time** in percentage +47. **Galera Cluster Status** in status + + - status + +48. **Galera Cluster State** in state + + - state + +49. **Galera Number of Nodes in the Cluster** in num + + - nodes + +50. **Galera Total Weight of the Current Members in the Cluster** in weight + + - weight + +51. **Galera Whether the Node is Connected to the Cluster** in boolean + + - connected + +52. **Galera Whether the Node is Ready to Accept Queries** in boolean + + - ready + +53. **Galera Open Transactions** in num + + - open transactions + +54. **Galera Total Number of WSRep (applier/rollbacker) Threads** in num + + - threads + +55. **Users CPU time** in percentage - users diff --git a/collectors/python.d.plugin/mysql/mysql.chart.py b/collectors/python.d.plugin/mysql/mysql.chart.py index 46d0712fb..f37315479 100644 --- a/collectors/python.d.plugin/mysql/mysql.chart.py +++ b/collectors/python.d.plugin/mysql/mysql.chart.py @@ -117,6 +117,14 @@ GLOBAL_STATS = [ 'Connection_errors_peer_address', 'Connection_errors_select', 'Connection_errors_tcpwrap', + 'Com_delete', + 'Com_insert', + 'Com_select', + 'Com_update', + 'Com_replace' +] + +GALERA_STATS = [ 'wsrep_local_recv_queue', 'wsrep_local_send_queue', 'wsrep_received', @@ -126,11 +134,14 @@ GLOBAL_STATS = [ 'wsrep_local_bf_aborts', 'wsrep_local_cert_failures', 'wsrep_flow_control_paused_ns', - 'Com_delete', - 'Com_insert', - 'Com_select', - 'Com_update', - 'Com_replace' + 'wsrep_cluster_weight', + 'wsrep_cluster_size', + 'wsrep_cluster_status', + 'wsrep_local_state', + 'wsrep_open_transactions', + 'wsrep_connected', + 'wsrep_ready', + 'wsrep_thread_count' ] @@ -216,7 +227,15 @@ ORDER = [ 'galera_queue', 'galera_conflicts', 'galera_flow_control', - 'userstats_cpu' + 'galera_cluster_status', + 'galera_cluster_state', + 'galera_cluster_size', + 'galera_cluster_weight', + 'galera_connected', + 'galera_ready', + 'galera_open_transactions', + 'galera_thread_count', + 'userstats_cpu', ] CHARTS = { @@ -594,6 +613,58 @@ CHARTS = { ['wsrep_flow_control_paused_ns', 'paused', 'incremental', 1, 1000000], ] }, + 'galera_cluster_status': { + 'options': [None, 'Cluster Component Status', 'status', 'galera', 'mysql.galera_cluster_status', 'line'], + 'lines': [ + ['wsrep_cluster_status', 'status', 'absolute'], + ] + }, + 'galera_cluster_state': { + 'options': [None, 'Cluster Component State', 'state', 'galera', 'mysql.galera_cluster_state', 'line'], + 'lines': [ + ['wsrep_local_state', 'state', 'absolute'], + ] + }, + 'galera_cluster_size': { + 'options': [None, 'Number of Nodes in the Cluster', 'num', 'galera', 'mysql.galera_cluster_size', 'line'], + 'lines': [ + ['wsrep_cluster_size', 'nodes', 'absolute'], + ] + }, + 'galera_cluster_weight': { + 'options': [None, 'The Total Weight of the Current Members in the Cluster', 'weight', 'galera', + 'mysql.galera_cluster_weight', 'line'], + 'lines': [ + ['wsrep_cluster_weight', 'weight', 'absolute'], + ] + }, + 'galera_connected': { + 'options': [None, 'Whether the Node is Connected to the Cluster', 'boolean', 'galera', + 'mysql.galera_connected', 'line'], + 'lines': [ + ['wsrep_connected', 'connected', 'absolute'], + ] + }, + 'galera_ready': { + 'options': [None, 'Whether the Node is Ready to Accept Queries', 'boolean', 'galera', + 'mysql.galera_ready', 'line'], + 'lines': [ + ['wsrep_ready', 'ready', 'absolute'], + ] + }, + 'galera_open_transactions': { + 'options': [None, 'Open Transactions', 'num', 'galera', 'mysql.galera_open_transactions', 'line'], + 'lines': [ + ['wsrep_open_transactions', 'open transactions', 'absolute'], + ] + }, + 'galera_thread_count': { + 'options': [None, 'Total Number of WSRep (applier/rollbacker) Threads', 'num', 'galera', + 'mysql.galera_thread_count', 'line'], + 'lines': [ + ['wsrep_thread_count', 'threads', 'absolute'], + ] + }, 'userstats_cpu': { 'options': [None, 'Users CPU time', 'percentage', 'userstats', 'mysql.userstats_cpu', 'stacked'], 'lines': [] @@ -663,6 +734,59 @@ def userstats_chart_template(name): DEFAULT_REPL_CHANNEL = '' +# Write Set REPlication +# https://galeracluster.com/library/documentation/galera-status-variables.html +# https://www.percona.com/doc/percona-xtradb-cluster/LATEST/wsrep-status-index.html +class WSRepDataConverter: + unknown_value = -1 + + def convert(self, key, value): + if key == 'wsrep_connected': + return self.convert_connected(value) + elif key == 'wsrep_ready': + return self.convert_ready(value) + elif key == 'wsrep_cluster_status': + return self.convert_cluster_status(value) + return value + + def convert_connected(self, value): + # https://www.percona.com/doc/percona-xtradb-cluster/LATEST/wsrep-status-index.html#wsrep_connected + if value == 'OFF': + return 0 + if value == 'ON': + return 1 + return self.unknown_value + + def convert_ready(self, value): + # https://www.percona.com/doc/percona-xtradb-cluster/LATEST/wsrep-status-index.html#wsrep_ready + if value == 'OFF': + return 0 + if value == 'ON': + return 1 + return self.unknown_value + + def convert_cluster_status(self, value): + # https://www.percona.com/doc/percona-xtradb-cluster/LATEST/wsrep-status-index.html#wsrep_cluster_status + # https://github.com/codership/wsrep-API/blob/eab2d5d5a31672c0b7d116ef1629ff18392fd7d0/wsrep_api.h + # typedef enum wsrep_view_status { + # WSREP_VIEW_PRIMARY, //!< primary group configuration (quorum present) + # WSREP_VIEW_NON_PRIMARY, //!< non-primary group configuration (quorum lost) + # WSREP_VIEW_DISCONNECTED, //!< not connected to group, retrying. + # WSREP_VIEW_MAX + # } wsrep_view_status_t; + value = value.lower() + if value == 'primary': + return 0 + elif value == 'non-primary': + return 1 + elif value == 'disconnected': + return 2 + return self.unknown_value + + +wsrep_converter = WSRepDataConverter() + + class Service(MySQLService): def __init__(self, configuration=None, name=None): MySQLService.__init__(self, configuration=configuration, name=name) @@ -686,12 +810,9 @@ class Service(MySQLService): data = dict() if 'global_status' in raw_data: - global_status = dict(raw_data['global_status'][0]) - for key in GLOBAL_STATS: - if key in global_status: - data[key] = global_status[key] - if 'Threads_created' in data and 'Connections' in data: - data['Thread_cache_misses'] = round(int(data['Threads_created']) / float(data['Connections']) * 10000) + global_status = self.get_global_status(raw_data['global_status']) + if global_status: + data.update(global_status) if 'slave_status' in raw_data: status = self.get_slave_status(raw_data['slave_status']) @@ -712,6 +833,52 @@ class Service(MySQLService): return data or None + @staticmethod + def convert_wsrep(key, value): + return wsrep_converter.convert(key, value) + + def get_global_status(self, raw_global_status): + # ( + # ( + # ('Aborted_clients', '18'), + # ('Aborted_connects', '33'), + # ('Access_denied_errors', '80'), + # ('Acl_column_grants', '0'), + # ('Acl_database_grants', '0'), + # ('Acl_function_grants', '0'), + # ('wsrep_ready', 'OFF'), + # ('wsrep_rollbacker_thread_count', '0'), + # ('wsrep_thread_count', '0') + # ), + # ( + # ('Variable_name', 253, 60, 64, 64, 0, 0), + # ('Value', 253, 48, 2048, 2048, 0, 0), + # ) + # ) + rows = raw_global_status[0] + if not rows: + return + + global_status = dict(rows) + data = dict() + + for key in GLOBAL_STATS: + if key not in global_status: + continue + value = global_status[key] + data[key] = value + + for key in GALERA_STATS: + if key not in global_status: + continue + value = global_status[key] + value = self.convert_wsrep(key, value) + data[key] = value + + if 'Threads_created' in data and 'Connections' in data: + data['Thread_cache_misses'] = round(int(data['Threads_created']) / float(data['Connections']) * 10000) + return data + def get_slave_status(self, slave_status_data): rows, description = slave_status_data[0], slave_status_data[1] description_keys = [v[0] for v in description] @@ -742,41 +909,39 @@ class Service(MySQLService): self.add_new_charts(slave_status_chart_template, name) def get_userstats(self, raw_data): - # raw_data['user_statistics'] contains the following data structure: - # ( - # ( - # ('netdata', 42L, 0L, 1264L, 3.111252999999968, 2.968510299999994, 110267L, 19741424L, 0L, 0L, 1265L, 0L, - # 0L, 0L, 3L, 0L, 1301L, 0L, 0L, 7633L, 0L, 83L, 44L, 0L, 0L), - # ('root', 60L, 0L, 184L, 0.22856499999999966, 0.1601419999999998, 11605L, 1516513L, 0L, 9L, 220L, 0L, 2L, 1L, - # 6L, 4L,127L, 0L, 0L, 45L, 0L, 45L, 0L, 0L, 0L) - # ), - # ( - # ('User', 253, 9, 128, 128, 0, 0), - # ('Total_connections', 3, 2, 11, 11, 0, 0), - # ('Concurrent_connections', 3, 1, 11, 11, 0, 0), - # ('Connected_time', 3, 4, 11, 11, 0, 0), - # ('Busy_time', 5, 21, 21, 21, 31, 0), - # ('Cpu_time', 5, 18, 21, 21, 31, 0), - # ('Bytes_received', 8, 6, 21, 21, 0, 0), - # ('Bytes_sent', 8, 8, 21, 21, 0, 0), - # ('Binlog_bytes_written', 8, 1, 21, 21, 0, 0), - # ('Rows_read', 8, 1, 21, 21, 0, 0), - # ('Rows_sent', 8, 4, 21, 21, 0, 0), - # ('Rows_deleted', 8, 1, 21, 21, 0, 0), - # ('Rows_inserted', 8, 1, 21, 21, 0, 0), - # ('Rows_updated', 8, 1, 21, 21, 0, 0), - # ('Select_commands', 8, 1, 21, 21, 0, 0), - # ('Update_commands', 8, 1, 21, 21, 0, 0), - # ('Other_commands', 8, 4, 21, 21, 0, 0), - # ('Commit_transactions', 8, 1, 21, 21, 0, 0), - # ('Rollback_transactions', 8, 1, 21, 21, 0, 0), - # ('Denied_connections', 8, 4, 21, 21, 0, 0), - # ('Lost_connections', 8, 1, 21, 21, 0, 0), - # ('Access_denied', 8, 2, 21, 21, 0, 0), - # ('Empty_queries', 8, 2, 21, 21, 0, 0), - # ('Total_ssl_connections', 8, 1, 21, 21, 0, 0), - # ('Max_statement_time_exceeded', 8, 1, 21, 21, 0, 0)), - # ) + # ( + # ( + # ('netdata', 1L, 0L, 60L, 0.15842499999999984, 0.15767439999999996, 5206L, 963957L, 0L, 0L, + # 61L, 0L, 0L, 0L, 0L, 0L, 62L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), + # ), + # ( + # ('User', 253, 7, 128, 128, 0, 0), + # ('Total_connections', 3, 2, 11, 11, 0, 0), + # ('Concurrent_connections', 3, 1, 11, 11, 0, 0), + # ('Connected_time', 3, 2, 11, 11, 0, 0), + # ('Busy_time', 5, 20, 21, 21, 31, 0), + # ('Cpu_time', 5, 20, 21, 21, 31, 0), + # ('Bytes_received', 8, 4, 21, 21, 0, 0), + # ('Bytes_sent', 8, 6, 21, 21, 0, 0), + # ('Binlog_bytes_written', 8, 1, 21, 21, 0, 0), + # ('Rows_read', 8, 1, 21, 21, 0, 0), + # ('Rows_sent', 8, 2, 21, 21, 0, 0), + # ('Rows_deleted', 8, 1, 21, 21, 0, 0), + # ('Rows_inserted', 8, 1, 21, 21, 0, 0), + # ('Rows_updated', 8, 1, 21, 21, 0, 0), + # ('Select_commands', 8, 2, 21, 21, 0, 0), + # ('Update_commands', 8, 1, 21, 21, 0, 0), + # ('Other_commands', 8, 2, 21, 21, 0, 0), + # ('Commit_transactions', 8, 1, 21, 21, 0, 0), + # ('Rollback_transactions', 8, 1, 21, 21, 0, 0), + # ('Denied_connections', 8, 1, 21, 21, 0, 0), + # ('Lost_connections', 8, 1, 21, 21, 0, 0), + # ('Access_denied', 8, 1, 21, 21, 0, 0), + # ('Empty_queries', 8, 2, 21, 21, 0, 0), + # ('Total_ssl_connections', 8, 1, 21, 21, 0, 0), + # ('Max_statement_time_exceeded', 8, 1, 21, 21, 0, 0) + # ) + # ) data = dict() userstats_vars = [e[0] for e in raw_data['user_statistics'][1]] for i, _ in enumerate(raw_data['user_statistics'][0]): diff --git a/collectors/python.d.plugin/python.d.conf b/collectors/python.d.plugin/python.d.conf index e2ee8eeec..65a5cba28 100644 --- a/collectors/python.d.plugin/python.d.conf +++ b/collectors/python.d.plugin/python.d.conf @@ -49,6 +49,7 @@ example: no # exim: yes # fail2ban: yes # freeradius: yes +# gearman: yes go_expvar: no # gunicorn_log has been replaced by web_log diff --git a/collectors/python.d.plugin/python.d.plugin.in b/collectors/python.d.plugin/python.d.plugin.in index 5b8b50a67..7aa48cbdd 100644 --- a/collectors/python.d.plugin/python.d.plugin.in +++ b/collectors/python.d.plugin/python.d.plugin.in @@ -1,7 +1,21 @@ #!/usr/bin/env bash '''':; -exec "$(command -v python || command -v python3 || command -v python2 || -echo "ERROR python IS NOT AVAILABLE IN THIS SYSTEM")" "$0" "$@" # ''' +pybinary=$(which python || which python3 || which python2) +filtered=() +for arg in "$@" +do + case $arg in + -p*) pybinary=${arg:2} + shift 1 ;; + *) filtered+=("$arg") ;; + esac +done +if [ "$pybinary" = "" ] +then + echo "ERROR python IS NOT AVAILABLE IN THIS SYSTEM" + exit 1 +fi +exec "$pybinary" "$0" "${filtered[@]}" # ''' # -*- coding: utf-8 -*- # Description: @@ -197,7 +211,7 @@ class ModuleConfig: return [v for v in self.config if isinstance(self.config.get(v), dict)] def single_job(self): - return [self.create_job(self.name)] + return [self.create_job(self.name, self.config)] def multi_job(self): return [self.create_job(n, self.config[n]) for n in self.job_names()] @@ -574,16 +588,16 @@ class Plugin: try: job.init() except Exception as error: - self.log.warning("{0}[{1}] : unhandled exception on init : {2}, skipping the job", - job.module_name, job.real_name, repr(error)) + self.log.warning("{0}[{1}] : unhandled exception on init : {2}, skipping the job".format( + job.module_name, job.real_name, repr(error))) job.status = JOB_STATUS_DROPPED continue try: ok = job.check() except Exception as error: - self.log.warning("{0}[{1}] : unhandled exception on check : {2}, skipping the job", - job.module_name, job.real_name, repr(error)) + self.log.warning("{0}[{1}] : unhandled exception on check : {2}, skipping the job".format( + job.module_name, job.real_name, repr(error))) job.status = JOB_STATUS_DROPPED continue if not ok: @@ -595,8 +609,8 @@ class Plugin: try: job.create() except Exception as error: - self.log.error("{0}[{1}] : unhandled exception on create : {2}, skipping the job", - job.module_name, job.real_name, repr(error)) + self.log.warning("{0}[{1}] : unhandled exception on create : {2}, skipping the job".format( + job.module_name, job.real_name, repr(error))) job.status = JOB_STATUS_DROPPED continue diff --git a/collectors/python.d.plugin/rabbitmq/README.md b/collectors/python.d.plugin/rabbitmq/README.md index 346cc23f7..1d7ad956d 100644 --- a/collectors/python.d.plugin/rabbitmq/README.md +++ b/collectors/python.d.plugin/rabbitmq/README.md @@ -1,6 +1,6 @@ # rabbitmq -Module monitor rabbitmq performance and health metrics. +This module monitors [RabbitMQ](https://www.rabbitmq.com/) performance and health metrics. Following charts are drawn: @@ -48,6 +48,20 @@ Following charts are drawn: - free disk space in gigabytes + +Per Vhost charts: + +1. **Vhost Messages** + + - ack + - confirm + - deliver + - get + - get_no_ack + - publish + - redeliver + - return_unroutable + ## configuration ```yaml diff --git a/collectors/python.d.plugin/rabbitmq/rabbitmq.chart.py b/collectors/python.d.plugin/rabbitmq/rabbitmq.chart.py index d947121d6..ad7dcce21 100644 --- a/collectors/python.d.plugin/rabbitmq/rabbitmq.chart.py +++ b/collectors/python.d.plugin/rabbitmq/rabbitmq.chart.py @@ -9,6 +9,7 @@ from bases.FrameworkServices.UrlService import UrlService API_NODE = 'api/nodes' API_OVERVIEW = 'api/overview' +API_VHOSTS = 'api/vhosts' NODE_STATS = [ 'fd_used', @@ -33,6 +34,17 @@ OVERVIEW_STATS = [ 'message_stats.publish' ] +VHOST_MESSAGE_STATS = [ + 'message_stats.ack', + 'message_stats.confirm', + 'message_stats.deliver', + 'message_stats.get', + 'message_stats.get_no_ack', + 'message_stats.publish', + 'message_stats.redeliver', + 'message_stats.return_unroutable', +] + ORDER = [ 'queued_messages', 'message_rates', @@ -111,6 +123,51 @@ CHARTS = { } +def vhost_chart_template(name): + order = [ + 'vhost_{0}_message_stats'.format(name), + ] + family = 'vhost {0}'.format(name) + + charts = { + order[0]: { + 'options': [ + None, 'Vhost "{0}" Messages'.format(name), 'messages/s', family, 'rabbitmq.vhost_messages', 'stacked'], + 'lines': [ + ['vhost_{0}_message_stats_ack'.format(name), 'ack', 'incremental'], + ['vhost_{0}_message_stats_confirm'.format(name), 'confirm', 'incremental'], + ['vhost_{0}_message_stats_deliver'.format(name), 'deliver', 'incremental'], + ['vhost_{0}_message_stats_get'.format(name), 'get', 'incremental'], + ['vhost_{0}_message_stats_get_no_ack'.format(name), 'get_no_ack', 'incremental'], + ['vhost_{0}_message_stats_publish'.format(name), 'publish', 'incremental'], + ['vhost_{0}_message_stats_redeliver'.format(name), 'redeliver', 'incremental'], + ['vhost_{0}_message_stats_return_unroutable'.format(name), 'return_unroutable', 'incremental'], + ] + }, + } + + return order, charts + + +class VhostStatsBuilder: + def __init__(self): + self.stats = None + + def set(self, raw_stats): + self.stats = raw_stats + + def name(self): + return self.stats['name'] + + def has_msg_stats(self): + return bool(self.stats.get('message_stats')) + + def msg_stats(self): + name = self.name() + stats = fetch_data(raw_data=self.stats, metrics=VHOST_MESSAGE_STATS) + return dict(('vhost_{0}_{1}'.format(name, k), v) for k, v in stats.items()) + + class Service(UrlService): def __init__(self, configuration=None, name=None): UrlService.__init__(self, configuration=configuration, name=name) @@ -122,63 +179,107 @@ class Service(UrlService): configuration.get('port', 15672), ) self.node_name = str() + self.vhost = VhostStatsBuilder() + self.collected_vhosts = set() def _get_data(self): data = dict() stats = self.get_overview_stats() - if not stats: return None data.update(stats) stats = self.get_nodes_stats() - if not stats: return None data.update(stats) + stats = self.get_vhosts_stats() + if stats: + data.update(stats) + return data or None def get_overview_stats(self): url = '{0}/{1}'.format(self.url, API_OVERVIEW) - + self.debug("doing http request to '{0}'".format(url)) raw = self._get_raw_data(url) - if not raw: return None data = loads(raw) - self.node_name = data['node'] + self.debug("found node name: '{0}'".format(self.node_name)) - return fetch_data(raw_data=data, metrics=OVERVIEW_STATS) + stats = fetch_data(raw_data=data, metrics=OVERVIEW_STATS) + self.debug("number of metrics: {0}".format(len(stats))) + return stats def get_nodes_stats(self): - url = '{0}/{1}/{2}'.format(self.url, API_NODE, self.node_name) + if self.node_name == "": + self.error("trying to get node stats, but node name is not set") + return None + url = '{0}/{1}/{2}'.format(self.url, API_NODE, self.node_name) + self.debug("doing http request to '{0}'".format(url)) raw = self._get_raw_data(url) - if not raw: return None data = loads(raw) + stats = fetch_data(raw_data=data, metrics=NODE_STATS) + self.debug("number of metrics: {0}".format(len(stats))) + return stats - return fetch_data(raw_data=data, metrics=NODE_STATS) + def get_vhosts_stats(self): + url = '{0}/{1}'.format(self.url, API_VHOSTS) + self.debug("doing http request to '{0}'".format(url)) + raw = self._get_raw_data(url) + if not raw: + return None + + data = dict() + vhosts = loads(raw) + charts_initialized = len(self.charts) > 0 + + for vhost in vhosts: + self.vhost.set(vhost) + if not self.vhost.has_msg_stats(): + continue + + if charts_initialized and self.vhost.name() not in self.collected_vhosts: + self.collected_vhosts.add(self.vhost.name()) + self.add_vhost_charts(self.vhost.name()) + + data.update(self.vhost.msg_stats()) + + self.debug("number of vhosts: {0}, metrics: {1}".format(len(vhosts), len(data))) + return data + + def add_vhost_charts(self, vhost_name): + order, charts = vhost_chart_template(vhost_name) + + for chart_name in order: + params = [chart_name] + charts[chart_name]['options'] + dimensions = charts[chart_name]['lines'] + + new_chart = self.charts.add_chart(params) + for dimension in dimensions: + new_chart.add_dimension(dimension) def fetch_data(raw_data, metrics): data = dict() - for metric in metrics: value = raw_data metrics_list = metric.split('.') try: for m in metrics_list: value = value[m] - except KeyError: + except (KeyError, TypeError): continue data['_'.join(metrics_list)] = value diff --git a/collectors/slabinfo.plugin/Makefile.am b/collectors/slabinfo.plugin/Makefile.am new file mode 100644 index 000000000..07796ea7b --- /dev/null +++ b/collectors/slabinfo.plugin/Makefile.am @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +CLEANFILES = \ + slabinfo.plugin \ + $(NULL) + +include $(top_srcdir)/build/subst.inc +SUFFIXES = .in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/collectors/slabinfo.plugin/README.md b/collectors/slabinfo.plugin/README.md new file mode 100644 index 000000000..e21802397 --- /dev/null +++ b/collectors/slabinfo.plugin/README.md @@ -0,0 +1,22 @@ +# slabinfo.plugin + +SLAB is a cache mechanism used by the Kernel to avoid fragmentation. + +Each internal structure (process, file descriptor, inode...) is stored within a SLAB. + + +## configuring Netdata for slabinfo + +There is currently no configuration needed. + +As `/proc/slabinfo` is only readable by root, this plugin is setuid root. + +## For what use + +This slabinfo details allows to have clues on actions done on your system. +In the following screenshot, you can clearly see a `find` done on a ext4 filesystem (the number of `ext4_inode_cache` & `dentry` are rising fast), and a few seconds later, an admin issued a `echo 3 > /proc/sys/vm/drop_cached` as their count dropped. + +![netdata_slabinfo](https://user-images.githubusercontent.com/9157986/64433811-7f06e500-d0bf-11e9-8e1e-087497e61033.png) + + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fslabinfo.plugin%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/collectors/slabinfo.plugin/slabinfo.c b/collectors/slabinfo.plugin/slabinfo.c new file mode 100644 index 000000000..b92bc8ac2 --- /dev/null +++ b/collectors/slabinfo.plugin/slabinfo.c @@ -0,0 +1,418 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "libnetdata/libnetdata.h" +#include "daemon/common.h" + +#define PLUGIN_SLABINFO_NAME "slabinfo.plugin" +#define PLUGIN_SLABINFO_PROCFILE "/proc/slabinfo" + +#define CHART_TYPE "mem" +#define CHART_FAMILY "slab" +#define CHART_PRIO 3000 + +// #define slabdebug(...) if (debug) { fprintf(stderr, __VA_ARGS__); } +#define slabdebug(args...) if (debug) { \ + fprintf(stderr, "slabinfo.plugin DEBUG (%04d@%-10.10s:%-15.15s)::", __LINE__, __FILE__, __FUNCTION__); \ + fprintf(stderr, ##args); \ + fprintf(stderr, "\n"); } + + +// ---------------------------------------------------------------------------- + +// callback required by fatal() +void netdata_cleanup_and_exit(int ret) { + exit(ret); +} + +void send_statistics(const char *action, const char *action_result, const char *action_data) { + (void) action; + (void) action_result; + (void) action_data; + return; +} + +// callbacks required by popen() +void signals_block(void) {}; +void signals_unblock(void) {}; +void signals_reset(void) {}; + +// callback required by eval() +int health_variable_lookup(const char *variable, uint32_t hash, struct rrdcalc *rc, calculated_number *result) { + (void)variable; + (void)hash; + (void)rc; + (void)result; + return 0; +}; + +// required by get_system_cpus() +char *netdata_configured_host_prefix = ""; + + +int running = 1; +int debug = 0; + +// ---------------------------------------------------------------------------- + +// Slabinfo format : +// format 2.1 Was provided by 57ed3eda977a215f054102b460ab0eb5d8d112e6 (2.6.24-rc6) as: +// seq_puts(m, "# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab>"); +// seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>"); +// seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>"); +// +// With max values: +// seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", +// cache_name(s), sinfo.active_objs, sinfo.num_objs, s->size, sinfo.objects_per_slab, (1 << sinfo.cache_order)); +// seq_printf(m, " : tunables %4u %4u %4u", +// sinfo.limit, sinfo.batchcount, sinfo.shared); +// seq_printf(m, " : slabdata %6lu %6lu %6lu", +// sinfo.active_slabs, sinfo.num_slabs, sinfo.shared_avail); +// +// If CONFIG_DEBUG_SLAB is set, it will also add columns from slabinfo_show_stats (for SLAB only): +// seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu %4lu %4lu %4lu %4lu %4lu", +// allocs, high, grown, reaped, errors, max_freeable, node_allocs, node_frees, overflows); +// seq_printf(m, " : cpustat %6lu %6lu %6lu %6lu", +// allochit, allocmiss, freehit, freemiss); +// +// Implementation choices: +// - Iterates through a linked list of kmem_cache. +// - Name is a char* from struct kmem_cache (mm/slab.h). +// - max name size found is 24: +// grep -roP 'kmem_cache_create\(".+"'| awk '{split($0,a,"\""); print a[2],length(a[2]); }' | sort -k2 -n +// - Using uint64 everywhere, as types fits and allows to use standard helpers + +struct slabinfo { + // procfile fields + const char *name; + uint64_t active_objs; + uint64_t num_objs; + uint64_t obj_size; + uint64_t obj_per_slab; + uint64_t pages_per_slab; + uint64_t tune_limit; + uint64_t tune_batchcnt; + uint64_t tune_shared_factor; + uint64_t data_active_slabs; + uint64_t data_num_slabs; + uint64_t data_shared_avail; + + // Calculated fields + uint64_t mem_usage; + uint64_t mem_waste; + uint8_t obj_filling; + + uint32_t hash; + struct slabinfo *next; +} *slabinfo_root = NULL, *slabinfo_next = NULL, *slabinfo_last_used = NULL; + +// The code is very inspired from "proc_net_dev.c" and "perf_plugin.c" + +// Get the existing object, or create a new one +static struct slabinfo *get_slabstruct(const char *name) { + struct slabinfo *s; + + slabdebug("--> Requested slabstruct %s", name); + + uint32_t hash = simple_hash(name); + + // Search it, from the next to the end + for (s = slabinfo_next; s; s = s->next) { + if ((hash = s->hash) && !strcmp(name, s->name)) { + slabdebug("<-- Found existing slabstruct after %s", slabinfo_last_used->name); + // Prepare the next run + slabinfo_next = s->next; + slabinfo_last_used = s; + return s; + } + } + + // Search it from the begining to the last position we used + for (s = slabinfo_root; s != slabinfo_last_used; s = s->next) { + if (hash == s->hash && !strcmp(name, s->name)) { + slabdebug("<-- Found existing slabstruct after root %s", slabinfo_root->name); + slabinfo_next = s->next; + slabinfo_last_used = s; + return s; + } + } + + // Create a new one + s = callocz(1, sizeof(struct slabinfo)); + s->name = strdupz(name); + s->hash = hash; + + // Add it to the current postion + if (slabinfo_root) { + slabdebug("<-- Creating new slabstruct after %s", slabinfo_last_used->name); + s->next = slabinfo_last_used->next; + slabinfo_last_used->next = s; + slabinfo_last_used = s; + } + else { + slabdebug("<-- Creating new slabstruct as root"); + slabinfo_root = slabinfo_last_used = s; + } + + return s; +} + + +// Read a full pass of slabinfo to update the structs +struct slabinfo *read_file_slabinfo() { + + slabdebug("-> Reading procfile %s", PLUGIN_SLABINFO_PROCFILE); + + static procfile *ff = NULL; + static long slab_pagesize = 0; + + if (unlikely(!slab_pagesize)) { + slab_pagesize = sysconf(_SC_PAGESIZE); + slabdebug(" Discovered pagesize: %ld", slab_pagesize); + } + + if(unlikely(!ff)) { + ff = procfile_reopen(ff, PLUGIN_SLABINFO_PROCFILE, " ,:" , PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff)) { + error("<- Cannot open file '%s", PLUGIN_SLABINFO_PROCFILE); + exit(1); + } + } + + ff = procfile_readall(ff); + if(unlikely(!ff)) { + error("<- Cannot read file '%s'", PLUGIN_SLABINFO_PROCFILE); + exit(0); + } + + + // Iterate on all lines to populate / update the slabinfo struct + size_t lines = procfile_lines(ff), l; + + slabdebug(" Read %lu lines from procfile", (unsigned long)lines); + for(l = 2; l < lines; l++) { + if (unlikely(procfile_linewords(ff, l) < 14)) { + slabdebug(" Line %lu has only %lu words, skipping", (unsigned long)l, procfile_linewords(ff,l)); + continue; + } + + char *name = procfile_lineword(ff, l, 0); + struct slabinfo *s = get_slabstruct(name); + + s->active_objs = str2uint64_t(procfile_lineword(ff, l, 1)); + s->num_objs = str2uint64_t(procfile_lineword(ff, l, 2)); + s->obj_size = str2uint64_t(procfile_lineword(ff, l, 3)); + s->obj_per_slab = str2uint64_t(procfile_lineword(ff, l, 4)); + s->pages_per_slab = str2uint64_t(procfile_lineword(ff, l, 5)); + + s->tune_limit = str2uint64_t(procfile_lineword(ff, l, 7)); + s->tune_batchcnt = str2uint64_t(procfile_lineword(ff, l, 8)); + s->tune_shared_factor = str2uint64_t(procfile_lineword(ff, l, 9)); + + s->data_active_slabs = str2uint64_t(procfile_lineword(ff, l, 11)); + s->data_num_slabs = str2uint64_t(procfile_lineword(ff, l, 12)); + s->data_shared_avail = str2uint64_t(procfile_lineword(ff, l, 13)); + + uint32_t memperslab = s->pages_per_slab * slab_pagesize; + // Internal fragmentation: loss per slab, due to objects not being a multiple of pagesize + //uint32_t lossperslab = memperslab - s->obj_per_slab * s->obj_size; + + // Total usage = slabs * pages per slab * page size + s->mem_usage = (uint64_t)(s->data_num_slabs * memperslab); + + // Wasted memory (filling): slabs allocated but not filled: sum total slab - sum total objects + s->mem_waste = s->mem_usage - (uint64_t)(s->active_objs * s->obj_size); + //if (s->data_num_slabs > 1) + // s->mem_waste += s->data_num_slabs * lossperslab; + + + // Slab filling efficiency + if (s->num_objs > 0) + s->obj_filling = 100 * s->active_objs / s->num_objs; + else + s->obj_filling = 0; + + slabdebug(" Updated slab %s: %lu %lu %lu %lu %lu / %lu %lu %lu / %lu %lu %lu / %lu %lu %hhu", + name, s->active_objs, s->num_objs, s->obj_size, s->obj_per_slab, s->pages_per_slab, + s->tune_limit, s->tune_batchcnt, s->tune_shared_factor, + s->data_active_slabs, s->data_num_slabs, s->data_shared_avail, + s->mem_usage, s->mem_waste, s->obj_filling); + } + + return slabinfo_root; +} + + + +unsigned int do_slab_stats(int update_every) { + + static unsigned int loops = 0; + struct slabinfo *sactive = NULL, *s = NULL; + + // Main processing loop + while (running) { + + sactive = read_file_slabinfo(); + + // Init Charts + if (unlikely(loops == 0)) { + // Memory Usage + printf("CHART %s.%s '' 'Memory Usage' 'B' '%s' '' line %d %d %s\n" + , CHART_TYPE + , "slabmemory" + , CHART_FAMILY + , CHART_PRIO + , update_every + , PLUGIN_SLABINFO_NAME + ); + for (s = sactive; s; s = s->next) { + printf("DIMENSION %s '' absolute 1 1\n", s->name); + } + + // Slab active usage (filling) + printf("CHART %s.%s '' 'Object Filling' '%%' '%s' '' line %d %d %s\n" + , CHART_TYPE + , "slabfilling" + , CHART_FAMILY + , CHART_PRIO + 1 + , update_every + , PLUGIN_SLABINFO_NAME + ); + for (s = sactive; s; s = s->next) { + printf("DIMENSION %s '' absolute 1 1\n", s->name); + } + + // Memory waste + printf("CHART %s.%s '' 'Memory waste' 'B' '%s' '' line %d %d %s\n" + , CHART_TYPE + , "slabwaste" + , CHART_FAMILY + , CHART_PRIO + 2 + , update_every + , PLUGIN_SLABINFO_NAME + ); + for (s = sactive; s; s = s->next) { + printf("DIMENSION %s '' absolute 1 1\n", s->name); + } + } + + + // + // Memory usage + // + printf("BEGIN %s.%s\n" + , CHART_TYPE + , "slabmemory" + ); + for (s = sactive; s; s = s->next) { + printf("SET %s = %lu\n" + , s->name + , s->mem_usage + ); + } + printf("END\n"); + + // + // Slab active usage + // + printf("BEGIN %s.%s\n" + , CHART_TYPE + , "slabfilling" + ); + for (s = sactive; s; s = s->next) { + printf("SET %s = %u\n" + , s->name + , s->obj_filling + ); + } + printf("END\n"); + + // + // Memory waste + // + printf("BEGIN %s.%s\n" + , CHART_TYPE + , "slabwaste" + ); + for (s = sactive; s; s = s->next) { + printf("SET %s = %lu\n" + , s->name + , s->mem_waste + ); + } + printf("END\n"); + + + loops++; + + sleep(update_every); + } + + return loops; +} + + + + +// ---------------------------------------------------------------------------- +// main + +void usage(void) { + fprintf(stderr, "%s\n", program_name); + exit(1); +} + +int main(int argc, char **argv) { + + program_name = argv[0]; + program_version = "0.1"; + error_log_syslog = 0; + + int update_every = 1, i, n, freq = 0; + + for (i = 1; i < argc; i++) { + // Frequency parsing + if(isdigit(*argv[i]) && !freq) { + n = (int) str2l(argv[i]); + if (n > 0) { + if (n >= UPDATE_EVERY_MAX) { + error("Invalid interval value: %s", argv[i]); + exit(1); + } + freq = n; + } + } + else if (strcmp("debug", argv[i]) == 0) { + debug = 1; + continue; + } + else { + fprintf(stderr, + "netdata slabinfo.plugin %s\n" + "This program is a data collector plugin for netdata.\n" + "\n" + "Available command line options:\n" + "\n" + " COLLECTION_FREQUENCY data collection frequency in seconds\n" + " minimum: %d\n" + "\n" + " debug enable verbose output\n" + " default: disabled\n" + "\n", + program_version, + update_every + ); + exit(1); + } + } + + if(freq >= update_every) + update_every = freq; + else if(freq) + error("update frequency %d seconds is too small for slabinfo. Using %d.", freq, update_every); + + + // Call the main function. Time drift to be added + do_slab_stats(update_every); + + return 0; +} diff --git a/collectors/tc.plugin/README.md b/collectors/tc.plugin/README.md index 4095c6a3a..6e5306128 100644 --- a/collectors/tc.plugin/README.md +++ b/collectors/tc.plugin/README.md @@ -62,7 +62,7 @@ QoS is about 2 features: When your system is under a DDoS attack, it will get a lot more bandwidth compared to the one it can handle and probably your applications will crash. Setting a limit on the inbound traffic using QoS, will protect your servers (throttle the requests) and depending on the size of the attack may allow your legitimate users to access the server, while the attack is taking place. - Using QoS together with a [SYNPROXY](../proc.plugin/README.md#linux-anti-ddos) will provide a great degree of protection against most DDoS attacks. Actually when I wrote that article, a few folks tried to DDoS the Netdata demo site to see in real-time the SYNPROXY operation. They did not do it right, but anyway a great deal of requests reached the Netdata server. What saved Netdata was QoS. The Netdata demo server has QoS installed, so the requests were throttled and the server did not even reach the point of resource starvation. Read about it [here](../proc.plugin/README.md#linux-anti-ddos). + Using QoS together with a [SYNPROXY](../../collectors/proc.plugin/README.md) will provide a great degree of protection against most DDoS attacks. Actually when I wrote that article, a few folks tried to DDoS the Netdata demo site to see in real-time the SYNPROXY operation. They did not do it right, but anyway a great deal of requests reached the Netdata server. What saved Netdata was QoS. The Netdata demo server has QoS installed, so the requests were throttled and the server did not even reach the point of resource starvation. Read about it [here](../../collectors/proc.plugin/README.md). On top of all these, QoS is extremely light. You will configure it once, and this is it. It will not bother you again and it will not use any noticeable CPU resources, especially on application and database servers. diff --git a/configs.signatures b/configs.signatures index e29883ac5..0214c87c0 100644 --- a/configs.signatures +++ b/configs.signatures @@ -381,7 +381,7 @@ declare -A configs_signatures=( ['7deb236ec68a512b9bdd18e6a51d76f7']='python.d/mysql.conf' ['7e5fc1644aa7a54f9dbb1bd102521b09']='health.d/memcached.conf' ['7f13631183fbdf79c21c8e5a171e9b34']='health.d/zfs.conf' - ['93674f3206872ae9c43ecbc54988413b']='health.d/dbengine.conf' + ['e48b89d4a97b96acf9a88970ab858c3b']='health.d/dbengine.conf' ['7fb8184d56a27040e73261ed9c6fc76f']='health_alarm_notify.conf' ['80266bddd3df374923c750a6de91d120']='health.d/apache.conf' ['803a7f9dcb942eeac0fd764b9e3e38ca']='fping.conf' diff --git a/configure.ac b/configure.ac index 9c82e1472..a966f0ea6 100644 --- a/configure.ac +++ b/configure.ac @@ -774,6 +774,19 @@ AM_CONDITIONAL([ENABLE_PLUGIN_PERF], [test "${enable_plugin_perf}" = "yes"]) # ----------------------------------------------------------------------------- +# slabinfo.plugin + +AC_MSG_CHECKING([if slabinfo.plugin should be enabled]) +if test "${build_target}" == "linux"; then + enable_plugin_slabinfo="yes" +else + enable_plugin_slabinfo="no" +fi +AC_MSG_RESULT([${enable_plugin_slabinfo}]) +AM_CONDITIONAL([ENABLE_PLUGIN_SLABINFO], [test "${enable_plugin_slabinfo}" = "yes"]) + + +# ----------------------------------------------------------------------------- # AWS Kinesis backend - libaws-cpp-sdk-kinesis, libaws-cpp-sdk-core, libssl, libcrypto, libcurl PKG_CHECK_MODULES( @@ -1147,6 +1160,7 @@ AC_CONFIG_FILES([ collectors/plugins.d/Makefile collectors/proc.plugin/Makefile collectors/python.d.plugin/Makefile + collectors/slabinfo.plugin/Makefile collectors/statsd.plugin/Makefile collectors/tc.plugin/Makefile collectors/xenstat.plugin/Makefile diff --git a/contrib/README.md b/contrib/README.md index 8f28282a5..4f32d9dfb 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -11,23 +11,23 @@ To build Netdata for a Debian Jessie system, the debian directory has to be available in the root of the Netdata source. The easiest way to do this is with a symlink: -``` -~/netdata$ ln -s contrib/debian +```sh +ln -s contrib/debian ``` Then build the debian package: -``` -~/netdata$ dpkg-buildpackage -us -uc -rfakeroot +```sh +dpkg-buildpackage -us -uc -rfakeroot ``` This should give a package that can be installed in the parent directory, which you can install manually with dpkg. -``` -~/netdata$ ls ../*.deb +```sh +ls ../*.deb ../netdata_1.0.0_amd64.deb -~/netdata$ sudo dpkg -i ../netdata_1.0.0_amd64.deb +sudo dpkg -i ../netdata_1.0.0_amd64.deb ``` ### Building for a Debian system without systemd diff --git a/contrib/debian/control b/contrib/debian/control index ed5bd94b8..be9a77860 100644 --- a/contrib/debian/control +++ b/contrib/debian/control @@ -43,7 +43,6 @@ Depends: adduser, openssl, libmnl0, libjson-c3, - cups, freeipmi, libnetfilter-acct1, libprotobuf-c1, @@ -56,3 +55,9 @@ Description: real-time charts for system monitoring and presents a web site to view and analyze them. The presentation is also real-time and full of interactive charts that precisely render all collected values. + +Package: netdata-plugin-cups +Architecture: any +Depends: cups, + netdata (>= ${source:Version}) +Description: The Common Unix Printing System plugin for metrics collection from cupds diff --git a/contrib/debian/control.buster b/contrib/debian/control.buster index 56c59ae88..1166883be 100644 --- a/contrib/debian/control.buster +++ b/contrib/debian/control.buster @@ -43,7 +43,6 @@ Depends: adduser, openssl, libmnl0, libjson-c3, - cups, freeipmi, libnetfilter-acct1, libprotobuf-c1, @@ -56,3 +55,9 @@ Description: real-time charts for system monitoring and presents a web site to view and analyze them. The presentation is also real-time and full of interactive charts that precisely render all collected values. + +Package: netdata-plugin-cups +Architecture: any +Depends: cups, + netdata (>= ${source:Version}) +Description: The Common Unix Printing System plugin for metrics collection from cupds diff --git a/contrib/debian/control.jessie b/contrib/debian/control.jessie index ced85d20e..79db7839c 100644 --- a/contrib/debian/control.jessie +++ b/contrib/debian/control.jessie @@ -41,7 +41,6 @@ Depends: adduser, openssl, libmnl0, libjson-c3, - cups, freeipmi, libnetfilter-acct1, libprotobuf-c1, @@ -54,3 +53,9 @@ Description: real-time charts for system monitoring and presents a web site to view and analyze them. The presentation is also real-time and full of interactive charts that precisely render all collected values. + +Package: netdata-plugin-cups +Architecture: any +Depends: cups, + netdata (>= ${source:Version}) +Description: The Common Unix Printing System plugin for metrics collection from cupds diff --git a/contrib/debian/control.trusty b/contrib/debian/control.trusty index cb8a52e01..918d2ad35 100644 --- a/contrib/debian/control.trusty +++ b/contrib/debian/control.trusty @@ -41,7 +41,6 @@ Depends: adduser, openssl, libmnl0, libjson-c2, - cups, freeipmi, libnetfilter-acct1, libprotobuf-c0, @@ -54,3 +53,9 @@ Description: real-time charts for system monitoring and presents a web site to view and analyze them. The presentation is also real-time and full of interactive charts that precisely render all collected values. + +Package: netdata-plugin-cups +Architecture: any +Depends: cups, + netdata (>= ${source:Version}) +Description: The Common Unix Printing System plugin for metrics collection from cupds diff --git a/contrib/debian/control.wheezy b/contrib/debian/control.wheezy index cde1d560c..dc23b788e 100644 --- a/contrib/debian/control.wheezy +++ b/contrib/debian/control.wheezy @@ -23,3 +23,9 @@ Description: real-time charts for system monitoring and presents a web site to view and analyze them. The presentation is also real-time and full of interactive charts that precisely render all collected values. + +Package: netdata-plugin-cups +Architecture: any +Depends: cups, + netdata (>= ${source:Version}) +Description: The Common Unix Printing System plugin for metrics collection from cupds diff --git a/contrib/debian/control.xenial b/contrib/debian/control.xenial index 08a6df43c..412b389e8 100644 --- a/contrib/debian/control.xenial +++ b/contrib/debian/control.xenial @@ -43,7 +43,6 @@ Depends: adduser, openssl, libmnl0, libjson-c2, - cups, freeipmi, libnetfilter-acct1, libprotobuf-c1, @@ -56,3 +55,9 @@ Description: real-time charts for system monitoring and presents a web site to view and analyze them. The presentation is also real-time and full of interactive charts that precisely render all collected values. + +Package: netdata-plugin-cups +Architecture: any +Depends: cups, + netdata (>= ${source:Version}) +Description: The Common Unix Printing System plugin for metrics collection from cupds diff --git a/contrib/debian/netdata.postrm b/contrib/debian/netdata.postrm index 4ab4eeadd..94e82bcd4 100644 --- a/contrib/debian/netdata.postrm +++ b/contrib/debian/netdata.postrm @@ -15,6 +15,10 @@ case "$1" in dpkg-statoverride --remove /var/lib/netdata/www fi + if dpkg-statoverride --list | grep -qw /var/lib/netdata/registry; then + dpkg-statoverride --remove /var/lib/netdata/registry + fi + if dpkg-statoverride --list | grep -qw /var/lib/netdata; then dpkg-statoverride --remove /var/lib/netdata fi diff --git a/contrib/debian/rules b/contrib/debian/rules index 036e0108e..0e17e3953 100755 --- a/contrib/debian/rules +++ b/contrib/debian/rules @@ -4,6 +4,7 @@ # the location of plugins in /usr/lib DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) TOP = $(CURDIR)/debian/netdata +TEMPTOP = $(CURDIR)/debian/tmp %: # For jessie and beyond @@ -31,13 +32,40 @@ override_dh_install: debian/netdata.postinst # find "$(TOP)" -name .keep -exec rm '{}' ';' + # Set the CUPS plugin install rule + # + mkdir -p $(TOP)-plugin-cups/usr/libexec/netdata/plugins.d + mv -f $(TEMPTOP)/usr/libexec/netdata/plugins.d/cups.plugin \ + $(TOP)-plugin-cups/usr/libexec/netdata/plugins.d/cups.plugin + + # Set the rest of the software in the main package + # + cp -rp $(TEMPTOP)/usr $(TOP)/usr + cp -rp $(TEMPTOP)/var $(TOP)/var + #cp -rp $(TEMPTOP)/etc $(TOP)/etc + + # Copy sample netdata.conf + cp -p $(CURDIR)/system/edit-config $(TOP)/etc/netdata/ + + # Create placeholder dirs in netdata configuration directory + # + mkdir -p $(TOP)/etc/netdata/health.d + mkdir -p $(TOP)/etc/netdata/python.d + mkdir -p $(TOP)/etc/netdata/charts.d + mkdir -p $(TOP)/etc/netdata/cystonm-plugins.d + mkdir -p $(TOP)/etc/netdata/go.d + mkdir -p $(TOP)/etc/netdata/ssl + mkdir -p $(TOP)/etc/netdata/node.d + mkdir -p $(TOP)/etc/netdata/statsd.d + + # Move files that local user shouldn't be editing to /usr/share/netdata # - mkdir -p "$(TOP)/usr/share/netdata" + mkdir -p "$(TOP)/usr/share/netdata/www" for D in $$(find "$(TOP)/var/lib/netdata/www/" -maxdepth 1 -type d -printf '%f '); do \ echo Relocating $$D; \ mv "$(TOP)/var/lib/netdata/www/$$D" "$(TOP)/usr/share/netdata/www/$$D"; \ - ln -s "/usr/share/netdata/$$D" "$(TOP)/var/lib/netdata/www/$$D"; \ + ln -s "/usr/share/netdata/www/$$D" "$(TOP)/var/lib/netdata/www/$$D"; \ done # Update postinst to set correct group for www files on installation. @@ -55,7 +83,7 @@ override_dh_install: debian/netdata.postinst # Install go # - debian/install_go.sh $$(cat ${CURDIR}/packaging/go.d.version) $(TOP)/usr/lib/$(DEB_HOST_MULTIARCH)/netdata/ $(TOP)/usr/libexec/netdata + debian/install_go.sh $$(cat ${CURDIR}/packaging/go.d.version) $(TOP)/usr/lib/netdata $(TOP)/usr/libexec/netdata override_dh_installdocs: dh_installdocs @@ -79,8 +107,16 @@ override_dh_fixperms: chmod 0754 $(TOP)/usr/libexec/netdata/plugins.d/apps.plugin chmod 0754 $(TOP)/usr/libexec/netdata/plugins.d/freeipmi.plugin chmod 0754 $(TOP)/usr/libexec/netdata/plugins.d/perf.plugin + chmod 0754 $(TOP)/usr/libexec/netdata/plugins.d/slabinfo.plugin chmod 0750 $(TOP)/usr/libexec/netdata/plugins.d/go.d.plugin + # Support script for configuration file management + # + chmod 0750 $(TOP)/etc/netdata/edit-config + + # CUPS plugin package + chmod 0750 $(TOP)-plugin-cups/usr/libexec/netdata/plugins.d/cups.plugin + override_dh_installlogrotate: cp system/netdata.logrotate debian/netdata.logrotate dh_installlogrotate diff --git a/daemon/README.md b/daemon/README.md index 2facbdda6..0d4b0cdbb 100644 --- a/daemon/README.md +++ b/daemon/README.md @@ -4,13 +4,13 @@ - You can start Netdata by executing it with `/usr/sbin/netdata` (the installer will also start it). -- You can stop Netdata by killing it with `killall netdata`. - You can stop and start Netdata at any point. Netdata saves on exit its round robbin - database to `/var/cache/netdata` so that it will continue from where it stopped the last time. +- You can stop Netdata by killing it with `killall netdata`. You can stop and start Netdata at any point. Netdata + saves on exit its round robbin database to `/var/cache/netdata` so that it will continue from where it stopped the + last time. Access to the web site, for all graphs, is by default on port `19999`, so go to: -``` +```sh http://127.0.0.1:19999/ ``` @@ -18,7 +18,8 @@ You can get the running config file at any time, by accessing `http://127.0.0.1: ### Starting Netdata at boot -In the `system` directory you can find scripts and configurations for the various distros. +In the `system` directory you can find scripts and configurations for the +various distros. #### systemd @@ -45,7 +46,8 @@ systemctl start netdata #### init.d -In the system directory you can find `netdata-lsb`. Copy it to the proper place according to your distribution documentation. For Ubuntu, this can be done via running the following commands as root. +In the system directory you can find `netdata-lsb`. Copy it to the proper place according to your distribution +documentation. For Ubuntu, this can be done via running the following commands as root. ```sh # copy the Netdata startup file to /etc/init.d @@ -60,11 +62,13 @@ update-rc.d netdata defaults #### openrc (gentoo) -In the `system` directory you can find `netdata-openrc`. Copy it to the proper place according to your distribution documentation. +In the `system` directory you can find `netdata-openrc`. Copy it to the proper +place according to your distribution documentation. #### CentOS / Red Hat Enterprise Linux -For older versions of RHEL/CentOS that don't have systemd, an init script is included in the system directory. This can be installed by running the following commands as root. +For older versions of RHEL/CentOS that don't have systemd, an init script is included in the system directory. This can +be installed by running the following commands as root. ```sh # copy the Netdata startup file to /etc/init.d @@ -77,7 +81,8 @@ chmod +x /etc/init.d/netdata chkconfig --add netdata ``` -_There have been some recent work on the init script, see PR <https://github.com/netdata/netdata/pull/403>_ +_There have been some recent work on the init script, see PR +<https://github.com/netdata/netdata/pull/403>_ #### other systems @@ -99,7 +104,7 @@ The program will print the supported command line parameters. The command line options of the Netdata 1.10.0 version are the following: -``` +```sh ^ |.-. .-. .-. .-. . netdata | '-' '-' '-' '-' real-time performance monitoring, done right! @@ -188,34 +193,34 @@ Netdata uses 3 log files: 2. `access.log` 3. `debug.log` -Any of them can be disabled by setting it to `/dev/null` or `none` in `netdata.conf`. -By default `error.log` and `access.log` are enabled. `debug.log` is only enabled if -debugging/tracing is also enabled (Netdata needs to be compiled with debugging enabled). +Any of them can be disabled by setting it to `/dev/null` or `none` in `netdata.conf`. By default `error.log` and +`access.log` are enabled. `debug.log` is only enabled if debugging/tracing is also enabled (Netdata needs to be compiled +with debugging enabled). Log files are stored in `/var/log/netdata/` by default. -#### error.log +### error.log -The `error.log` is the `stderr` of the `netdata` daemon and all external plugins run by netdata. +The `error.log` is the `stderr` of the `netdata` daemon and all external plugins +run by `netdata`. So if any process, in the Netdata process tree, writes anything to its standard error, it will appear in `error.log`. -For most Netdata programs (including standard external plugins shipped by netdata), the -following lines may appear: +For most Netdata programs (including standard external plugins shipped by netdata), the following lines may appear: -| tag|description| +| tag | description | |:-:|:----------| -| `INFO`|Something important the user should know.| -| `ERROR`|Something that might disable a part of netdata.<br/>The log line includes `errno` (if it is not zero).| -| `FATAL`|Something prevented a program from running.<br/>The log line includes `errno` (if it is not zero) and the program exited.| +| `INFO` | Something important the user should know. | +| `ERROR` | Something that might disable a part of netdata.<br/>The log line includes `errno` (if it is not zero). | +| `FATAL` | Something prevented a program from running.<br/>The log line includes `errno` (if it is not zero) and the program exited. | -So, when auto-detection of data collection fail, `ERROR` lines are logged and the relevant modules -are disabled, but the program continues to run. +So, when auto-detection of data collection fail, `ERROR` lines are logged and the relevant modules are disabled, but the +program continues to run. When a Netdata program cannot run at all, a `FATAL` line is logged. -#### access.log +### access.log The `access.log` logs web requests. The format is: @@ -231,21 +236,22 @@ where: - `PERCENT_COMPRESSION` is the percentage of traffic saved due to compression. - `PREP_TIME` is the time in milliseconds needed to prepared the response. - `SENT_TIME` is the time in milliseconds needed to sent the response to the client. -- `TOTAL_TIME` is the total time the request was inside Netdata (from the first byte of the request to the last byte of the response). +- `TOTAL_TIME` is the total time the request was inside Netdata (from the first byte of the request to the last byte + of the response). - `ACTION` can be `filecopy`, `options` (used in CORS), `data` (API call). -#### debug.log +### debug.log See [debugging](#debugging). ## OOM Score -Netdata runs with `OOMScore = 1000`. This means Netdata will be the first to be killed when your -server runs out of memory. +Netdata runs with `OOMScore = 1000`. This means Netdata will be the first to be killed when your server runs out of +memory. You can set Netdata OOMScore in `netdata.conf`, like this: -``` +```conf [global] OOM score = 1000 ``` @@ -257,15 +263,13 @@ Netdata logs its OOM score when it starts: 2017-10-15 03:47:31: netdata INFO : Adjusted my Out-Of-Memory (OOM) score from 0 to 1000. ``` -#### OOM score and systemd +### OOM score and systemd -Netdata will not be able to lower its OOM Score below zero, when it is started as the `netdata` -user (systemd case). +Netdata will not be able to lower its OOM Score below zero, when it is started as the `netdata` user (systemd case). -To allow Netdata control its OOM Score in such cases, you will need to edit -`netdata.service` and set: +To allow Netdata control its OOM Score in such cases, you will need to edit `netdata.service` and set: -``` +```sh [Service] # The minimum Netdata Out-Of-Memory (OOM) score. # Netdata (via [global].OOM score in netdata.conf) can only increase the value set here. @@ -276,12 +280,11 @@ OOMScoreAdjust=-1000 Run `systemctl daemon-reload` to reload these changes. -The above, sets and OOMScore for Netdata to `-1000`, so that Netdata can increase it via -`netdata.conf`. +The above, sets and OOMScore for Netdata to `-1000`, so that Netdata can increase it via `netdata.conf`. If you want to control it entirely via systemd, you can set in `netdata.conf`: -``` +```conf [global] OOM score = keep ``` @@ -290,25 +293,26 @@ Using the above, whatever OOM Score you have set at `netdata.service` will be ma ## Netdata process scheduling policy -By default Netdata runs with the `idle` process scheduling policy, so that it uses CPU resources, only when there is idle CPU to spare. On very busy servers (or weak servers), this can lead to gaps on the charts. +By default Netdata runs with the `idle` process scheduling policy, so that it uses CPU resources, only when there is +idle CPU to spare. On very busy servers (or weak servers), this can lead to gaps on the charts. You can set Netdata scheduling policy in `netdata.conf`, like this: -``` +```conf [global] process scheduling policy = idle ``` You can use the following: -| policy|description| +| policy | description | |:----:|:----------| -| `idle`|use CPU only when there is spare - this is lower than nice 19 - it is the default for Netdata and it is so low that Netdata will run in "slow motion" under extreme system load, resulting in short (1-2 seconds) gaps at the charts.| -| `other`<br/>or<br/>`nice`|this is the default policy for all processes under Linux. It provides dynamic priorities based on the `nice` level of each process. Check below for setting this `nice` level for netdata.| -| `batch`|This policy is similar to `other` in that it schedules the thread according to its dynamic priority (based on the `nice` value). The difference is that this policy will cause the scheduler to always assume that the thread is CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty with respect to wake-up behavior, so that this thread is mildly disfavored in scheduling decisions.| -| `fifo`|`fifo` can be used only with static priorities higher than 0, which means that when a `fifo` threads becomes runnable, it will always immediately preempt any currently running `other`, `batch`, or `idle` thread. `fifo` is a simple scheduling algorithm without time slicing.| -| `rr`|a simple enhancement of `fifo`. Everything described above for `fifo` also applies to `rr`, except that each thread is allowed to run only for a maximum time quantum.| -| `keep`<br/>or<br/>`none`|do not set scheduling policy, priority or nice level - i.e. keep running with whatever it is set already (e.g. by systemd).| +| `idle` | use CPU only when there is spare - this is lower than nice 19 - it is the default for Netdata and it is so low that Netdata will run in "slow motion" under extreme system load, resulting in short (1-2 seconds) gaps at the charts. | +| `other`<br/>or<br/>`nice` | this is the default policy for all processes under Linux. It provides dynamic priorities based on the `nice` level of each process. Check below for setting this `nice` level for netdata. | +| `batch` | This policy is similar to `other` in that it schedules the thread according to its dynamic priority (based on the `nice` value). The difference is that this policy will cause the scheduler to always assume that the thread is CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty with respect to wake-up behavior, so that this thread is mildly disfavored in scheduling decisions. | +| `fifo` | `fifo` can be used only with static priorities higher than 0, which means that when a `fifo` threads becomes runnable, it will always immediately preempt any currently running `other`, `batch`, or `idle` thread. `fifo` is a simple scheduling algorithm without time slicing. | +| `rr` | a simple enhancement of `fifo`. Everything described above for `fifo` also applies to `rr`, except that each thread is allowed to run only for a maximum time quantum. | +| `keep`<br/>or<br/>`none` | do not set scheduling policy, priority or nice level - i.e. keep running with whatever it is set already (e.g. by systemd). | For more information see `man sched`. @@ -316,29 +320,31 @@ For more information see `man sched`. Once the policy is set to one of `rr` or `fifo`, the following will appear: -``` +```conf [global] process scheduling priority = 0 ``` -These priorities are usually from 0 to 99. Higher numbers make the process more important. +These priorities are usually from 0 to 99. Higher numbers make the process more +important. ### nice level for policies `other` or `batch` When the policy is set to `other`, `nice`, or `batch`, the following will appear: -``` +```conf [global] process nice level = 19 ``` ## scheduling settings and systemd -Netdata will not be able to set its scheduling policy and priority to more important values when it is started as the `netdata` user (systemd case). +Netdata will not be able to set its scheduling policy and priority to more important values when it is started as the +`netdata` user (systemd case). You can set these settings at `/etc/systemd/system/netdata.service`: -``` +```sh [Service] # By default Netdata switches to scheduling policy idle, which makes it use CPU, only # when there is spare available. @@ -357,20 +363,23 @@ You can set these settings at `/etc/systemd/system/netdata.service`: Run `systemctl daemon-reload` to reload these changes. -Now, tell Netdata to keep these settings, as set by systemd, by editing `netdata.conf` and setting: +Now, tell Netdata to keep these settings, as set by systemd, by editing +`netdata.conf` and setting: -``` +```conf [global] process scheduling policy = keep ``` -Using the above, whatever scheduling settings you have set at `netdata.service` will be maintained by netdata. +Using the above, whatever scheduling settings you have set at `netdata.service` +will be maintained by netdata. -#### Example 1: Netdata with nice -1 on non-systemd systems +### Example 1: Netdata with nice -1 on non-systemd systems -On a system that is not based on systemd, to make Netdata run with nice level -1 (a little bit higher to the default for all programs), edit `netdata.conf` and set: +On a system that is not based on systemd, to make Netdata run with nice level -1 (a little bit higher to the default for +all programs), edit `netdata.conf` and set: -``` +```conf [global] process scheduling policy = other process nice level = -1 @@ -384,16 +393,17 @@ sudo service netdata restart #### Example 2: Netdata with nice -1 on systemd systems -On a system that is based on systemd, to make Netdata run with nice level -1 (a little bit higher to the default for all programs), edit `netdata.conf` and set: +On a system that is based on systemd, to make Netdata run with nice level -1 (a little bit higher to the default for all +programs), edit `netdata.conf` and set: -``` +```conf [global] process scheduling policy = keep ``` edit /etc/systemd/system/netdata.service and set: -``` +```sh [Service] CPUSchedulingPolicy=other Nice=-1 @@ -408,45 +418,53 @@ sudo systemctl restart netdata ## Virtual memory -You may notice that netdata's virtual memory size, as reported by `ps` or `/proc/pid/status` (or even netdata's applications virtual memory chart) is unrealistically high. +You may notice that netdata's virtual memory size, as reported by `ps` or `/proc/pid/status` (or even netdata's +applications virtual memory chart) is unrealistically high. -For example, it may be reported to be 150+MB, even if the resident memory size is just 25MB. Similar values may be reported for Netdata plugins too. +For example, it may be reported to be 150+MB, even if the resident memory size is just 25MB. Similar values may be +reported for Netdata plugins too. -Check this for example: A Netdata installation with default settings on Ubuntu 16.04LTS. The top chart is **real memory used**, while the bottom one is **virtual memory**: +Check this for example: A Netdata installation with default settings on Ubuntu +16.04LTS. The top chart is **real memory used**, while the bottom one is +**virtual memory**: ![image](https://cloud.githubusercontent.com/assets/2662304/19013772/5eb7173e-87e3-11e6-8f2b-a2ccfeb06faf.png) -**Why does this happen?** +### Why does this happen? -The system memory allocator allocates virtual memory arenas, per thread running. -On Linux systems this defaults to 16MB per thread on 64 bit machines. So, if you get the -difference between real and virtual memory and divide it by 16MB you will roughly get the -number of threads running. +The system memory allocator allocates virtual memory arenas, per thread running. On Linux systems this defaults to 16MB +per thread on 64 bit machines. So, if you get the difference between real and virtual memory and divide it by 16MB you +will roughly get the number of threads running. -The system does this for speed. Having a separate memory arena for each thread, allows the -threads to run in parallel in multi-core systems, without any locks between them. +The system does this for speed. Having a separate memory arena for each thread, allows the threads to run in parallel in +multi-core systems, without any locks between them. -This behaviour is system specific. For example, the chart above when running Netdata on Alpine Linux (that uses **musl** instead of **glibc**) is this: +This behaviour is system specific. For example, the chart above when running +Netdata on Alpine Linux (that uses **musl** instead of **glibc**) is this: ![image](https://cloud.githubusercontent.com/assets/2662304/19013807/7cf5878e-87e4-11e6-9651-082e68701eab.png) -**Can we do anything to lower it?** +### Can we do anything to lower it? -Since Netdata already uses minimal memory allocations while it runs (i.e. it adapts its memory on start, so that while repeatedly collects data it does not do memory allocations), it already instructs the system memory allocator to minimize the memory arenas for each thread. We have also added [2 configuration options](https://github.com/netdata/netdata/blob/5645b1ee35248d94e6931b64a8688f7f0d865ec6/src/main.c#L410-L418) -to allow you tweak these settings: `glibc malloc arena max for plugins` and `glibc malloc arena max for netdata`. +Since Netdata already uses minimal memory allocations while it runs (i.e. it adapts its memory on start, so that while +repeatedly collects data it does not do memory allocations), it already instructs the system memory allocator to +minimize the memory arenas for each thread. We have also added [2 configuration +options](https://github.com/netdata/netdata/blob/5645b1ee35248d94e6931b64a8688f7f0d865ec6/src/main.c#L410-L418) to allow +you tweak these settings: `glibc malloc arena max for plugins` and `glibc malloc arena max for netdata`. -However, even if we instructed the memory allocator to use just one arena, it seems it allocates an arena per thread. +However, even if we instructed the memory allocator to use just one arena, it +seems it allocates an arena per thread. -Netdata also supports `jemalloc` and `tcmalloc`, however both behave exactly the same to the glibc memory allocator in this aspect. +Netdata also supports `jemalloc` and `tcmalloc`, however both behave exactly the +same to the glibc memory allocator in this aspect. -**Is this a problem?** +### Is this a problem? No, it is not. -Linux reserves real memory (physical RAM) in pages (on x86 machines pages are 4KB each). -So even if the system memory allocator is allocating huge amounts of virtual memory, -only the 4KB pages that are actually used are reserving physical RAM. The **real memory** chart -on Netdata application section, shows the amount of physical memory these pages occupy(it +Linux reserves real memory (physical RAM) in pages (on x86 machines pages are 4KB each). So even if the system memory +allocator is allocating huge amounts of virtual memory, only the 4KB pages that are actually used are reserving physical +RAM. The **real memory** chart on Netdata application section, shows the amount of physical memory these pages occupy(it accounts the whole pages, even if parts of them are actually used). ## Debugging @@ -455,13 +473,19 @@ When you compile Netdata with debugging: 1. compiler optimizations for your CPU are disabled (Netdata will run somewhat slower) -2. a lot of code is added all over netdata, to log debug messages to `/var/log/netdata/debug.log`. However, nothing is printed by default. Netdata allows you to select which sections of Netdata you want to trace. Tracing is activated via the config option `debug flags`. It accepts a hex number, to enable or disable specific sections. You can find the options supported at [log.h](../libnetdata/log/log.h). They are the `D_*` defines. The value `0xffffffffffffffff` will enable all possible debug flags. +2. a lot of code is added all over netdata, to log debug messages to `/var/log/netdata/debug.log`. However, nothing is + printed by default. Netdata allows you to select which sections of Netdata you want to trace. Tracing is activated + via the config option `debug flags`. It accepts a hex number, to enable or disable specific sections. You can find + the options supported at [log.h](../libnetdata/log/log.h). They are the `D_*` defines. The value + `0xffffffffffffffff` will enable all possible debug flags. -Once Netdata is compiled with debugging and tracing is enabled for a few sections, the file `/var/log/netdata/debug.log` will contain the messages. +Once Netdata is compiled with debugging and tracing is enabled for a few sections, the file `/var/log/netdata/debug.log` +will contain the messages. -> Do not forget to disable tracing (`debug flags = 0`) when you are done tracing. The file `debug.log` can grow too fast. +> Do not forget to disable tracing (`debug flags = 0`) when you are done tracing. The file `debug.log` can grow too +> fast. -#### compiling Netdata with debugging +### compiling Netdata with debugging To compile Netdata with debugging, use this: @@ -473,13 +497,17 @@ cd /usr/src/netdata.git CFLAGS="-O1 -ggdb -DNETDATA_INTERNAL_CHECKS=1" ./netdata-installer.sh ``` -The above will compile and install Netdata with debugging info embedded. You can now use `debug flags` to set the section(s) you need to trace. +The above will compile and install Netdata with debugging info embedded. You can now use `debug flags` to set the +section(s) you need to trace. -#### debugging crashes +### debugging crashes -We have made the most to make Netdata crash free. If however, Netdata crashes on your system, it would be very helpful to provide stack traces of the crash. Without them, is will be almost impossible to find the issue (the code base is quite large to find such an issue by just objerving it). +We have made the most to make Netdata crash free. If however, Netdata crashes on your system, it would be very helpful +to provide stack traces of the crash. Without them, is will be almost impossible to find the issue (the code base is +quite large to find such an issue by just objerving it). -To provide stack traces, **you need to have Netdata compiled with debugging**. There is no need to enable any tracing (`debug flags`). +To provide stack traces, **you need to have Netdata compiled with debugging**. There is no need to enable any tracing +(`debug flags`). Then you need to be in one of the following 2 cases: @@ -487,9 +515,10 @@ Then you need to be in one of the following 2 cases: 2. you can reproduce the crash -If you are not on these cases, you need to find a way to be (i.e. if your system does not produce core dumps, check your distro documentation to enable them). +If you are not on these cases, you need to find a way to be (i.e. if your system does not produce core dumps, check your +distro documentation to enable them). -#### Netdata crashes and you have a core dump +### Netdata crashes and you have a core dump > you need to have Netdata compiled with debugging info for this to work (check above) @@ -499,7 +528,7 @@ Run the following command and post the output on a github issue. gdb $(which netdata) /path/to/core/dump ``` -#### you can reproduce a Netdata crash on your system +### you can reproduce a Netdata crash on your system > you need to have Netdata compiled with debugging info for this to work (check above) @@ -509,6 +538,7 @@ Install the package `valgrind` and run: valgrind $(which netdata) -D ``` -Netdata will start and it will be a lot slower. Now reproduce the crash and `valgrind` will dump on your console the stack trace. Open a new github issue and post the output. +Netdata will start and it will be a lot slower. Now reproduce the crash and `valgrind` will dump on your console the +stack trace. Open a new github issue and post the output. [![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fdaemon%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/daemon/main.c b/daemon/main.c index bd0970fdd..4189ac7bd 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -306,7 +306,13 @@ int help(int exitcode) { " -W stacksize=N Set the stacksize (in bytes).\n\n" " -W debug_flags=N Set runtime tracing to debug.log.\n\n" " -W unittest Run internal unittests and exit.\n\n" +#ifdef ENABLE_DBENGINE " -W createdataset=N Create a DB engine dataset of N seconds and exit.\n\n" + " -W stresstest=A,B,C,D,E Run a DB engine stress test for A seconds,\n" + " with B writers and C readers, with a ramp up\n" + " time of D seconds for writers, a page cache\n" + " size of E MiB, and exit.\n\n" +#endif " -W set section option value\n" " set netdata.conf option from the command line.\n\n" " -W simple-pattern pattern string\n" @@ -719,7 +725,7 @@ int get_system_info(struct rrdhost_system_info *system_info) { } char n[51], v[101]; snprintfz(n, 50,"%s",name); - snprintfz(v, 101,"%s",value); + snprintfz(v, 100,"%s",value); if(unlikely(rrdhost_set_system_info_variable(system_info, n, v))) { info("Unexpected environment variable %s=%s", n, v); } @@ -887,6 +893,7 @@ int main(int argc, char **argv) { char* stacksize_string = "stacksize="; char* debug_flags_string = "debug_flags="; char* createdataset_string = "createdataset="; + char* stresstest_string = "stresstest="; if(strcmp(optarg, "unittest") == 0) { if(unit_test_buffer()) return 1; @@ -905,14 +912,33 @@ int main(int argc, char **argv) { fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); return 0; } +#ifdef ENABLE_DBENGINE else if(strncmp(optarg, createdataset_string, strlen(createdataset_string)) == 0) { optarg += strlen(createdataset_string); -#ifdef ENABLE_DBENGINE - unsigned history_seconds = (unsigned )strtoull(optarg, NULL, 0); + unsigned history_seconds = strtoul(optarg, NULL, 0); generate_dbengine_dataset(history_seconds); -#endif return 0; } + else if(strncmp(optarg, stresstest_string, strlen(stresstest_string)) == 0) { + char *endptr; + unsigned test_duration_sec = 0, dset_charts = 0, query_threads = 0, ramp_up_seconds = 0, + page_cache_mb = 0; + + optarg += strlen(stresstest_string); + test_duration_sec = (unsigned)strtoul(optarg, &endptr, 0); + if (',' == *endptr) + dset_charts = (unsigned)strtoul(endptr + 1, &endptr, 0); + if (',' == *endptr) + query_threads = (unsigned)strtoul(endptr + 1, &endptr, 0); + if (',' == *endptr) + ramp_up_seconds = (unsigned)strtoul(endptr + 1, &endptr, 0); + if (',' == *endptr) + page_cache_mb = (unsigned)strtoul(endptr + 1, &endptr, 0); + dbengine_stress_test(test_duration_sec, dset_charts, query_threads, ramp_up_seconds, + page_cache_mb); + return 0; + } +#endif else if(strcmp(optarg, "simple-pattern") == 0) { if(optind + 2 > argc) { fprintf(stderr, "%s", "\nUSAGE: -W simple-pattern 'pattern' 'string'\n\n" diff --git a/daemon/unit_test.c b/daemon/unit_test.c index 36ccd9f6b..31718eeea 100644 --- a/daemon/unit_test.c +++ b/daemon/unit_test.c @@ -1688,7 +1688,8 @@ static time_t test_dbengine_create_metrics(RRDSET *st[CHARTS], RRDDIM *rd[CHARTS st[i]->usec_since_last_update = USEC_PER_SEC * update_every; for (j = 0; j < DIMS; ++j) { - next = i * DIMS * REGION_POINTS[current_region] + j * REGION_POINTS[current_region] + c; + next = ((collected_number)i * DIMS) * REGION_POINTS[current_region] + + j * REGION_POINTS[current_region] + c; rrddim_set_by_pointer_fake_time(rd[i][j], next, time_now); } rrdset_done(st[i]); @@ -1719,13 +1720,14 @@ static int test_dbengine_check_metrics(RRDSET *st[CHARTS], RRDDIM *rd[CHARTS][DI for (j = 0; j < DIMS; ++j) { rd[i][j]->state->query_ops.init(rd[i][j], &handle, time_now, time_now + QUERY_BATCH * update_every); for (k = 0; k < QUERY_BATCH; ++k) { - last = i * DIMS * REGION_POINTS[current_region] + j * REGION_POINTS[current_region] + c + k; + last = ((collected_number)i * DIMS) * REGION_POINTS[current_region] + + j * REGION_POINTS[current_region] + c + k; expected = unpack_storage_number(pack_storage_number((calculated_number)last, SN_EXISTS)); n = rd[i][j]->state->query_ops.next_metric(&handle, &time_retrieved); value = unpack_storage_number(n); - same = (calculated_number_round(value * 10000000.0) == calculated_number_round(expected * 10000000.0)) ? 1 : 0; + same = (calculated_number_round(value) == calculated_number_round(expected)) ? 1 : 0; if(!same) { fprintf(stderr, " DB-engine unittest %s/%s: at %lu secs, expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", ### E R R O R ###\n", @@ -1780,7 +1782,7 @@ static int test_dbengine_check_rrdr(RRDSET *st[CHARTS], RRDDIM *rd[CHARTS][DIMS] last = i * DIMS * REGION_POINTS[current_region] + j * REGION_POINTS[current_region] + c; expected = unpack_storage_number(pack_storage_number((calculated_number)last, SN_EXISTS)); - same = (calculated_number_round(value * 10000000.0) == calculated_number_round(expected * 10000000.0)) ? 1 : 0; + same = (calculated_number_round(value) == calculated_number_round(expected)) ? 1 : 0; if(!same) { fprintf(stderr, " DB-engine unittest %s/%s: at %lu secs, expecting value " CALCULATED_NUMBER_FORMAT ", RRDR found " CALCULATED_NUMBER_FORMAT ", ### E R R O R ###\n", @@ -1902,7 +1904,7 @@ int test_dbengine(void) collected_number last = i * DIMS * REGION_POINTS[current_region] + j * REGION_POINTS[current_region] + c - point_offset; calculated_number expected = unpack_storage_number(pack_storage_number((calculated_number)last, SN_EXISTS)); - uint8_t same = (calculated_number_round(value * 10000000.0) == calculated_number_round(expected * 10000000.0)) ? 1 : 0; + uint8_t same = (calculated_number_round(value) == calculated_number_round(expected)) ? 1 : 0; if(!same) { fprintf(stderr, " DB-engine unittest %s/%s: at %lu secs, expecting value " CALCULATED_NUMBER_FORMAT ", RRDR found " CALCULATED_NUMBER_FORMAT ", ### E R R O R ###\n", @@ -1932,20 +1934,27 @@ struct dbengine_chart_thread { uv_thread_t thread; RRDHOST *host; char *chartname; /* Will be prefixed by type, e.g. "example_local1.", "example_local2." etc */ - int dset_charts; /* number of charts */ - int dset_dims; /* dimensions per chart */ - int chart_i; /* current chart offset */ + unsigned dset_charts; /* number of charts */ + unsigned dset_dims; /* dimensions per chart */ + unsigned chart_i; /* current chart offset */ time_t time_present; /* current virtual time of the benchmark */ + volatile time_t time_max; /* latest timestamp of stored values */ unsigned history_seconds; /* how far back in the past to go */ + + volatile long done; /* initialize to 0, set to 1 to stop thread */ + struct completion charts_initialized; + unsigned long errors, stored_metrics_nr; /* statistics */ + + RRDSET *st; + RRDDIM *rd[]; /* dset_dims elements */ }; -collected_number generate_dbengine_chart_value(struct dbengine_chart_thread *thread_info, int dim_i, - time_t time_current) +collected_number generate_dbengine_chart_value(int chart_i, int dim_i, time_t time_current) { collected_number value; - value = ((collected_number)time_current) * thread_info->chart_i; - value += ((collected_number)time_current) * dim_i; + value = ((collected_number)time_current) * (chart_i + 1); + value += ((collected_number)time_current) * (dim_i + 1); value %= 1024LLU; return value; @@ -1956,44 +1965,47 @@ static void generate_dbengine_chart(void *arg) struct dbengine_chart_thread *thread_info = (struct dbengine_chart_thread *)arg; RRDHOST *host = thread_info->host; char *chartname = thread_info->chartname; - const int DSET_DIMS = thread_info->dset_dims; + const unsigned DSET_DIMS = thread_info->dset_dims; unsigned history_seconds = thread_info->history_seconds; time_t time_present = thread_info->time_present; - int j, update_every = 1; + unsigned j, update_every = 1; RRDSET *st; RRDDIM *rd[DSET_DIMS]; char name[RRD_ID_LENGTH_MAX + 1]; time_t time_current; // create the chart - snprintfz(name, RRD_ID_LENGTH_MAX, "example_local%d", thread_info->chart_i + 1); - st = rrdset_create(host, name, chartname, chartname, "example", NULL, chartname, chartname, chartname, NULL, 1, - update_every, RRDSET_TYPE_LINE); + snprintfz(name, RRD_ID_LENGTH_MAX, "example_local%u", thread_info->chart_i + 1); + thread_info->st = st = rrdset_create(host, name, chartname, chartname, "example", NULL, chartname, chartname, + chartname, NULL, 1, update_every, RRDSET_TYPE_LINE); for (j = 0 ; j < DSET_DIMS ; ++j) { - snprintfz(name, RRD_ID_LENGTH_MAX, "%s%d", chartname, j); + snprintfz(name, RRD_ID_LENGTH_MAX, "%s%u", chartname, j + 1); - rd[j] = rrddim_add(st, name, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + thread_info->rd[j] = rd[j] = rrddim_add(st, name, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } + complete(&thread_info->charts_initialized); // feed it with the test data time_current = time_present - history_seconds; for (j = 0 ; j < DSET_DIMS ; ++j) { rd[j]->last_collected_time.tv_sec = - st->last_collected_time.tv_sec = st->last_updated.tv_sec = time_current; + st->last_collected_time.tv_sec = st->last_updated.tv_sec = time_current - update_every; rd[j]->last_collected_time.tv_usec = st->last_collected_time.tv_usec = st->last_updated.tv_usec = 0; } - for( ; time_current < time_present ; ++time_current) { - st->usec_since_last_update = USEC_PER_SEC; + for( ; !thread_info->done && time_current < time_present ; time_current += update_every) { + st->usec_since_last_update = USEC_PER_SEC * update_every; for (j = 0; j < DSET_DIMS; ++j) { collected_number value; - value = generate_dbengine_chart_value(thread_info, j, time_current); + value = generate_dbengine_chart_value(thread_info->chart_i, j, time_current); rrddim_set_by_pointer_fake_time(rd[j], value, time_current); + ++thread_info->stored_metrics_nr; } rrdset_done(st); + thread_info->time_max = time_current; } } @@ -2003,7 +2015,7 @@ void generate_dbengine_dataset(unsigned history_seconds) const int DSET_DIMS = 128; const uint64_t EXPECTED_COMPRESSION_RATIO = 20; RRDHOST *host = NULL; - struct dbengine_chart_thread thread_info[DSET_CHARTS]; + struct dbengine_chart_thread **thread_info; int i; time_t time_present; @@ -2021,25 +2033,259 @@ void generate_dbengine_dataset(unsigned history_seconds) if (NULL == host) return; + thread_info = mallocz(sizeof(*thread_info) * DSET_CHARTS); + for (i = 0 ; i < DSET_CHARTS ; ++i) { + thread_info[i] = mallocz(sizeof(*thread_info[i]) + sizeof(RRDDIM *) * DSET_DIMS); + } fprintf(stderr, "\nRunning DB-engine workload generator\n"); time_present = now_realtime_sec(); for (i = 0 ; i < DSET_CHARTS ; ++i) { - thread_info[i].host = host; - thread_info[i].chartname = "random"; - thread_info[i].dset_charts = DSET_CHARTS; - thread_info[i].chart_i = i; - thread_info[i].dset_dims = DSET_DIMS; - thread_info[i].history_seconds = history_seconds; - thread_info[i].time_present = time_present; - assert(0 == uv_thread_create(&thread_info[i].thread, generate_dbengine_chart, &thread_info[i])); + thread_info[i]->host = host; + thread_info[i]->chartname = "random"; + thread_info[i]->dset_charts = DSET_CHARTS; + thread_info[i]->chart_i = i; + thread_info[i]->dset_dims = DSET_DIMS; + thread_info[i]->history_seconds = history_seconds; + thread_info[i]->time_present = time_present; + thread_info[i]->time_max = 0; + thread_info[i]->done = 0; + init_completion(&thread_info[i]->charts_initialized); + assert(0 == uv_thread_create(&thread_info[i]->thread, generate_dbengine_chart, thread_info[i])); + wait_for_completion(&thread_info[i]->charts_initialized); + destroy_completion(&thread_info[i]->charts_initialized); } for (i = 0 ; i < DSET_CHARTS ; ++i) { - assert(0 == uv_thread_join(&thread_info[i].thread)); + assert(0 == uv_thread_join(&thread_info[i]->thread)); } + for (i = 0 ; i < DSET_CHARTS ; ++i) { + freez(thread_info[i]); + } + freez(thread_info); rrd_wrlock(); rrdhost_free(host); rrd_unlock(); } + +struct dbengine_query_thread { + uv_thread_t thread; + RRDHOST *host; + char *chartname; /* Will be prefixed by type, e.g. "example_local1.", "example_local2." etc */ + unsigned dset_charts; /* number of charts */ + unsigned dset_dims; /* dimensions per chart */ + time_t time_present; /* current virtual time of the benchmark */ + unsigned history_seconds; /* how far back in the past to go */ + volatile long done; /* initialize to 0, set to 1 to stop thread */ + unsigned long errors, queries_nr, queried_metrics_nr; /* statistics */ + + struct dbengine_chart_thread *chart_threads[]; /* dset_charts elements */ +}; + +static void query_dbengine_chart(void *arg) +{ + struct dbengine_query_thread *thread_info = (struct dbengine_query_thread *)arg; + const int DSET_CHARTS = thread_info->dset_charts; + const int DSET_DIMS = thread_info->dset_dims; + time_t time_after, time_before, time_min, time_max, duration; + int i, j, update_every = 1; + RRDSET *st; + RRDDIM *rd; + uint8_t same; + time_t time_now, time_retrieved; + collected_number generatedv; + calculated_number value, expected; + storage_number n; + struct rrddim_query_handle handle; + + do { + // pick a chart and dimension + i = random() % DSET_CHARTS; + st = thread_info->chart_threads[i]->st; + j = random() % DSET_DIMS; + rd = thread_info->chart_threads[i]->rd[j]; + + time_min = thread_info->time_present - thread_info->history_seconds + 1; + time_max = thread_info->chart_threads[i]->time_max; + if (!time_max) { + time_before = time_after = time_min; + } else { + time_after = time_min + random() % (MAX(time_max - time_min, 1)); + duration = random() % 3600; + time_before = MIN(time_after + duration, time_max); /* up to 1 hour queries */ + } + + rd->state->query_ops.init(rd, &handle, time_after, time_before); + ++thread_info->queries_nr; + for (time_now = time_after ; time_now <= time_before ; time_now += update_every) { + generatedv = generate_dbengine_chart_value(i, j, time_now); + expected = unpack_storage_number(pack_storage_number((calculated_number) generatedv, SN_EXISTS)); + + if (unlikely(rd->state->query_ops.is_finished(&handle))) { + fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, expecting value " + CALCULATED_NUMBER_FORMAT ", found data gap, ### E R R O R ###\n", + st->name, rd->name, (unsigned long) time_now, expected); + ++thread_info->errors; + break; + } + n = rd->state->query_ops.next_metric(&handle, &time_retrieved); + if (SN_EMPTY_SLOT == n) { + fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, expecting value " + CALCULATED_NUMBER_FORMAT ", found data gap, ### E R R O R ###\n", + st->name, rd->name, (unsigned long) time_now, expected); + ++thread_info->errors; + break; + } + ++thread_info->queried_metrics_nr; + value = unpack_storage_number(n); + + same = (calculated_number_round(value) == calculated_number_round(expected)) ? 1 : 0; + if (!same) { + fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, expecting value " + CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", ### E R R O R ###\n", + st->name, rd->name, (unsigned long) time_now, expected, value); + ++thread_info->errors; + } + if (time_retrieved != time_now) { + fprintf(stderr, " DB-engine stresstest %s/%s: at %lu secs, found timestamp %lu ### E R R O R ###\n", + st->name, rd->name, (unsigned long) time_now, (unsigned long) time_retrieved); + ++thread_info->errors; + } + } + rd->state->query_ops.finalize(&handle); + } while(!thread_info->done); +} + +void dbengine_stress_test(unsigned TEST_DURATION_SEC, unsigned DSET_CHARTS, unsigned QUERY_THREADS, + unsigned RAMP_UP_SECONDS, unsigned PAGE_CACHE_MB) +{ + const unsigned DSET_DIMS = 128; + const uint64_t EXPECTED_COMPRESSION_RATIO = 20; + const unsigned HISTORY_SECONDS = 3600 * 24 * 365; /* 1 year of history */ + RRDHOST *host = NULL; + struct dbengine_chart_thread **chart_threads; + struct dbengine_query_thread **query_threads; + unsigned i, j; + time_t time_start, time_end; + + if (!TEST_DURATION_SEC) + TEST_DURATION_SEC = 10; + if (!DSET_CHARTS) + DSET_CHARTS = 1; + if (!QUERY_THREADS) + QUERY_THREADS = 1; + if (PAGE_CACHE_MB < RRDENG_MIN_PAGE_CACHE_SIZE_MB) + PAGE_CACHE_MB = RRDENG_MIN_PAGE_CACHE_SIZE_MB; + + default_rrd_memory_mode = RRD_MEMORY_MODE_DBENGINE; + default_rrdeng_page_cache_mb = PAGE_CACHE_MB; + // Worst case for uncompressible data + default_rrdeng_disk_quota_mb = (((uint64_t)DSET_DIMS * DSET_CHARTS) * sizeof(storage_number) * HISTORY_SECONDS) / + (1024 * 1024); + default_rrdeng_disk_quota_mb -= default_rrdeng_disk_quota_mb * EXPECTED_COMPRESSION_RATIO / 100; + + error_log_limit_unlimited(); + debug(D_RRDHOST, "Initializing localhost with hostname 'dbengine-stress-test'"); + + host = dbengine_rrdhost_find_or_create("dbengine-stress-test"); + if (NULL == host) + return; + + chart_threads = mallocz(sizeof(*chart_threads) * DSET_CHARTS); + for (i = 0 ; i < DSET_CHARTS ; ++i) { + chart_threads[i] = mallocz(sizeof(*chart_threads[i]) + sizeof(RRDDIM *) * DSET_DIMS); + } + query_threads = mallocz(sizeof(*query_threads) * QUERY_THREADS); + for (i = 0 ; i < QUERY_THREADS ; ++i) { + query_threads[i] = mallocz(sizeof(*query_threads[i]) + sizeof(struct dbengine_chart_thread *) * DSET_CHARTS); + } + fprintf(stderr, "\nRunning DB-engine stress test, %u seconds writers ramp-up time,\n" + "%u seconds of concurrent readers and writers, %u writer threads, %u reader threads,\n" + "%u MiB of page cache.\n", + RAMP_UP_SECONDS, TEST_DURATION_SEC, DSET_CHARTS, QUERY_THREADS, PAGE_CACHE_MB); + + time_start = now_realtime_sec(); + for (i = 0 ; i < DSET_CHARTS ; ++i) { + chart_threads[i]->host = host; + chart_threads[i]->chartname = "random"; + chart_threads[i]->dset_charts = DSET_CHARTS; + chart_threads[i]->chart_i = i; + chart_threads[i]->dset_dims = DSET_DIMS; + chart_threads[i]->history_seconds = HISTORY_SECONDS; + chart_threads[i]->time_present = time_start; + chart_threads[i]->time_max = 0; + chart_threads[i]->done = 0; + chart_threads[i]->errors = chart_threads[i]->stored_metrics_nr = 0; + init_completion(&chart_threads[i]->charts_initialized); + assert(0 == uv_thread_create(&chart_threads[i]->thread, generate_dbengine_chart, chart_threads[i])); + } + /* barrier so that subsequent queries can access valid chart data */ + for (i = 0 ; i < DSET_CHARTS ; ++i) { + wait_for_completion(&chart_threads[i]->charts_initialized); + destroy_completion(&chart_threads[i]->charts_initialized); + } + sleep(RAMP_UP_SECONDS); + /* at this point data have already began being written to the database */ + for (i = 0 ; i < QUERY_THREADS ; ++i) { + query_threads[i]->host = host; + query_threads[i]->chartname = "random"; + query_threads[i]->dset_charts = DSET_CHARTS; + query_threads[i]->dset_dims = DSET_DIMS; + query_threads[i]->history_seconds = HISTORY_SECONDS; + query_threads[i]->time_present = time_start; + query_threads[i]->done = 0; + query_threads[i]->errors = query_threads[i]->queries_nr = query_threads[i]->queried_metrics_nr = 0; + for (j = 0 ; j < DSET_CHARTS ; ++j) { + query_threads[i]->chart_threads[j] = chart_threads[j]; + } + assert(0 == uv_thread_create(&query_threads[i]->thread, query_dbengine_chart, query_threads[i])); + } + sleep(TEST_DURATION_SEC); + /* stop workload */ + for (i = 0 ; i < DSET_CHARTS ; ++i) { + chart_threads[i]->done = 1; + } + for (i = 0 ; i < QUERY_THREADS ; ++i) { + query_threads[i]->done = 1; + } + for (i = 0 ; i < DSET_CHARTS ; ++i) { + assert(0 == uv_thread_join(&chart_threads[i]->thread)); + } + for (i = 0 ; i < QUERY_THREADS ; ++i) { + assert(0 == uv_thread_join(&query_threads[i]->thread)); + } + time_end = now_realtime_sec(); + fprintf(stderr, "\nDB-engine stress test finished in %ld seconds.\n", time_end - time_start); + unsigned long stored_metrics_nr = 0; + for (i = 0 ; i < DSET_CHARTS ; ++i) { + stored_metrics_nr += chart_threads[i]->stored_metrics_nr; + } + unsigned long queries_nr = 0, queried_metrics_nr = 0; + for (i = 0 ; i < QUERY_THREADS ; ++i) { + queries_nr += query_threads[i]->queries_nr; + queried_metrics_nr += query_threads[i]->queried_metrics_nr; + } + fprintf(stderr, "%u metrics were stored (dataset size of %lu MiB) in %u charts by 1 writer thread per chart.\n", + DSET_CHARTS * DSET_DIMS, stored_metrics_nr * sizeof(storage_number) / (1024 * 1024), DSET_CHARTS); + fprintf(stderr, "Metrics were being generated per 1 emulated second and time was accelerated.\n"); + fprintf(stderr, "%lu metric data points were queried by %u reader threads.\n", queried_metrics_nr, QUERY_THREADS); + fprintf(stderr, "Query starting time is randomly chosen from the beginning of the time-series up to the time of\n" + "the latest data point, and ending time from 1 second up to 1 hour after the starting time.\n"); + fprintf(stderr, "Performance is %lu written data points/sec and %lu read data points/sec.\n", + stored_metrics_nr / (time_end - time_start), queried_metrics_nr / (time_end - time_start)); + + for (i = 0 ; i < DSET_CHARTS ; ++i) { + freez(chart_threads[i]); + } + freez(chart_threads); + for (i = 0 ; i < QUERY_THREADS ; ++i) { + freez(query_threads[i]); + } + freez(query_threads); + rrdeng_exit(host->rrdeng_ctx); + rrd_wrlock(); + rrdhost_delete_charts(host); + rrd_unlock(); +} + #endif diff --git a/daemon/unit_test.h b/daemon/unit_test.h index fd3e80170..230a70085 100644 --- a/daemon/unit_test.h +++ b/daemon/unit_test.h @@ -11,6 +11,9 @@ extern int unit_test_buffer(void); #ifdef ENABLE_DBENGINE extern int test_dbengine(void); extern void generate_dbengine_dataset(unsigned history_seconds); +extern void dbengine_stress_test(unsigned TEST_DURATION_SEC, unsigned DSET_CHARTS, unsigned QUERY_THREADS, + unsigned RAMP_UP_SECONDS, unsigned PAGE_CACHE_MB); + #endif #endif /* NETDATA_UNIT_TEST_H */ diff --git a/database/README.md b/database/README.md index 2fcb69b67..143615a0e 100644 --- a/database/README.md +++ b/database/README.md @@ -1,59 +1,54 @@ # Database -Although `netdata` does all its calculations using `long double`, it stores all values using -a [custom-made 32-bit number](../libnetdata/storage_number/). +Although `netdata` does all its calculations using `long double`, it stores all values using a [custom-made 32-bit +number](../libnetdata/storage_number/). -So, for each dimension of a chart, Netdata will need: `4 bytes for the value * the entries -of its history`. It will not store any other data for each value in the time series database. -Since all its values are stored in a time series with fixed step, the time each value -corresponds can be calculated at run time, using the position of a value in the round robin database. +So, for each dimension of a chart, Netdata will need: `4 bytes for the value * the entries of its history`. It will not +store any other data for each value in the time series database. Since all its values are stored in a time series with +fixed step, the time each value corresponds can be calculated at run time, using the position of a value in the round +robin database. -The default history is 3.600 entries, thus it will need 14.4KB for each chart dimension. -If you need 1.000 dimensions, they will occupy just 14.4MB. +The default history is 3.600 entries, thus it will need 14.4KB for each chart dimension. If you need 1.000 dimensions, +they will occupy just 14.4MB. -Of course, 3.600 entries is a very short history, especially if data collection frequency is set -to 1 second. You will have just one hour of data. +Of course, 3.600 entries is a very short history, especially if data collection frequency is set to 1 second. You will +have just one hour of data. -For a day of data and 1.000 dimensions, you will need: 86.400 seconds * 4 bytes * 1.000 -dimensions = 345MB of RAM. +For a day of data and 1.000 dimensions, you will need: `86.400 seconds * 4 bytes * 1.000 dimensions = 345MB of RAM`. -One option you have to lower this number is to use -**[Memory Deduplication - Kernel Same Page Merging - KSM](#ksm)**. Another possibility is to -use the **[Database Engine](engine/)**. +One option you have to lower this number is to use **[Memory Deduplication - Kernel Same Page Merging - KSM](#ksm)**. +Another possibility is to use the **[Database Engine](engine/)**. ## Memory modes Currently Netdata supports 6 memory modes: -1. `ram`, data are purely in memory. Data are never saved on disk. This mode uses `mmap()` and - supports [KSM](#ksm). +1. `ram`, data are purely in memory. Data are never saved on disk. This mode uses `mmap()` and supports [KSM](#ksm). -2. `save`, (the default) data are only in RAM while Netdata runs and are saved to / loaded from - disk on Netdata restart. It also uses `mmap()` and supports [KSM](#ksm). +2. `save`, data are only in RAM while Netdata runs and are saved to / loaded from disk on Netdata + restart. It also uses `mmap()` and supports [KSM](#ksm). -3. `map`, data are in memory mapped files. This works like the swap. Keep in mind though, this - will have a constant write on your disk. When Netdata writes data on its memory, the Linux kernel - marks the related memory pages as dirty and automatically starts updating them on disk. - Unfortunately we cannot control how frequently this works. The Linux kernel uses exactly the - same algorithm it uses for its swap memory. Check below for additional information on running a - dedicated central Netdata server. This mode uses `mmap()` but does not support [KSM](#ksm). +3. `map`, data are in memory mapped files. This works like the swap. Keep in mind though, this will have a constant + write on your disk. When Netdata writes data on its memory, the Linux kernel marks the related memory pages as dirty + and automatically starts updating them on disk. Unfortunately we cannot control how frequently this works. The Linux + kernel uses exactly the same algorithm it uses for its swap memory. Check below for additional information on + running a dedicated central Netdata server. This mode uses `mmap()` but does not support [KSM](#ksm). 4. `none`, without a database (collected metrics can only be streamed to another Netdata). -5. `alloc`, like `ram` but it uses `calloc()` and does not support [KSM](#ksm). This mode is the - fallback for all others except `none`. +5. `alloc`, like `ram` but it uses `calloc()` and does not support [KSM](#ksm). This mode is the fallback for all + others except `none`. -6. `dbengine`, data are in database files. The [Database Engine](engine/) works like a traditional - database. There is some amount of RAM dedicated to data caching and indexing and the rest of - the data reside compressed on disk. The number of history entries is not fixed in this case, - but depends on the configured disk space and the effective compression ratio of the data stored. - This is the **only mode** that supports changing the data collection update frequency - (`update_every`) **without losing** the previously stored metrics. - For more details see [here](engine/). +6. `dbengine`, (the default) data are in database files. The [Database Engine](engine/) works like a traditional + database. There is some amount of RAM dedicated to data caching and indexing and the rest of the data reside + compressed on disk. The number of history entries is not fixed in this case, but depends on the configured disk + space and the effective compression ratio of the data stored. This is the **only mode** that supports changing the + data collection update frequency (`update_every`) **without losing** the previously stored metrics. For more details + see [here](engine/). You can select the memory mode by editing `netdata.conf` and setting: -``` +```conf [global] # ram, save (the default, save on exit, load on start), map (swap like) memory mode = save @@ -69,64 +64,60 @@ Embedded devices usually have very limited RAM resources available. There are 2 settings for you to tweak: 1. `update every`, which controls the data collection frequency -2. `history`, which controls the size of the database in RAM +2. `history`, which controls the size of the database in RAM (except for `memory mode = dbengine`) -By default `update every = 1` and `history = 3600`. This gives you an hour of data with per -second updates. +By default `update every = 1` and `history = 3600`. This gives you an hour of data with per second updates. -If you set `update every = 2` and `history = 1800`, you will still have an hour of data, but -collected once every 2 seconds. This will **cut in half** both CPU and RAM resources consumed -by Netdata. Of course experiment a bit. On very weak devices you might have to use -`update every = 5` and `history = 720` (still 1 hour of data, but 1/5 of the CPU and RAM resources). +If you set `update every = 2` and `history = 1800`, you will still have an hour of data, but collected once every 2 +seconds. This will **cut in half** both CPU and RAM resources consumed by Netdata. Of course experiment a bit. On very +weak devices you might have to use `update every = 5` and `history = 720` (still 1 hour of data, but 1/5 of the CPU and +RAM resources). -You can also disable [data collection plugins](../collectors) you don't need. -Disabling such plugins will also free both CPU and RAM resources. +You can also disable [data collection plugins](../collectors) you don't need. Disabling such plugins will also free both +CPU and RAM resources. ## Running a dedicated central Netdata server -Netdata allows streaming data between Netdata nodes. This allows us to have a central Netdata -server that will maintain the entire database for all nodes, and will also run health checks/alarms -for all nodes. +Netdata allows streaming data between Netdata nodes. This allows us to have a central Netdata server that will maintain +the entire database for all nodes, and will also run health checks/alarms for all nodes. -For this central Netdata, memory size can be a problem. Fortunately, Netdata supports several -memory modes. **One interesting option** for this setup is `memory mode = map`. +For this central Netdata, memory size can be a problem. Fortunately, Netdata supports several memory modes. **One +interesting option** for this setup is `memory mode = map`. ### map -In this mode, the database of Netdata is stored in memory mapped files. Netdata continues to read -and write the database in memory, but the kernel automatically loads and saves memory pages from/to -disk. +In this mode, the database of Netdata is stored in memory mapped files. Netdata continues to read and write the database +in memory, but the kernel automatically loads and saves memory pages from/to disk. -**We suggest _not_ to use this mode on nodes that run other applications.** There will always be -dirty memory to be synced and this syncing process may influence the way other applications work. -This mode however is useful when we need a central Netdata server that would normally need huge -amounts of memory. Using memory mode `map` we can overcome all memory restrictions. +**We suggest _not_ to use this mode on nodes that run other applications.** There will always be dirty memory to be +synced and this syncing process may influence the way other applications work. This mode however is useful when we need +a central Netdata server that would normally need huge amounts of memory. Using memory mode `map` we can overcome all +memory restrictions. -There are a few kernel options that provide finer control on the way this syncing works. But before -explaining them, a brief introduction of how Netdata database works is needed. +There are a few kernel options that provide finer control on the way this syncing works. But before explaining them, a +brief introduction of how Netdata database works is needed. For each chart, Netdata maps the following files: -1. `chart/main.db`, this is the file that maintains chart information. Every time data are collected - for a chart, this is updated. -2. `chart/dimension_name.db`, this is the file for each dimension. At its beginning there is a - header, followed by the round robin database where metrics are stored. +1. `chart/main.db`, this is the file that maintains chart information. Every time data are collected for a chart, this + is updated. +2. `chart/dimension_name.db`, this is the file for each dimension. At its beginning there is a header, followed by the + round robin database where metrics are stored. So, every time Netdata collects data, the following pages will become dirty: 1. the chart file 2. the header part of all dimension files -3. if the collected metrics are stored far enough in the dimension file, another page will - become dirty, for each dimension +3. if the collected metrics are stored far enough in the dimension file, another page will become dirty, for each + dimension -Each page in Linux is 4KB. So, with 200 charts and 1000 dimensions, there will be 1200 to 2200 4KB -pages dirty pages every second. Of course 1200 of them will always be dirty (the chart header and -the dimensions headers) and 1000 will be dirty for about 1000 seconds (4 bytes per metric, 4KB per -page, so 1000 seconds, or 16 minutes per page). +Each page in Linux is 4KB. So, with 200 charts and 1000 dimensions, there will be 1200 to 2200 4KB pages dirty pages +every second. Of course 1200 of them will always be dirty (the chart header and the dimensions headers) and 1000 will be +dirty for about 1000 seconds (4 bytes per metric, 4KB per page, so 1000 seconds, or 16 minutes per page). -Hopefully, the Linux kernel does not sync all these data every second. The frequency they are -synced is controlled by `/proc/sys/vm/dirty_expire_centisecs` or the -`sysctl` `vm.dirty_expire_centisecs`. The default on most systems is 3000 (30 seconds). +Hopefully, the Linux kernel does not sync all these data every second. The frequency they are synced is controlled by +`/proc/sys/vm/dirty_expire_centisecs` or the `sysctl` `vm.dirty_expire_centisecs`. The default on most systems is 3000 +(30 seconds). On a busy server centralizing metrics from 20+ servers you will experience this: @@ -134,62 +125,59 @@ On a busy server centralizing metrics from 20+ servers you will experience this: As you can see, there is quite some stress (this is `iowait`) every 30 seconds. -A simple solution is to increase this time to 10 minutes (60000). This is the same system -with this setting in 10 minutes: +A simple solution is to increase this time to 10 minutes (60000). This is the same system with this setting in 10 +minutes: ![image](https://cloud.githubusercontent.com/assets/2662304/23834784/d2304f72-0764-11e7-8389-fb830ffd973a.png) -Of course, setting this to 10 minutes means that data on disk might be up to 10 minutes old if you -get an abnormal shutdown. +Of course, setting this to 10 minutes means that data on disk might be up to 10 minutes old if you get an abnormal +shutdown. There are 2 more options to tweak: 1. `dirty_background_ratio`, by default `10`. 2. `dirty_ratio`, by default `20`. -These control the amount of memory that should be dirty for disk syncing to be triggered. -On dedicated Netdata servers, you can use: `80` and `90` respectively, so that all RAM is given -to Netdata. +These control the amount of memory that should be dirty for disk syncing to be triggered. On dedicated Netdata servers, +you can use: `80` and `90` respectively, so that all RAM is given to Netdata. -With these settings, you can expect a little `iowait` spike once every 10 minutes and in case -of system crash, data on disk will be up to 10 minutes old. +With these settings, you can expect a little `iowait` spike once every 10 minutes and in case of system crash, data on +disk will be up to 10 minutes old. ![image](https://cloud.githubusercontent.com/assets/2662304/23835030/ba4bf506-0768-11e7-9bc6-3b23e080c69f.png) -To have these settings automatically applied on boot, create the file `/etc/sysctl.d/netdata-memory.conf` with these contents: +To have these settings automatically applied on boot, create the file `/etc/sysctl.d/netdata-memory.conf` with these +contents: -``` +```conf vm.dirty_expire_centisecs = 60000 vm.dirty_background_ratio = 80 vm.dirty_ratio = 90 vm.dirty_writeback_centisecs = 0 ``` -There is another memory mode to help overcome the memory size problem. What is **most interesting -for this setup** is `memory mode = dbengine`. +There is another memory mode to help overcome the memory size problem. What is **most interesting for this setup** is +`memory mode = dbengine`. ### dbengine -In this mode, the database of Netdata is stored in database files. The [Database Engine](engine/) -works like a traditional database. There is some amount of RAM dedicated to data caching and -indexing and the rest of the data reside compressed on disk. The number of history entries is not -fixed in this case, but depends on the configured disk space and the effective compression ratio -of the data stored. +In this mode, the database of Netdata is stored in database files. The [Database Engine](engine/) works like a +traditional database. There is some amount of RAM dedicated to data caching and indexing and the rest of the data reside +compressed on disk. The number of history entries is not fixed in this case, but depends on the configured disk space +and the effective compression ratio of the data stored. -We suggest to use **this** mode on nodes that also run other applications. The Database Engine uses -direct I/O to avoid polluting the OS filesystem caches and does not generate excessive I/O traffic -so as to create the minimum possible interference with other applications. Using memory mode -`dbengine` we can overcome most memory restrictions. For more details see [here](engine/). +We suggest to use **this** mode on nodes that also run other applications. The Database Engine uses direct I/O to avoid +polluting the OS filesystem caches and does not generate excessive I/O traffic so as to create the minimum possible +interference with other applications. Using memory mode `dbengine` we can overcome most memory restrictions. For more +details see [here](engine/). ## KSM -Netdata offers all its round robin database to kernel for deduplication -(except for `memory mode = dbengine`). +Netdata offers all its round robin database to kernel for deduplication (except for `memory mode = dbengine`). -In the past KSM has been criticized for consuming a lot of CPU resources. -Although this is true when KSM is used for deduplicating certain applications, it is not true with -netdata, since the Netdata memory is written very infrequently (if you have 24 hours of metrics in -netdata, each byte at the in-memory database will be updated just once per day). +In the past KSM has been criticized for consuming a lot of CPU resources. Although this is true when KSM is used for +deduplicating certain applications, it is not true with netdata, since the Netdata memory is written very infrequently +(if you have 24 hours of metrics in netdata, each byte at the in-memory database will be updated just once per day). KSM is a solution that will provide 60+% memory savings to Netdata. @@ -203,15 +191,20 @@ CONFIG_KSM=y When KSM is enabled at the kernel is just available for the user to enable it. -So, if you build a kernel with `CONFIG_KSM=y` you will just get a few files in `/sys/kernel/mm/ksm`. Nothing else happens. There is no performance penalty (apart I guess from the memory this code occupies into the kernel). +So, if you build a kernel with `CONFIG_KSM=y` you will just get a few files in `/sys/kernel/mm/ksm`. Nothing else +happens. There is no performance penalty (apart I guess from the memory this code occupies into the kernel). The files that `CONFIG_KSM=y` offers include: -- `/sys/kernel/mm/ksm/run` by default `0`. You have to set this to `1` for the kernel to spawn `ksmd`. -- `/sys/kernel/mm/ksm/sleep_millisecs`, by default `20`. The frequency ksmd should evaluate memory for deduplication. -- `/sys/kernel/mm/ksm/pages_to_scan`, by default `100`. The amount of pages ksmd will evaluate on each run. +- `/sys/kernel/mm/ksm/run` by default `0`. You have to set this to `1` for the + kernel to spawn `ksmd`. +- `/sys/kernel/mm/ksm/sleep_millisecs`, by default `20`. The frequency ksmd + should evaluate memory for deduplication. +- `/sys/kernel/mm/ksm/pages_to_scan`, by default `100`. The amount of pages + ksmd will evaluate on each run. -So, by default `ksmd` is just disabled. It will not harm performance and the user/admin can control the CPU resources he/she is willing `ksmd` to use. +So, by default `ksmd` is just disabled. It will not harm performance and the user/admin can control the CPU resources +he/she is willing `ksmd` to use. ### Run `ksmd` kernel daemon @@ -222,7 +215,8 @@ echo 1 >/sys/kernel/mm/ksm/run echo 1000 >/sys/kernel/mm/ksm/sleep_millisecs ``` -With these settings ksmd does not even appear in the running process list (it will run once per second and evaluate 100 pages for de-duplication). +With these settings ksmd does not even appear in the running process list (it will run once per second and evaluate 100 +pages for de-duplication). Put the above lines in your boot sequence (`/etc/rc.local` or equivalent) to have `ksmd` run at boot. @@ -232,4 +226,4 @@ Netdata will create charts for kernel memory de-duplication performance, like th ![image](https://cloud.githubusercontent.com/assets/2662304/11998786/eb23ae54-aab6-11e5-94d4-e848e8a5c56a.png) -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fdatabase%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fdatabase%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>)
\ No newline at end of file diff --git a/database/engine/README.md b/database/engine/README.md index 7791a549f..78f3b15ec 100644 --- a/database/engine/README.md +++ b/database/engine/README.md @@ -1,18 +1,17 @@ # Database engine -The Database Engine works like a traditional -database. There is some amount of RAM dedicated to data caching and indexing and the rest of -the data reside compressed on disk. The number of history entries is not fixed in this case, -but depends on the configured disk space and the effective compression ratio of the data stored. -This is the **only mode** that supports changing the data collection update frequency -(`update_every`) **without losing** the previously stored metrics. +The Database Engine works like a traditional database. There is some amount of RAM dedicated to data caching and +indexing and the rest of the data reside compressed on disk. The number of history entries is not fixed in this case, +but depends on the configured disk space and the effective compression ratio of the data stored. This is the **only +mode** that supports changing the data collection update frequency (`update_every`) **without losing** the previously +stored metrics. ## Files -With the DB engine memory mode the metric data are stored in database files. These files are -organized in pairs, the datafiles and their corresponding journalfiles, e.g.: +With the DB engine memory mode the metric data are stored in database files. These files are organized in pairs, the +datafiles and their corresponding journalfiles, e.g.: -``` +```sh datafile-1-0000000001.ndf journalfile-1-0000000001.njf datafile-1-0000000002.ndf @@ -22,21 +21,19 @@ journalfile-1-0000000003.njf ... ``` -They are located under their host's cache directory in the directory `./dbengine` -(e.g. for localhost the default location is `/var/cache/netdata/dbengine/*`). The higher -numbered filenames contain more recent metric data. The user can safely delete some pairs -of files when Netdata is stopped to manually free up some space. +They are located under their host's cache directory in the directory `./dbengine` (e.g. for localhost the default +location is `/var/cache/netdata/dbengine/*`). The higher numbered filenames contain more recent metric data. The user +can safely delete some pairs of files when Netdata is stopped to manually free up some space. _Users should_ **back up** _their `./dbengine` folders if they consider this data to be important._ ## Configuration -There is one DB engine instance per Netdata host/node. That is, there is one `./dbengine` folder -per node, and all charts of `dbengine` memory mode in such a host share the same storage space -and DB engine instance memory state. You can select the memory mode for localhost by editing -netdata.conf and setting: +There is one DB engine instance per Netdata host/node. That is, there is one `./dbengine` folder per node, and all +charts of `dbengine` memory mode in such a host share the same storage space and DB engine instance memory state. You +can select the memory mode for localhost by editing netdata.conf and setting: -``` +```conf [global] memory mode = dbengine ``` @@ -44,110 +41,157 @@ netdata.conf and setting: For setting the memory mode for the rest of the nodes you should look at [streaming](../../streaming/). -The `history` configuration option is meaningless for `memory mode = dbengine` and is ignored -for any metrics being stored in the DB engine. +The `history` configuration option is meaningless for `memory mode = dbengine` and is ignored for any metrics being +stored in the DB engine. -All DB engine instances, for localhost and all other streaming recipient nodes inherit their -configuration from `netdata.conf`: +All DB engine instances, for localhost and all other streaming recipient nodes inherit their configuration from +`netdata.conf`: -``` +```conf [global] page cache size = 32 dbengine disk space = 256 ``` -The above values are the default and minimum values for Page Cache size and DB engine disk space -quota. Both numbers are in **MiB**. All DB engine instances will allocate the configured resources -separately. +The above values are the default and minimum values for Page Cache size and DB engine disk space quota. Both numbers are +in **MiB**. All DB engine instances will allocate the configured resources separately. -The `page cache size` option determines the amount of RAM in **MiB** that is dedicated to caching -Netdata metric values themselves. +The `page cache size` option determines the amount of RAM in **MiB** that is dedicated to caching Netdata metric values +themselves as far as queries are concerned. The total page cache size will be greater since data collection itself will +consume additional memory as is described in the [Memory requirements](#memory-requirements) section. -The `dbengine disk space` option determines the amount of disk space in **MiB** that is dedicated -to storing Netdata metric values and all related metadata describing them. +The `dbengine disk space` option determines the amount of disk space in **MiB** that is dedicated to storing Netdata +metric values and all related metadata describing them. ## Operation -The DB engine stores chart metric values in 4096-byte pages in memory. Each chart dimension gets -its own page to store consecutive values generated from the data collectors. Those pages comprise -the **Page Cache**. +The DB engine stores chart metric values in 4096-byte pages in memory. Each chart dimension gets its own page to store +consecutive values generated from the data collectors. Those pages comprise the **Page Cache**. -When those pages fill up they are slowly compressed and flushed to disk. -It can take `4096 / 4 = 1024 seconds = 17 minutes`, for a chart dimension that is being collected -every 1 second, to fill a page. Pages can be cut short when we stop Netdata or the DB engine -instance so as to not lose the data. When we query the DB engine for data we trigger disk read -I/O requests that fill the Page Cache with the requested pages and potentially evict cold -(not recently used) pages. +When those pages fill up they are slowly compressed and flushed to disk. It can take `4096 / 4 = 1024 seconds = 17 +minutes`, for a chart dimension that is being collected every 1 second, to fill a page. Pages can be cut short when we +stop Netdata or the DB engine instance so as to not lose the data. When we query the DB engine for data we trigger disk +read I/O requests that fill the Page Cache with the requested pages and potentially evict cold (not recently used) +pages. -When the disk quota is exceeded the oldest values are removed from the DB engine at real time, by -automatically deleting the oldest datafile and journalfile pair. Any corresponding pages residing -in the Page Cache will also be invalidated and removed. The DB engine logic will try to maintain -between 10 and 20 file pairs at any point in time. +When the disk quota is exceeded the oldest values are removed from the DB engine at real time, by automatically deleting +the oldest datafile and journalfile pair. Any corresponding pages residing in the Page Cache will also be invalidated +and removed. The DB engine logic will try to maintain between 10 and 20 file pairs at any point in time. -The Database Engine uses direct I/O to avoid polluting the OS filesystem caches and does not -generate excessive I/O traffic so as to create the minimum possible interference with other -applications. +The Database Engine uses direct I/O to avoid polluting the OS filesystem caches and does not generate excessive I/O +traffic so as to create the minimum possible interference with other applications. ## Memory requirements -Using memory mode `dbengine` we can overcome most memory restrictions and store a dataset that -is much larger than the available memory. +Using memory mode `dbengine` we can overcome most memory restrictions and store a dataset that is much larger than the +available memory. -There are explicit memory requirements **per** DB engine **instance**, meaning **per** Netdata -**node** (e.g. localhost and streaming recipient nodes): +There are explicit memory requirements **per** DB engine **instance**, meaning **per** Netdata **node** (e.g. localhost +and streaming recipient nodes): -- `page cache size` must be at least `#dimensions-being-collected x 4096 x 2` bytes. +- The total page cache memory footprint will be an additional `#dimensions-being-collected x 4096 x 2` bytes over what + the user configured with `page cache size`. - an additional `#pages-on-disk x 4096 x 0.03` bytes of RAM are allocated for metadata. - roughly speaking this is 3% of the uncompressed disk space taken by the DB files. - - for very highly compressible data (compression ratio > 90%) this RAM overhead - is comparable to the disk space footprint. + - for very highly compressible data (compression ratio > 90%) this RAM overhead is comparable to the disk space + footprint. -An important observation is that RAM usage depends on both the `page cache size` and the -`dbengine disk space` options. +An important observation is that RAM usage depends on both the `page cache size` and the `dbengine disk space` options. ## File descriptor requirements -The Database Engine may keep a **significant** amount of files open per instance (e.g. per streaming -slave or master server). When configuring your system you should make sure there are at least 50 -file descriptors available per `dbengine` instance. +The Database Engine may keep a **significant** amount of files open per instance (e.g. per streaming slave or master +server). When configuring your system you should make sure there are at least 50 file descriptors available per +`dbengine` instance. -Netdata allocates 25% of the available file descriptors to its Database Engine instances. This means that only 25% -of the file descriptors that are available to the Netdata service are accessible by dbengine instances. -You should take that into account when configuring your service -or system-wide file descriptor limits. You can roughly estimate that the Netdata service needs 2048 file -descriptors for every 10 streaming slave hosts when streaming is configured to use `memory mode = dbengine`. +Netdata allocates 25% of the available file descriptors to its Database Engine instances. This means that only 25% of +the file descriptors that are available to the Netdata service are accessible by dbengine instances. You should take +that into account when configuring your service or system-wide file descriptor limits. You can roughly estimate that the +Netdata service needs 2048 file descriptors for every 10 streaming slave hosts when streaming is configured to use +`memory mode = dbengine`. -If for example one wants to allocate 65536 file descriptors to the Netdata service on a systemd system -one needs to override the Netdata service by running `sudo systemctl edit netdata` and creating a -file with contents: +If for example one wants to allocate 65536 file descriptors to the Netdata service on a systemd system one needs to +override the Netdata service by running `sudo systemctl edit netdata` and creating a file with contents: -``` +```sh [Service] LimitNOFILE=65536 ``` For other types of services one can add the line: -``` +```sh ulimit -n 65536 ``` -at the beginning of the service file. Alternatively you can change the system-wide limits of the kernel by changing `/etc/sysctl.conf`. For linux that would be: +at the beginning of the service file. Alternatively you can change the system-wide limits of the kernel by changing + `/etc/sysctl.conf`. For linux that would be: -``` +```conf fs.file-max = 65536 ``` In FreeBSD and OS X you change the lines like this: -``` +```conf kern.maxfilesperproc=65536 kern.maxfiles=65536 ``` You can apply the settings by running `sysctl -p` or by rebooting. +## Evaluation + +We have evaluated the performance of the `dbengine` API that the netdata daemon uses internally. This is **not** the +web API of netdata. Our benchmarks ran on a **single** `dbengine` instance, multiple of which can be running in a +netdata master server. We used a server with an AMD Ryzen Threadripper 2950X 16-Core Processor and 2 disk drives, a +Seagate Constellation ES.3 2TB magnetic HDD and a SAMSUNG MZQLB960HAJR-00007 960GB NAND Flash SSD. + +For our workload, we defined 32 charts with 128 metrics each, giving us a total of 4096 metrics. We defined 1 worker +thread per chart (32 threads) that generates new data points with a data generation interval of 1 second. The time axis +of the time-series is emulated and accelerated so that the worker threads can generate as many data points as possible +without delays. + +We also defined 32 worker threads that perform queries on random metrics with semi-random time ranges. The +starting time of the query is randomly selected between the beginning of the time-series and the time of the latest data +point. The ending time is randomly selected between 1 second and 1 hour after the starting time. The pseudo-random +numbers are generated with a uniform distribution. + +The data are written to the database at the same time as they are read from it. This is a concurrent read/write mixed +workload with a duration of 60 seconds. The faster `dbengine` runs, the bigger the dataset size becomes since more +data points will be generated. We set a page cache size of 64MiB for the two disk-bound scenarios. This way, the dataset +size of the metric data is much bigger than the RAM that is being used for caching so as to trigger I/O requests most +of the time. In our final scenario, we set the page cache size to 16 GiB. That way, the dataset fits in the page cache +so as to avoid all disk bottlenecks. + +The reported numbers are the following: + +| device | page cache | dataset | reads/sec | writes/sec | +| :---: | :---: | ---: | ---: | ---: | +| HDD | 64 MiB | 4.1 GiB | 813K | 18.0M | +| SSD | 64 MiB | 9.8 GiB | 1.7M | 43.0M | +| N/A | 16 GiB | 6.8 GiB |118.2M | 30.2M | + +where "reads/sec" is the number of metric data points being read from the database via its API per second and +"writes/sec" is the number of metric data points being written to the database per second. + +Notice that the HDD numbers are pretty high and not much slower than the SSD numbers. This is thanks to the database +engine design being optimized for rotating media. In the database engine disk I/O requests are: + +- asynchronous to mask the high I/O latency of HDDs. +- mostly large to reduce the amount of HDD seeking time. +- mostly sequential to reduce the amount of HDD seeking time. +- compressed to reduce the amount of required throughput. + +As a result, the HDD is not thousands of times slower than the SSD, which is typical for other workloads. + +An interesting observation to make is that the CPU-bound run (16 GiB page cache) generates fewer data than the SSD run +(6.8 GiB vs 9.8 GiB). The reason is that the 32 reader threads in the SSD scenario are more frequently blocked by I/O, +and generate a read load of 1.7M/sec, whereas in the CPU-bound scenario the read load is 70 times higher at 118M/sec. +Consequently, there is a significant degree of interference by the reader threads, that slow down the writer threads. +This is also possible because the interference effects are greater than the SSD impact on data generation throughput. + [![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fdatabase%2Fengine%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/database/engine/pagecache.c b/database/engine/pagecache.c index 457bcb218..a419ba981 100644 --- a/database/engine/pagecache.c +++ b/database/engine/pagecache.c @@ -209,9 +209,31 @@ static void pg_cache_release_pages(struct rrdengine_instance *ctx, unsigned numb pg_cache_release_pages_unsafe(ctx, number); uv_rwlock_wrunlock(&pg_cache->pg_cache_rwlock); } + +/* + * This function returns the maximum number of pages allowed in the page cache. + * The caller must hold the page cache lock. + */ +static inline unsigned long pg_cache_hard_limit(struct rrdengine_instance *ctx) +{ + /* it's twice the number of producers since we pin 2 pages per producer */ + return ctx->max_cache_pages + 2 * (unsigned long)ctx->stats.metric_API_producers; +} + +/* + * This function returns the low watermark number of pages in the page cache. The page cache should strive to keep the + * number of pages below that number. + * The caller must hold the page cache lock. + */ +static inline unsigned long pg_cache_soft_limit(struct rrdengine_instance *ctx) +{ + /* it's twice the number of producers since we pin 2 pages per producer */ + return ctx->cache_pages_low_watermark + 2 * (unsigned long)ctx->stats.metric_API_producers; +} + /* * This function will block until it reserves #number populated pages. - * It will trigger evictions or dirty page flushing if the ctx->max_cache_pages limit is hit. + * It will trigger evictions or dirty page flushing if the pg_cache_hard_limit() limit is hit. */ static void pg_cache_reserve_pages(struct rrdengine_instance *ctx, unsigned number) { @@ -223,10 +245,10 @@ static void pg_cache_reserve_pages(struct rrdengine_instance *ctx, unsigned numb assert(number < ctx->max_cache_pages); uv_rwlock_wrlock(&pg_cache->pg_cache_rwlock); - if (pg_cache->populated_pages + number >= ctx->max_cache_pages + 1) + if (pg_cache->populated_pages + number >= pg_cache_hard_limit(ctx) + 1) debug(D_RRDENGINE, "==Page cache full. Reserving %u pages.==", number); - while (pg_cache->populated_pages + number >= ctx->max_cache_pages + 1) { + while (pg_cache->populated_pages + number >= pg_cache_hard_limit(ctx) + 1) { if (!pg_cache_try_evict_one_page_unsafe(ctx)) { /* failed to evict */ @@ -260,7 +282,7 @@ static void pg_cache_reserve_pages(struct rrdengine_instance *ctx, unsigned numb /* * This function will attempt to reserve #number populated pages. - * It may trigger evictions if the ctx->cache_pages_low_watermark limit is hit. + * It may trigger evictions if the pg_cache_soft_limit() limit is hit. * Returns 0 on failure and 1 on success. */ static int pg_cache_try_reserve_pages(struct rrdengine_instance *ctx, unsigned number) @@ -272,7 +294,7 @@ static int pg_cache_try_reserve_pages(struct rrdengine_instance *ctx, unsigned n assert(number < ctx->max_cache_pages); uv_rwlock_wrlock(&pg_cache->pg_cache_rwlock); - if (pg_cache->populated_pages + number >= ctx->cache_pages_low_watermark + 1) { + if (pg_cache->populated_pages + number >= pg_cache_soft_limit(ctx) + 1) { debug(D_RRDENGINE, "==Page cache full. Trying to reserve %u pages.==", number); @@ -280,11 +302,11 @@ static int pg_cache_try_reserve_pages(struct rrdengine_instance *ctx, unsigned n if (!pg_cache_try_evict_one_page_unsafe(ctx)) break; ++count; - } while (pg_cache->populated_pages + number >= ctx->cache_pages_low_watermark + 1); + } while (pg_cache->populated_pages + number >= pg_cache_soft_limit(ctx) + 1); debug(D_RRDENGINE, "Evicted %u pages.", count); } - if (pg_cache->populated_pages + number < ctx->max_cache_pages + 1) { + if (pg_cache->populated_pages + number < pg_cache_hard_limit(ctx) + 1) { pg_cache->populated_pages += number; ret = 1; /* success */ } diff --git a/database/engine/pagecache.h b/database/engine/pagecache.h index d464211e9..ab1a5c1ad 100644 --- a/database/engine/pagecache.h +++ b/database/engine/pagecache.h @@ -183,4 +183,42 @@ extern void free_page_cache(struct rrdengine_instance *ctx); extern void pg_cache_add_new_metric_time(struct pg_cache_page_index *page_index, struct rrdeng_page_descr *descr); extern void pg_cache_update_metric_times(struct pg_cache_page_index *page_index); +static inline void + pg_cache_atomic_get_pg_info(struct rrdeng_page_descr *descr, usec_t *end_timep, uint32_t *page_lengthp) +{ + usec_t end_time, old_end_time; + uint32_t page_length; + + if (NULL == descr->extent) { + /* this page is currently being modified, get consistent info locklessly */ + do { + end_time = descr->end_time; + __sync_synchronize(); + old_end_time = end_time; + page_length = descr->page_length; + __sync_synchronize(); + end_time = descr->end_time; + __sync_synchronize(); + } while ((end_time != old_end_time || (end_time & 1) != 0)); + + *end_timep = end_time; + *page_lengthp = page_length; + } else { + *end_timep = descr->end_time; + *page_lengthp = descr->page_length; + } +} + +/* The caller must hold a reference to the page and must have already set the new data */ +static inline void pg_cache_atomic_set_pg_info(struct rrdeng_page_descr *descr, usec_t end_time, uint32_t page_length) +{ + assert(!(end_time & 1)); + __sync_synchronize(); + descr->end_time |= 1; /* mark start of uncertainty period by adding 1 microsecond */ + __sync_synchronize(); + descr->page_length = page_length; + __sync_synchronize(); + descr->end_time = end_time; /* mark end of uncertainty period */ +} + #endif /* NETDATA_PAGECACHE_H */ diff --git a/database/engine/rrdengine.c b/database/engine/rrdengine.c index 36d917541..896d71f16 100644 --- a/database/engine/rrdengine.c +++ b/database/engine/rrdengine.c @@ -5,6 +5,8 @@ rrdeng_stats_t global_io_errors = 0; rrdeng_stats_t global_fs_errors = 0; +rrdeng_stats_t global_pg_cache_warnings = 0; +rrdeng_stats_t global_pg_cache_errors = 0; rrdeng_stats_t rrdeng_reserved_file_descriptors = 0; void sanity_check(void) @@ -251,13 +253,10 @@ void flush_pages_cb(uv_fs_t* req) { struct rrdengine_worker_config* wc = req->loop->data; struct rrdengine_instance *ctx = wc->ctx; - struct page_cache *pg_cache = &ctx->pg_cache; struct extent_io_descriptor *xt_io_descr; struct rrdeng_page_descr *descr; struct page_cache_descr *pg_cache_descr; - int ret; unsigned i, count; - Word_t commit_id; xt_io_descr = req->data; if (req->result < 0) { @@ -277,13 +276,6 @@ void flush_pages_cb(uv_fs_t* req) /* care, we don't hold the descriptor mutex */ descr = xt_io_descr->descr_array[i]; - uv_rwlock_wrlock(&pg_cache->commited_page_index.lock); - commit_id = xt_io_descr->descr_commit_idx_array[i]; - ret = JudyLDel(&pg_cache->commited_page_index.JudyL_array, commit_id, PJE0); - assert(1 == ret); - --pg_cache->commited_page_index.nr_commited_pages; - uv_rwlock_wrunlock(&pg_cache->commited_page_index.lock); - pg_cache_replaceQ_insert(ctx, descr); rrdeng_page_descr_mutex_lock(ctx, descr); @@ -331,7 +323,7 @@ static int do_flush_pages(struct rrdengine_worker_config* wc, int force, struct if (force) { debug(D_RRDENGINE, "Asynchronous flushing of extent has been forced by page pressure."); } - uv_rwlock_rdlock(&pg_cache->commited_page_index.lock); + uv_rwlock_wrlock(&pg_cache->commited_page_index.lock); for (Index = 0, count = 0, uncompressed_payload_length = 0, PValue = JudyLFirst(pg_cache->commited_page_index.JudyL_array, &Index, PJE0), descr = unlikely(NULL == PValue) ? NULL : *PValue ; @@ -340,11 +332,15 @@ static int do_flush_pages(struct rrdengine_worker_config* wc, int force, struct PValue = JudyLNext(pg_cache->commited_page_index.JudyL_array, &Index, PJE0), descr = unlikely(NULL == PValue) ? NULL : *PValue) { + uint8_t page_write_pending; + assert(0 != descr->page_length); + page_write_pending = 0; rrdeng_page_descr_mutex_lock(ctx, descr); pg_cache_descr = descr->pg_cache_descr; if (!(pg_cache_descr->flags & RRD_PAGE_WRITE_PENDING)) { + page_write_pending = 1; /* care, no reference being held */ pg_cache_descr->flags |= RRD_PAGE_WRITE_PENDING; uncompressed_payload_length += descr->page_length; @@ -352,8 +348,14 @@ static int do_flush_pages(struct rrdengine_worker_config* wc, int force, struct eligible_pages[count++] = descr; } rrdeng_page_descr_mutex_unlock(ctx, descr); + + if (page_write_pending) { + ret = JudyLDel(&pg_cache->commited_page_index.JudyL_array, Index, PJE0); + assert(1 == ret); + --pg_cache->commited_page_index.nr_commited_pages; + } } - uv_rwlock_rdunlock(&pg_cache->commited_page_index.lock); + uv_rwlock_wrunlock(&pg_cache->commited_page_index.lock); if (!count) { debug(D_RRDENGINE, "%s: no pages eligible for flushing.", __func__); @@ -813,47 +815,6 @@ error_after_loop_init: complete(&ctx->rrdengine_completion); } - -#define NR_PAGES (256) -static void basic_functional_test(struct rrdengine_instance *ctx) -{ - int i, j, failed_validations; - uuid_t uuid[NR_PAGES]; - void *buf; - struct rrdeng_page_descr *handle[NR_PAGES]; - char uuid_str[UUID_STR_LEN]; - char backup[NR_PAGES][UUID_STR_LEN * 100]; /* backup storage for page data verification */ - - for (i = 0 ; i < NR_PAGES ; ++i) { - uuid_generate(uuid[i]); - uuid_unparse_lower(uuid[i], uuid_str); -// fprintf(stderr, "Generated uuid[%d]=%s\n", i, uuid_str); - buf = rrdeng_create_page(ctx, &uuid[i], &handle[i]); - /* Each page contains 10 times its own UUID stringified */ - for (j = 0 ; j < 100 ; ++j) { - strcpy(buf + UUID_STR_LEN * j, uuid_str); - strcpy(backup[i] + UUID_STR_LEN * j, uuid_str); - } - rrdeng_commit_page(ctx, handle[i], (Word_t)i); - } - fprintf(stderr, "\n********** CREATED %d METRIC PAGES ***********\n\n", NR_PAGES); - failed_validations = 0; - for (i = 0 ; i < NR_PAGES ; ++i) { - buf = rrdeng_get_latest_page(ctx, &uuid[i], (void **)&handle[i]); - if (NULL == buf) { - ++failed_validations; - fprintf(stderr, "Page %d was LOST.\n", i); - } - if (memcmp(backup[i], buf, UUID_STR_LEN * 100)) { - ++failed_validations; - fprintf(stderr, "Page %d data comparison with backup FAILED validation.\n", i); - } - rrdeng_put_page(ctx, handle[i]); - } - fprintf(stderr, "\n********** CORRECTLY VALIDATED %d/%d METRIC PAGES ***********\n\n", - NR_PAGES - failed_validations, NR_PAGES); - -} /* C entry point for development purposes * make "LDFLAGS=-errdengine_main" */ @@ -866,8 +827,6 @@ void rrdengine_main(void) if (ret) { exit(ret); } - basic_functional_test(ctx); - rrdeng_exit(ctx); fprintf(stderr, "Hello world!"); exit(0); diff --git a/database/engine/rrdengineapi.c b/database/engine/rrdengineapi.c index bf373f31c..5fa23d8fd 100644 --- a/database/engine/rrdengineapi.c +++ b/database/engine/rrdengineapi.c @@ -4,7 +4,7 @@ /* Default global database instance */ static struct rrdengine_instance default_global_ctx; -int default_rrdeng_page_cache_mb = RRDENG_MIN_PAGE_CACHE_SIZE_MB; +int default_rrdeng_page_cache_mb = 32; int default_rrdeng_disk_quota_mb = RRDENG_MIN_DISK_SPACE_MB; /* @@ -95,9 +95,8 @@ void rrdeng_store_metric_flush_current_page(RRDDIM *rd) if (likely(descr->page_length)) { int ret, page_is_empty; -#ifdef NETDATA_INTERNAL_CHECKS rrd_stat_atomic_add(&ctx->stats.metric_API_producers, -1); -#endif + if (handle->prev_descr) { /* unpin old second page */ pg_cache_put(ctx, handle->prev_descr); @@ -185,16 +184,14 @@ void rrdeng_store_metric_next(RRDDIM *rd, usec_t point_in_time, storage_number n } page = descr->pg_cache_descr->page; page[descr->page_length / sizeof(number)] = number; - descr->end_time = point_in_time; - descr->page_length += sizeof(number); + pg_cache_atomic_set_pg_info(descr, point_in_time, descr->page_length + sizeof(number)); + if (perfect_page_alignment) rd->rrdset->rrddim_page_alignment = descr->page_length; if (unlikely(INVALID_TIME == descr->start_time)) { descr->start_time = point_in_time; -#ifdef NETDATA_INTERNAL_CHECKS rrd_stat_atomic_add(&ctx->stats.metric_API_producers, 1); -#endif pg_cache_insert(ctx, handle->page_index, descr); } else { pg_cache_add_new_metric_time(handle->page_index, descr); @@ -312,8 +309,9 @@ unsigned rrdeng_variable_step_boundaries(RRDSET *st, time_t start_time, time_t e curr = &page_info_array[i]; *pginfo_to_points(curr) = 0; /* initialize to invalid page */ *pginfo_to_dt(curr) = 0; /* no known data collection interval yet */ - if (unlikely(INVALID_TIME == curr->start_time || INVALID_TIME == curr->end_time)) { - info("Ignoring page with invalid timestamp."); + if (unlikely(INVALID_TIME == curr->start_time || INVALID_TIME == curr->end_time || + curr->end_time < curr->start_time)) { + info("Ignoring page with invalid timestamps."); prev = old_prev; continue; } @@ -366,7 +364,7 @@ unsigned rrdeng_variable_step_boundaries(RRDSET *st, time_t start_time, time_t e continue; } - if (unlikely(0 == dt)) { /* unknown data collection interval */ + if (unlikely(0 == *pginfo_to_dt(curr))) { /* unknown data collection interval */ assert(1 == page_points); if (likely(NULL != prev)) { /* get interval from previous page */ @@ -454,7 +452,8 @@ storage_number rrdeng_load_metric_next(struct rrddim_query_handle *rrdimm_handle struct rrdeng_page_descr *descr; storage_number *page, ret; unsigned position, entries; - usec_t next_page_time, current_position_time; + usec_t next_page_time, current_position_time, page_end_time; + uint32_t page_length; handle = &rrdimm_handle->rrdeng; if (unlikely(INVALID_TIME == handle->next_page_time)) { @@ -464,15 +463,17 @@ storage_number rrdeng_load_metric_next(struct rrddim_query_handle *rrdimm_handle if (unlikely(NULL == (descr = handle->descr))) { /* it's the first call */ next_page_time = handle->next_page_time * USEC_PER_SEC; + } else { + pg_cache_atomic_get_pg_info(descr, &page_end_time, &page_length); } position = handle->position + 1; if (unlikely(NULL == descr || - position >= (descr->page_length / sizeof(storage_number)))) { + position >= (page_length / sizeof(storage_number)))) { /* We need to get a new page */ if (descr) { /* Drop old page's reference */ - handle->next_page_time = (descr->end_time / USEC_PER_SEC) + 1; + handle->next_page_time = (page_end_time / USEC_PER_SEC) + 1; if (unlikely(handle->next_page_time > rrdimm_handle->end_time)) { goto no_more_metrics; } @@ -492,26 +493,27 @@ storage_number rrdeng_load_metric_next(struct rrddim_query_handle *rrdimm_handle rrd_stat_atomic_add(&ctx->stats.metric_API_consumers, 1); #endif handle->descr = descr; + pg_cache_atomic_get_pg_info(descr, &page_end_time, &page_length); if (unlikely(INVALID_TIME == descr->start_time || - INVALID_TIME == descr->end_time)) { + INVALID_TIME == page_end_time)) { goto no_more_metrics; } - if (unlikely(descr->start_time != descr->end_time && next_page_time > descr->start_time)) { + if (unlikely(descr->start_time != page_end_time && next_page_time > descr->start_time)) { /* we're in the middle of the page somewhere */ - entries = descr->page_length / sizeof(storage_number); - position = ((uint64_t)(next_page_time - descr->start_time)) * entries / - (descr->end_time - descr->start_time + 1); + entries = page_length / sizeof(storage_number); + position = ((uint64_t)(next_page_time - descr->start_time)) * (entries - 1) / + (page_end_time - descr->start_time); } else { position = 0; } } page = descr->pg_cache_descr->page; ret = page[position]; - entries = descr->page_length / sizeof(storage_number); + entries = page_length / sizeof(storage_number); if (entries > 1) { usec_t dt; - dt = (descr->end_time - descr->start_time) / (entries - 1); + dt = (page_end_time - descr->start_time) / (entries - 1); current_position_time = descr->start_time + position * dt; } else { current_position_time = descr->start_time; diff --git a/database/engine/rrdengineapi.h b/database/engine/rrdengineapi.h index 9b1ab1874..c876705e4 100644 --- a/database/engine/rrdengineapi.h +++ b/database/engine/rrdengineapi.h @@ -5,7 +5,7 @@ #include "rrdengine.h" -#define RRDENG_MIN_PAGE_CACHE_SIZE_MB (32) +#define RRDENG_MIN_PAGE_CACHE_SIZE_MB (8) #define RRDENG_MIN_DISK_SPACE_MB (256) #define RRDENG_NR_STATS (33) diff --git a/database/engine/rrdenginelib.c b/database/engine/rrdenginelib.c index 96504b275..1a04dc2a4 100644 --- a/database/engine/rrdenginelib.c +++ b/database/engine/rrdenginelib.c @@ -8,7 +8,7 @@ void print_page_cache_descr(struct rrdeng_page_descr *descr) { struct page_cache_descr *pg_cache_descr = descr->pg_cache_descr; char uuid_str[UUID_STR_LEN]; - char str[BUFSIZE]; + char str[BUFSIZE + 1]; int pos = 0; uuid_unparse_lower(*descr->id, uuid_str); @@ -31,7 +31,7 @@ void print_page_cache_descr(struct rrdeng_page_descr *descr) void print_page_descr(struct rrdeng_page_descr *descr) { char uuid_str[UUID_STR_LEN]; - char str[BUFSIZE]; + char str[BUFSIZE + 1]; int pos = 0; uuid_unparse_lower(*descr->id, uuid_str); diff --git a/database/rrd.c b/database/rrd.c index 31ad3f07e..dcab65189 100644 --- a/database/rrd.c +++ b/database/rrd.c @@ -15,7 +15,11 @@ int rrd_delete_unupdated_dimensions = 0; int default_rrd_update_every = UPDATE_EVERY; int default_rrd_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; +#ifdef ENABLE_DBENGINE +RRD_MEMORY_MODE default_rrd_memory_mode = RRD_MEMORY_MODE_DBENGINE; +#else RRD_MEMORY_MODE default_rrd_memory_mode = RRD_MEMORY_MODE_SAVE; +#endif int gap_when_lost_iterations_above = 1; diff --git a/database/rrd.h b/database/rrd.h index 39e881252..e335f0dd0 100644 --- a/database/rrd.h +++ b/database/rrd.h @@ -697,6 +697,7 @@ struct rrdhost { // RRDCALCs may be linked to charts at any point // (charts may or may not exist when these are loaded) RRDCALC *alarms; + RRDCALC *alarms_with_foreach; avl_tree_lock alarms_idx_health_log; avl_tree_lock alarms_idx_name; @@ -709,6 +710,7 @@ struct rrdhost { // these are used to create alarms when charts // are created or renamed, that match them RRDCALCTEMPLATE *templates; + RRDCALCTEMPLATE *alarms_template_with_foreach; // ------------------------------------------------------------------------ @@ -1008,6 +1010,7 @@ static inline time_t rrdset_slot2time(RRDSET *st, size_t slot) { // ---------------------------------------------------------------------------- // RRD DIMENSION functions +extern void rrdcalc_link_to_rrddim(RRDDIM *rd, RRDSET *st, RRDHOST *host); extern RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collected_number multiplier, collected_number divisor, RRD_ALGORITHM algorithm, RRD_MEMORY_MODE memory_mode); #define rrddim_add(st, id, name, multiplier, divisor, algorithm) rrddim_add_custom(st, id, name, multiplier, divisor, algorithm, (st)->rrd_memory_mode) diff --git a/database/rrdcalc.c b/database/rrdcalc.c index 908fc2ebf..9f16ce374 100644 --- a/database/rrdcalc.c +++ b/database/rrdcalc.c @@ -255,6 +255,53 @@ inline uint32_t rrdcalc_get_unique_id(RRDHOST *host, const char *chart, const ch return host->health_log.next_alarm_id++; } +/** + * Alarm name with dimension + * + * Change the name of the current alarm appending a new diagram. + * + * @param name the alarm name + * @param namelen is the length of the previous vector. + * @param dim the dimension of the chart. + * @param dimlen is the length of the previous vector. + * + * @return It returns the new name on success and the old otherwise + */ +char *alarm_name_with_dim(char *name, size_t namelen, const char *dim, size_t dimlen) { + char *newname,*move; + + newname = malloc(namelen + dimlen + 2); + if(newname) { + move = newname; + memcpy(move, name, namelen); + move += namelen; + + *move++ = '_'; + memcpy(move, dim, dimlen); + move += dimlen; + *move = '\0'; + } else { + newname = name; + } + + return newname; +} + +/** + * Remove pipe comma + * + * Remove the pipes and commas converting to space. + * + * @param str the string to change. + */ +void dimension_remove_pipe_comma(char *str) { + while(*str) { + if(*str == '|' || *str == ',') *str = ' '; + + str++; + } +} + inline void rrdcalc_add_to_host(RRDHOST *host, RRDCALC *rc) { rrdhost_check_rdlock(host); @@ -282,24 +329,39 @@ inline void rrdcalc_add_to_host(RRDHOST *host, RRDCALC *rc) { rc->critical->rrdcalc = rc; } - // link it to the host - if(likely(host->alarms)) { - // append it - RRDCALC *t; - for(t = host->alarms; t && t->next ; t = t->next) ; - t->next = rc; - } - else { - host->alarms = rc; - } + if(!rc->foreachdim) { + // link it to the host alarms list + if(likely(host->alarms)) { + // append it + RRDCALC *t; + for(t = host->alarms; t && t->next ; t = t->next) ; + t->next = rc; + } + else { + host->alarms = rc; + } - // link it to its chart - RRDSET *st; - rrdset_foreach_read(st, host) { - if(rrdcalc_is_matching_this_rrdset(rc, st)) { - rrdsetcalc_link(st, rc); - break; + // link it to its chart + RRDSET *st; + rrdset_foreach_read(st, host) { + if(rrdcalc_is_matching_this_rrdset(rc, st)) { + rrdsetcalc_link(st, rc); + break; + } + } + } else { + //link it case there is a foreach + if(likely(host->alarms_with_foreach)) { + // append it + RRDCALC *t; + for(t = host->alarms_with_foreach; t && t->next ; t = t->next) ; + t->next = rc; } + else { + host->alarms_with_foreach = rc; + } + + //I am not linking this alarm direct to the host here, this will be done when the children is created } } @@ -311,13 +373,19 @@ inline RRDCALC *rrdcalc_create_from_template(RRDHOST *host, RRDCALCTEMPLATE *rt, RRDCALC *rc = callocz(1, sizeof(RRDCALC)); rc->next_event_id = 1; - rc->id = rrdcalc_get_unique_id(host, chart, rt->name, &rc->next_event_id); rc->name = strdupz(rt->name); rc->hash = simple_hash(rc->name); rc->chart = strdupz(chart); rc->hash_chart = simple_hash(rc->chart); + rc->id = rrdcalc_get_unique_id(host, rc->chart, rc->name, &rc->next_event_id); + if(rt->dimensions) rc->dimensions = strdupz(rt->dimensions); + if(rt->foreachdim) { + rc->foreachdim = strdupz(rt->foreachdim); + rc->spdim = health_pattern_from_foreach(rc->foreachdim); + } + rc->foreachcounter = rt->foreachcounter; rc->green = rt->green; rc->red = rt->red; @@ -361,7 +429,7 @@ inline RRDCALC *rrdcalc_create_from_template(RRDHOST *host, RRDCALCTEMPLATE *rt, error("Health alarm '%s.%s': failed to re-parse critical expression '%s'", chart, rt->name, rt->critical->source); } - debug(D_HEALTH, "Health runtime added alarm '%s.%s': exec '%s', recipient '%s', green " CALCULATED_NUMBER_FORMAT_AUTO ", red " CALCULATED_NUMBER_FORMAT_AUTO ", lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f, warn_repeat_every %u, crit_repeat_every %u", + debug(D_HEALTH, "Health runtime added alarm '%s.%s': exec '%s', recipient '%s', green " CALCULATED_NUMBER_FORMAT_AUTO ", red " CALCULATED_NUMBER_FORMAT_AUTO ", lookup: group %d, after %d, before %d, options %u, dimensions '%s', for each dimension '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f, warn_repeat_every %u, crit_repeat_every %u", (rc->chart)?rc->chart:"NOCHART", rc->name, (rc->exec)?rc->exec:"DEFAULT", @@ -373,6 +441,7 @@ inline RRDCALC *rrdcalc_create_from_template(RRDHOST *host, RRDCALCTEMPLATE *rt, rc->before, rc->options, (rc->dimensions)?rc->dimensions:"NONE", + (rc->foreachdim)?rc->foreachdim:"NONE", rc->update_every, (rc->calculation)?rc->calculation->parsed_as:"NONE", (rc->warning)?rc->warning->parsed_as:"NONE", @@ -387,18 +456,94 @@ inline RRDCALC *rrdcalc_create_from_template(RRDHOST *host, RRDCALCTEMPLATE *rt, ); rrdcalc_add_to_host(host, rc); - RRDCALC *rdcmp = (RRDCALC *) avl_insert_lock(&(host)->alarms_idx_health_log,(avl *)rc); - if (rdcmp != rc) { - error("Cannot insert the alarm index ID %s",rc->name); + if(!rt->foreachdim) { + RRDCALC *rdcmp = (RRDCALC *) avl_insert_lock(&(host)->alarms_idx_health_log,(avl *)rc); + if (rdcmp != rc) { + error("Cannot insert the alarm index ID %s",rc->name); + } } return rc; } +/** + * Create from RRDCALC + * + * Create a new alarm using another alarm as template. + * + * @param rc is the alarm that will be used as source + * @param host is the host structure. + * @param name is the newest chart name. + * @param dimension is the current dimension + * @param foreachdim the whole list of dimension + * + * @return it returns the new alarm changed. + */ +inline RRDCALC *rrdcalc_create_from_rrdcalc(RRDCALC *rc, RRDHOST *host, const char *name, const char *dimension) { + RRDCALC *newrc = callocz(1, sizeof(RRDCALC)); + + newrc->next_event_id = 1; + newrc->id = rrdcalc_get_unique_id(host, rc->chart, name, &rc->next_event_id); + newrc->name = (char *)name; + newrc->hash = simple_hash(newrc->name); + newrc->chart = strdupz(rc->chart); + newrc->hash_chart = simple_hash(rc->chart); + + newrc->dimensions = strdupz(dimension); + newrc->foreachdim = NULL; + rc->foreachcounter++; + newrc->foreachcounter = rc->foreachcounter; + + newrc->green = rc->green; + newrc->red = rc->red; + newrc->value = NAN; + newrc->old_value = NAN; + + newrc->delay_up_duration = rc->delay_up_duration; + newrc->delay_down_duration = rc->delay_down_duration; + newrc->delay_max_duration = rc->delay_max_duration; + newrc->delay_multiplier = rc->delay_multiplier; + + newrc->last_repeat = 0; + newrc->warn_repeat_every = rc->warn_repeat_every; + newrc->crit_repeat_every = rc->crit_repeat_every; + + newrc->group = rc->group; + newrc->after = rc->after; + newrc->before = rc->before; + newrc->update_every = rc->update_every; + newrc->options = rc->options; + + if(rc->exec) newrc->exec = strdupz(rc->exec); + if(rc->recipient) newrc->recipient = strdupz(rc->recipient); + if(rc->source) newrc->source = strdupz(rc->source); + if(rc->units) newrc->units = strdupz(rc->units); + if(rc->info) newrc->info = strdupz(rc->info); + + if(rc->calculation) { + newrc->calculation = expression_parse(rc->calculation->source, NULL, NULL); + if(!newrc->calculation) + error("Health alarm '%s.%s': failed to parse calculation expression '%s'", rc->chart, rc->name, rc->calculation->source); + } + + if(rc->warning) { + newrc->warning = expression_parse(rc->warning->source, NULL, NULL); + if(!newrc->warning) + error("Health alarm '%s.%s': failed to re-parse warning expression '%s'", rc->chart, rc->name, rc->warning->source); + } + + if(rc->critical) { + newrc->critical = expression_parse(rc->critical->source, NULL, NULL); + if(!newrc->critical) + error("Health alarm '%s.%s': failed to re-parse critical expression '%s'", rc->chart, rc->name, rc->critical->source); + } + + return newrc; +} + void rrdcalc_free(RRDCALC *rc) { if(unlikely(!rc)) return; - expression_free(rc->calculation); expression_free(rc->warning); expression_free(rc->critical); @@ -407,11 +552,13 @@ void rrdcalc_free(RRDCALC *rc) { freez(rc->chart); freez(rc->family); freez(rc->dimensions); + freez(rc->foreachdim); freez(rc->exec); freez(rc->recipient); freez(rc->source); freez(rc->units); freez(rc->info); + simple_pattern_free(rc->spdim); freez(rc); } @@ -437,21 +584,19 @@ void rrdcalc_unlink_and_free(RRDHOST *host, RRDCALC *rc) { error("Cannot unlink alarm '%s.%s' from host '%s': not found", rc->chart?rc->chart:"NOCHART", rc->name, host->hostname); } - if (rc) { - RRDCALC *rdcmp = (RRDCALC *) avl_search_lock(&(host)->alarms_idx_health_log, (avl *)rc); - if (rdcmp) { - rdcmp = (RRDCALC *) avl_remove_lock(&(host)->alarms_idx_health_log, (avl *)rc); - if (!rdcmp) { - error("Cannot remove the health alarm index from health_log"); - } + RRDCALC *rdcmp = (RRDCALC *) avl_search_lock(&(host)->alarms_idx_health_log, (avl *)rc); + if (rdcmp) { + rdcmp = (RRDCALC *) avl_remove_lock(&(host)->alarms_idx_health_log, (avl *)rc); + if (!rdcmp) { + error("Cannot remove the health alarm index from health_log"); } + } - rdcmp = (RRDCALC *) avl_search_lock(&(host)->alarms_idx_name, (avl *)rc); - if (rdcmp) { - rdcmp = (RRDCALC *) avl_remove_lock(&(host)->alarms_idx_name, (avl *)rc); - if (!rdcmp) { - error("Cannot remove the health alarm index from idx_name"); - } + rdcmp = (RRDCALC *) avl_search_lock(&(host)->alarms_idx_name, (avl *)rc); + if (rdcmp) { + rdcmp = (RRDCALC *) avl_remove_lock(&(host)->alarms_idx_name, (avl *)rc); + if (!rdcmp) { + error("Cannot remove the health alarm index from idx_name"); } } diff --git a/database/rrdcalc.h b/database/rrdcalc.h index f0c34b543..e0b632597 100644 --- a/database/rrdcalc.h +++ b/database/rrdcalc.h @@ -37,7 +37,7 @@ struct rrdcalc { uint32_t next_event_id; // the next event id that will be used for this alarm char *name; // the name of this alarm - uint32_t hash; + uint32_t hash; // the hash of the alarm name char *exec; // the command to execute when this alarm switches state char *recipient; // the recipient of the alarm (the first parameter to exec) @@ -59,7 +59,11 @@ struct rrdcalc { // database lookup settings char *dimensions; // the chart dimensions - RRDR_GROUPING group; // grouping method: average, max, etc. + char *foreachdim; // the group of dimensions that the `foreach` will be applied. + SIMPLE_PATTERN *spdim; // used if and only if there is a simple pattern for the chart. + int foreachcounter; // the number of alarms created with foreachdim, this also works as an id of the + // children + RRDR_GROUPING group; // grouping method: average, max, etc. int before; // ending point in time-series int after; // starting point in time-series uint32_t options; // calculation options @@ -148,7 +152,10 @@ extern void rrdcalc_unlink_and_free(RRDHOST *host, RRDCALC *rc); extern int rrdcalc_exists(RRDHOST *host, const char *chart, const char *name, uint32_t hash_chart, uint32_t hash_name); extern uint32_t rrdcalc_get_unique_id(RRDHOST *host, const char *chart, const char *name, uint32_t *next_event_id); extern RRDCALC *rrdcalc_create_from_template(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *chart); +extern RRDCALC *rrdcalc_create_from_rrdcalc(RRDCALC *rc, RRDHOST *host, const char *name, const char *dimension); extern void rrdcalc_add_to_host(RRDHOST *host, RRDCALC *rc); +extern void dimension_remove_pipe_comma(char *str); +extern char *alarm_name_with_dim(char *name, size_t namelen, const char *dim, size_t dimlen); static inline int rrdcalc_isrepeating(RRDCALC *rc) { if (unlikely(rc->warn_repeat_every > 0 || rc->crit_repeat_every > 0)) { diff --git a/database/rrdcalctemplate.c b/database/rrdcalctemplate.c index f2b9767c6..f7a085561 100644 --- a/database/rrdcalctemplate.c +++ b/database/rrdcalctemplate.c @@ -5,23 +5,35 @@ // ---------------------------------------------------------------------------- // RRDCALCTEMPLATE management +/** + * RRDCALC TEMPLATE LINK MATCHING + * + * @param rt is the template used to create the chart. + * @param st is the chart where the alarm will be attached. + */ +void rrdcalctemplate_link_matching_test(RRDCALCTEMPLATE *rt, RRDSET *st, RRDHOST *host ) { + if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context) + && (!rt->family_pattern || simple_pattern_matches(rt->family_pattern, st->family))) { + RRDCALC *rc = rrdcalc_create_from_template(host, rt, st->id); + if(unlikely(!rc)) + info("Health tried to create alarm from template '%s' on chart '%s' of host '%s', but it failed", rt->name, st->id, host->hostname); +#ifdef NETDATA_INTERNAL_CHECKS + else if(rc->rrdset != st && !rc->foreachdim) //When we have a template with foreadhdim, the child will be added to the index late + error("Health alarm '%s.%s' should be linked to chart '%s', but it is not", rc->chart?rc->chart:"NOCHART", rc->name, st->id); +#endif + } +} void rrdcalctemplate_link_matching(RRDSET *st) { RRDHOST *host = st->rrdhost; RRDCALCTEMPLATE *rt; for(rt = host->templates; rt ; rt = rt->next) { - if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context) - && (!rt->family_pattern || simple_pattern_matches(rt->family_pattern, st->family))) { - RRDCALC *rc = rrdcalc_create_from_template(host, rt, st->id); - if(unlikely(!rc)) - info("Health tried to create alarm from template '%s' on chart '%s' of host '%s', but it failed", rt->name, st->id, host->hostname); + rrdcalctemplate_link_matching_test(rt, st, host); + } -#ifdef NETDATA_INTERNAL_CHECKS - else if(rc->rrdset != st) - error("Health alarm '%s.%s' should be linked to chart '%s', but it is not", rc->chart?rc->chart:"NOCHART", rc->name, st->id); -#endif - } + for(rt = host->alarms_template_with_foreach; rt ; rt = rt->next) { + rrdcalctemplate_link_matching_test(rt, st, host); } } @@ -43,6 +55,8 @@ inline void rrdcalctemplate_free(RRDCALCTEMPLATE *rt) { freez(rt->units); freez(rt->info); freez(rt->dimensions); + freez(rt->foreachdim); + simple_pattern_free(rt->spdim); freez(rt); } @@ -67,5 +81,3 @@ inline void rrdcalctemplate_unlink_and_free(RRDHOST *host, RRDCALCTEMPLATE *rt) rrdcalctemplate_free(rt); } - - diff --git a/database/rrdcalctemplate.h b/database/rrdcalctemplate.h index 92bb4138e..676b4cf64 100644 --- a/database/rrdcalctemplate.h +++ b/database/rrdcalctemplate.h @@ -35,7 +35,11 @@ struct rrdcalctemplate { // database lookup settings char *dimensions; // the chart dimensions - RRDR_GROUPING group; // grouping method: average, max, etc. + char *foreachdim; // the group of dimensions that the lookup will be applied. + SIMPLE_PATTERN *spdim; // used if and only if there is a simple pattern for the chart. + int foreachcounter; // the number of alarms created with foreachdim, this also works as an id of the + // children + RRDR_GROUPING group; // grouping method: average, max, etc. int before; // ending point in time-series int after; // starting point in time-series uint32_t options; // calculation options @@ -70,5 +74,5 @@ extern void rrdcalctemplate_link_matching(RRDSET *st); extern void rrdcalctemplate_free(RRDCALCTEMPLATE *rt); extern void rrdcalctemplate_unlink_and_free(RRDHOST *host, RRDCALCTEMPLATE *rt); - +extern void rrdcalctemplate_create_alarms(RRDHOST *host, RRDCALCTEMPLATE *rt, RRDSET *st); #endif //NETDATA_RRDCALCTEMPLATE_H diff --git a/database/rrddim.c b/database/rrddim.c index 019ca34a1..8ab5a7237 100644 --- a/database/rrddim.c +++ b/database/rrddim.c @@ -156,7 +156,37 @@ static time_t rrddim_query_oldest_time(RRDDIM *rd) { // ---------------------------------------------------------------------------- // RRDDIM create a dimension +void rrdcalc_link_to_rrddim(RRDDIM *rd, RRDSET *st, RRDHOST *host) { + RRDCALC *rrdc; + for (rrdc = host->alarms_with_foreach; rrdc ; rrdc = rrdc->next) { + if (simple_pattern_matches(rrdc->spdim, rd->id) || simple_pattern_matches(rrdc->spdim, rd->name)) { + if (!strcmp(rrdc->chart, st->name)) { + char *usename = alarm_name_with_dim(rrdc->name, strlen(rrdc->name), rd->name, strlen(rd->name)); + if (usename) { + if(rrdcalc_exists(host, st->name, usename, 0, 0)){ + freez(usename); + continue; + } + + RRDCALC *child = rrdcalc_create_from_rrdcalc(rrdc, host, usename, rd->name); + if (child) { + rrdcalc_add_to_host(host, child); + RRDCALC *rdcmp = (RRDCALC *) avl_insert_lock(&(host)->alarms_idx_health_log,(avl *)child); + if (rdcmp != child) { + error("Cannot insert the alarm index ID %s",child->name); + } + } else { + error("Cannot allocate a new alarm."); + rrdc->foreachcounter--; + } + } + } + } + } +} + RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collected_number multiplier, collected_number divisor, RRD_ALGORITHM algorithm, RRD_MEMORY_MODE memory_mode) { + RRDHOST *host = st->rrdhost; rrdset_wrlock(st); rrdset_flag_set(st, RRDSET_FLAG_SYNC_CLOCK); @@ -175,7 +205,6 @@ RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collecte return rd; } - RRDHOST *host = st->rrdhost; char filename[FILENAME_MAX + 1]; char fullfilename[FILENAME_MAX + 1]; @@ -371,7 +400,28 @@ RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collecte if(unlikely(rrddim_index_add(st, rd) != rd)) error("RRDDIM: INTERNAL ERROR: attempt to index duplicate dimension '%s' on chart '%s'", rd->id, st->id); + if (host->alarms_with_foreach || host->alarms_template_with_foreach) { + int count = 0; + int hostlocked; + for (count = 0 ; count < 5 ; count++) { + hostlocked = netdata_rwlock_trywrlock(&host->rrdhost_rwlock); + if (!hostlocked) { + rrdcalc_link_to_rrddim(rd, st, host); + rrdhost_unlock(host); + break; + } else if (hostlocked != EBUSY) { + error("Cannot lock host to create an alarm for the dimension."); + } + usleep(200000); + } + + if (count == 5) { + error("Failed to create an alarm for dimension %s of chart %s 5 times. Skipping alarm." + , rd->name, st->name); + } + } rrdset_unlock(st); + return(rd); } diff --git a/database/rrdhost.c b/database/rrdhost.c index d6252d206..9075787b0 100644 --- a/database/rrdhost.c +++ b/database/rrdhost.c @@ -598,9 +598,23 @@ void rrdhost_free(RRDHOST *host) { while(host->alarms) rrdcalc_unlink_and_free(host, host->alarms); + RRDCALC *rc,*nc; + for(rc = host->alarms_with_foreach; rc ; rc = nc) { + nc = rc->next; + rrdcalc_free(rc); + } + host->alarms_with_foreach = NULL; + while(host->templates) rrdcalctemplate_unlink_and_free(host, host->templates); + RRDCALCTEMPLATE *rt,*next; + for(rt = host->alarms_template_with_foreach; rt ; rt = next) { + next = rt->next; + rrdcalctemplate_free(rt); + } + host->alarms_template_with_foreach = NULL; + debug(D_RRD_CALLS, "RRDHOST: Cleaning up remaining host variables for host '%s'", host->hostname); rrdvar_free_remaining_variables(host, &host->rrdvar_root_index); diff --git a/database/rrdset.c b/database/rrdset.c index f8962b2fb..26df8d737 100644 --- a/database/rrdset.c +++ b/database/rrdset.c @@ -150,7 +150,7 @@ int rrdset_set_name(RRDSET *st, const char *name) { rrdset_strncpyz_name(b, n, CONFIG_MAX_VALUE); if(rrdset_index_find_name(host, b, 0)) { - error("RRDSET: chart name '%s' on host '%s' already exists.", b, host->hostname); + info("RRDSET: chart name '%s' on host '%s' already exists.", b, host->hostname); return 0; } diff --git a/docs/Add-more-charts-to-netdata.md b/docs/Add-more-charts-to-netdata.md index 3b1bb9626..fe0341ced 100644 --- a/docs/Add-more-charts-to-netdata.md +++ b/docs/Add-more-charts-to-netdata.md @@ -70,6 +70,7 @@ To control which plugins Netdata run, edit `netdata.conf` and check the `[plugin # apps = yes # xenstat = yes # perf = no + # slabinfo = no ``` The default for all plugins is the option `enable running new plugins`. So, setting this to `no` will disable all the plugins, except the ones specifically enabled. @@ -96,7 +97,7 @@ sudo su -s /bin/bash netdata ``` Similarly, you can use `charts.d.plugin` for BASH plugins and `node.d.plugin` for node.js plugins. -Other plugins (like `apps.plugin`, `freeipmi.plugin`, `fping.plugin`, `ioping.plugin`, `nfacct.plugin`, `xenstat.plugin`, `perf.plugin`) use the native Netdata plugin API and can be run directly. +Other plugins (like `apps.plugin`, `freeipmi.plugin`, `fping.plugin`, `ioping.plugin`, `nfacct.plugin`, `xenstat.plugin`, `perf.plugin`, `slabinfo.plugin`) use the native Netdata plugin API and can be run directly. If you need to configure a Netdata plugin or module, all user supplied configuration is kept at `/etc/netdata` while the stock versions of all files is at `/usr/lib/netdata/conf.d`. To copy a stock file and edit it, run `/etc/netdata/edit-config`. Running this command without an argument, will list the available stock files. @@ -126,6 +127,7 @@ This is a map of the all supported configuration options: | `proc.plugin`<br/>(internal plugin for monitoring Linux system resources)|`C`|`netdata.conf` section `[plugin:proc]`|one section for each module `[plugin:proc:MODULE]`. Each module may provide additional sections in the form of `[plugin:proc:MODULE:SUBSECTION]`.| | `python.d.plugin`<br/>(external plugin orchestrator for running python modules)|`python`<br/>v2 or v3<br/>both are supported|`python.d.conf`|a file for each module in `/etc/netdata/python.d/`.| | `statsd.plugin`<br/>(internal plugin for collecting statsd metrics)|`C`|`netdata.conf` section `[statsd]`|Synthetic statsd charts can be configured with files in `/etc/netdata/statsd.d/`.| +| `slabinfo.plugin`<br/>(external plugin for monitoring Kernel SLAB cache on Linux)|`C`|`netdata.conf` section `[plugin:slabinfo]`|N/A| | `tc.plugin`<br/>(internal plugin for collecting Linux traffic QoS)|`C`|`netdata.conf` section `[plugin:tc]`|The plugin runs an external helper called `tc-qos-helper.sh` to interface with the `tc` command. This helper supports a few additional options using `tc-qos-helper.conf`.| ## writing data collection modules @@ -316,6 +318,7 @@ These are all the data collection plugins currently available. | cpu_apps|BASH<br/>Shell Script|Collects the CPU utilization of select apps.<br/><br/>DEPRECATED IN FAVOR OF `apps.plugin`. It is still supplied only as an example module to shell scripting plugins.<br/> <br/>Netdata plugin: [charts.d.plugin](../collectors/charts.d.plugin#chartsdplugin)<br/>plugin module: [cpu_apps.chart.sh](../collectors/charts.d.plugin/cpu_apps)<br/>configuration file: [charts.d/cpu_apps.conf](../collectors/charts.d.plugin/cpu_apps)| | load_average|BASH<br/>Shell Script|Collects the current system load average.<br/><br/>DEPRECATED IN FAVOR OF THE NETDATA INTERNAL ONE. It is still supplied only as an example module to shell scripting plugins.<br/> <br/>Netdata plugin: [charts.d.plugin](../collectors/charts.d.plugin#chartsdplugin)<br/>plugin module: [load_average.chart.sh](../collectors/charts.d.plugin/load_average)<br/>configuration file: [charts.d/load_average.conf](../collectors/charts.d.plugin/load_average)| | mem_apps|BASH<br/>Shell Script|Collects the memory footprint of select applications.<br/><br/>DEPRECATED IN FAVOR OF `apps.plugin`. It is still supplied only as an example module to shell scripting plugins.<br/> <br/>Netdata plugin: [charts.d.plugin](../collectors/charts.d.plugin#chartsdplugin)<br/>plugin module: [mem_apps.chart.sh](../collectors/charts.d.plugin/mem_apps)<br/>configuration file: [charts.d/mem_apps.conf](../collectors/charts.d.plugin/mem_apps)| +| slabinfo|C|`slabinfo.plugin` collects Kernel SLAB cache metrics on Linux .<br/> <br/>[Documentation of `slabinfo.plugin`](../collectors/slabinfo.plugin/).<br/> <br/>Netdata plugin: [`slabinfo_plugin.c`](../collectors/slabinfo.plugin)| --- diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md deleted file mode 100644 index 7fd7a5382..000000000 --- a/docs/GettingStarted.md +++ /dev/null @@ -1,182 +0,0 @@ -# Getting Started - -These are your first steps **after** you have installed Netdata. If you haven't installed it already, please check the [installation page](../packaging/installer). - -## Accessing the dashboard - -To access the Netdata dashboard, navigate with your browser to: - -``` -http://your.server.ip:19999/ -``` - -<details markdown="1"><summary>Click here, if it does not work.</summary> - -**Verify Netdata is running.** - -Open an ssh session to the server and execute `sudo ps -e | grep netdata`. It should respond with the PID of the Netdata daemon. If it prints nothing, Netdata is not running. Check the [installation page](../packaging/installer) to install it. - -**Verify Netdata responds to HTTP requests.** - -Using the same ssh session, execute `curl -Ss http://localhost:19999`. It should dump on your screen the `index.html` page of the dashboard. If it does not, check the [installation page](../packaging/installer) to install it. - -**Verify Netdata receives the HTTP requests.** - -On the same ssh session, execute `tail -f /var/log/netdata/access.log` (if you installed the static 64bit package, use: `tail -f /opt/netdata/var/log/netdata/access.log`). This command will print on your screen all HTTP requests Netdata receives. - -Next, try to access the dashboard using your web browser, using the URL posted above. If nothing is printed on your terminal, the HTTP request is not routed to your Netdata. - -If you are not sure about your server IP, run this for a hint: `ip route get 8.8.8.8 | grep -oP " src [0-9\.]+ "`. It should print the IP of your server. - -If still Netdata does not receive the requests, something is blocking them. A firewall possibly. Please check your network. - -</details> <br/> - -When you install multiple Netdata servers, all your servers will appear at the node menu at the top left of the dashboard. For this to work, you have to manually access just once, the dashboard of each of your Netdata servers. - -The node menu is more than just browser bookmarks. When switching Netdata servers from that menu, any settings of the current view are propagated to the other Netdata server: - -- the current charts panning (drag the charts left or right), -- the current charts zooming (`SHIFT` + mouse wheel over a chart), -- the highlighted time-frame (`ALT` + select an area on a chart), -- the scrolling position of the dashboard, -- the theme you use, -- etc. - -are all sent over to other Netdata server, to allow you troubleshoot cross-server performance issues easily. - -## Starting and stopping Netdata - -Netdata installer integrates Netdata to your init / systemd environment. - -To start/stop Netdata, depending on your environment, you should use: - -- `systemctl start netdata` and `systemctl stop netdata` -- `service netdata start` and `service netdata stop` -- `/etc/init.d/netdata start` and `/etc/init.d/netdata stop` - -Once Netdata is installed, the installer configures it to start at boot and stop at shutdown. - -For more information about using these commands, consult your system documentation. - -## Sizing Netdata - -The default installation of Netdata is configured for a small round-robin database: just 1 hour of data. Depending on the memory your system has and the amount you can dedicate to Netdata, you should adapt this. On production systems with limited RAM, we suggest to set this to 3-4 hours. For best results you should set this to 24 or 48 hours. - -For every hour of data, Netdata needs about 25MB of RAM. If you can dedicate about 100MB of RAM to Netdata, you should set its database size to 4 hours. - -To do this, edit `/etc/netdata/netdata.conf` (or `/opt/netdata/etc/netdata/netdata.conf`) and set: - -``` -[global] - history = SECONDS -``` - -Make sure the `history` line is not commented (comment lines start with `#`). - -1 hour is 3600 seconds, so the number you need to set is the result of `HOURS * 3600`. - -!!! danger - Be careful when you set this on production systems. If you set it too high, your system may run out of memory. By default, Netdata is configured to be killed first when the system starves for memory, but better be careful to avoid issues. - -For more information about Netdata memory requirements, [check this page](../database). - -If your kernel supports KSM (most do), you can [enable KSM to half Netdata memory requirement](../database#ksm). - -## Service discovery and auto-detection - -Netdata supports auto-detection of data collection sources. It auto-detects almost everything: database servers, web servers, dns server, etc. - -This auto-detection process happens **only once**, when Netdata starts. To have Netdata re-discover data sources, you need to restart it. There are a few exceptions to this: - -- containers and VMs are auto-detected forever (when Netdata is running at the host). -- many data sources are collected but are silenced by default, until there is useful information to collect (for example network interface dropped packet, will appear after a packet has been dropped). -- services that are not optimal to collect on all systems, are disabled by default. -- services we received feedback from users that caused issues when monitored, are also disabled by default (for example, `chrony` is disabled by default, because CentOS ships a version of it that uses 100% CPU when queried for statistics). - -Once a data collection source is detected, Netdata will never quit trying to collect data from it, until Netdata is restarted. So, if you stop your web server, Netdata will pick it up automatically when it is started again. - -Since Netdata is installed on all your systems (even inside containers), auto-detection is limited to `localhost`. This simplifies significantly the security model of a Netdata monitored infrastructure, since most applications allow `localhost` access by default. - -A few well known data collection sources that commonly need to be configured are: - -- [systemd services utilization](../collectors/cgroups.plugin/#monitoring-systemd-services) are not exposed by default on most systems, so `systemd` has to be configured to expose those metrics. - -## Configuration quick start - -In Netdata we have: - -- **internal** data collection plugins (running inside the Netdata daemon) -- **external** data collection plugins (independent processes, sending data to Netdata over pipes) -- modular plugin **orchestrators** (external plugins that have multiple data collection modules) - -You can enable and disable plugins (internal and external) via `netdata.conf` at the section `[plugins]`. - -All plugins have dedicated sections in `netdata.conf`, like `[plugin:XXX]` for overwriting their default data collection frequency and providing additional command line options to them. - -All external plugins have their own `.conf` file. - -All modular plugin orchestrators have a directory in `/etc/netdata` with a `.conf` file for each of their modules. - -It is complex. So, let's see the whole configuration tree for the `nginx` module of `python.d.plugin`: - -In `netdata.conf` at the `[plugins]` section, `python.d.plugin` can be enabled or disabled: - -``` -[plugins] - python.d = yes -``` - -In `netdata.conf` at the `[plugin:python.d]` section, we can provide additional command line options for `python.d.plugin` and overwite its data collection frequency: - -``` -[plugin:python.d] - update every = 1 - command options = -``` - -`python.d.plugin` has its own configuration file for enabling and disabling its modules (here you can disable `nginx` for example): - -```bash -sudo /etc/netdata/edit-config python.d.conf -``` - -Then, `nginx` has its own configuration file for configuring its data collection jobs (most modules can collect data from multiple sources, so the `nginx` module can collect metrics from multiple, local or remote, `nginx` servers): - -```bash -sudo /etc/netdata/edit-config python.d/nginx.conf -``` - -## Health monitoring and alarms - -Netdata ships hundreds of health monitoring alarms for detecting anomalies. These are optimized for production servers. - -Many users install Netdata on workstations and are frustrated by the default alarms shipped with Netdata. On these cases, we suggest to disable health monitoring. - -To disable it, edit `/etc/netdata/netdata.conf` (or `/opt/netdata/etc/netdata/netdata.conf` if you installed the static 64bit package) and set: - -``` -[health] - enabled = no -``` - -The above will disable health monitoring entirely. - -If you want to keep health monitoring enabled for the dashboard, but you want to disable email notifications, run this: - -```bash -sudo /etc/netdata/edit-config health_alarm_notify.conf -``` - -and set `SEND_EMAIL="NO"`. - -(For static 64bit installations use `sudo /opt/netdata/etc/netdata/edit-config health_alarm_notify.conf`). - -## What is next? - -- Check [Data Collection](../collectors) for configuring data collection plugins. -- Check [Health Monitoring](../health) for configuring your own alarms, or setting up alarm notifications. -- Check [Streaming](../streaming) for centralizing Netdata metrics. -- Check [Backends](../backends) for long term archiving of Netdata metrics to time-series databases. - -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fdocs%2FGettingStarted&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/docs/Running-behind-haproxy.md b/docs/Running-behind-haproxy.md index cf95a491c..cf411b9f8 100644 --- a/docs/Running-behind-haproxy.md +++ b/docs/Running-behind-haproxy.md @@ -1,16 +1,21 @@ # Netdata via HAProxy -> HAProxy is a free, very fast and reliable solution offering high availability, load balancing, and proxying for TCP and HTTP-based applications. It is particularly suited for very high traffic web sites and powers quite a number of the world's most visited ones. +> HAProxy is a free, very fast and reliable solution offering high availability, load balancing, +> and proxying for TCP and HTTP-based applications. It is particularly suited for very high traffic web sites +> and powers quite a number of the world's most visited ones. -If Netdata is running on a host running HAProxy, rather than connecting to Netdata from a port number, a domain name can be pointed at HAProxy, and HAProxy can redirect connections to the Netdata port. This can make it possible to connect to Netdata at <https://example.com> or <https://example.com/netdata/>, which is a much nicer experience then <http://example.com:19999>. +If Netdata is running on a host running HAProxy, rather than connecting to Netdata from a port number, a domain name +can be pointed at HAProxy, and HAProxy can redirect connections to the Netdata port. This can make it possible to +connect to Netdata at <https://example.com> or <https://example.com/netdata/>, which is a much nicer experience then <http://example.com:19999>. -To proxy requests from [HAProxy](https://github.com/haproxy/haproxy) to Netdata, the following configuration can be used: +To proxy requests from [HAProxy](https://github.com/haproxy/haproxy) to Netdata, +the following configuration can be used: ## Default Configuration For all examples, set the mode to `http` -``` +```conf defaults mode http ``` @@ -23,7 +28,7 @@ A simple example where the base URL, say <http://example.com>, is used with no s Create a frontend to recieve the request. -``` +```conf frontend http_frontend ## HTTP ipv4 and ipv6 on all ips ## bind :::80 v4v6 @@ -35,7 +40,7 @@ frontend http_frontend Create the Netdata backend which will send requests to port `19999`. -``` +```conf backend netdata_backend option forwardfor server netdata_local 127.0.0.1:19999 @@ -54,7 +59,7 @@ A example where the base URL is used with a subpath `/netdata/`: To use a subpath, create an ACL, which will set a variable based on the subpath. -``` +```conf frontend http_frontend ## HTTP ipv4 and ipv6 on all ips ## bind :::80 v4v6 @@ -77,7 +82,7 @@ frontend http_frontend Same as simple example, expept remove `/netdata/` with regex. -``` +```conf backend netdata_backend option forwardfor server netdata_local 127.0.0.1:19999 @@ -92,13 +97,14 @@ backend netdata_backend ## Using TLS communication -TLS can be used by adding port `443` and a cert to the frontend. This example will only use Netdata if host matches example.com (replace with your domain). +TLS can be used by adding port `443` and a cert to the frontend. +This example will only use Netdata if host matches example.com (replace with your domain). ### Frontend This frontend uses a certificate list. -``` +```conf frontend https_frontend ## HTTP ## bind :::80 v4v6 @@ -123,14 +129,15 @@ In the cert list file place a mapping from a certificate file to the domain used `/etc/letsencrypt/certslist.txt`: -``` +```txt example.com /etc/letsencrypt/live/example.com/example.com.pem ``` -The file `/etc/letsencrypt/live/example.com/example.com.pem` should contain the key and certificate (in that order) concatenated into a `.pem` file.: +The file `/etc/letsencrypt/live/example.com/example.com.pem` should contain the key and +certificate (in that order) concatenated into a `.pem` file.: -``` -$ cat /etc/letsencrypt/live/example.com/fullchain.pem \ +```sh +cat /etc/letsencrypt/live/example.com/fullchain.pem \ /etc/letsencrypt/live/example.com/privkey.pem > \ /etc/letsencrypt/live/example.com/example.com.pem ``` @@ -139,7 +146,7 @@ $ cat /etc/letsencrypt/live/example.com/fullchain.pem \ Same as simple, except set protocol `https`. -``` +```conf backend netdata_backend option forwardfor server netdata_local 127.0.0.1:19999 @@ -155,7 +162,7 @@ backend netdata_backend To use basic HTTP Authentication, create a authentication list: -``` +```conf # HTTP Auth userlist basic-auth-list group is-admin @@ -165,20 +172,20 @@ userlist basic-auth-list You can create a hashed password using the `mkpassword` utility. -``` -$ printf "passwordhere" | mkpasswd --stdin --method=sha-256 +```sh + printf "passwordhere" | mkpasswd --stdin --method=sha-256 $5$l7Gk0VPIpKO$f5iEcxvjfdF11khw.utzSKqP7W.0oq8wX9nJwPLwzy1 ``` Replace `passwordhere` with hash: -``` +```conf user admin password $5$l7Gk0VPIpKO$f5iEcxvjfdF11khw.utzSKqP7W.0oq8wX9nJwPLwzy1 groups is-admin ``` Now add at the top of the backend: -``` +```conf acl devops-auth http_auth_group(basic-auth-list) is-admin http-request auth realm netdata_local unless devops-auth ``` @@ -187,7 +194,7 @@ http-request auth realm netdata_local unless devops-auth Full example configuration with HTTP auth over TLS with subpath: -``` +```conf global maxconn 20000 diff --git a/docs/configuration-guide.md b/docs/configuration-guide.md index c13347749..600848e2e 100644 --- a/docs/configuration-guide.md +++ b/docs/configuration-guide.md @@ -106,7 +106,7 @@ The page on [Netdata performance](Performance.md) has an excellent guide on how ##### Change when Netdata saves metrics to disk -[netdata.conf \[global\]](../daemon/config/#global-section-options) : `memory mode`</details> +[netdata.conf \[global\]](../daemon/config/#global-section-options) : `memory mode` ##### Prevent Netdata from getting immediately killed when my server runs out of memory diff --git a/docs/contributing/contributing-documentation.md b/docs/contributing/contributing-documentation.md index 7cf0d820f..6f94d5bf1 100644 --- a/docs/contributing/contributing-documentation.md +++ b/docs/contributing/contributing-documentation.md @@ -1,25 +1,38 @@ # Contributing to documentation -We welcome contributions to Netdata's already extensive documentation, which we host at [docs.netdata.cloud](https://docs.netdata.cloud/) and store inside of the [main repository](https://github.com/netdata/netdata) on GitHub. +We welcome contributions to Netdata's already extensive documentation, +which we host at [docs.netdata.cloud](https://docs.netdata.cloud/) +and store inside of the [main repository](https://github.com/netdata/netdata) on GitHub. -Like all contributing to all other aspects of Netdata, we ask that anyone who wants to help with documentation read and abide by the [Contributor Convenant Code of Conduct](https://docs.netdata.cloud/code_of_conduct/) and follow the instructions outlined in our [Contributing document](../../CONTRIBUTING.md). +Like all contributing to all other aspects of Netdata, we ask that anyone who wants to help with documentation +read and abide by the [Contributor Convenant Code of Conduct](https://docs.netdata.cloud/code_of_conduct/) +and follow the instructions outlined in our [Contributing document](../../CONTRIBUTING.md). -We also ask you to read our [documentation style guide](style-guide.md), which, while not complete, will give you some guidance on how we write and organize our documentation. +We also ask you to read our [documentation style guide](style-guide.md), which, while not complete, +will give you some guidance on how we write and organize our documentation. -All our documentation uses the Markdown syntax. If you're not familiar with how it works, please read the [Markdown introduction post](https://daringfireball.net/projects/markdown/) by its creator, followed by [Mastering Markdown](https://guides.github.com/features/mastering-markdown/) guide from GitHub. +All our documentation uses the Markdown syntax. If you're not familiar with how it works, +please read the [Markdown introduction post](https://daringfireball.net/projects/markdown/) by its creator, +followed by [Mastering Markdown](https://guides.github.com/features/mastering-markdown/) guide from GitHub. ## How contributing to the documentation works There are two ways to contribute to Netdata's documentation: -1. Edit documentation [directly in GitHub](#edit-documentation-directly-on-gitHub). +1. Edit documentation [directly in GitHub](#edit-documentation-directly-on-github). 2. Download the repository and [edit documentation locally](#edit-documentation-locally). -Editing in GitHub is a simpler process and is perfect for quick edits to a single document, such as fixing a typo or clarifying a confusing sentence. +Editing in GitHub is a simpler process and is perfect for quick edits to a single document, +such as fixing a typo or clarifying a confusing sentence. -Editing locally is more complex, as you need to download the Netdata repository and build the documentation using `mkdocs`, but allows you to better organize complex projects. By building documentation locally, you can preview your work using a local web server before you submit your PR. +Editing locally is more complex, as you need to download the Netdata repository +and build the documentation using `mkdocs`, but allows you to better organize complex projects. +By building documentation locally, you can preview your work using a local web server before you submit your PR. -In both cases, you'll finish by submitting a pull request (PR). Once you submit your PR, GitHub will initiate a number of jobs, including a Netlify preview. You can use this preview to view the documentation site with your changes applied, which might help you catch any lingering issues. +In both cases, you'll finish by submitting a pull request (PR). +Once you submit your PR, GitHub will initiate a number of jobs, including a Netlify preview. +You can use this preview to view the documentation site with your changes applied, +which might help you catch any lingering issues. To continue, follow one of the paths below: @@ -28,109 +41,149 @@ To continue, follow one of the paths below: ## Edit documentation directly on GitHub -Start editing documentation on GitHub by clicking the small pencil icon on any page on Netdata's [documentation site](https://docs.netdata.cloud/). You can find them at the top of every page. +Start editing documentation on GitHub by clicking the small pencil icon on any page on Netdata's [documentation site](https://docs.netdata.cloud/). +You can find them at the top of every page. -Clicking on this icon will take you to the associated page in the `netdata/netdata` repository. Then click the small pencil icon on any documentation file (those ending in the `.md` [Markdown] extension) in the `netdata/netdata` repository. +Clicking on this icon will take you to the associated page in the `netdata/netdata` repository. +Then click the small pencil icon on any documentation file (those ending in the `.md` Markdown extension) in the `netdata/netdata` repository. ![A screenshot of editing a Markdown file directly in the Netdata repository](https://user-images.githubusercontent.com/1153921/59637188-10426d00-910a-11e9-99f2-ec564d6fb7d5.png) -If you know where a file resides in the Netdata repository already, you can skip the step of beginning on the documentation site and go directly to GitHub. +If you know where a file resides in the Netdata repository already, +you can skip the step of beginning on the documentation site and go directly to GitHub. -Once you've clicked the pencil icon on GitHub, you'll see a full Markdown version of the file. Make changes as you see fit. You can use the `Preview changes` button to ensure your Markdown syntax is working properly. +Once you've clicked the pencil icon on GitHub, you'll see a full Markdown version of the file. +Make changes as you see fit. +You can use the `Preview changes` button to ensure your Markdown syntax is working properly. -Under the `Propose file change` header, write in a descriptive title for your requested change. Beneath that, add a concise descrition of what you've changed and why you think it's important. Then, click the `Propose file change` button. +Under the `Propose file change` header, write in a descriptive title for your requested change. +Beneath that, add a concise descrition of what you've changed and why you think it's important. Then, click the `Propose file change` button. -After you've hit that button, jump down to our instructions on [pull requests and cleanup](#pull-requests-and-final-steps) for your next steps. +After you've hit that button, +jump down to our instructions on [pull requests and cleanup](#pull-requests-and-final-steps) for your next steps. !!! note - This process will create a branch directly on the `netdata/netdata` repository, which then requires manual cleanup. If you're going to make significant documentation contributions, or contribute often, we recommend the local editing process just below. + This process will create a branch directly on the `netdata/netdata` repository, which then requires manual cleanup. + If you're going to make significant documentation contributions, or contribute often, + we recommend the local editing process just below. ## Edit documentation locally -Editing documentation locally is the preferred method for complex changes, PRs that span across multiple documents, or those that change the styling or underlying functionality of the documentation. +Editing documentation locally is the preferred method for complex changes, PRs that span across multiple documents, +or those that change the styling or underlying functionality of the documentation. -Here is the workflow for editing documentation locally. First, create a fork of the Netdata repository, if you don't have one already. Visit the [Netdata repository](https://github.com/netdata/netdata) and click on the `Fork` button in the upper-right corner of the window. +Here is the workflow for editing documentation locally. First, create a fork of the Netdata repository, +if you don't have one already. Visit the [Netdata repository](https://github.com/netdata/netdata) +and click on the `Fork` button in the upper-right corner of the window. ![Screenshot of forking the Netdata repository](https://user-images.githubusercontent.com/1153921/59873572-25f5a380-9351-11e9-92a4-a681fe4a2ed9.png) -GitHub will ask you where you want to clone the repository, and once finished you'll end up at the index of your forked Netdata repository. Clone your fork to your local machine: +GitHub will ask you where you want to clone the repository, +and once finished you'll end up at the index of your forked Netdata repository. +Clone your fork to your local machine: ```bash -$ git clone https://github.com/YOUR-GITHUB-USERNAME/netdata.git +git clone https://github.com/YOUR-GITHUB-USERNAME/netdata.git ``` You can now jump into the directory and explore Netdata's structure for yourself. ### Understanding the structure of Netdata's documentation -All of Netdata's documentation is stored within the repository itself, as close as possible to the code it corresponds to. Many sub-folders contain a `README.md` file, which is then used to populate the documentation about that feature/component of Netdata. +All of Netdata's documentation is stored within the repository itself, as close as possible to the code it +corresponds to. Many sub-folders contain a `README.md` file, +which is then used to populate the documentation about that feature/component of Netdata. -For example, the file at `packaging/installer/README.md` becomes `https://docs.netdata.cloud/packaging/installer/` and is our installation documentation. By co-locating it with quick-start installtion code, we ensure documentation is always tightly knit with the functions it describes. +For example, the file at `packaging/installer/README.md` becomes `https://docs.netdata.cloud/packaging/installer/` +and is our installation documentation. By co-locating it with quick-start installtion code, +we ensure documentation is always tightly knit with the functions it describes. -You might find other `.md` files within these directories. The `packaging/installer/` folder also contains `UPDATE.md` and `UNINSTALL.md`, which become `https://docs.netdata.cloud/packaging/installer/update/` and `https://docs.netdata.cloud/packaging/installer/uninstall/`, respectively. +You might find other `.md` files within these directories. The `packaging/installer/` folder also contains `UPDATE.md` +and `UNINSTALL.md`, which become `https://docs.netdata.cloud/packaging/installer/update/` +and `https://docs.netdata.cloud/packaging/installer/uninstall/`, respectively. -If the documentation you're working on has a direct correlation to some component of Netdata, place it into the correct folder and either name it `README.md` for generic documentation, or with another name for very specific instructions. +If the documentation you're working on has a direct correlation to some component of Netdata, place it into the correct +folder and either name it `README.md` for generic documentation, or with another name for very specific instructions. #### The `docs` folder -At the root of the Netdata repository is a `docs/` folder. Inside this folder we place documentation that does not have a direct relationship to a specific component of Netdata. It's where we house our [getting started guide](../GettingStarted.md), guides on [running Netdata behind Nginx](../Running-behind-nginx.md), and more. +At the root of the Netdata repository is a `docs/` folder. Inside this folder we place documentation that does not have +a direct relationship to a specific component of Netdata. It's where we house our [getting started +guide](../../docs/getting-started.md), guides on [running Netdata behind Nginx](../../docs/Running-behind-nginx.md), and +more. -If the documentation you're working on doesn't have a direct relaionship to a component of Netdata, it can be placed in this `docs/` folder. +If the documentation you're working on doesn't have a direct relaionship to a component of Netdata, +it can be placed in this `docs/` folder. ### Make your edits -Now that you're set up and understand where to find or create your `.md` file, you can now begin to make your edits. Just use your favorite editor and keep in mind our [style guide](style-guide.md) as you work. +Now that you're set up and understand where to find or create your `.md` file, you can now begin to make your edits. +Just use your favorite editor and keep in mind our [style guide](style-guide.md) as you work. -If you add a new file to the documentation, you may need to modify the `buildyaml.sh` file to ensure it's added to the site's navigation. This is true for any file added to the `docs/` folder. +If you add a new file to the documentation, you may need to modify the `buildyaml.sh` file to ensure +it's added to the site's navigation. This is true for any file added to the `docs/` folder. -Be sure to periodically add/commit your edits so that you don't lose your work! We use version control software for a reason. +Be sure to periodically add/commit your edits so that you don't lose your work! +We use version control software for a reason. ### Build the documentation -Building the documentation periodically gives you a glimpse into the final product, and is generally required if you're making changes to the table of contents. +Building the documentation periodically gives you a glimpse into the final product, and is generally required +if you're making changes to the table of contents. !!! attention "" - We have only tested the build process on Linux. Initial tests on OS X have been unsuccessful. Windows is fully untested at this point, but we would love to know if it works there as well! + We have only tested the build process on Linux. Initial tests on OS X have been unsuccessful. + Windows is fully untested at this point, but we would love to know if it works there as well! To build the documentation, you need `python`/`pip`, `mkdocs`, and `mkdocs-material` installed on your machine. Follow the [Python installation instructions](https://www.python.org/downloads/) for your machine. -Use `pip`, which was installed alongside Python, to install `mkdocs` and `mkdocs-material`. Your operating system might force you to use `pip2` or `pip3` instead, dependin on which version of Python you have installed. +Use `pip`, which was installed alongside Python, to install `mkdocs` and `mkdocs-material`. +Your operating system might force you to use `pip2` or `pip3` instead, +dependin on which version of Python you have installed. ```bash -$ pip install mkdocs mkdocs-material +pip install mkdocs mkdocs-material ``` ??? note "Troubleshooting" If you're having trouble with the installation of Python, `mkdocs`, or `mkdocs-material`, try looking into the `mkdocs` [installation instructions](https://squidfunk.github.io/mkdocs-material/getting-started/#installation). -When `pip` is finished installing, navigate to the root directory of the Netdata repository and run the documentation generator script. +When `pip` is finished installing, navigate to the root directory of the Netdata repository +and run the documentation generator script. ```bash -$ sh docs/generator/buildhtml.sh +sh docs/generator/buildhtml.sh ``` This process will take some time. Once finished, the built documentation site will be located at `docs/generator/build/`. ### Run a local web server to test documentation -The best way to view the documentation site you just built is to run a simple web server from the `docs/generator/build/` directory. So, navigate there and run a Python-based web server: +The best way to view the documentation site you just built is to run a simple web server from the `docs/generator/build/` directory. +So, navigate there and run a Python-based web server: -``` -$ cd docs/generator/build/ -$ python3 -m http.server 20000 +```sh +cd docs/generator/build/ +python3 -m http.server 20000 ``` -Feel free to replace the port number you want this web server to listen on (port `20000` in this case [only one higher than the agent!]). +Feel free to replace the port number you want this web server to listen on (port `20000` in this case (only one higher +than the agent!)). -Open your web browser and navigate to `http://localhost:20000`. If you replaced the port earlier, change it here as well. You can now navigate through the documentation as you would on the live site! +Open your web browser and navigate to `http://localhost:20000`. +If you replaced the port earlier, change it here as well. +You can now navigate through the documentation as you would on the live site! ## Pull requests and final steps -When you're finished with your changes, add and commit them to your fork of the Netdata repository. Head over to GitHub to create your pull request (PR). +When you're finished with your changes, add and commit them to your fork of the Netdata repository. +Head over to GitHub to create your pull request (PR). -Once we receive your pull request (PR), we'll take time to read through it and assess it for correctness, conciseness, and overall quality. We may point to specific sections and ask for additional information or other fixes. +Once we receive your pull request (PR), we'll take time to read through it and assess it for correctness, conciseness, +and overall quality. +We may point to specific sections and ask for additional information or other fixes. ## What's next diff --git a/docs/generator/buildyaml.sh b/docs/generator/buildyaml.sh index 427f9d896..04d6098fc 100755 --- a/docs/generator/buildyaml.sh +++ b/docs/generator/buildyaml.sh @@ -149,7 +149,7 @@ echo -ne " - 'docs/what-is-netdata.md' - 'packaging/installer/UPDATE.md' - 'packaging/DISTRIBUTIONS.md' - 'packaging/installer/UNINSTALL.md' -- 'docs/GettingStarted.md' +- 'docs/getting-started.md' - Running Netdata: - 'daemon/README.md' - 'docs/configuration-guide.md' @@ -250,6 +250,7 @@ navpart 3 collectors/freeipmi.plugin navpart 3 collectors/nfacct.plugin navpart 3 collectors/xenstat.plugin navpart 3 collectors/perf.plugin +navpart 3 collectors/slabinfo.plugin echo -ne " - 'docs/Third-Party-Plugins.md' @@ -285,4 +286,4 @@ navpart 2 packaging/makeself "" "" 4 navpart 2 libnetdata "" "libnetdata" 4 navpart 2 contrib navpart 2 tests "" "" 2 -navpart 2 diagrams/data_structures
\ No newline at end of file +navpart 2 diagrams/data_structures diff --git a/docs/generator/checklinks.sh b/docs/generator/checklinks.sh index 6521ca9ad..a453d8ff2 100755 --- a/docs/generator/checklinks.sh +++ b/docs/generator/checklinks.sh @@ -31,16 +31,16 @@ printhelp () { fix () { if [ "$EXECUTE" -eq 0 ] ; then - echo "-- SHOULD EXECUTE: $1" + echo " - SHOULD EXECUTE: $1" else - dbg "-- EXECUTING: $1" + dbg " - EXECUTING: $1" eval "$1" fi } testURL () { if [ "$TESTURLS" -eq 0 ] ; then return 0 ; fi - dbg "-- Testing URL $1" + dbg " - Testing URL $1" curl -sS "$1" > /dev/null if [ $? -gt 0 ] ; then return 1 @@ -54,13 +54,13 @@ testinternal () { ifile=${2} ilnk=${3} header=${ilnk//-/} - dbg "-- Searching for \"$header\" in $ifile" + dbg " - Searching for \"$header\" in $ifile" tr -d '[],_.:? `'< "$ifile" | sed 's/-//g' | grep -i "^\\#*$header\$" >/dev/null if [ $? -eq 0 ] ; then - dbg "-- $ilnk found in $ifile" + dbg " - $ilnk found in $ifile" return 0 else - echo "-- ERROR: $ff - $ilnk header not found in file $ifile" + echo " - ERROR: $ff - $ilnk header not found in file $ifile" EXITCODE=1 return 1 fi @@ -71,10 +71,10 @@ testf () { tf=$2 if [ -f "$tf" ] ; then - dbg "-- $tf exists" + dbg " - $tf exists" return 0 else - echo "-- ERROR: $sf - $tf does not exist" + echo " - ERROR: $sf - $tf does not exist" EXITCODE=1 return 1 fi @@ -83,16 +83,16 @@ testf () { ck_netdata_relative () { f=${1} rlnk=${2} - dbg "-- Checking relative link $rlnk" + dbg " - Checking relative link $rlnk" fpath="." fname="$f" # First ensure that the link works in the repo, then try to fix it in htmldocs if [[ $f =~ ^(.*)/([^/]*)$ ]] ; then fpath="${BASH_REMATCH[1]}" fname="${BASH_REMATCH[2]}" - dbg "-- Current file is at $fpath" + dbg " - Current file is at $fpath" else - dbg "-- Current file is at root directory" + dbg " - Current file is at root directory" fi # Cases to handle: # (#somelink) @@ -109,11 +109,11 @@ ck_netdata_relative () { case "$rlnk" in \#* ) - dbg "-- # (#somelink)" + dbg " - # (#somelink)" testinternal "$f" "$f" "$rlnk" ;; */ ) - dbg "-- # (path/)" + dbg " - # (path/)" TRGT="$fpath/${rlnk}README.md" testf "$f" "$TRGT" if [ $? -eq 0 ] ; then @@ -121,11 +121,11 @@ ck_netdata_relative () { fi ;; */\#* ) - dbg "-- # (path/#somelink)" + dbg " - # (path/#somelink)" if [[ $rlnk =~ ^(.*)/#(.*)$ ]] ; then TRGT="$fpath/${BASH_REMATCH[1]}/README.md" LNK="#${BASH_REMATCH[2]}" - dbg "-- Look for $LNK in $TRGT" + dbg " - Look for $LNK in $TRGT" testf "$f" "$TRGT" if [ $? -eq 0 ] ; then testinternal "$f" "$TRGT" "$LNK" @@ -136,21 +136,21 @@ ck_netdata_relative () { fi ;; *.md ) - dbg "-- # (path/filename.md) -> htmldoc (path/filename/)" + dbg " - # (path/filename.md) -> htmldoc (path/filename/)" testf "$f" "$fpath/$rlnk" if [ $? -eq 0 ] ; then if [[ $rlnk =~ ^(.*)/(.*).md$ ]] ; then if [ "${BASH_REMATCH[2]}" = "README" ] ; then - s="../${BASH_REMATCH[1]}/" + s="${BASH_REMATCH[1]}/" else - s="../${BASH_REMATCH[1]}/${BASH_REMATCH[2]}/" + s="${BASH_REMATCH[1]}/${BASH_REMATCH[2]}/" fi if [ "$fname" != "README.md" ] ; then s="../$s"; fi fi fi ;; *.md\#* ) - dbg "-- # (path/filename.md#somelink) -> htmldoc (path/filename/#somelink)" + dbg " - # (path/filename.md#somelink) -> htmldoc (path/filename/#somelink)" if [[ $rlnk =~ ^(.*)#(.*)$ ]] ; then TRGT="$fpath/${BASH_REMATCH[1]}" LNK="#${BASH_REMATCH[2]}" @@ -160,9 +160,9 @@ ck_netdata_relative () { if [ $? -eq 0 ] ; then if [[ $lnk =~ ^(.*)/(.*).md#(.*)$ ]] ; then if [ "${BASH_REMATCH[2]}" = "README" ] ; then - s="../${BASH_REMATCH[1]}/#${BASH_REMATCH[3]}" + s="${BASH_REMATCH[1]}/#${BASH_REMATCH[3]}" else - s="../${BASH_REMATCH[1]}/${BASH_REMATCH[2]}/#${BASH_REMATCH[3]}" + s="${BASH_REMATCH[1]}/${BASH_REMATCH[2]}/#${BASH_REMATCH[3]}" fi if [ "$fname" != "README.md" ] ; then s="../$s"; fi fi @@ -171,7 +171,7 @@ ck_netdata_relative () { fi ;; *\#* ) - dbg "-- # (path#somelink) -> (path/#somelink)" + dbg " - # (path#somelink) -> (path/#somelink)" if [[ $rlnk =~ ^(.*)#(.*)$ ]] ; then TRGT="$fpath/${BASH_REMATCH[1]}/README.md" LNK="#${BASH_REMATCH[2]}" @@ -189,7 +189,7 @@ ck_netdata_relative () { ;; * ) if [ -d "$fpath/$rlnk" ] ; then - dbg "-- # (path) -> htmldoc (path/)" + dbg " - # (path) -> htmldoc (path/)" testf "$f" "$fpath/$rlnk/README.md" if [ $? -eq 0 ] ; then s="$rlnk/" @@ -198,14 +198,14 @@ ck_netdata_relative () { else cd - >/dev/null if [ -f "$fpath/$rlnk" ] ; then - dbg "-- # (path/someotherfile) $rlnk" + dbg " - # (path/someotherfile) $rlnk" if [ "$fpath" = "." ] ; then s="https://github.com/netdata/netdata/tree/master/$rlnk" else s="https://github.com/netdata/netdata/tree/master/$fpath/$rlnk" fi else - echo "-- ERROR: $f - $rlnk is neither a file or a directory. Giving up!" + echo " - ERROR: $f - $rlnk is neither a file or a directory. Giving up!" EXITCODE=1 fi cd $DOCS_DIR >/dev/null @@ -229,29 +229,29 @@ checklinks () { if [[ $word =~ .*\]\(([^\(\) ]*)\).* ]] ; then lnk=$(echo "${BASH_REMATCH[1]}" | tr -d '<>') if [ -z "$lnk" ] ; then continue ; fi - dbg "-$lnk" + dbg " $lnk" case "$lnk" in - mailto:* ) dbg "-- Mailto link, ignoring" ;; + mailto:* ) dbg " - Mailto link, ignoring" ;; https://github.com/netdata/netdata/wiki* ) - dbg "-- Wiki Link $lnk" - if [ "$CHKWIKI" -eq 1 ] ; then echo "-- WARNING: $f - $lnk points to the wiki. Please replace it manually" ; fi + dbg " - Wiki Link $lnk" + if [ "$CHKWIKI" -eq 1 ] ; then echo " - WARNING: $f - $lnk points to the wiki. Please replace it manually" ; fi ;; https://github.com/netdata/netdata/????/master* ) - echo "-- ERROR: $f - $lnk is an absolute link to a Netdata file. Please convert to relative." + echo " - ERROR: $f - $lnk is an absolute link to a Netdata file. Please convert to relative." EXITCODE=1 ;; http* ) - dbg "-- External link $lnk" + dbg " - External link $lnk" if [ "$CHKEXTERNAL" -eq 1 ] ; then testURL "$lnk" if [ $? -eq 1 ] ; then - echo "-- ERROR: $f - $lnk is a broken link" + echo " - ERROR: $f - $lnk is a broken link" EXITCODE=1 fi fi ;; * ) - dbg "-- Relative link $lnk" + dbg " - Relative link $lnk" if [ "$CHKRELATIVE" -eq 1 ] ; then ck_netdata_relative "$f" "$lnk" ; fi ;; esac diff --git a/docs/generator/custom/themes/material/partials/header.html b/docs/generator/custom/themes/material/partials/header.html index 54086ecf5..85f874905 100644 --- a/docs/generator/custom/themes/material/partials/header.html +++ b/docs/generator/custom/themes/material/partials/header.html @@ -92,6 +92,7 @@ <select id="sel" onchange="setLanguage(this);" style="vertical-align: middle; background-color: #3f51b5; color: white; border: none;"> <option href="#" value='en'>English</option> <option href="#" value='zh'>中文</option> + <option href="#" value='pt'>Portugues-Brasil</option> </select> </div> diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 000000000..ce3558192 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,233 @@ +# Getting started guide + +Thanks for trying Netdata! In this guide, we'll quickly walk you through the first steps you should take after getting +Netdata installed. + +Netdata can collect thousands of metrics in real-time without any configuration, but there are some valuable things to +know to get the most of out Netdata based on your needs. + +> If you haven't installed Netdata yet, visit the [installation instructions](../packaging/installer) for details, +> including our one-liner script, which automatically installs Netdata on almost all Linux distributions. + +## Access the dashboard + +Open up your web browser of choice and navigate to `http://YOUR-HOST:19999`. Welcome to Netdata! + +![Animated GIF of navigating to the +dashboard](https://user-images.githubusercontent.com/1153921/63463901-fcb9c800-c412-11e9-8f67-8fe182e8b0d2.gif) + +**What's next?**: + +- Read more about the [standard Netdata dashboard](../web/gui/). +- Learn all the specifics of [using charts](../web/README.md#using-charts) or the differences between [charts, + context, and families](../web/README.md#charts-contexts-families). + +## Configuration basics + +Netdata primarily uses the `netdata.conf` file for custom configurations. + +On most systems, you can find that file at `/etc/netdata/netdata.conf`. + +> Some operating systems will place your `netdata.conf` at `/opt/netdata/etc/netdata/netdata.conf`, so check there if +> you find nothing at `/etc/netdata/netdata.conf`. + +The `netdata.conf` file is broken up into various sections, such as `[global]`, `[web]`, `[registry]`, and more. By +default, most options are commented, so you'll have to uncomment them (remove the `#`) for Netdata to recognize your +change. + +Once you save your changes, [restart Netdata](#start-stop-and-restart-netdata) to load your new configuration. + +**What's next?**: + +- [Change how long Netdata stores metrics](#change-how-long-netdata-stores-metrics) by either increasing the `history` + option or switching to the database engine. +- Move Netdata's dashboard to a [different port](https://docs.netdata.cloud/web/server/) or enable TLS/HTTPS + encryption. +- See all the `netdata.conf` options in our [daemon configuration documentation](../daemon/config/). +- Run your own [registry](../registry/README.md#run-your-own-registry). + +## Collect data from more sources + +When Netdata _starts_, it auto-detects dozens of **data sources**, such as database servers, web servers, and more. To +auto-detect and collect metrics from a service or application you just installed, you need to [restart +Netdata](#start-stop-and-restart-netdata). + +> There is one exception: When Netdata is running on the host (as in not in a container itself), it will always +> auto-detect containers and VMs. + +However, auto-detection only works if you installed the source using its standard installation procedure. If Netdata +isn't collecting metrics after a restart, your source probably isn't configured correctly. Look at the [external plugin +documentation](../collectors/plugins.d/) to find the appropriate module for your source. Those pages will contain more +information about how to configure your source for auto-detection. + +Some modules, like `chrony`, are disabled by default and must be enabled manually for auto-detection to work. + +Once Netdata detects a valid source of data, it will continue trying to collect data from it. For example, if +Netdata is collecting data from an Nginx web server, and you shut Nginx down, Netdata will collect new data as soon as +you start the web server back up—no restart necessary. + +### Configuring plugins + +Even if Netdata auto-detects your service/application, you might want to configure what, or how often, Netdata is +collecting data. + +Netdata uses **internal** and **external** plugins to collect data. Internal plugins run within the Netdata dæmon, while +external plugins are independent processes that send metrics to Netdata over pipes. There are also plugin +**orchestrators**, which are external plugins with one or more data collection **modules**. + +You can configure both internal and external plugins, along with the individual modules. There are many ways to do so: + +- In `netdata.conf`, `[plugins]` section: Enable or disable internal or external plugins with `yes` or `no`. +- In `netdata.conf`, `[plugin:XXX]` sections: Each plugin has a section for changing collection frequency or passing + options to the plugin. +- In `.conf` files for each external plugin: For example, at `/etc/netdata/python.d.conf`. +- In `.conf` files for each module : For example, at `/etc/netdata/python.d/nginx.conf`. + +It's complex, so let's walk through an example of the various `.conf` files responsible for collecting data from an +Nginx web server using the `nginx` module and the `python.d` plugin orchestrator. + +First, you can enable or disable the `python.d` plugin entirely in `netdata.conf`. + +```conf +[plugins] + # Enabled + python.d = yes + # Disabled + python.d = no +``` + +You can also configure the entire `python.d` external plugin via the `[plugin:python.d]` section in `netdata.conf`. +Here, you can change how often Netdata uses `python.d` to collect metrics or pass other command options: + +```conf +[plugin:python.d] + update every = 1 + command options = +``` + +The `python.d` plugin has a separate configuration file at `/etc/netdata/python.d.conf` for enabling and disabling +modules. You can use the `edit-config` script to edit the file, or open it with your text editor of choice: + +```bash +sudo /etc/netdata/edit-config python.d.conf +``` + +Finally, the `nginx` module has a configuration file called `nginx.conf` in the `python.d` folder. Again, use +`edit-config` or your editor of choice: + +```bash +sudo /etc/netdata/edit-config python.d/nginx.conf +``` + +In the `nginx.conf` file, you'll find additional options. The default works in most situations, but you may need to make +changes based on your particular Nginx setup. + +**What's next?**: + +- Look at the [full list of data collection modules](Add-more-charts-to-netdata.md#available-data-collection-modules) + to configure your sources for auto-detection and monitoring. +- Improve the [performance](Performance.md) of Netdata on low-memory systems. +- Configure `systemd` to expose [systemd services + utilization](../collectors/cgroups.plugin/README.md#monitoring-systemd-services) metrics automatically. +- [Reconfigure individual charts](../daemon/config/README.md#per-chart-configuration) in `netdata.conf`. + +## Health monitoring and alarms + +Netdata comes with hundreds of health monitoring alarms for detecting anomalies on production servers. If you're running +Netdata on a workstation, you might want to disable Netdata's alarms. + +Edit your `/etc/netdata/netdata.conf` file and set the following: + +```conf +[health] + enabled = no +``` + +If you want to keep health monitoring enabled, but turn email notifications off, edit your `health_alarm_notify.conf` +file with `edit-config`, or with your the text editor of your choice: + +```bash +sudo /etc/netdata/edit-config health_alarm_notify.conf +``` + +Find the `SEND_EMAIL="YES"` line and change it to `SEND_EMAIL="NO"`. + +**What's next?**: + +- Write your own health alarm using the [examples](../health/README.md#examples). +- Add a new notification method, like [Slack](../health/notifications/slack/). + +## Change how long Netdata stores metrics + +By default, Netdata stores 1 hour of historical metrics and uses about 25MB of RAM. + +If that's not enough for you, Netdata is quite adaptable to long-term storage of your system's metrics. + +There are two quick ways to increase the depth of historical metrics: increase the `history` value for the round-robin +that's enabled by default, or switch to the database engine. + +We have a tutorial that walks you through both options: [**Changing how long Netdata stores +metrics**](../docs/tutorials/longer-metrics-storage.md). + +**What's next?**: + +- Learn more about the [memory requirements for the database engine](../database/engine/README.md#memory-requirements) + to understand how much RAM/disk space you should commit to storing historical metrics. +- Read up on the memory requirements of the [round-robin database](../database/), or figure out whether your system + has KSM enabled, which can [reduce the default database's memory usage](../database/README.md#ksm) by about 60%. + +## Monitoring multiple systems with Netdata + +If you have Netdata installed on multiple systems, you can have them all appear in the **My nodes** menu at the top-left +corner of the dashboard. + +To show all your servers in that menu, you need to [register for or sign in](../docs/netdata-cloud/signing-in.md) to +[Netdata Cloud](../docs/netdata-cloud/) from each system. Each system will then appear in the **My nodes** menu, which +you can use to navigate between your systems quickly. + +![Animated GIF of the My Nodes menu in +action](https://user-images.githubusercontent.com/1153921/64389938-9aa7b800-cff9-11e9-9653-a77e791811ad.gif) + +Whenever you pan, zoom, highlight, select, or pause a chart, Netdata will synchronize those settings with any other +agent you visit via the My nodes menu. Even your scroll position is synchronized, so you'll see the same charts and +respective data for easy comparisons or root cause analysis. + +You can now seamlessly track performance anomalies across your entire infrastructure! + +**What's next?**: + +- Read up on how the [Netdata Cloud registry works](../registry/), and what kind of data it stores and sends to your + web browser. +- Familiarize yourself with the [Nodes View](../docs/netdata-cloud/nodes-view.md) + +## Start, stop, and restart Netdata + +When you install Netdata, it's configured to start at boot, and stop and restart/shutdown. You shouldn't need to start +or stop Netdata manually, but you will probably need to restart Netdata at some point. + +- To **start** Netdata, open a terminal and run `service netdata start`. +- To **stop** Netdata, run `service netdata stop`. +- To **restart** Netdata, run `service netdata restart`. + +The `service` command is a wrapper script that tries to use your system's preferred method of starting or stopping +Netdata based on your system. But, if either of those commands fails, try using the equivalent commands for `systemd` +and `init.d`: + +- **systemd**: `systemctl start netdata`, `systemctl stop netdata`, `systemctl restart netdata` +- **init.d**: `/etc/init.d/netdata start`, `/etc/init.d/netdata stop`, `/etc/init.d/netdata restart` + +## What's next? + +Even after you've configured `netdata.conf`, tweaked alarms, learned the basics of performance troubleshooting, and +added all your systems to the **My nodes** menu, you've just gotten started with Netdata. + +Take a look at some more advanced features and configurations: + +- Centralize Netdata metrics from many systems with [streaming](../streaming) +- Enable long-term archiving of Netdata metrics via [backends](../backends) to time-series databases. +- Improve security by putting Netdata behind an [Nginx proxy with SSL](Running-behind-nginx.md). + +Or, learn more about how you can contribute to [Netdata core](../CONTRIBUTING.md) or our +[documentation](../docs/contributing/contributing-documentation.md)! + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fdocs%2FGettingStarted&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/docs/high-performance-netdata.md b/docs/high-performance-netdata.md index 3611fee38..3b33c03f1 100644 --- a/docs/high-performance-netdata.md +++ b/docs/high-performance-netdata.md @@ -126,7 +126,7 @@ You can check limits with following commands: ```sh cat /proc/$(ps aux | grep "nginx: master process" | grep -v grep | awk '{print $2}')/limits | grep "Max open files" -cat /proc/$(ps aux | grep "netdata" | head -n1 | grep -v grep | awk '{print $2}')/limits | grep "Max open files" +cat /proc/$(ps aux | grep "\/[n]etdata " | head -n1 | grep -v grep | awk '{print $2}')/limits | grep "Max open files" ``` View of the files: diff --git a/docs/netdata-security.md b/docs/netdata-security.md index e3ce6d56c..59c1ae29b 100644 --- a/docs/netdata-security.md +++ b/docs/netdata-security.md @@ -86,6 +86,41 @@ In Netdata v1.9+ there is also access list support, like this: allow connections from = localhost 10.* 192.168.* ``` +#### Fine-grainined access control + +The access list support allows filtering of all incoming connections, by specific IP addresses, ranges +or validated DNS lookups. Only connections that match an entry on the list will be allowed: + +``` +[web] + allow connections from = localhost 192.168.* 1.2.3.4 homeip.net +``` + +Connections from the IP addresses are allowed if the connection IP matches one of the patterns given. +The alias localhost is alway checked against 127.0.0.1, any other symbolic names need to resolve in +both directions using DNS. In the above example the IP address of `homeip.net` must reverse DNS resolve +to the incoming IP address and a DNS lookup on `homeip.net` must return the incoming IP address as +one of the resolved addresses. + +More specific control of what each incoming connection can do can be specified through the access control +list settings: + +``` +[web] + allow connections from = 160.1.* + allow badges from = 160.1.1.2 + allow streaming from = 160.1.2.* + allow management from = control.subnet.ip + allow netdata.conf from = updates.subnet.ip + allow dashboard from = frontend.subnet.ip +``` + +In this example only connections from `160.1.x.x` are allowed, only the specific IP address `160.1.1.2` +can access badges, only IP addresses in the smaller range `160.1.2.x` can stream data. The three +hostnames shown can access specific features, this assumes that DNS is setup to resolve these names +to IP addresses within the `160.1.x.x` range and that reverse DNS is setup for these hosts. + + #### Use an authenticating web server in proxy mode Use one web server to provide authentication in front of **all your Netdata servers**. So, you will be accessing all your Netdata with URLs like `http://{HOST}/netdata/{NETDATA_HOSTNAME}/` and authentication will be shared among all of them (you will sign-in once for all your servers). Instructions are provided on how to set the proxy configuration to have Netdata run behind [nginx](Running-behind-nginx.md), [Apache](Running-behind-apache.md), [lighthttpd](Running-behind-lighttpd.md#netdata-via-lighttpd-v14x) and [Caddy](Running-behind-caddy.md#netdata-via-caddy). diff --git a/docs/tutorials/longer-metrics-storage.md b/docs/tutorials/longer-metrics-storage.md new file mode 100644 index 000000000..e227f5bda --- /dev/null +++ b/docs/tutorials/longer-metrics-storage.md @@ -0,0 +1,155 @@ +# Change how long Netdata stores metrics + +Netdata helps you collect thousands of system and application metrics every second, but what about storing them for the +long term? + +Many people think Netdata can only store about an hour's worth of real-time metrics, but that's just the default +configuration today. With the right settings, Netdata is quite capable of efficiently storing hours or days worth of +historical, per-second metrics without having to rely on a [backend](../../backends/). + +This tutorial gives two options for configuring Netdata to store more metrics. We recommend the [**database +engine**](#using-the-database-engine), as it will soon be the default configuration. However, you can stick with the +current default **round-robin database** if you prefer. + +Let's get started. + +## Using the database engine + +The database engine uses RAM to store recent metrics while also using a "spill to disk" feature that takes advantage of +available disk space for long-term metrics storage.This feature of the database engine allows you to store a much larger +dataset than your system's available RAM. + +The database engine will eventually become the default method of retaining metrics, but until then, you can switch to +the database engine by changing a single option. + +Edit your `netdata.conf` file and change the `memory mode` setting to `dbengine`: + +```conf +[global] + memory mode = dbengine +``` + +Next, restart Netdata. On Linux systems, we recommend running `sudo service netdata restart`. You're now using the +database engine! + +> Learn more about how we implemented the database engine, and our vision for its future, on our blog: [_How and why +> we're bringing long-term storage to Netdata_](https://blog.netdata.cloud/posts/db-engine/). + +What makes the database engine efficient? While it's structured like a traditional database, the database engine splits +data between RAM and disk. The database engine caches and indexes data on RAM to keep memory usage low, and then +compresses older metrics onto disk for long-term storage. + +When the Netdata dashboard queries for historical metrics, the database engine will use its cache, stored in RAM, to +return relevant metrics for visualization in charts. + +Now, given that the database engine uses _both_ RAM and disk, there are two other settings to consider: `page cache +size` and `dbengine disk space`. + +```conf +[global] + page cache size = 32 + dbengine disk space = 256 +``` + +`page cache size` sets the maximum amount of RAM (in MiB) the database engine will use for caching and indexing. +`dbengine disk space` sets the maximum disk space (again, in MiB) the database engine will use for storing compressed +metrics. + +Based on our testing, these default settings will retain about two day's worth of metrics when Netdata collects 2,000 +metrics every second. + +If you'd like to change these options, read more about the [database engine's memory +footprint](../../database/engine/README.md#memory-requirements). + +With the database engine active, you can back up your `/var/cache/netdata/dbengine/` folder to another location for +redundancy. + +Now that you know how to switch to the database engine, let's cover the default round-robin database for those who +aren't ready to make the move. + +## Using the round-robin database + +By default, Netdata uses a round-robin database to store 1 hour of per-second metrics. Here's the default setting for +`history` in the `netdata.conf` file that comes pre-installed with Netdata. + +```conf +[global] + history = 3600 +``` + +One hour has 3,600 seconds, hence the `3600` value! + +To increase your historical metrics, you can increase `history` to the number of seconds you'd like to store: + +```conf +[global] + # 2 hours = 2 * 60 * 60 = 7200 seconds + history = 7200 + # 4 hours = 4 * 60 * 60 = 14440 seconds + history = 14440 + # 24 hours = 24 * 60 * 60 = 86400 seconds + history = 86400 +``` + +And so on. + +Next, check to see how many metrics Netdata collects on your system, and how much RAM that uses. Visit the Netdata +dashboard and look at the bottom-right corner of the interface. You'll find a sentence similar to the following: + +> Every second, Netdata collects 1,938 metrics, presents them in 299 charts and monitors them with 81 alarms. Netdata is +> using 25 MB of memory on **netdata-linux** for 1 hour, 6 minutes and 36 seconds of real-time history. + +On this desktop system, using a Ryzen 5 1600 and 16GB of RAM, the round-robin databases uses 25 MB of RAM to store just +over an hour's worth of data for nearly 2,000 metrics. + +To increase the `history` option, you need to edit your `netdata.conf` file and increase the `history` setting. In most +installations, you'll find it at `/etc/netdata/netdata.conf`, but some operating systems place it at +`/opt/netdata/etc/netdata/netdata.conf`. + +Use `/etc/netdata/edit-config netdata.conf`, or your favorite text editor, to replace `3600` with the number of seconds +you'd like to store. + +You should base this number on two things: How much history you need for your use case, and how much RAM you're willing +to dedicate to Netdata. + +> Take care when you change the `history` option on production systems. Netdata is configured to stop its process if +> your system starts running out of RAM, but you can never be too careful. Out of memory situations are very bad. + +How much RAM will a longer history use? Let's use a little math. + +The round-robin database needs 4 bytes for every value Netdata collects. If Netdata collects metrics every second, +that's 4 bytes, per second, per metric. + +```text +4 bytes * X seconds * Y metrics = RAM usage in bytes +``` + +Let's assume your system collects 1,000 metrics per second. + +```text +4 bytes * 3600 seconds * 1,000 metrics = 14400000 bytes = 14.4 MB RAM +``` + +With that formula, you can calculate the RAM usage for much larger history settings. + +```conf +# 2 hours at 1,000 metrics per second +4 bytes * 7200 seconds * 1,000 metrics = 28800000 bytes = 28.8 MB RAM +# 2 hours at 2,000 metrics per second +4 bytes * 7200 seconds * 2,000 metrics = 57600000 bytes = 57.6 MB RAM +# 4 hours at 2,000 metrics per second +4 bytes * 14440 seconds * 2,000 metrics = 115520000 bytes = 115.52 MB RAM +# 24 hours at 1,000 metrics per second +4 bytes * 86400 seconds * 1,000 metrics = 345600000 bytes = 345.6 MB RAM +``` + +## What's next? + +Now that you have either configured database engine or round-robin database engine to store more metrics, you'll +probably want to see it in action! + +For more information about how to pan charts to view historical metrics, see our documentation on [using +charts](../../web/README.md#using-charts). + +And if you'd now like to reduce Netdata's resource usage, view our [performance guide](../../docs/Performance.md) for +our best practices on optimization. diff --git a/docs/what-is-netdata.md b/docs/what-is-netdata.md index b134dc2ca..e9b4d1598 100644 --- a/docs/what-is-netdata.md +++ b/docs/what-is-netdata.md @@ -43,7 +43,7 @@ We provide docker images for the most common architectures. These are statistics ### Registry -When you install multiple Netdata, they are integrated into **one distributed application**, via a [Netdata registry](../registry/#registry). This is a web browser feature and it allows us to count the number of unique users and unique Netdata servers installed. The following information comes from the global public Netdata registry we run: +When you install multiple Netdata, they are integrated into **one distributed application**, via a [Netdata registry](../registry/). This is a web browser feature and it allows us to count the number of unique users and unique Netdata servers installed. The following information comes from the global public Netdata registry we run: [![User Base](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=persons&label=user%20base&units=M&value_color=blue&precision=2÷=1000000&v43)](https://registry.my-netdata.io/#menu_netdata_submenu_registry) [![Monitored Servers](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=machines&label=servers%20monitored&units=k÷=1000&value_color=orange&precision=2&v43)](https://registry.my-netdata.io/#menu_netdata_submenu_registry) [![Sessions Served](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_sessions&label=sessions%20served&units=M&value_color=yellowgreen&precision=2÷=1000000&v43)](https://registry.my-netdata.io/#menu_netdata_submenu_registry) @@ -91,12 +91,12 @@ This is how it works: |Function|Description|Documentation| |:------:|:----------|:-----------:| -|**Collect**|Multiple independent data collection workers are collecting metrics from their sources using the optimal protocol for each application and push the metrics to the database. Each data collection worker has lockless write access to the metrics it collects.|[`collectors`](../collectors/#data-collection-plugins)| -|**Store**|Metrics are stored in RAM in a round robin database (ring buffer), using a custom made floating point number for minimal footprint.|[`database`](../database/#database)| -|**Check**|A lockless independent watchdog is evaluating **health checks** on the collected metrics, triggers alarms, maintains a health transaction log and dispatches alarm notifications.|[`health`](../health/#health-monitoring)| -|**Stream**|An lockless independent worker is streaming metrics, in full detail and in real-time, to remote Netdata servers, as soon as they are collected.|[`streaming`](../streaming/#streaming-and-replication)| +|**Collect**|Multiple independent data collection workers are collecting metrics from their sources using the optimal protocol for each application and push the metrics to the database. Each data collection worker has lockless write access to the metrics it collects.|[`collectors`](../collectors/)| +|**Store**|Metrics are stored in RAM in a round robin database (ring buffer), using a custom made floating point number for minimal footprint.|[`database`](../database/)| +|**Check**|A lockless independent watchdog is evaluating **health checks** on the collected metrics, triggers alarms, maintains a health transaction log and dispatches alarm notifications.|[`health`](../health/)| +|**Stream**|An lockless independent worker is streaming metrics, in full detail and in real-time, to remote Netdata servers, as soon as they are collected.|[`streaming`](../streaming/)| |**Archive**|A lockless independent worker is down-sampling the metrics and pushes them to **backend** time-series databases.|[`backends`](../backends/)| -|**Query**|Multiple independent workers are attached to the [internal web server](../web/server/#web-server), servicing API requests, including [data queries](../web/api/queries/#database-queries).|[`web/api`](../web/api/#api)| +|**Query**|Multiple independent workers are attached to the [internal web server](../web/server/), servicing API requests, including [data queries](../web/api/queries/README.md).|[`web/api`](../web/api/)| The result is a highly efficient, low latency system, supporting multiple readers and one writer on each metric. diff --git a/health/Makefile.am b/health/Makefile.am index e9fceddb7..a314b3516 100644 --- a/health/Makefile.am +++ b/health/Makefile.am @@ -42,7 +42,9 @@ dist_healthconfig_DATA = \ health.d/fping.conf \ health.d/ioping.conf \ health.d/fronius.conf \ + health.d/gearman.conf \ health.d/haproxy.conf \ + health.d/hdfs.conf \ health.d/httpcheck.conf \ health.d/ipc.conf \ health.d/ipfs.conf \ @@ -84,10 +86,12 @@ dist_healthconfig_DATA = \ health.d/tcp_resets.conf \ health.d/udp_errors.conf \ health.d/varnish.conf \ + health.d/vcsa.conf \ health.d/vsphere.conf \ health.d/web_log.conf \ health.d/wmi.conf \ health.d/x509check.conf \ health.d/zfs.conf \ + health.d/zookeeper.conf \ health.d/dbengine.conf \ $(NULL) diff --git a/health/README.md b/health/README.md index ab8d6882a..0ffbbdb51 100644 --- a/health/README.md +++ b/health/README.md @@ -163,7 +163,7 @@ This line makes a database lookup to find a value. This result of this lookup is The format is: ``` -lookup: METHOD AFTER [at BEFORE] [every DURATION] [OPTIONS] [of DIMENSIONS] +lookup: METHOD AFTER [at BEFORE] [every DURATION] [OPTIONS] [of DIMENSIONS] [foreach DIMENSIONS] ``` Everything is the same with [badges](../web/api/badges/). In short: @@ -190,6 +190,11 @@ Everything is the same with [badges](../web/api/badges/). In short: have spaces in their names). This accepts Netdata simple patterns and the `match-ids` and `match-names` options affect the searches for dimensions. +- `foreach DIMENSIONS` is optional, will always be the last parameter, and uses the same `,`/`|` + rules as the `of` parameter. Each dimension you specify in `foreach` will use the same rule + to trigger an alarm. If you set both `of` and `foreach`, Netdata will ignore the `of` parameter + and replace it with one of the dimensions you gave to `foreach`. + The result of the lookup will be available as `$this` and `$NAME` in expressions. The timestamps of the timeframe evaluated by the database lookup is available as variables `$after` and `$before` (both are unix timestamps). @@ -660,6 +665,43 @@ Note that the drops chart does not exist if a network interface has never droppe When Netdata detects a dropped packet, it will add the chart and it will automatically attach this alarm to it. +### Example 5 + +Check if user or system dimension is using more than 50% of cpu: + +``` + alarm: dim_template + on: system.cpu + os: linux +lookup: average -3s percentage foreach system,user + units: % + every: 10s + warn: $this > 50 + crit: $this > 80 +``` + +The `lookup` line will calculate the average CPU usage from system and user in the last 3 seconds. Because we have +the foreach in the `lookup` line, Netdata will create two independent alarms called `dim_template_system` +and `dim_template_user` that will have all the other parameters shared among them. + +### Example 6 + +Check if all dimensions are using more than 50% of cpu: + +``` + alarm: dim_template + on: system.cpu + os: linux +lookup: average -3s percentage foreach * + units: % + every: 10s + warn: $this > 50 + crit: $this > 80 +``` + +The `lookup` line will calculate the average of CPU usage from system and user in the last 3 seconds. In this case +Netdata will create alarms for all dimensions of the chart. + ## Troubleshooting You can compile Netdata with [debugging](../daemon#debugging) and then set in `netdata.conf`: diff --git a/health/health.c b/health/health.c index 1460b5ba4..329191fb8 100644 --- a/health/health.c +++ b/health/health.c @@ -45,32 +45,30 @@ inline char *health_stock_config_dir(void) { * Function used to initialize the silencer structure. */ void health_silencers_init(void) { - struct stat statbuf; - if (!stat(silencers_filename,&statbuf)) { - off_t length = statbuf.st_size; - if (length && length < HEALTH_SILENCERS_MAX_FILE_LEN) { - FILE *fd = fopen(silencers_filename, "r"); - if (fd) { - char *str = mallocz((length+1)* sizeof(char)); - if(str) { - size_t copied; - copied = fread(str, sizeof(char), length, fd); - if (copied == (length* sizeof(char))) { - str[length] = 0x00; - json_parse(str, NULL, health_silencers_json_read_callback); - info("Parsed health silencers file %s", silencers_filename); - } else { - error("Cannot read the data from health silencers file %s", silencers_filename); - } - freez(str); + FILE *fd = fopen(silencers_filename, "r"); + if (fd) { + fseek(fd, 0 , SEEK_END); + off_t length = (off_t) ftell(fd); + fseek(fd, 0 , SEEK_SET); + + if (length > 0 && length < HEALTH_SILENCERS_MAX_FILE_LEN) { + char *str = mallocz((length+1)* sizeof(char)); + if(str) { + size_t copied; + copied = fread(str, sizeof(char), length, fd); + if (copied == (length* sizeof(char))) { + str[length] = 0x00; + json_parse(str, NULL, health_silencers_json_read_callback); + info("Parsed health silencers file %s", silencers_filename); + } else { + error("Cannot read the data from health silencers file %s", silencers_filename); } - fclose(fd); - } else { - error("Cannot open the file %s",silencers_filename); + freez(str); } } else { error("Health silencers file %s has the size %ld that is out of range[ 1 , %d ]. Aborting read.", silencers_filename, length, HEALTH_SILENCERS_MAX_FILE_LEN); } + fclose(fd); } else { error("Cannot open the file %s",silencers_filename); } @@ -115,9 +113,23 @@ void health_reload_host(RRDHOST *host) { while(host->templates) rrdcalctemplate_unlink_and_free(host, host->templates); + RRDCALCTEMPLATE *rt,*next; + for(rt = host->alarms_template_with_foreach; rt ; rt = next) { + next = rt->next; + rrdcalctemplate_free(rt); + } + host->alarms_template_with_foreach = NULL; + while(host->alarms) rrdcalc_unlink_and_free(host, host->alarms); + RRDCALC *rc,*nc; + for(rc = host->alarms_with_foreach; rc ; rc = nc) { + nc = rc->next; + rrdcalc_free(rc); + } + host->alarms_with_foreach = NULL; + rrdhost_unlock(host); // invalidate all previous entries in the alarm log @@ -141,9 +153,17 @@ void health_reload_host(RRDHOST *host) { health_readdir(host, user_path, stock_path, NULL); // link the loaded alarms to their charts + RRDDIM *rd; rrdset_foreach_write(st, host) { rrdsetcalc_link_matching(st); rrdcalctemplate_link_matching(st); + + //This loop must be the last, because ` rrdcalctemplate_link_matching` will create alarms related to it. + rrdset_rdlock(st); + rrddim_foreach_read(rd, st) { + rrdcalc_link_to_rrddim(rd, st, host); + } + rrdset_unlock(st); } rrdhost_unlock(host); @@ -890,6 +910,7 @@ void *health_main(void *ptr) { } } } + if(unlikely(repeat_every > 0 && (rc->last_repeat + repeat_every) <= now)) { rc->last_repeat = now; ALARM_ENTRY *ae = health_create_alarm_entry( diff --git a/health/health.d/dbengine.conf b/health/health.d/dbengine.conf index 956abf294..ce6427cd2 100644 --- a/health/health.d/dbengine.conf +++ b/health/health.d/dbengine.conf @@ -1,26 +1,26 @@ # you can disable an alarm notification by setting the 'to' line to: silent - alarm: 10min_dbengine_global_fs_errors - on: netdata.dbengine_global_errors - os: linux freebsd macos - hosts: * - lookup: sum -10m unaligned of FS errors - units: errors - every: 10s - crit: $this > 0 - delay: down 15m multiplier 1.5 max 1h - info: number of File-System errors dbengine came across the last 10 minutes (too many open files, wrong permissions etc) - to: sysadmin + alarm: 10min_dbengine_global_fs_errors + on: netdata.dbengine_global_errors + os: linux freebsd macos + hosts: * +lookup: sum -10m unaligned of FS errors + units: errors + every: 10s + crit: $this > 0 + delay: down 15m multiplier 1.5 max 1h + info: number of File-System errors dbengine came across the last 10 minutes (too many open files, wrong permissions etc) + to: sysadmin - alarm: 10min_dbengine_global_io_errors - on: netdata.dbengine_global_errors - os: linux freebsd macos - hosts: * - lookup: sum -10m unaligned of I/O errors - units: errors - every: 10s - crit: $this > 0 - delay: down 1h multiplier 1.5 max 3h - info: number of IO errors dbengine came across the last 10 minutes (CRC errors, out of space, bad disk etc) - to: sysadmin + alarm: 10min_dbengine_global_io_errors + on: netdata.dbengine_global_errors + os: linux freebsd macos + hosts: * +lookup: sum -10m unaligned of I/O errors + units: errors + every: 10s + crit: $this > 0 + delay: down 1h multiplier 1.5 max 3h + info: number of IO errors dbengine came across the last 10 minutes (CRC errors, out of space, bad disk etc) + to: sysadmin
\ No newline at end of file diff --git a/health/health.d/gearman.conf b/health/health.d/gearman.conf new file mode 100644 index 000000000..e3863ae5e --- /dev/null +++ b/health/health.d/gearman.conf @@ -0,0 +1,22 @@ +# make sure Gearman is running +template: gearman_last_collected_secs + on: gearman.total_jobs + calc: $now - $last_collected_t + units: seconds ago + every: 10s + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) + delay: down 5m multiplier 1.5 max 1h + info: number of seconds since the last successful data collection + to: sysadmin + +template: gearman_workers_queued + on: gearman.single_job + lookup: average -10m unaligned match-names of Queued + units: workers + every: 10s + warn: $this > 30000 + crit: $this > 100000 + delay: down 5m multiplier 1.5 max 1h + info: number of queued jobs + to: sysadmin
\ No newline at end of file diff --git a/health/health.d/hdfs.conf b/health/health.d/hdfs.conf new file mode 100644 index 000000000..678faab4c --- /dev/null +++ b/health/health.d/hdfs.conf @@ -0,0 +1,75 @@ + +# make sure hdfs is running + +template: hdfs_last_collected_secs + on: hdfs.heap_memory + calc: $now - $last_collected_t + units: seconds ago + every: 10s + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) + delay: down 5m multiplier 1.5 max 1h + info: number of seconds since the last successful data collection + to: webmaster + + +# Common + +template: hdfs_capacity_usage + on: hdfs.capacity + calc: ($used) * 100 / ($used + $remaining) + units: % + every: 10s + warn: $this > (($status >= $WARNING) ? (70) : (80)) + crit: $this > (($status == $CRITICAL) ? (80) : (98)) + delay: down 15m multiplier 1.5 max 1h + info: used capacity + to: sysadmin + + +# NameNode + +template: hdfs_missing_blocks + on: hdfs.blocks + calc: $missing + units: missing blocks + every: 10s + warn: $this > 0 + delay: down 15m multiplier 1.5 max 1h + info: missing blocks + to: sysadmin + + +template: hdfs_stale_nodes + on: hdfs.data_nodes + calc: $stale + units: dead nodes + every: 10s + warn: $this > 0 + delay: down 15m multiplier 1.5 max 1h + info: stale data nodes + to: sysadmin + + +template: hdfs_dead_nodes + on: hdfs.data_nodes + calc: $dead + units: dead nodes + every: 10s + crit: $this > 0 + delay: down 15m multiplier 1.5 max 1h + info: dead data nodes + to: sysadmin + + +# DataNode + +template: hdfs_num_failed_volumes + on: hdfs.num_failed_volumes + calc: $fsds_num_failed_volumes + units: failed volumes + every: 10s + warn: $this > 0 + delay: down 15m multiplier 1.5 max 1h + info: failed volumes + to: sysadmin diff --git a/health/health.d/mysql.conf b/health/health.d/mysql.conf index 39c401915..ce7b98a87 100644 --- a/health/health.d/mysql.conf +++ b/health/health.d/mysql.conf @@ -98,3 +98,37 @@ template: mysql_replication_lag info: the number of seconds mysql replication is behind this master to: dba + +# ----------------------------------------------------------------------------- +# galera cluster size + +template: mysql_galera_cluster_size_max_2m + on: mysql.galera_cluster_size + lookup: max -2m absolute + units: nodes + every: 10s + info: max cluster size 2 minute + to: dba + +template: mysql_galera_cluster_size + on: mysql.galera_cluster_size + calc: $nodes + units: nodes + every: 10s + warn: $this > $mysql_galera_cluster_size_max_2m + crit: $this < $mysql_galera_cluster_size_max_2m + delay: up 20s down 5m multiplier 1.5 max 1h + info: cluster size has changed + to: dba + +# galera node state + +template: mysql_galera_cluster_state + on: mysql.galera_cluster_state + calc: $state + every: 10s + warn: $this < 4 + crit: $this < 2 + delay: up 30s down 5m multiplier 1.5 max 1h + info: node state (0: undefined, 1: joining, 2: donor/desynced, 3: joined, 4: synced) + to: dba diff --git a/health/health.d/vcsa.conf b/health/health.d/vcsa.conf new file mode 100644 index 000000000..7bb98a9ba --- /dev/null +++ b/health/health.d/vcsa.conf @@ -0,0 +1,122 @@ + +# make sure vcsa is running and responding + +template: vcsa_last_collected_secs + on: vcsa.system_health + calc: $now - $last_collected_t + units: seconds ago + every: 10s + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) + delay: down 5m multiplier 1.5 max 1h + info: number of seconds since the last successful data collection + to: sysadmin + +# Overall system health: +# - 0: all components are healthy. +# - 1: one or more components might become overloaded soon. +# - 2: one or more components in the appliance might be degraded. +# - 3: one or more components might be in an unusable status and the appliance might become unresponsive soon. +# - 4: no health data is available. + +template: vcsa_system_health + on: vcsa.system_health + lookup: max -10s unaligned of system + units: status + every: 10s + warn: ($this == 1) || ($this == 2) + crit: $this == 3 + delay: down 1m multiplier 1.5 max 1h + info: overall system health status + to: sysadmin + +# Components health: +# - 0: healthy. +# - 1: healthy, but may have some problems. +# - 2: degraded, and may have serious problems. +# - 3: unavailable, or will stop functioning soon. +# - 4: no health data is available. + +template: vcsa_swap_health + on: vcsa.components_health + lookup: max -10s unaligned of swap + units: status + every: 10s + warn: $this == 1 + crit: ($this == 2) || ($this == 3) + delay: down 1m multiplier 1.5 max 1h + info: swap health status + to: sysadmin + +template: vcsa_storage_health + on: vcsa.components_health + lookup: max -10s unaligned of storage + units: status + every: 10s + warn: $this == 1 + crit: ($this == 2) || ($this == 3) + delay: down 1m multiplier 1.5 max 1h + info: storage health status + to: sysadmin + +template: vcsa_mem_health + on: vcsa.components_health + lookup: max -10s unaligned of mem + units: status + every: 10s + warn: $this == 1 + crit: ($this == 2) || ($this == 3) + delay: down 1m multiplier 1.5 max 1h + info: mem health status + to: sysadmin + +template: vcsa_load_health + on: vcsa.components_health + lookup: max -10s unaligned of load + units: status + every: 10s + warn: $this == 1 + crit: ($this == 2) || ($this == 3) + delay: down 1m multiplier 1.5 max 1h + info: load health status + to: sysadmin + +template: vcsa_database_storage_health + on: vcsa.components_health + lookup: max -10s unaligned of database_storage + units: status + every: 10s + warn: $this == 1 + crit: ($this == 2) || ($this == 3) + delay: down 1m multiplier 1.5 max 1h + info: database storage health status + to: sysadmin + +template: vcsa_applmgmt_health + on: vcsa.components_health + lookup: max -10s unaligned of applmgmt + units: status + every: 10s + warn: $this == 1 + crit: ($this == 2) || ($this == 3) + delay: down 1m multiplier 1.5 max 1h + info: appl mgmt health status + to: sysadmin + + +# Software updates health: +# - 0: no updates available. +# - 2: non-security updates are available. +# - 3: security updates are available. +# - 4: an error retrieving information on software updates. + +template: vcsa_software_updates_health + on: vcsa.software_updates_health + lookup: max -10s unaligned of software_packages + units: status + every: 10s + warn: $this == 4 + crit: $this == 3 + delay: down 1m multiplier 1.5 max 1h + info: software packages health status + to: sysadmin diff --git a/health/health.d/zookeeper.conf b/health/health.d/zookeeper.conf new file mode 100644 index 000000000..ffbe31baf --- /dev/null +++ b/health/health.d/zookeeper.conf @@ -0,0 +1,14 @@ + +# make sure zookeeper is running + +template: zookeeper_last_collected_secs + on: zookeeper.requests + calc: $now - $last_collected_t + units: seconds ago + every: 10s + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) + delay: down 5m multiplier 1.5 max 1h + info: number of seconds since the last successful data collection + to: webmaster + diff --git a/health/health.h b/health/health.h index 8e4d0f7cb..ab367e903 100644 --- a/health/health.h +++ b/health/health.h @@ -48,6 +48,7 @@ extern unsigned int default_health_enabled; #define HEALTH_INFO_KEY "info" #define HEALTH_DELAY_KEY "delay" #define HEALTH_OPTIONS_KEY "options" +#define HEALTH_FOREACH_KEY "foreach" #define HEALTH_SILENCERS_MAX_FILE_LEN 10000 @@ -106,4 +107,6 @@ extern void health_alarm_log_free_one_nochecks_nounlink(ALARM_ENTRY *ae); extern void *health_cmdapi_thread(void *ptr); +extern SIMPLE_PATTERN *health_pattern_from_foreach(char *s); + #endif //NETDATA_HEALTH_H diff --git a/health/health_config.c b/health/health_config.c index 0d6e77a9e..65c6d8bd7 100644 --- a/health/health_config.c +++ b/health/health_config.c @@ -46,7 +46,7 @@ static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) { rc->id = rrdcalc_get_unique_id(host, rc->chart, rc->name, &rc->next_event_id); - debug(D_HEALTH, "Health configuration adding alarm '%s.%s' (%u): exec '%s', recipient '%s', green " CALCULATED_NUMBER_FORMAT_AUTO ", red " CALCULATED_NUMBER_FORMAT_AUTO ", lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f, warn_repeat_every %u, crit_repeat_every %u", + debug(D_HEALTH, "Health configuration adding alarm '%s.%s' (%u): exec '%s', recipient '%s', green " CALCULATED_NUMBER_FORMAT_AUTO ", red " CALCULATED_NUMBER_FORMAT_AUTO ", lookup: group %d, after %d, before %d, options %u, dimensions '%s', for each dimension '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f, warn_repeat_every %u, crit_repeat_every %u", rc->chart?rc->chart:"NOCHART", rc->name, rc->id, @@ -59,6 +59,7 @@ static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) { rc->before, rc->options, (rc->dimensions)?rc->dimensions:"NONE", + (rc->foreachdim)?rc->foreachdim:"NONE", rc->update_every, (rc->calculation)?rc->calculation->parsed_as:"NONE", (rc->warning)?rc->warning->parsed_as:"NONE", @@ -73,6 +74,7 @@ static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) { ); rrdcalc_add_to_host(host, rc); + return 1; } @@ -93,48 +95,70 @@ static inline int rrdcalctemplate_add_template_from_config(RRDHOST *host, RRDCAL } RRDCALCTEMPLATE *t, *last = NULL; - for (t = host->templates; t ; last = t, t = t->next) { - if(unlikely(t->hash_name == rt->hash_name - && !strcmp(t->name, rt->name) - && !strcmp(t->family_match?t->family_match:"*", rt->family_match?rt->family_match:"*") - )) { - error("Health configuration template '%s' already exists for host '%s'.", rt->name, host->hostname); - return 0; + if(!rt->foreachdim) { + for (t = host->templates; t ; last = t, t = t->next) { + if(unlikely(t->hash_name == rt->hash_name + && !strcmp(t->name, rt->name) + && !strcmp(t->family_match?t->family_match:"*", rt->family_match?rt->family_match:"*") + )) { + error("Health configuration template '%s' already exists for host '%s'.", rt->name, host->hostname); + return 0; + } + } + + if(likely(last)) { + last->next = rt; + } + else { + rt->next = host->templates; + host->templates = rt; + } + } else { + for (t = host->alarms_template_with_foreach; t ; last = t, t = t->next) { + if(unlikely(t->hash_name == rt->hash_name + && !strcmp(t->name, rt->name) + && !strcmp(t->family_match?t->family_match:"*", rt->family_match?rt->family_match:"*") + )) { + error("Health configuration template '%s' already exists for host '%s'.", rt->name, host->hostname); + return 0; + } + } + + if(likely(last)) { + last->next = rt; + } + else { + rt->next = host->alarms_template_with_foreach; + host->alarms_template_with_foreach = rt; } } - debug(D_HEALTH, "Health configuration adding template '%s': context '%s', exec '%s', recipient '%s', green " CALCULATED_NUMBER_FORMAT_AUTO ", red " CALCULATED_NUMBER_FORMAT_AUTO ", lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f, warn_repeat_every %u, crit_repeat_every %u", - rt->name, - (rt->context)?rt->context:"NONE", - (rt->exec)?rt->exec:"DEFAULT", - (rt->recipient)?rt->recipient:"DEFAULT", - rt->green, - rt->red, - (int)rt->group, - rt->after, - rt->before, - rt->options, - (rt->dimensions)?rt->dimensions:"NONE", - rt->update_every, - (rt->calculation)?rt->calculation->parsed_as:"NONE", - (rt->warning)?rt->warning->parsed_as:"NONE", - (rt->critical)?rt->critical->parsed_as:"NONE", - rt->source, - rt->delay_up_duration, - rt->delay_down_duration, - rt->delay_max_duration, - rt->delay_multiplier, - rt->warn_repeat_every, - rt->crit_repeat_every + debug(D_HEALTH, "Health configuration adding template '%s': context '%s', exec '%s', recipient '%s', green " CALCULATED_NUMBER_FORMAT_AUTO ", red " CALCULATED_NUMBER_FORMAT_AUTO ", lookup: group %d, after %d, before %d, options %u, dimensions '%s', for each dimension '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f, warn_repeat_every %u, crit_repeat_every %u", + rt->name, + (rt->context)?rt->context:"NONE", + (rt->exec)?rt->exec:"DEFAULT", + (rt->recipient)?rt->recipient:"DEFAULT", + rt->green, + rt->red, + (int)rt->group, + rt->after, + rt->before, + rt->options, + (rt->dimensions)?rt->dimensions:"NONE", + (rt->foreachdim)?rt->foreachdim:"NONE", + rt->update_every, + (rt->calculation)?rt->calculation->parsed_as:"NONE", + (rt->warning)?rt->warning->parsed_as:"NONE", + (rt->critical)?rt->critical->parsed_as:"NONE", + rt->source, + rt->delay_up_duration, + rt->delay_down_duration, + rt->delay_max_duration, + rt->delay_multiplier, + rt->warn_repeat_every, + rt->crit_repeat_every ); - if(likely(last)) { - last->next = rt; - } - else { - rt->next = host->templates; - host->templates = rt; - } return 1; } @@ -291,16 +315,37 @@ static inline int health_parse_repeat( return 1; } +/** + * Health pattern from Foreach + * + * Create a new simple pattern using the user input + * + * @param s the string that will be used to create the simple pattern. + */ +SIMPLE_PATTERN *health_pattern_from_foreach(char *s) { + char *convert= strdupz(s); + SIMPLE_PATTERN *val = NULL; + if(convert) { + dimension_remove_pipe_comma(convert); + val = simple_pattern_create(convert, NULL, SIMPLE_PATTERN_EXACT); + + freez(convert); + } + + return val; +} static inline int health_parse_db_lookup( size_t line, const char *filename, char *string, RRDR_GROUPING *group_method, int *after, int *before, int *every, - uint32_t *options, char **dimensions + uint32_t *options, char **dimensions, char **foreachdim ) { debug(D_HEALTH, "Health configuration parsing database lookup %zu@%s: %s", line, filename, string); if(*dimensions) freez(*dimensions); + if(*foreachdim) freez(*foreachdim); *dimensions = NULL; + *foreachdim = NULL; *after = 0; *before = 0; *every = 0; @@ -387,8 +432,22 @@ static inline int health_parse_db_lookup( *options |= RRDR_OPTION_MATCH_NAMES; } else if(!strcasecmp(key, "of")) { - if(*s && strcasecmp(s, "all") != 0) + char *find = NULL; + if(*s && strcasecmp(s, "all") != 0) { + find = strcasestr(s, " foreach"); + if(find) { + *find = '\0'; + } *dimensions = strdupz(s); + } + + if(!find) { + break; + } + s = ++find; + } + else if(!strcasecmp(key, HEALTH_FOREACH_KEY )) { + *foreachdim = strdupz(s); break; } else { @@ -521,8 +580,12 @@ static int health_readfile(const char *filename, void *data) { uint32_t hash = simple_uhash(key); if(hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) { - if (rc && (ignore_this || !rrdcalc_add_alarm_from_config(host, rc))) - rrdcalc_free(rc); + if(rc) { + if(ignore_this || !rrdcalc_add_alarm_from_config(host, rc)) { + rrdcalc_free(rc); + } + // health_add_alarms_loop(host, rc, ignore_this) ; + } if(rt) { if (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt)) @@ -552,14 +615,18 @@ static int health_readfile(const char *filename, void *data) { } else if(hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) { if(rc) { - if(ignore_this || !rrdcalc_add_alarm_from_config(host, rc)) +// health_add_alarms_loop(host, rc, ignore_this) ; + if(ignore_this || !rrdcalc_add_alarm_from_config(host, rc)) { rrdcalc_free(rc); + } rc = NULL; } - if(rt && (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt))) - rrdcalctemplate_free(rt); + if(rt) { + if(ignore_this || !rrdcalctemplate_add_template_from_config(host, rt)) + rrdcalctemplate_free(rt); + } rt = callocz(1, sizeof(RRDCALCTEMPLATE)); rt->name = strdupz(value); @@ -622,8 +689,10 @@ static int health_readfile(const char *filename, void *data) { } else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { health_parse_db_lookup(line, filename, value, &rc->group, &rc->after, &rc->before, - &rc->update_every, - &rc->options, &rc->dimensions); + &rc->update_every, &rc->options, &rc->dimensions, &rc->foreachdim); + if(rc->foreachdim) { + rc->spdim = health_pattern_from_foreach(rc->foreachdim); + } } else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { if(!config_parse_duration(value, &rc->update_every)) @@ -752,7 +821,10 @@ static int health_readfile(const char *filename, void *data) { } else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { health_parse_db_lookup(line, filename, value, &rt->group, &rt->after, &rt->before, - &rt->update_every, &rt->options, &rt->dimensions); + &rt->update_every, &rt->options, &rt->dimensions, &rt->foreachdim); + if(rt->foreachdim) { + rt->spdim = health_pattern_from_foreach(rt->foreachdim); + } } else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { if(!config_parse_duration(value, &rt->update_every)) @@ -866,11 +938,17 @@ static int health_readfile(const char *filename, void *data) { } } - if(rc && (ignore_this || !rrdcalc_add_alarm_from_config(host, rc))) - rrdcalc_free(rc); + if(rc) { + //health_add_alarms_loop(host, rc, ignore_this) ; + if(ignore_this || !rrdcalc_add_alarm_from_config(host, rc)) { + rrdcalc_free(rc); + } + } - if(rt && (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt))) - rrdcalctemplate_free(rt); + if(rt) { + if(ignore_this || !rrdcalctemplate_add_template_from_config(host, rt)) + rrdcalctemplate_free(rt); + } fclose(fp); return 1; @@ -881,5 +959,6 @@ void health_readdir(RRDHOST *host, const char *user_path, const char *stock_path debug(D_HEALTH, "CONFIG health is not enabled for host '%s'", host->hostname); return; } + recursive_config_double_dir_load(user_path, stock_path, subpath, health_readfile, (void *) host, 0); } diff --git a/health/notifications/README.md b/health/notifications/README.md index a0065729a..c086e79b1 100644 --- a/health/notifications/README.md +++ b/health/notifications/README.md @@ -39,7 +39,18 @@ by running `/etc/netdata/edit-config health_alarm_notify.conf`: all notification methods except email, require some configuration (i.e. API keys, tokens, destination rooms, channels, etc). -2. **recipients** per **role** per **notification method** +- **recipients** per **role** per **notification method** + +```sh +grep sysadmin /etc/netdata/health_alarm_notify.conf + +role_recipients_email[sysadmin]="${DEFAULT_RECIPIENT_EMAIL}" +role_recipients_pushover[sysadmin]="${DEFAULT_RECIPIENT_PUSHOVER}" +role_recipients_pushbullet[sysadmin]="${DEFAULT_RECIPIENT_PUSHBULLET}" +role_recipients_telegram[sysadmin]="${DEFAULT_RECIPIENT_TELEGRAM}" +role_recipients_slack[sysadmin]="${DEFAULT_RECIPIENT_SLACK}" +... +``` ## Testing Notifications diff --git a/health/notifications/alarm-notify.sh.in b/health/notifications/alarm-notify.sh.in index bbb960918..509a8e88d 100755 --- a/health/notifications/alarm-notify.sh.in +++ b/health/notifications/alarm-notify.sh.in @@ -194,7 +194,7 @@ fi # ----------------------------------------------------------------------------- # parse command line parameters -if [ ${1} = "unittest" ]; then +if [[ ${1} = "unittest" ]]; then unittest=1 # enable unit testing mode roles="${2}" # the role that should be used for unit testing cfgfile="${3}" # the location of the config file to use for unit testing @@ -1783,7 +1783,7 @@ url_family="${REPLY}" urlencode "${name}" >/dev/null url_name="${REPLY}" -redirect_params="host=${url_host}&chart=${url_chart}&family=${url_family}&alarm=${url_name}&alarm_unique_id=${unique_id}&alarm_id=${alarm_id}&alarm_event_id=${event_id}" +redirect_params="host=${url_host}&chart=${url_chart}&family=${url_family}&alarm=${url_name}&alarm_unique_id=${unique_id}&alarm_id=${alarm_id}&alarm_event_id=${event_id}&alarm_when=${when}" GOTOCLOUD=0 if [ "${NETDATA_REGISTRY_URL}" == "https://registry.my-netdata.io" ]; then diff --git a/health/notifications/email/README.md b/health/notifications/email/README.md index 92916d192..bf03887ac 100644 --- a/health/notifications/email/README.md +++ b/health/notifications/email/README.md @@ -1,4 +1,4 @@ -# email +# Email You need a working `sendmail` command for email alerts to work. Almost all MTAs provide a `sendmail` interface. @@ -33,4 +33,26 @@ Where `[ROLE]` is the role you want to test. The default (if you don't give a `[ Note that in versions before 1.16, the plugins.d directory may be installed in a different location in certain OSs (e.g. under `/usr/lib/netdata`). You can always find the location of the alarm-notify.sh script in `netdata.conf`. +## Simple SMTP transport configuration + +If you want an alternative to `sendmail` in order to have a simple MTA configuration for sending emails and auth to an existing SMTP server, you can do the following: + +- Install `msmtp`. +- Modify the `sendmail` path in `health_alarm_notify.conf` to point to the location of `mstmp`: +``` +# The full path to the sendmail command. +# If empty, the system $PATH will be searched for it. +# If not found, email notifications will be disabled (silently). +sendmail="/usr/bin/msmtp" +``` +- Login as netdata : +```sh +(sudo) su -s /bin/bash netdata +``` +- Configure `~/.msmtprc` as shown [in the documentation](https://marlam.de/msmtp/documentation/). +- Finaly set the appropriate permissions on the `.msmtprc` file : +```sh +chmod 600 ~/.msmtprc +``` + [![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fhealth%2Fnotifications%2Femail%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/libnetdata/health/health.c b/libnetdata/health/health.c index b93de8b93..a70f284b1 100644 --- a/libnetdata/health/health.c +++ b/libnetdata/health/health.c @@ -136,7 +136,8 @@ int health_silencers_json_read_callback(JSON_ENTRY *e) else if (!strcmp(e->data.string,"DISABLE")) silencers->stype = STYPE_DISABLE_ALARMS; } else { debug(D_HEALTH, "JSON: Adding %s=%s", e->name, e->data.string); - health_silencers_addparam(e->callback_data, e->name, e->data.string); + SILENCER *test = health_silencers_addparam(e->callback_data, e->name, e->data.string); + (void)test; } break; diff --git a/libnetdata/json/jsmn.c b/libnetdata/json/jsmn.c index c8d9e73db..952535897 100644 --- a/libnetdata/json/jsmn.c +++ b/libnetdata/json/jsmn.c @@ -301,10 +301,12 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, } } - for (i = parser->toknext - 1; i >= 0; i--) { - /* Unmatched opened object or array */ - if (tokens[i].start != -1 && tokens[i].end == -1) { - return JSMN_ERROR_PART; + if (tokens) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } } } diff --git a/libnetdata/popen/popen.c b/libnetdata/popen/popen.c index 177aebfc0..906b10535 100644 --- a/libnetdata/popen/popen.c +++ b/libnetdata/popen/popen.c @@ -68,7 +68,7 @@ static inline FILE *custom_popene(const char *command, volatile pid_t *pidptr, c int i; for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i >= 0; i--) if(i != STDIN_FILENO && i != STDERR_FILENO) - fcntl(i, F_SETFD, FD_CLOEXEC); + (void)fcntl(i, F_SETFD, FD_CLOEXEC); if (!posix_spawn_file_actions_init(&fa)) { // move the pipe to stdout in the child @@ -97,7 +97,7 @@ static inline FILE *custom_popene(const char *command, volatile pid_t *pidptr, c debug(D_CHILDS, "Spawned command: '%s' on pid %d from parent pid %d.", command, pid, getpid()); } else { error("Failed to spawn command: '%s' from parent pid %d.", command, getpid()); - close(pipefd[PIPE_READ]); + fclose(fp); fp = NULL; } close(pipefd[PIPE_WRITE]); @@ -116,7 +116,11 @@ error_after_posix_spawn_file_actions_init: if (posix_spawn_file_actions_destroy(&fa)) error("posix_spawn_file_actions_destroy"); error_after_pipe: - close(pipefd[PIPE_READ]); + if (fp) + fclose(fp); + else + close(pipefd[PIPE_READ]); + close(pipefd[PIPE_WRITE]); return NULL; } diff --git a/libnetdata/socket/socket.c b/libnetdata/socket/socket.c index 22abb47f4..fa1414dc0 100644 --- a/libnetdata/socket/socket.c +++ b/libnetdata/socket/socket.c @@ -995,21 +995,103 @@ int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) { } #endif +/* + * --------------------------------------------------------------------------------------------------------------------- + * connection_allowed() - if there is an access list then check the connection matches a pattern. + * Numeric patterns are checked against the IP address first, only if they + * do not match is the hostname resolved (reverse-DNS) and checked. If the + * hostname matches then we perform forward DNS resolution to check the IP + * is really associated with the DNS record. This call is repeatable: the + * web server may check more refined matches against the connection. Will + * update the client_host if uninitialized - ensure the hostsize is the number + * of *writable* bytes (i.e. be aware of the strdup used to compact the pollinfo). + */ +extern int connection_allowed(int fd, char *client_ip, char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list, + const char *patname) { + if (!access_list) + return 1; + if (simple_pattern_matches(access_list, client_ip)) + return 1; + // If the hostname is unresolved (and needed) then attempt the DNS lookups. + if (client_host[0]==0) + { + struct sockaddr_storage sadr; + socklen_t addrlen = sizeof(sadr); + int err = getpeername(fd, (struct sockaddr*)&sadr, &addrlen); + if (err != 0 || + (err = getnameinfo((struct sockaddr *)&sadr, addrlen, client_host, (socklen_t)hostsize, + NULL, 0, NI_NAMEREQD)) != 0) { + error("Incoming connection on '%s' does not match a numeric pattern, " + "and host could not be resolved (err=%s)", client_ip, gai_strerror(err)); + if (hostsize >= 8) + strcpy(client_host,"UNKNOWN"); + return 0; + } + struct addrinfo *addr_infos = NULL; + if (getaddrinfo(client_host, NULL, NULL, &addr_infos) !=0 ) { + error("LISTENER: cannot validate hostname '%s' from '%s' by resolving it", + client_host, client_ip); + if (hostsize >= 8) + strcpy(client_host,"UNKNOWN"); + return 0; + } + struct addrinfo *scan = addr_infos; + int validated = 0; + while (scan) { + char address[INET6_ADDRSTRLEN]; + address[0] = 0; + switch (scan->ai_addr->sa_family) { + case AF_INET: + inet_ntop(AF_INET, &((struct sockaddr_in*)(scan->ai_addr))->sin_addr, address, INET6_ADDRSTRLEN); + break; + case AF_INET6: + inet_ntop(AF_INET6, &((struct sockaddr_in6*)(scan->ai_addr))->sin6_addr, address, INET6_ADDRSTRLEN); + break; + } + debug(D_LISTENER, "Incoming ip %s rev-resolved onto %s, validating against forward-resolution %s", + client_ip, client_host, address); + if (!strcmp(client_ip, address)) { + validated = 1; + break; + } + scan = scan->ai_next; + } + if (!validated) { + error("LISTENER: Cannot validate '%s' as ip of '%s', not listed in DNS", client_ip, client_host); + if (hostsize >= 8) + strcpy(client_host,"UNKNOWN"); + } + if (addr_infos!=NULL) + freeaddrinfo(addr_infos); + } + if (!simple_pattern_matches(access_list, client_host)) { + debug(D_LISTENER, "Incoming connection on '%s' (%s) does not match allowed pattern for %s", + client_ip, client_host, patname); + return 0; + } + return 1; +} // -------------------------------------------------------------------------------------------------------------------- // accept_socket() - accept a socket and store client IP and port -int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, SIMPLE_PATTERN *access_list) { +int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, + char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list) { struct sockaddr_storage sadr; socklen_t addrlen = sizeof(sadr); int nfd = accept4(fd, (struct sockaddr *)&sadr, &addrlen, flags); if (likely(nfd >= 0)) { - if (getnameinfo((struct sockaddr *)&sadr, addrlen, client_ip, (socklen_t)ipsize, client_port, (socklen_t)portsize, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { + if (getnameinfo((struct sockaddr *)&sadr, addrlen, client_ip, (socklen_t)ipsize, + client_port, (socklen_t)portsize, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { error("LISTENER: cannot getnameinfo() on received client connection."); strncpyz(client_ip, "UNKNOWN", ipsize - 1); strncpyz(client_port, "UNKNOWN", portsize - 1); } + if(!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) { + strncpy(client_ip, "localhost", ipsize); + client_ip[ipsize - 1] = '\0'; + } #ifdef __FreeBSD__ if(((struct sockaddr *)&sadr)->sa_family == AF_LOCAL) @@ -1044,21 +1126,12 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien debug(D_LISTENER, "New UNKNOWN web client from %s port %s on socket %d.", client_ip, client_port, fd); break; } - - if(access_list) { - if(!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) { - strncpy(client_ip, "localhost", ipsize); - client_ip[ipsize - 1] = '\0'; - } - - if(unlikely(!simple_pattern_matches(access_list, client_ip))) { - errno = 0; - debug(D_LISTENER, "Permission denied for client '%s', port '%s'", client_ip, client_port); - error("DENIED ACCESS to client '%s'", client_ip); - close(nfd); - nfd = -1; - errno = EPERM; - } + if(!connection_allowed(nfd, client_ip, client_host, hostsize, access_list, "connection")) { + errno = 0; + error("Permission denied for client '%s', port '%s'", client_ip, client_port); + close(nfd); + nfd = -1; + errno = EPERM; } } #ifdef HAVE_ACCEPT4 @@ -1084,6 +1157,7 @@ inline POLLINFO *poll_add_fd(POLLJOB *p , uint32_t flags , const char *client_ip , const char *client_port + , const char *client_host , void *(*add_callback)(POLLINFO * /*pi*/, short int * /*events*/, void * /*data*/) , void (*del_callback)(POLLINFO * /*pi*/) , int (*rcv_callback)(POLLINFO * /*pi*/, short int * /*events*/) @@ -1123,6 +1197,7 @@ inline POLLINFO *poll_add_fd(POLLJOB *p p->inf[i].client_ip = NULL; p->inf[i].client_port = NULL; + p->inf[i].client_host = NULL; p->inf[i].del_callback = p->del_callback; p->inf[i].rcv_callback = p->rcv_callback; p->inf[i].snd_callback = p->snd_callback; @@ -1153,8 +1228,9 @@ inline POLLINFO *poll_add_fd(POLLJOB *p pi->port_acl = port_acl; pi->flags = flags; pi->next = NULL; - pi->client_ip = strdupz(client_ip); + pi->client_ip = strdupz(client_ip); pi->client_port = strdupz(client_port); + pi->client_host = strdupz(client_host); pi->del_callback = del_callback; pi->rcv_callback = rcv_callback; @@ -1224,6 +1300,9 @@ inline void poll_close_fd(POLLINFO *pi) { freez(pi->client_port); pi->client_port = NULL; + freez(pi->client_host); + pi->client_host = NULL; + pi->next = p->first_free; p->first_free = pi; @@ -1356,13 +1435,16 @@ static void poll_events_process(POLLJOB *p, POLLINFO *pi, struct pollfd *pf, sho int nfd; do { - char client_ip[NI_MAXHOST + 1]; - char client_port[NI_MAXSERV + 1]; - client_ip[0] = 0x00; - client_port[0] = 0x00; + char client_ip[INET6_ADDRSTRLEN]; + char client_port[NI_MAXSERV]; + char client_host[NI_MAXHOST]; + client_host[0] = 0; + client_ip[0] = 0; + client_port[0] = 0; debug(D_POLLFD, "POLLFD: LISTENER: calling accept4() slot %zu (fd %d)", i, fd); - nfd = accept_socket(fd, SOCK_NONBLOCK, client_ip, NI_MAXHOST + 1, client_port, NI_MAXSERV + 1, p->access_list); + nfd = accept_socket(fd, SOCK_NONBLOCK, client_ip, INET6_ADDRSTRLEN, client_port, NI_MAXSERV, + client_host, NI_MAXHOST, p->access_list); if (unlikely(nfd < 0)) { // accept failed @@ -1387,6 +1469,7 @@ static void poll_events_process(POLLJOB *p, POLLINFO *pi, struct pollfd *pf, sho , POLLINFO_FLAG_CLIENT_SOCKET , client_ip , client_port + , client_host , p->add_callback , p->del_callback , p->rcv_callback @@ -1530,6 +1613,7 @@ void poll_events(LISTEN_SOCKETS *sockets , POLLINFO_FLAG_SERVER_SOCKET , (sockets->fds_names[i])?sockets->fds_names[i]:"UNKNOWN" , "" + , "" , p.add_callback , p.del_callback , p.rcv_callback diff --git a/libnetdata/socket/socket.h b/libnetdata/socket/socket.h index 76b15def5..227f05434 100644 --- a/libnetdata/socket/socket.h +++ b/libnetdata/socket/socket.h @@ -72,7 +72,10 @@ extern int sock_setreuse_port(int fd, int reuse); extern int sock_enlarge_in(int fd); extern int sock_enlarge_out(int fd); -extern int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, SIMPLE_PATTERN *access_list); +extern int connection_allowed(int fd, char *client_ip, char *client_host, size_t hostsize, + SIMPLE_PATTERN *access_list, const char *patname); +extern int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, + char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list); #ifndef HAVE_ACCEPT4 extern int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags); @@ -104,8 +107,9 @@ typedef struct pollinfo { int fd; // the file descriptor int socktype; // the client socket type WEB_CLIENT_ACL port_acl; // the access lists permitted on this web server port (it's -1 for client sockets) - char *client_ip; // the connected client IP - char *client_port; // the connected client port + char *client_ip; // Max INET6_ADDRSTRLEN bytes + char *client_port; // Max NI_MAXSERV bytes + char *client_host; // Max NI_MAXHOST bytes time_t connected_t; // the time the socket connected time_t last_received_t; // the time the socket last received data @@ -173,6 +177,7 @@ extern POLLINFO *poll_add_fd(POLLJOB *p , uint32_t flags , const char *client_ip , const char *client_port + , const char *client_host , void *(*add_callback)(POLLINFO *pi, short int *events, void *data) , void (*del_callback)(POLLINFO *pi) , int (*rcv_callback)(POLLINFO *pi, short int *events) diff --git a/libnetdata/url/url.c b/libnetdata/url/url.c index 7df9faaf0..d1d508139 100644 --- a/libnetdata/url/url.c +++ b/libnetdata/url/url.c @@ -44,23 +44,6 @@ char *url_encode(char *str) { } /** - * URL Decode - * - * Returns a url-decoded version of str - * IMPORTANT: be sure to free() the returned string after use - * - * @param str the string that will be decode - * - * @return a pointer for the url decoded. - */ -char *url_decode(char *str) { - size_t size = strlen(str) + 1; - - char *buf = mallocz(size); - return url_decode_r(buf, str, size); -} - -/** * Percentage escape decode * * Decode %XX character or return 0 if cannot diff --git a/netdata-installer.sh b/netdata-installer.sh index 781cd9b1d..4c3aeee71 100755 --- a/netdata-installer.sh +++ b/netdata-installer.sh @@ -752,6 +752,11 @@ if [ "${UID}" -eq 0 ]; then run chmod 4750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/perf.plugin" fi + if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/slabinfo.plugin" ]; then + run chown root:${NETDATA_GROUP} "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/slabinfo.plugin" + run chmod 4750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/slabinfo.plugin" + fi + if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/ioping" ]; then run chown root:${NETDATA_GROUP} "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/ioping" run chmod 4750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/ioping" @@ -807,9 +812,19 @@ install_go() { tmp=$(mktemp -d /tmp/netdata-go-XXXXXX) GO_PACKAGE_BASENAME="go.d.plugin-${GO_PACKAGE_VERSION}.${OS}-${ARCH}.tar.gz" - download_go "https://github.com/netdata/go.d.plugin/releases/download/${GO_PACKAGE_VERSION}/${GO_PACKAGE_BASENAME}" "${tmp}/${GO_PACKAGE_BASENAME}" + if [ -z "${NETDATA_LOCAL_TARBALL_OVERRIDE_GO_PLUGIN}" ]; then + download_go "https://github.com/netdata/go.d.plugin/releases/download/${GO_PACKAGE_VERSION}/${GO_PACKAGE_BASENAME}" "${tmp}/${GO_PACKAGE_BASENAME}" + else + progress "Using provided go.d tarball ${NETDATA_LOCAL_TARBALL_OVERRIDE_GO_PLUGIN}" + run cp "${NETDATA_LOCAL_TARBALL_OVERRIDE_GO_PLUGIN}" "${tmp}/${GO_PACKAGE_BASENAME}" + fi - download_go "https://github.com/netdata/go.d.plugin/releases/download/${GO_PACKAGE_VERSION}/config.tar.gz" "${tmp}/config.tar.gz" + if [ -z "${NETDATA_LOCAL_TARBALL_OVERRIDE_GO_PLUGIN_CONFIG}" ]; then + download_go "https://github.com/netdata/go.d.plugin/releases/download/${GO_PACKAGE_VERSION}/config.tar.gz" "${tmp}/config.tar.gz" + else + progress "Using provided config file for go.d ${NETDATA_LOCAL_TARBALL_OVERRIDE_GO_PLUGIN_CONFIG}" + run cp "${NETDATA_LOCAL_TARBALL_OVERRIDE_GO_PLUGIN_CONFIG}" "${tmp}/config.tar.gz" + fi if [ ! -f "${tmp}/${GO_PACKAGE_BASENAME}" ] || [ ! -f "${tmp}/config.tar.gz" ] || [ ! -s "${tmp}/config.tar.gz" ] || [ ! -s "${tmp}/${GO_PACKAGE_BASENAME}" ]; then run_failed "go.d plugin download failed, go.d plugin will not be available" @@ -866,7 +881,20 @@ progress "Install netdata at system init" NETDATA_START_CMD="${NETDATA_PREFIX}/usr/sbin/netdata" if grep -q docker /proc/1/cgroup >/dev/null 2>&1; then - echo >&2 "We are running within a docker container, will not be installing netdata service" + # If docker runs systemd for some weird reason, let the install proceed + is_systemd_running="NO" + if command -v pidof >/dev/null 2>&1; then + is_systemd_running="$(pidof /usr/sbin/init || pidof systemd || echo "NO")" + else + is_systemd_running="$( (ps -p 1 | grep -q systemd && echo "1") || echo "NO")" + fi + + if [ "${is_systemd_running}" == "1" ]; then + echo >&2 "Found systemd within the docker container, running install_netdata_service() method" + install_netdata_service || run_failed "Cannot install netdata init service." + else + echo >&2 "We are running within a docker container, will not be installing netdata service" + fi echo >&2 else install_netdata_service || run_failed "Cannot install netdata init service." diff --git a/netdata.spec.in b/netdata.spec.in index 217e79c35..edf6a6c36 100644 --- a/netdata.spec.in +++ b/netdata.spec.in @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-3.0-or-later %global contentdir %{_datadir}/netdata - +%global version @PACKAGE_VERSION@ #TODO: Temporary fix for the build-id error during go.d plugin set up %global _missing_build_ids_terminate_build 0 @@ -83,7 +83,7 @@ fi \ Summary: Real-time performance monitoring, done right! Name: netdata -Version: @PACKAGE_VERSION@ +Version: %{version} Release: 1%{?dist} License: GPLv3+ Group: Applications/System @@ -192,8 +192,9 @@ Requires: freeipmi # end - freeipmi plugin dependencies # CUPS plugin dependencies -BuildRequires: cups-devel -Requires: cups +%if 0%{?centos_ver} != 6 && 0%{?centos_ver} != 7 +BuildRequires: cups-devel >= 1.7 +%endif # end - cups plugin dependencies # Prometheus remote write dependencies @@ -277,6 +278,16 @@ install -m 4750 -p apps.plugin "${RPM_BUILD_ROOT}%{_libexecdir}/%{name}/plugins. install -m 4750 -p perf.plugin "${RPM_BUILD_ROOT}%{_libexecdir}/%{name}/plugins.d/perf.plugin" # ########################################################### +# Install cups.plugin +%if 0%{?centos_ver} != 6 && 0%{?centos_ver} != 7 +install -m 0750 -p cups.plugin "${RPM_BUILD_ROOT}%{_libexecdir}/%{name}/plugins.d/cups.plugin" +%endif + +# ########################################################### +# Install slabinfo.plugin +install -m 4750 -p slabinfo.plugin "${RPM_BUILD_ROOT}%{_libexecdir}/%{name}/plugins.d/slabinfo.plugin" + +# ########################################################### # Install registry directory install -m 755 -d "${RPM_BUILD_ROOT}%{_localstatedir}/lib/%{name}/registry" install -m 755 -d "${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/custom-plugins.d" @@ -447,6 +458,8 @@ rm -rf "${RPM_BUILD_ROOT}" # perf plugin %caps(cap_setuid=ep) %attr(4750,root,netdata) %{_libexecdir}/%{name}/plugins.d/perf.plugin +# perf plugin +%caps(cap_setuid=ep) %attr(4550,root,netdata) %{_libexecdir}/%{name}/plugins.d/slabinfo.plugin # freeipmi files %caps(cap_setuid=ep) %attr(4550,root,netdata) %{_libexecdir}/%{name}/plugins.d/freeipmi.plugin @@ -483,8 +496,29 @@ rm -rf "${RPM_BUILD_ROOT}" %attr(0770,netdata,netdata) %dir %{_localstatedir}/lib/%{name} %attr(0770,netdata,netdata) %dir %{_localstatedir}/lib/%{name}/registry +# CUPS belongs to a different sub package +%if 0%{?centos_ver} != 6 && 0%{?centos_ver} != 7 +%exclude %{_libexecdir}/%{name}/plugins.d/cups.plugin + +%package plugin-cups +Summary: The Common Unix Printing System plugin for netdata +Group: Applications/System +Requires: cups >= 1.7 +Requires: netdata = %{version} + +%description plugin-cups + This is the Common Unix Printing System plugin for the netdata daemon. +Use this plugin to enable metrics collection from cupsd, the daemon running when CUPS is enabled on the system + +%files plugin-cups +%attr(0750,root,netdata) %{_libexecdir}/%{name}/plugins.d/cups.plugin +%endif %changelog +* Mon Sep 23 2019 Konstantinos Natsakis <konstantinos.natsakis@gmail.com> 0.0.0-9 +- Do not build CUPS plugin subpackage on CentOS 6 and CentOS 7 +* Tue Aug 20 2019 Pavlos Emm. Katsoulakis <paul@netdat.acloud> - 0.0.0-8 +- Split CUPS functionality on separate package * Fri Jun 28 2019 Pavlos Emm. Katsoulakis <paul@netdata.cloud> - 0.0.0-7 - Raise the path overrides to the spec file level, not just the configure. - Adjust tighter permissions on some folders, based on what we did on our installer diff --git a/netlify.toml b/netlify.toml index 927941240..6ef10918f 100644 --- a/netlify.toml +++ b/netlify.toml @@ -10,3 +10,7 @@ # Default build command. command = "./buildhtml.sh" + +[[redirects]] + from = "/docs/GettingStarted/" + to = "/docs/getting-started"
\ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..3ad52f7c2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5527 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "dev": true, + "requires": { + "@babel/types": "^7.5.5", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "dev": true + }, + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/traverse": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@types/unist": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "adverb-where": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/adverb-where/-/adverb-where-0.0.9.tgz", + "integrity": "sha1-CcXN3Y1QO5/l924LjcXHCo8ZPjQ=", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "aggregate-error": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.0.tgz", + "integrity": "sha512-yKD9kEoJIR+2IFqhMwayIBgheLYbB3PS2OBhWae1L/ODTd/JF/30cW0bc9TqzRL3k4U41Dieu3BF4I29p8xesA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^3.2.0" + }, + "dependencies": { + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + } + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.0.tgz", + "integrity": "sha512-Ozz7l4ixzI7Oxj2+cw+p0tVUt27BpaJ+1+q1TCeANWxHpvyn2+Un+YamBdfKu0uh8xLodGhoa1v7595NhKDAuA==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + } + } + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-iterate": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.3.tgz", + "integrity": "sha512-7MIv7HE9MuzfK6B2UnWv07oSHBLOaY1UUXAxZ07bIeRM+4IkPTlveMDs9MY//qvxPZPSvCn2XV4bmtQgSkVodg==", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "automated-readability": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/automated-readability/-/automated-readability-1.0.4.tgz", + "integrity": "sha512-jv3Ukp/aAFJpVqw6r67Y7rMvj9b6wnxycylbHck3T2hxazBHHCZBBGAsInYH5d3/JREuAPGmPW34pLuE55COrQ==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "bail": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.4.tgz", + "integrity": "sha512-S8vuDB4w6YpRhICUDET3guPlQpaJl7od94tpZ0Fvnyp+MKW/HyDTcRDck+29C9g+d/qQHnddRH3+94kZdrW0Ww==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "bluebird": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", + "dev": true + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "ccount": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.4.tgz", + "integrity": "sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "character-entities": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.3.tgz", + "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==", + "dev": true + }, + "character-entities-html4": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.3.tgz", + "integrity": "sha512-SwnyZ7jQBCRHELk9zf2CN5AnGEc2nA+uKMZLHvcqhpPprjkYhiLn0DywMHgN5ttFZuITMATbh68M6VIVKwJbcg==", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.3.tgz", + "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.3.tgz", + "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==", + "dev": true + }, + "check-links": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/check-links/-/check-links-1.1.7.tgz", + "integrity": "sha512-BlewZuP+EGGbEXhnNXPR2QSVzIL4p4w2jyeB/GGFFL/NWGSOVStrFMdq0fyP0t9wEeOxpoQO2HoIScOW+E8/xQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "is-relative-url": "^2.0.0", + "p-map": "^2.0.0", + "p-memoize": "^2.1.0" + } + }, + "chokidar": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.0.2.tgz", + "integrity": "sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==", + "dev": true, + "requires": { + "anymatch": "^3.0.1", + "braces": "^3.0.2", + "fsevents": "^2.0.6", + "glob-parent": "^5.0.0", + "is-binary-path": "^2.1.0", + "is-glob": "^4.0.1", + "normalize-path": "^3.0.0", + "readdirp": "^3.1.1" + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "co": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", + "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=", + "dev": true + }, + "coffeescript": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.4.1.tgz", + "integrity": "sha512-34GV1aHrsMpTaO3KfMJL40ZNuvKDR/g98THHnE9bQj8HjMaZvSrLik99WWqyMhRtbe8V5hpx5iLgdcSvM/S2wg==", + "dev": true + }, + "coleman-liau": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coleman-liau/-/coleman-liau-1.0.4.tgz", + "integrity": "sha512-TKPhY4dE9YyC5n35jBrt1kYDFCunwZ0f9rH41OlPeYd9wWgcr6UKvXJlo+OqC6E/b7BBg4FRJdLeFnW1KUfftw==", + "dev": true + }, + "collapse-white-space": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.5.tgz", + "integrity": "sha512-703bOOmytCYAX9cXYqoikYIx6twmFCXsnzRQheBcTG3nzKYBR4P/+wkYeH+Mvj7qUz8zZDtdyzbxfnEi/kYzRQ==", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true, + "optional": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "core-js": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz", + "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "cuss": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/cuss/-/cuss-1.16.0.tgz", + "integrity": "sha512-VtYrZxNqRWLd/z3a57ezUv9WLR0l0n0qmYA5O9QBepliUWlEvRgBUnfZO6bZK29KocssaZ6ks7EistDLYPFWhA==", + "dev": true + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "dale-chall": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dale-chall/-/dale-chall-1.0.3.tgz", + "integrity": "sha512-GmZBdpSuvTg6qHZ4fPhZMEz9fa1xMrPOf/iIuWsmo+M/B8j4WwnKIKfeiRu7c8LVfr0pvZFhrccXiIdOzGxT6g==", + "dev": true + }, + "dale-chall-formula": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dale-chall-formula/-/dale-chall-formula-1.0.4.tgz", + "integrity": "sha512-Kytq5NGrRTt46J9j3mqt4/igynll/jvIeNIPsLhYtpNiI44kWuGNx7LYgLfLUPp5BO6qfGwjYZcc6jUq1s136A==", + "dev": true + }, + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "dev": true + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defer-to-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.0.2.tgz", + "integrity": "sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "dictionary-en-us": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/dictionary-en-us/-/dictionary-en-us-2.1.1.tgz", + "integrity": "sha512-3182Q3ede8TEm6FthZ2u8FppaayB+D43wy5cnOSweZwg9vSmmUCjCA3zxmMpZLw0nIAILGLR0j+06o2l9aaCzA==", + "dev": true + }, + "dns-packet": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.2.1.tgz", + "integrity": "sha512-JHj2yJeKOqlxzeuYpN1d56GfhzivAxavNwHj9co3qptECel27B1rLY5PifJAvubsInX5pGLDjAHuCfCUc2Zv/w==", + "dev": true, + "requires": { + "ip": "^1.1.5" + } + }, + "dns-socket": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dns-socket/-/dns-socket-4.2.0.tgz", + "integrity": "sha512-4XuD3z28jht3jvHbiom6fAipgG5LkjYeDLrX5OH8cbl0AtzTyUUAxGckcW8T7z0pLfBBV5qOiuC4wUEohk6FrQ==", + "dev": true, + "requires": { + "dns-packet": "^5.1.2" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "e-prime": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/e-prime/-/e-prime-0.10.2.tgz", + "integrity": "sha1-6pN165hWNt6IATx6n7EprZ4V7/g=", + "dev": true + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.1.tgz", + "integrity": "sha512-cp/Tb1oA/rh2X7vqeSOvM+TSo3UkJLX70eNihgVEvnzwAgikjkTFr/QVgRCaxjm0knCNQzNoxxxcw2zO2LJdZA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.0.0", + "string.prototype.trimright": "^2.0.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fault": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.3.tgz", + "integrity": "sha512-sfFuP4X0hzrbGKjAUNXYvNqsZ5F6ohx/dZ9I0KQud/aiZNwg263r5L9yGB0clvXHCkzXh5W3t7RSHchggYIFmA==", + "dev": true, + "requires": { + "format": "^0.2.2" + } + }, + "figures": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.0.0.tgz", + "integrity": "sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "~5.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, + "flesch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/flesch/-/flesch-1.0.4.tgz", + "integrity": "sha512-PT0PbyEwA9EwCkaETWixiX5hbIT10ZC6k8F01piCpzNWBVimPVyjobFPq/8u9Vm5ikOdCpbFcVKrYRJ7+nxgjw==", + "dev": true + }, + "fn-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", + "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=", + "dev": true + }, + "follow-redirects": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.9.0.tgz", + "integrity": "sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==", + "dev": true, + "requires": { + "debug": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=", + "dev": true + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", + "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "^1.0.0" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "github-slugger": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.1.tgz", + "integrity": "sha512-SsZUjg/P03KPzQBt7OxJPasGw6NRO5uOgiZ5RGXVud5iSIZ0eNZeNp5rTwCxtavrRUa/A77j8mePVc5lEvk0KQ==", + "dev": true, + "requires": { + "emoji-regex": ">=6.0.0 <=6.1.1" + }, + "dependencies": { + "emoji-regex": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", + "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", + "dev": true + } + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", + "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "grunt": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.4.tgz", + "integrity": "sha512-PYsMOrOC+MsdGEkFVwMaMyc6Ob7pKmq+deg1Sjr+vvMWp35sztfwKE7qoN51V+UEtHsyNuMcGdgMLFkBHvMxHQ==", + "dev": true, + "requires": { + "coffeescript": "~1.10.0", + "dateformat": "~1.0.12", + "eventemitter2": "~0.4.13", + "exit": "~0.1.1", + "findup-sync": "~0.3.0", + "glob": "~7.0.0", + "grunt-cli": "~1.2.0", + "grunt-known-options": "~1.1.0", + "grunt-legacy-log": "~2.0.0", + "grunt-legacy-util": "~1.1.1", + "iconv-lite": "~0.4.13", + "js-yaml": "~3.13.0", + "minimatch": "~3.0.2", + "mkdirp": "~0.5.1", + "nopt": "~3.0.6", + "path-is-absolute": "~1.0.0", + "rimraf": "~2.6.2" + }, + "dependencies": { + "coffeescript": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", + "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=", + "dev": true + }, + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "grunt-cli": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", + "dev": true, + "requires": { + "findup-sync": "~0.3.0", + "grunt-known-options": "~1.1.0", + "nopt": "~3.0.6", + "resolve": "~1.1.0" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "grunt-exec": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-exec/-/grunt-exec-3.0.0.tgz", + "integrity": "sha512-cgAlreXf3muSYS5LzW0Cc4xHK03BjFOYk0MqCQ/MZ3k1Xz2GU7D+IAJg4UKicxpO+XdONJdx/NJ6kpy2wI+uHg==", + "dev": true + }, + "grunt-known-options": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz", + "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==", + "dev": true + }, + "grunt-legacy-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz", + "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==", + "dev": true, + "requires": { + "colors": "~1.1.2", + "grunt-legacy-log-utils": "~2.0.0", + "hooker": "~0.2.3", + "lodash": "~4.17.5" + } + }, + "grunt-legacy-log-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz", + "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==", + "dev": true, + "requires": { + "chalk": "~2.4.1", + "lodash": "~4.17.10" + } + }, + "grunt-legacy-util": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz", + "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==", + "dev": true, + "requires": { + "async": "~1.5.2", + "exit": "~0.1.1", + "getobject": "~0.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.10", + "underscore.string": "~3.3.4", + "which": "~1.3.0" + } + }, + "gunning-fog": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/gunning-fog/-/gunning-fog-1.0.5.tgz", + "integrity": "sha512-8vpowdgSoBFtYRyNcJef9lQ11CkFd8mVQ0YcaOTKI+iLY9lKjbX4/yWAeQKcwE530Uigli0ElFssyebnJxvKNA==", + "dev": true + }, + "handlebars": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.0.tgz", + "integrity": "sha512-Kb4xn5Qh1cxAKvQnzNWZ512DhABzyFNmsaJf3OAkWNa4NkaqWcNI8Tao8Tasi0/F4JD9oyG0YxuFyvyR57d+Gw==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "hosted-git-info": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", + "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", + "dev": true + }, + "http-cache-semantics": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", + "integrity": "sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.1.0.tgz", + "integrity": "sha512-pKnZpbgCTfH/1NLIlOduP/V+WRXzC2MOz3Qo8xmxk8C5GudJLgK5QyLVXOSWy3ParAH7Eemurl3xjv/WXYFvMA==", + "dev": true + }, + "irregular-plurals": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz", + "integrity": "sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw==", + "dev": true + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-alphabetical": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.3.tgz", + "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==", + "dev": true + }, + "is-alphanumeric": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", + "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", + "dev": true, + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-decimal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.3.tgz", + "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==", + "dev": true + }, + "is-empty": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", + "integrity": "sha1-3pu1snhzigWgsJpX4ftNSjQan2s=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-hexadecimal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.3.tgz", + "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==", + "dev": true + }, + "is-hidden": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-hidden/-/is-hidden-1.1.2.tgz", + "integrity": "sha512-kytBeNVW2QTIqZdJBDKIjP+EkUTzDT07rsc111w/gxqR6wK3ODkOswcpxgED6HU6t7fEhOxqojVZ2a2kU9rj+A==", + "dev": true + }, + "is-ip": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz", + "integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==", + "dev": true, + "requires": { + "ip-regex": "^4.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "is-online": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/is-online/-/is-online-8.2.0.tgz", + "integrity": "sha512-dvTrzRlziHPdl+uazMK+9ypLlwOA3szkaGfAWqI/MKuUutgNxOFBl2gfu2BTkV8C7A2YcYHNlVcsxHzZik3wUQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "p-any": "^2.0.0", + "p-timeout": "^3.0.0", + "public-ip": "^3.0.0" + } + }, + "is-plain-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.0.0.tgz", + "integrity": "sha512-EYisGhpgSCwspmIuRHGjROWTon2Xp8Z7U03Wubk/bTL5TTRC5R1rGVgyjzBrk9+ULdH6cRD06KRcw/xfqhVYKQ==", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-relative-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-relative-url/-/is-relative-url-2.0.0.tgz", + "integrity": "sha1-cpAtf+BLPUeS59sV+duEtyBMnO8=", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-whitespace-character": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.3.tgz", + "integrity": "sha512-SNPgMLz9JzPccD3nPctcj8sZlX9DAMJSKH8bP7Z6bohCwuNgX8xbWr1eTAYXX9Vpi/aSn8Y1akL9WgM3t43YNQ==", + "dev": true + }, + "is-word-character": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.3.tgz", + "integrity": "sha512-0wfcrFgOOOBdgRNT9H33xe6Zi6yhX/uoc4U8NBZGeQQB0ctU1dnlNTyL9JM2646bHDTpsDm1Brb3VPoCIMrd/A==", + "dev": true + }, + "is-wsl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.0.tgz", + "integrity": "sha512-pFTjpv/x5HRj8kbZ/Msxi9VrvtOMRBqaDi3OIcbwPI3OuH+r3lLxVWukLITBaOGJIbA/w2+M1eVmVa4XNQlAmQ==", + "dev": true + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "dev": true, + "requires": { + "handlebars": "^4.1.2" + } + }, + "jasmine": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.4.0.tgz", + "integrity": "sha512-sR9b4n+fnBFDEd7VS2el2DeHgKcPiMVn44rtKFumq9q7P/t8WrxsVIZPob4UDdgcDNCwyDqwxCt4k9TDRmjPoQ==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "jasmine-core": "~3.4.0" + } + }, + "jasmine-core": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.4.0.tgz", + "integrity": "sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==", + "dev": true + }, + "jasmine-growl-reporter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jasmine-growl-reporter/-/jasmine-growl-reporter-2.0.0.tgz", + "integrity": "sha512-RYwVfPaGgxQQSHDOt6jQ99/KAkFQ/Fiwg/AzBS+uO9A4UhGhxb7hwXaUUSU/Zs0MxBoFNqmIRC+7P4/+5O3lXg==", + "dev": true, + "requires": { + "growl": "^1.10.5" + } + }, + "jasmine-node": { + "version": "github:BrainDoctor/jasmine-node#eac79306acaf016256cdd5824003d99db053f722", + "from": "github:BrainDoctor/jasmine-node", + "dev": true, + "requires": { + "coffee-script": "~1.7.1", + "gaze": "~0.5.1", + "grunt-exec": "~0.4.5", + "jasmine-growl-reporter": "~0.2.0", + "jasmine-reporters": "~2.0.6", + "minimist": "~0.0.8", + "mkdirp": "~0.3.5", + "underscore": "~1.6.0", + "walkdir": "~0.0.7", + "xml2js": "~0.4.1" + }, + "dependencies": { + "coffee-script": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz", + "integrity": "sha1-YplqhheAx15tUGnROCJyO3NAS/w=", + "dev": true, + "requires": { + "mkdirp": "~0.3.5" + } + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "~0.1.0" + } + }, + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "growl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz", + "integrity": "sha1-3i1mE20ALhErpw8/EMMc98NQsto=", + "dev": true + }, + "grunt-exec": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/grunt-exec/-/grunt-exec-0.4.7.tgz", + "integrity": "sha1-QAUf+k6wyWV+BTuV6I1ENSocLCU=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "jasmine-growl-reporter": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/jasmine-growl-reporter/-/jasmine-growl-reporter-0.2.1.tgz", + "integrity": "sha1-1fCje5L2qD/VxkgrgJSVyQqLVf4=", + "dev": true, + "requires": { + "growl": "~1.7.0" + } + }, + "jasmine-reporters": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-2.0.8.tgz", + "integrity": "sha1-XLMn1yRFAqGHzuxml+WmJvgMNbo=", + "dev": true, + "requires": { + "mkdirp": "~0.3.5" + } + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + }, + "walkdir": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.12.tgz", + "integrity": "sha512-HFhaD4mMWPzFSqhpyDG48KDdrjfn409YQuVW7ckZYhW4sE87mYtWifdB/+73RA7+p4s4K18n5Jfx1kHthE1gBw==", + "dev": true + } + } + }, + "jasmine-reporters": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-2.3.2.tgz", + "integrity": "sha512-u/7AT9SkuZsUfFBLLzbErohTGNsEUCKaQbsVYnLFW1gEuL2DzmBL4n8v90uZsqIqlWvWUgian8J6yOt5Fyk/+A==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1", + "xmldom": "^0.1.22" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "karma": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.3.0.tgz", + "integrity": "sha512-NSPViHOt+RW38oJklvYxQC4BSQsv737oQlr/r06pCM+slDOr4myuI1ivkRmp+3dVpJDfZt2DmaPJ2wkx+ZZuMQ==", + "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "braces": "^3.0.2", + "chokidar": "^3.0.0", + "colors": "^1.1.0", + "connect": "^3.6.0", + "core-js": "^3.1.3", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "flatted": "^2.0.0", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.14", + "log4js": "^4.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" + } + }, + "karma-chrome-launcher": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", + "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "dev": true, + "requires": { + "which": "^1.2.1" + } + }, + "karma-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.0.1.tgz", + "integrity": "sha512-SnFkHsnLsaXfxkey51rRN9JDLAEKYW2Lb0qOEvcruukk0NkSNDkjobNDZPt9Ni3kIhLZkLtpGOz661hN7OaZvQ==", + "dev": true, + "requires": { + "dateformat": "^1.0.6", + "istanbul": "^0.4.0", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "lodash": "^4.17.11", + "minimatch": "^3.0.0", + "source-map": "^0.5.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "karma-firefox-launcher": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.2.0.tgz", + "integrity": "sha512-j9Zp8M8+VLq1nI/5xZGfzeaEPtGQ/vk3G+Y8vpmFWLvKLNZ2TDjD6cu2dUu7lDbu1HXNgatsAX4jgCZTkR9qhQ==", + "dev": true, + "requires": { + "is-wsl": "^2.1.0" + } + }, + "karma-jasmine": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-2.0.1.tgz", + "integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==", + "dev": true, + "requires": { + "jasmine-core": "^3.3" + } + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "levenshtein-edit-distance": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/levenshtein-edit-distance/-/levenshtein-edit-distance-1.0.0.tgz", + "integrity": "sha1-iVuvR4zOi1waDSfkXXwdl4pmHkk=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "load-plugin": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/load-plugin/-/load-plugin-2.3.1.tgz", + "integrity": "sha512-dYB1lbwqHgPTrruy9glukCu8Ya9vzj6TMfouCtj2H/GuJ+8syioisgKTBPxnCi6m8K8jINKfTOxOHngFkUYqHw==", + "dev": true, + "requires": { + "npm-prefix": "^1.2.0", + "resolve-from": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=", + "dev": true + }, + "lodash.intersection": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.intersection/-/lodash.intersection-4.4.0.tgz", + "integrity": "sha1-ChG6Yx0OlcI8fy9Mu5ppLtF45wU=", + "dev": true + }, + "log4js": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", + "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", + "dev": true, + "requires": { + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.4", + "streamroller": "^1.0.6" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "longest-streak": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.3.tgz", + "integrity": "sha512-9lz5IVdpwsKLMzQi0MQ+oD9EA0mIGcWYP7jXMTZVXP8D42PwuAk+M/HBFYQoxt1G5OR8m7aSIgb1UymfWGBWEw==", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "markdown-escapes": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.3.tgz", + "integrity": "sha512-XUi5HJhhV5R74k8/0H2oCbCiYf/u4cO/rX8tnGkRvrqhsr5BRNU6Mg0yt/8UIx1iIS8220BNJsDb7XnILhLepw==", + "dev": true + }, + "markdown-extensions": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz", + "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==", + "dev": true + }, + "markdown-table": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", + "dev": true + }, + "match-casing": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/match-casing/-/match-casing-1.0.2.tgz", + "integrity": "sha512-NH4X/9dxkjgl08sGHg0M15YJH8xk49kPpeSsVqr+5Ct4Qd8gaBn41ubSBd+nEzMZt5iJDdoeSnKXV57UVeyK2w==", + "dev": true + }, + "mdast-comment-marker": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/mdast-comment-marker/-/mdast-comment-marker-1.1.1.tgz", + "integrity": "sha512-TWZDaUtPLwKX1pzDIY48MkSUQRDwX/HqbTB4m3iYdL/zosi/Z6Xqfdv0C0hNVKvzrPjZENrpWDt4p4odeVO0Iw==", + "dev": true + }, + "mdast-util-compact": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.3.tgz", + "integrity": "sha512-nRiU5GpNy62rZppDKbLwhhtw5DXoFMqw9UNZFmlPsNaQCZ//WLjGKUwWMdJrUH+Se7UvtO2gXtAMe0g/N+eI5w==", + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "mdast-util-heading-style": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mdast-util-heading-style/-/mdast-util-heading-style-1.0.5.tgz", + "integrity": "sha512-8zQkb3IUwiwOdUw6jIhnwM6DPyib+mgzQuHAe7j2Hy1rIarU4VUxe472bp9oktqULW3xqZE+Kz6OD4Gi7IA3vw==", + "dev": true + }, + "mdast-util-to-nlcst": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/mdast-util-to-nlcst/-/mdast-util-to-nlcst-3.2.3.tgz", + "integrity": "sha512-hPIsgEg7zCvdU6/qvjcR6lCmJeRuIEpZGY5xBV+pqzuMOvQajyyF8b6f24f8k3Rw8u40GwkI3aAxUXr3bB2xag==", + "dev": true, + "requires": { + "nlcst-to-string": "^2.0.0", + "repeat-string": "^1.5.2", + "unist-util-position": "^3.0.0", + "vfile-location": "^2.0.0" + } + }, + "mdast-util-to-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.6.tgz", + "integrity": "sha512-868pp48gUPmZIhfKrLbaDneuzGiw3OTDjHc5M1kAepR2CWBJ+HpEsm252K4aXdiP5coVZaJPOqGtVU6Po8xnXg==", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + } + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "dev": true + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, + "nlcst-is-literal": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/nlcst-is-literal/-/nlcst-is-literal-1.2.0.tgz", + "integrity": "sha512-0f7SKVXHdQvXvibPzLL90Lp8KXbhO0ktZGvythpwyoc7mmXKGe2VtDjnPRailPWBO8TgzHRzvQzkPIz81PSyBA==", + "dev": true, + "requires": { + "nlcst-to-string": "^2.0.0" + } + }, + "nlcst-normalize": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/nlcst-normalize/-/nlcst-normalize-2.1.3.tgz", + "integrity": "sha512-TtAmaUsjZPU6zH+yksmLwTezMti5Db8R+kdViCmWv44pWGxNr4C90p7X33YbiULxDfA7i7J7gUutDX4fT9pn7g==", + "dev": true, + "requires": { + "nlcst-to-string": "^2.0.0" + } + }, + "nlcst-search": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/nlcst-search/-/nlcst-search-1.5.1.tgz", + "integrity": "sha512-G3ws0fgNlVsUvHvA2G1PTjyxzGOJ0caI0+WOvlZzev5iSUTX+R1q4lnlL4Y7E+he4ZMUW/0FMn9rYwdYon/13g==", + "dev": true, + "requires": { + "nlcst-is-literal": "^1.1.0", + "nlcst-normalize": "^2.1.0", + "unist-util-visit": "^1.0.0" + } + }, + "nlcst-to-string": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-2.0.3.tgz", + "integrity": "sha512-OY2QhGdf6jpYfHqS4vJwqF7aIBZkaMjMUkcHcskMPitvXLuYNGdQvgVWI/5yKwkmIdmhft3ounSJv+Re2yydng==", + "dev": true + }, + "no-cliches": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/no-cliches/-/no-cliches-0.1.1.tgz", + "integrity": "sha512-mYihjs47X5+N71CN3P+QBrEIBuclIfMMpgWEpkmLqFPvrOXdzokvDlhbLfjdBNZOqYgniaeZC6J1ZCgxFdyvXw==", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/normalize-strings/-/normalize-strings-1.1.0.tgz", + "integrity": "sha1-skp17UgXY5RAT3Rkm1y4BA6JmnU=", + "dev": true + }, + "normalize-url": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.3.0.tgz", + "integrity": "sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ==", + "dev": true + }, + "npm-prefix": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/npm-prefix/-/npm-prefix-1.2.0.tgz", + "integrity": "sha1-5hlFX3B0ulTMZtbQ033Z8b5ry8A=", + "dev": true, + "requires": { + "rc": "^1.1.0", + "shellsubstitute": "^1.1.0", + "untildify": "^2.1.0" + } + }, + "nspell": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/nspell/-/nspell-2.1.2.tgz", + "integrity": "sha512-j79L4A5aJSiswMUJ/6BW8+7ytgBUVce5BJX6xq8LtvKQpU96CMB340/yMeREH9U+gB/8dk4ctTn62DLiPMAXsA==", + "dev": true, + "requires": { + "is-buffer": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "number-to-words": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/number-to-words/-/number-to-words-1.2.4.tgz", + "integrity": "sha512-/fYevVkXRcyBiZDg6yzZbm0RuaD6i0qRfn8yr+6D0KgBMOndFPxuW10qCHpzs50nN8qKuv78k8MuotZhcVX6Pw==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-any": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-any/-/p-any-2.1.0.tgz", + "integrity": "sha512-JAERcaMBLYKMq+voYw36+x5Dgh47+/o7yuv2oQYuSSUml4YeqJEFznBrY2UeEkoSHqBua6hz518n/PsowTYLLg==", + "dev": true, + "requires": { + "p-cancelable": "^2.0.0", + "p-some": "^4.0.0", + "type-fest": "^0.3.0" + }, + "dependencies": { + "p-cancelable": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", + "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==", + "dev": true + } + } + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "p-memoize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-memoize/-/p-memoize-2.1.0.tgz", + "integrity": "sha512-c6+a2iV4JyX0r4+i2IBJYO0r6LZAT2fg/tcB6GQbv1uzZsfsmKT7Ej5DRT1G6Wi7XUJSV2ZiP9+YEtluvhCmkg==", + "dev": true, + "requires": { + "mem": "^4.0.0", + "mimic-fn": "^1.0.0" + } + }, + "p-some": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-some/-/p-some-4.1.0.tgz", + "integrity": "sha512-MF/HIbq6GeBqTrTIl5OJubzkGU+qfFhAFi0gnTAK6rgEIJIknEiABHOTtQu4e6JiXjIwuMPMUFQzyHh5QjCl1g==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0", + "p-cancelable": "^2.0.0" + }, + "dependencies": { + "p-cancelable": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", + "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==", + "dev": true + } + } + }, + "p-timeout": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.1.0.tgz", + "integrity": "sha512-C27DYI+tCroT8J8cTEyySGydl2B7FlxrGNF5/wmMbl1V+jeehUCzEE/BVgzRebdm2K3ZitKOKx8YbdFumDyYmw==", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, + "parse-english": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/parse-english/-/parse-english-4.1.2.tgz", + "integrity": "sha512-+PBf+1ifxqJlOpisODiKX4A8wBEgWm4goMvDB5O9zx/cQI58vzHTZeWFbAgCF9fUXRl8/YdINv1cfmfIRR1acg==", + "dev": true, + "requires": { + "nlcst-to-string": "^2.0.0", + "parse-latin": "^4.0.0", + "unist-util-modify-children": "^1.0.0", + "unist-util-visit-children": "^1.0.0" + } + }, + "parse-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "dev": true, + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-latin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-4.2.0.tgz", + "integrity": "sha512-b8PvsA1Ohh7hIQwDDy6kSjx3EbcuR3oKYm5lC1/l/zIB6mVVV5ESEoS1+Qr5+QgEGmp+aEZzc+D145FIPJUszw==", + "dev": true, + "requires": { + "nlcst-to-string": "^2.0.0", + "unist-util-modify-children": "^1.0.0", + "unist-util-visit-children": "^1.0.0" + } + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "passive-voice": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/passive-voice/-/passive-voice-0.1.0.tgz", + "integrity": "sha1-Fv+RrkC6DpLEPmcXY/3IQqcCcLE=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "picomatch": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", + "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "plur": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plur/-/plur-3.1.1.tgz", + "integrity": "sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w==", + "dev": true, + "requires": { + "irregular-plurals": "^2.0.0" + } + }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "propose": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/propose/-/propose-0.0.5.tgz", + "integrity": "sha1-SKBl2ex9TIZn9AULFcSi2F28pWs=", + "dev": true, + "requires": { + "levenshtein-edit-distance": "^1.0.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-ip": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/public-ip/-/public-ip-3.2.0.tgz", + "integrity": "sha512-DBq4o955zhrhESG4z6GkLN9mtY9NT/JOjEV8pvnYy3bjVQOQF0J5lJNwWLbEWwNstyNFJlY7JxCPFq4bdXSabw==", + "dev": true, + "requires": { + "dns-socket": "^4.2.0", + "got": "^9.6.0", + "is-ip": "^3.1.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "quotation": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/quotation/-/quotation-1.1.2.tgz", + "integrity": "sha512-96iP6AudZyiOQWEY8hOUjliGaRMNj4yiC22vCSSFMNDdvpp/5/MyfsHSwFcFswWjDVxdBdzQS7MqA3rYglizOQ==", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.2.tgz", + "integrity": "sha512-8rhl0xs2cxfVsqzreYCvs8EwBfn/DhVdqtoLmw19uI3SC5avYX9teCurlErfpPXGmYtMHReGaP2RsLnFvz/lnw==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "remark": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-11.0.1.tgz", + "integrity": "sha512-Fl2AvN+yU6sOBAjUz3xNC5iEvLkXV8PZicLOOLifjU8uKGusNvhHfGRCfETsqyvRHZ24JXqEyDY4hRLhoUd30A==", + "dev": true, + "requires": { + "remark-parse": "^7.0.0", + "remark-stringify": "^7.0.0", + "unified": "^8.2.0" + } + }, + "remark-cli": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/remark-cli/-/remark-cli-7.0.0.tgz", + "integrity": "sha512-gYomWviFnZsiRimG+Jdb4LQ9c8uSOcGmPTmzlvxImt0gvzabqlp1kaqndxTx4kYLsWGqwhQRO+M9iyqHDkoDlA==", + "dev": true, + "requires": { + "markdown-extensions": "^1.1.0", + "remark": "^11.0.0", + "unified-args": "^7.0.0" + } + }, + "remark-frontmatter": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-1.3.2.tgz", + "integrity": "sha512-2eayxITZ8rezsXdgcXnYB3iLivohm2V/ZT4Ne8uhua6A4pk6GdLE2ZzJnbnINtD1HRLaTdB7RwF9sgUbMptJZA==", + "dev": true, + "requires": { + "fault": "^1.0.1", + "xtend": "^4.0.1" + } + }, + "remark-lint": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-6.0.5.tgz", + "integrity": "sha512-o1I3ddm+KNsTxk60wWGI+p2yU1jB1gcm8jo2Sy6VhJ4ab2TrQIp1oQbp5xeLoFXYSh/NAqCpKjHkCM/BYpkFdQ==", + "dev": true, + "requires": { + "remark-message-control": "^4.0.0" + } + }, + "remark-lint-blockquote-indentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-blockquote-indentation/-/remark-lint-blockquote-indentation-1.0.3.tgz", + "integrity": "sha512-qK4C1l2VmeOVWEAkDYP0CaDtSFoaEBEo5l4oyz1kTkY7YB0Jh7llW2KjuhJz5IzMLmloKJzIyGwlu/odcwaHpg==", + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.2", + "plur": "^3.0.0", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-checkbox-character-style": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-checkbox-character-style/-/remark-lint-checkbox-character-style-1.0.3.tgz", + "integrity": "sha512-bQGrGHLlguTxOzuywHtYxNcg58TYhNgeEAMCTvdAggt5bYZIwmh/otx51JsQ0a96qxd/6/G0Ri2xzgyxf9wB8w==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1", + "vfile-location": "^2.0.1" + } + }, + "remark-lint-code-block-style": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-code-block-style/-/remark-lint-code-block-style-1.0.3.tgz", + "integrity": "sha512-DL+rudnd9ILP5YXm74tLpMzfWZLqziX7NwIwUhqRefaOyWwxgPPy7hbT59FJqcFc6E/zvDz+Oq4nR1BSV5kEdw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-definition-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-definition-case/-/remark-lint-definition-case-1.0.4.tgz", + "integrity": "sha512-ebl8vYOab9iy1Mr29Wo/9CmqcYGRjCfBievIZts08efrxIElWz+jB8/n7C17fh8k0djiiS/Of6W+bfRD+kMXLA==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.4.0" + } + }, + "remark-lint-definition-spacing": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-definition-spacing/-/remark-lint-definition-spacing-1.0.4.tgz", + "integrity": "sha512-UderghITmru72OXB5ErCFhVsY7up2wK/m1bUD3E2dm/TFn73/7WpykENt5UirCDT/aeyoHYl8QXUVL20rAc3XQ==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.4.0" + } + }, + "remark-lint-emphasis-marker": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-emphasis-marker/-/remark-lint-emphasis-marker-1.0.3.tgz", + "integrity": "sha512-ea2tEVyhZvYxwj6AHsW2qzgEDLljcnzq5taZ3FJFL0KMZYZHfWaIU90H43jrW4seGEtmaP1bmoqJaTavJ2x5Jw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-fenced-code-flag": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-fenced-code-flag/-/remark-lint-fenced-code-flag-1.0.3.tgz", + "integrity": "sha512-X8Oi6dhfqV9NI3cVg29myvT/NATDHVgRGCpnNz76w7VXwzhBvQtJr1MxZzuPxfWLox+ARCXF2rY9n9hbYFHYTg==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-fenced-code-marker": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-fenced-code-marker/-/remark-lint-fenced-code-marker-1.0.3.tgz", + "integrity": "sha512-JKnojSQ8JkwpIpbNm6wtKEfx8iiv8QIwNHFM06iTCHExMhXa4pJ3wb5M5f0wsWNHtoND3lrw6AcVPoZxEPnflg==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-file-extension": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-file-extension/-/remark-lint-file-extension-1.0.3.tgz", + "integrity": "sha512-P5gzsxKmuAVPN7Kq1W0f8Ss0cFKfu+OlezYJWXf+5qOa+9Y5GqHEUOobPnsmNFZrVMiM7JoqJN2C9ZjrUx3N6Q==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0" + } + }, + "remark-lint-final-definition": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-final-definition/-/remark-lint-final-definition-1.0.3.tgz", + "integrity": "sha512-QhbBYy99enfQDeUTElioCHrhgg+SgjMNRlru7/JlOguOufP6wn7AXgn2EVTrLZRoByY0VsNS2jCayXxUTzQ8KA==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-final-newline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-final-newline/-/remark-lint-final-newline-1.0.3.tgz", + "integrity": "sha512-ETAadktv75EwUS3XDhyZUVstXKxfPAEn7SmfN9kZ4+Jb4qo4hHE9gtTOzhE6HxLUxxl9BBhpC5mMO3JcL8UZ5A==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0" + } + }, + "remark-lint-hard-break-spaces": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-hard-break-spaces/-/remark-lint-hard-break-spaces-1.0.4.tgz", + "integrity": "sha512-YM82UpgliZCZhGNmFxEe7ArfhqR5CplFf2bc0k0+8w3rKWKx7EJcGMar2NK410tIi40gGeWtH/pIEypPJFCCiA==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-heading-increment": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-heading-increment/-/remark-lint-heading-increment-1.0.3.tgz", + "integrity": "sha512-/KL4/7D2pNxP07KKgktjcIUS+ga8pYI2k9Q/V91pMfyfSC+RYuCGOLFVJSKV0Affr/4Eqnfhw+gJ9X2HAanNuw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-heading-style": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-heading-style/-/remark-lint-heading-style-1.0.3.tgz", + "integrity": "sha512-ZUhMav0HHUxo5gzLqxQsOf2ZpP/I3m6EEK8q25/kqpCYnwm1uRJ5CQ40PDQx46pmKtVibIMzDmraYovxNG3ovw==", + "dev": true, + "requires": { + "mdast-util-heading-style": "^1.0.2", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-heading-whitespace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/remark-lint-heading-whitespace/-/remark-lint-heading-whitespace-1.0.0.tgz", + "integrity": "sha512-DykoBIXNbkihg64D+mztSOv3l82RTH4tIZW/HUB4QM4NpIEB+pVIPQpCYD0K4pTgvKiwoqsj4NY8qJ1EhNHAmQ==", + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.4", + "unified-lint-rule": "^1.0.2", + "unist-util-visit": "^1.3.0" + } + }, + "remark-lint-link-title-style": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-link-title-style/-/remark-lint-link-title-style-1.0.4.tgz", + "integrity": "sha512-61/uH3zDTiozLJqgxp6rHGnVKTChC3UjL3Q0KQDBpprEOL4qLYjTn4fFKscVz776d0uUX6jczrW+GT4AFVOUgg==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1", + "vfile-location": "^2.0.1" + } + }, + "remark-lint-list-item-bullet-indent": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-bullet-indent/-/remark-lint-list-item-bullet-indent-1.0.3.tgz", + "integrity": "sha512-iVxQbrgzLpMHG3C6o6wRta/+Bc96etOiBYJnh2zm/aWz6DJ7cGLDykngblP/C4he7LYSeWOD/8Y57HbXZwM2Og==", + "dev": true, + "requires": { + "plur": "^3.0.0", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-list-item-content-indent": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-content-indent/-/remark-lint-list-item-content-indent-1.0.3.tgz", + "integrity": "sha512-ZSIGJG2/6jd1xj/xEoDlkcJBf2Ksw8U6vIGJO0IFIA3BLCbJm2EMWJxto2cfzRvXoACmAaxTJMqW8qatPExa4w==", + "dev": true, + "requires": { + "plur": "^3.0.0", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-list-item-indent": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-indent/-/remark-lint-list-item-indent-1.0.4.tgz", + "integrity": "sha512-Sv0gVH6qP1/nFpbJuyyguB9sAD2o42StD2WbEZeUcEexXwRO4u/YaX0Pm5pMtCiEHyN+qyL6ShKBQMtgol9BeA==", + "dev": true, + "requires": { + "plur": "^3.0.0", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-list-item-spacing": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-spacing/-/remark-lint-list-item-spacing-1.1.3.tgz", + "integrity": "sha512-QzDY0Qfk6m+Az0kmxP57OfswIH1WRdd6SIpQLaUEgsTlsbrJOiO0sJYkkOlFPsyJIfp7SV/FCbr+aYCbHF+kRQ==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-maximum-heading-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-maximum-heading-length/-/remark-lint-maximum-heading-length-1.0.3.tgz", + "integrity": "sha512-ybcDpR5VHBjtjzdry7AdSjLFwslPo6rdhIJK2+WfHgfeEjIYnlz1uMvp1Z98QMmjpB5JSN83Kzg5fH8/B7poUw==", + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.2", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-maximum-line-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/remark-lint-maximum-line-length/-/remark-lint-maximum-line-length-1.2.1.tgz", + "integrity": "sha512-CSxX1qc+rAqixk8eBrI+yBsUmD8YGfOezFeJWjJRuUaoOvs67oqCIU+I2HbwcUYY8/KnDxF1MCp+uCM0RkjKKw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.4.0" + } + }, + "remark-lint-no-auto-link-without-protocol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-auto-link-without-protocol/-/remark-lint-no-auto-link-without-protocol-1.0.3.tgz", + "integrity": "sha512-k+hg2mXnO4Q9WV+UShPLen5oThvFxcRVWkx2hviVd/nu3eiszBKH3o38csBwjeJoMG3l2ZhdUW8dlOBhq8670Q==", + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.2", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-blockquote-without-marker": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-blockquote-without-marker/-/remark-lint-no-blockquote-without-marker-2.0.3.tgz", + "integrity": "sha512-faDzKrA6aKidsRXG6gcIlCO8TexLxIxe+n9B3mdnl8mhZGgE0FfWTkIWVMj0IYps/xVsVMf45KxhXgc1wU9kwg==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1", + "vfile-location": "^2.0.1" + } + }, + "remark-lint-no-consecutive-blank-lines": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-consecutive-blank-lines/-/remark-lint-no-consecutive-blank-lines-1.0.3.tgz", + "integrity": "sha512-2Ef7fPxrfLditA7sTo2Qfqd+xwh/luWl8GzILE5vcWIxLDqKk3dTLJkB5nP+7Cr4kqWJAwXnRkEDd77ehrRV3A==", + "dev": true, + "requires": { + "plur": "^3.0.0", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-dead-urls": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-dead-urls/-/remark-lint-no-dead-urls-0.5.0.tgz", + "integrity": "sha512-wMr1+7Sh5rRGF9hmF9iyajRNQfA2BnADc9myYjpRxsYozRDj6p2ddVwBh76loUKwCZ64sLRKamyhMDwQ0NIdYA==", + "dev": true, + "requires": { + "check-links": "^1.1.7", + "is-online": "^8.2.0", + "unified-lint-rule": "^1.0.4", + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.0.tgz", + "integrity": "sha512-E5JLUKRQlAYiJmN2PVBdSz01R3rUKRSM00X+0DB/yLqxdLu6wZZkRdTIsxDp9X+bkxh8Eq+O2YYRbZvLZtQT1A==", + "dev": true + }, + "unist-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.0.tgz", + "integrity": "sha512-kiTpWKsF54u/78L/UU/i7lxrnqGiEWBgqCpaIZBYP0gwUC+Akq0Ajm4U8JiNIoQNfAioBdsyarnOcTEAb9mLeQ==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.0.tgz", + "integrity": "sha512-H3K8d81S4V3XVXVwLvrLGk+R5VILryfUotD06/R/rLsTsPLGjkn6gIP8qEEVITcuIySNYj0ocJLsePjm9F/Vcg==", + "dev": true, + "requires": { + "@types/unist": "^2.0.3", + "unist-util-is": "^4.0.0" + } + } + } + }, + "remark-lint-no-duplicate-definitions": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-definitions/-/remark-lint-no-duplicate-definitions-1.0.5.tgz", + "integrity": "sha512-zKXmfNUODXhJsGQdqfguMG9Nl9v1sLaDsQgMjUtmOSoQRnNud9ThQAZl62eX5jBn5HKcpOifG80tgkyBvU5eEw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-stringify-position": "^2.0.0", + "unist-util-visit": "^1.4.0" + } + }, + "remark-lint-no-duplicate-headings": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-headings/-/remark-lint-no-duplicate-headings-1.0.4.tgz", + "integrity": "sha512-QuPw+VG502Ctpd/jBjnBYuRXTg0ToP3D+dd3TYds4TRcdgaEFYTZfQ5zjK6XrxLMg0Hn9/WpXr4UqTlV4YZupA==", + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.2", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-stringify-position": "^2.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-emphasis-as-heading": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-emphasis-as-heading/-/remark-lint-no-emphasis-as-heading-1.0.3.tgz", + "integrity": "sha512-HEmyeyKciUz95+CgpAH98RPR73jq5u5CZb2FOMSqgNl9B6FZXqVpq9F3txPqUw3nAqFYOAEnfiaoRgcqtioh0Q==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-file-name-articles": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-articles/-/remark-lint-no-file-name-articles-1.0.3.tgz", + "integrity": "sha512-YZDJDKUWZEmhrO6tHB0u0K0K2qJKxyg/kryr14OaRMvWLS62RgMn97sXPZ38XOSN7mOcCnl0k7/bClghJXx0sg==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0" + } + }, + "remark-lint-no-file-name-consecutive-dashes": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-consecutive-dashes/-/remark-lint-no-file-name-consecutive-dashes-1.0.3.tgz", + "integrity": "sha512-7f4vyXn/ca5lAguWWC3eu5hi8oZ7etX7aQlnTSgQZeslnJCbVJm6V6prFJKAzrqbBzMicUXr5pZLBDoXyTvHHw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0" + } + }, + "remark-lint-no-file-name-irregular-characters": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-irregular-characters/-/remark-lint-no-file-name-irregular-characters-1.0.3.tgz", + "integrity": "sha512-b4xIy1Yi8qZpM2vnMN+6gEujagPGxUBAs1judv6xJQngkl5d5zT8VQZsYsTGHku4NWHjjh3b7vK5mr0/yp4JSg==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0" + } + }, + "remark-lint-no-file-name-mixed-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-mixed-case/-/remark-lint-no-file-name-mixed-case-1.0.3.tgz", + "integrity": "sha512-d7rJ4c8CzDbEbGafw2lllOY8k7pvnsO77t8cV4PHFylwQ3hmCdTHLuDvK87G3DaWCeKclp0PMyamfOgJWKMkPA==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0" + } + }, + "remark-lint-no-file-name-outer-dashes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-outer-dashes/-/remark-lint-no-file-name-outer-dashes-1.0.4.tgz", + "integrity": "sha512-+bZvvme2Bm3Vp5L2iKuvGHYVmHKrTkkRt8JqJPGepuhvBvT4Q7+CgfKyMtC/hIjyl+IcuJQ2H0qPRzdicjy1wQ==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0" + } + }, + "remark-lint-no-heading-content-indent": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-heading-content-indent/-/remark-lint-no-heading-content-indent-1.0.3.tgz", + "integrity": "sha512-7xM6X5E/dt8OXOHdejH+sfYb139a3kMr8ZSSkcp90Ab1y+ZQBNaWsR3mYh8FRKkYPTN5eyd+KjhNpLWyqqCbgg==", + "dev": true, + "requires": { + "mdast-util-heading-style": "^1.0.2", + "plur": "^3.0.0", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-heading-punctuation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-heading-punctuation/-/remark-lint-no-heading-punctuation-1.0.3.tgz", + "integrity": "sha512-JQD05RjLS99ePBQ4Bed1uWsQTlIMBTcGgIgF6jFXSCEqhwnrIUDwk6S3MG1RZsKd3TLw2xuT/i+POpfBc2+1kQ==", + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.2", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-inline-padding": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-no-inline-padding/-/remark-lint-no-inline-padding-1.0.4.tgz", + "integrity": "sha512-u5rgbDkcfVv645YxxOwoGBBJbsHEwWm/XqnO8EhfKTxkfKOF4ZItG7Ajhj89EDaeXMkvCcB/avBl4bj50eJH3g==", + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.2", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.4.0" + } + }, + "remark-lint-no-literal-urls": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-literal-urls/-/remark-lint-no-literal-urls-1.0.3.tgz", + "integrity": "sha512-H5quyMzl2kaewK+jYD1FI0G1SIinIsIp4DEyOUwIR+vYUoKwo0B4vvW0cmPpD1dgqqxHYx0B2B0JQQKFVWzGiw==", + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.2", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-multiple-toplevel-headings": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-no-multiple-toplevel-headings/-/remark-lint-no-multiple-toplevel-headings-1.0.4.tgz", + "integrity": "sha512-0wDddx6htN5sL9/rofesiQF0oEgwN5224UmueiDx0ZUlYrn6VS0/SS0X3WWxtXmyeqlExfWF3D/g89tNs7dcjw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-stringify-position": "^2.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-shell-dollars": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-shell-dollars/-/remark-lint-no-shell-dollars-1.0.3.tgz", + "integrity": "sha512-fT3lQMTjEkPryL+63qDP1NfrohP3tG5i3SkNWSSR4VLU6OSsSSXlHGQGjo0ag//+EPKHB5/9frB/YQ0gDEPRGQ==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-shortcut-reference-image": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-image/-/remark-lint-no-shortcut-reference-image-1.0.3.tgz", + "integrity": "sha512-CGm27X54kXp/5ehXejDTsZjqzK4uIhLGcrFzN3k/KjdwunQouEY92AARGrLSEuJ1hQx0bJsmnvr/hvQyWAfNJg==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-shortcut-reference-link": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-link/-/remark-lint-no-shortcut-reference-link-1.0.4.tgz", + "integrity": "sha512-FXdMJYqspZBhPlxYqfVgVluVXjxStg0RHJzqrk8G9wS8fCS62AE3reoaoiCahwoH1tfKcA+poktbKqDAmZo7Jg==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-no-table-indentation": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-no-table-indentation/-/remark-lint-no-table-indentation-1.0.4.tgz", + "integrity": "sha512-H4VGHcg1k8sTIbwazFYLNbDqpPR+M0aHHKDf+93b/xyd27Dp0ODQrMnQbls1Cls5qOAQnwAQbx+75wcpFxP3OQ==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.4.0" + } + }, + "remark-lint-no-undefined-references": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-undefined-references/-/remark-lint-no-undefined-references-1.1.1.tgz", + "integrity": "sha512-b1eIjWFaCu6m16Ax2uG33o1v+eRYqDTQRUqU6UeQ76JXmDmVtVO75ZuyRpqqE7VTZRW8YLVurXfJPDXfIa5Wng==", + "dev": true, + "requires": { + "collapse-white-space": "^1.0.4", + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.4.0" + } + }, + "remark-lint-no-unused-definitions": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-1.0.5.tgz", + "integrity": "sha512-Bo22e0RNzc1QMW317KTuStGFDG7uTDUQhm/TrW6Qzud0WXnNnqUyvts+e7wTYoj8VnwhhjyjyoA9lKA3uXMdAQ==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-visit": "^1.4.0" + } + }, + "remark-lint-ordered-list-marker-style": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-style/-/remark-lint-ordered-list-marker-style-1.0.3.tgz", + "integrity": "sha512-24TmW1eUa/2JlwprZg9jJ8LKLxNGKnlKiI5YOhN4taUp2yv8daqlV9vR54yfn/ZZQh6EQvbIX0jeVY9NYgQUtw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-ordered-list-marker-value": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-value/-/remark-lint-ordered-list-marker-value-1.0.3.tgz", + "integrity": "sha512-WQ9yLD8cI9DSk/CE+APKUT6ZeXp0/RzOnsYqzMxEa8n1QHSqRSF7hVEiisqNTG9+gV64OEE66e+m4c7RVSUADw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-rule-style": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-rule-style/-/remark-lint-rule-style-1.0.3.tgz", + "integrity": "sha512-SJe7IFORYRdo8JUhMSdcTktVAUVNVp36YYl1ZD9CfHqQHWlFD+3vWYzJXOZfog/i+CyWf7Yi0WVYmQes+167dA==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-strong-marker": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-strong-marker/-/remark-lint-strong-marker-1.0.3.tgz", + "integrity": "sha512-PFkH282dCwfRsVEw9IxbYbaZBY4UcTuT2SN+lA3R0cBeocWnOySVw8YEm4sv9JfV8BLcQA5gc4tj66/U3KCScw==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-table-cell-padding": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/remark-lint-table-cell-padding/-/remark-lint-table-cell-padding-1.0.4.tgz", + "integrity": "sha512-AQWWtV1yca1PN27QaFRJbBK6Ro/bopv1XnVKxj/iMebhOU2D2FBJ8rXmMZXVMC3G9OB2WSzGgqH3nP6QY12LoA==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.4.0" + } + }, + "remark-lint-table-pipe-alignment": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-table-pipe-alignment/-/remark-lint-table-pipe-alignment-1.0.3.tgz", + "integrity": "sha512-5fhEMcKqNjK6S/y7cVG0+iVqhmhXFW+awIuN7vOBhmDbZ3HF9rCCy20XiHoaG6FzrPJ+zfkjK/QZAbq2Vf58HA==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-table-pipes": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-table-pipes/-/remark-lint-table-pipes-1.0.3.tgz", + "integrity": "sha512-K9NnGZp6i0m/CaOH7ZT4Ymt2seyiRPcBIlNMMGXBm6gpy34KJDDxYqsNUrh+j7dR+Zg4rYAQLnr3BiSHvj+rbQ==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-unordered-list-marker-style": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/remark-lint-unordered-list-marker-style/-/remark-lint-unordered-list-marker-style-1.0.3.tgz", + "integrity": "sha512-0nn/Yscy5ImO4fqByrk/Ua02UwGx8LRu+0kdCbkVz4IxPO5qxTEfyccUQZR71zTdMJp1d2OeqyD9XtMaO4X7Ww==", + "dev": true, + "requires": { + "unified-lint-rule": "^1.0.0", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.1" + } + }, + "remark-lint-write-good": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remark-lint-write-good/-/remark-lint-write-good-1.1.0.tgz", + "integrity": "sha512-+3L7fp2O03DQJqwVACyo0PYAOyWRgtIsqbdgiTpgwJLK3SCCMicDLKMSKcg465ARRsQnueeMiNKMda1ZLI6EHQ==", + "dev": true, + "requires": { + "nlcst-to-string": "^2.0.0", + "unified-lint-rule": "^1.0.1", + "unist-util-visit": "^1.1.1", + "write-good": "^0.11.1" + } + }, + "remark-message-control": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/remark-message-control/-/remark-message-control-4.2.0.tgz", + "integrity": "sha512-WXH2t5ljTyhsXlK1zPBLF3iPHbXl58R94phPMreS1xcHWBZJt6Oiu8RtNjy1poZFb3PqKnbYLJeR/CWcZ1bTFw==", + "dev": true, + "requires": { + "mdast-comment-marker": "^1.0.0", + "unified-message-control": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "remark-parse": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-7.0.1.tgz", + "integrity": "sha512-WOZLa545jYXtSy+txza6ACudKWByQac4S2DmGk+tAGO/3XnVTOxwyCIxB7nTcLlk8Aayhcuf3cV1WV6U6L7/DQ==", + "dev": true, + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "remark-preset-lint-consistent": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/remark-preset-lint-consistent/-/remark-preset-lint-consistent-2.0.3.tgz", + "integrity": "sha512-mrtGznAikgXvBwgQdkT3LAWn47wQGvFs9IsLuBjNluv9JnCqkt2CpOG5htlES5aB3YnVdxzSS7AntF5iNxSlpA==", + "dev": true, + "requires": { + "remark-lint": "^6.0.0", + "remark-lint-blockquote-indentation": "^1.0.0", + "remark-lint-checkbox-character-style": "^1.0.0", + "remark-lint-code-block-style": "^1.0.0", + "remark-lint-emphasis-marker": "^1.0.0", + "remark-lint-fenced-code-marker": "^1.0.0", + "remark-lint-heading-style": "^1.0.0", + "remark-lint-link-title-style": "^1.0.0", + "remark-lint-list-item-content-indent": "^1.0.0", + "remark-lint-ordered-list-marker-style": "^1.0.0", + "remark-lint-rule-style": "^1.0.0", + "remark-lint-strong-marker": "^1.0.0", + "remark-lint-table-cell-padding": "^1.0.0" + } + }, + "remark-preset-lint-markdown-style-guide": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/remark-preset-lint-markdown-style-guide/-/remark-preset-lint-markdown-style-guide-2.1.3.tgz", + "integrity": "sha512-H/jSoLvTY8abUcB+7/062I2oHevlHcHdrfRMP2RMh19QA1wmARgNEn3tZfdBXFq1TpzhevGgb6VwSdOjdU8NOQ==", + "dev": true, + "requires": { + "remark-lint": "^6.0.0", + "remark-lint-blockquote-indentation": "^1.0.0", + "remark-lint-code-block-style": "^1.0.0", + "remark-lint-definition-case": "^1.0.0", + "remark-lint-definition-spacing": "^1.0.0", + "remark-lint-emphasis-marker": "^1.0.0", + "remark-lint-fenced-code-flag": "^1.0.0", + "remark-lint-fenced-code-marker": "^1.0.0", + "remark-lint-file-extension": "^1.0.0", + "remark-lint-final-definition": "^1.0.0", + "remark-lint-hard-break-spaces": "^1.0.0", + "remark-lint-heading-increment": "^1.0.0", + "remark-lint-heading-style": "^1.0.0", + "remark-lint-link-title-style": "^1.0.0", + "remark-lint-list-item-content-indent": "^1.0.0", + "remark-lint-list-item-indent": "^1.0.0", + "remark-lint-list-item-spacing": "^1.0.0", + "remark-lint-maximum-heading-length": "^1.0.0", + "remark-lint-maximum-line-length": "^1.0.0", + "remark-lint-no-auto-link-without-protocol": "^1.0.0", + "remark-lint-no-blockquote-without-marker": "^2.0.0", + "remark-lint-no-consecutive-blank-lines": "^1.0.0", + "remark-lint-no-duplicate-headings": "^1.0.0", + "remark-lint-no-emphasis-as-heading": "^1.0.0", + "remark-lint-no-file-name-articles": "^1.0.0", + "remark-lint-no-file-name-consecutive-dashes": "^1.0.0", + "remark-lint-no-file-name-irregular-characters": "^1.0.0", + "remark-lint-no-file-name-mixed-case": "^1.0.0", + "remark-lint-no-file-name-outer-dashes": "^1.0.0", + "remark-lint-no-heading-punctuation": "^1.0.0", + "remark-lint-no-inline-padding": "^1.0.0", + "remark-lint-no-literal-urls": "^1.0.0", + "remark-lint-no-multiple-toplevel-headings": "^1.0.0", + "remark-lint-no-shell-dollars": "^1.0.0", + "remark-lint-no-shortcut-reference-image": "^1.0.0", + "remark-lint-no-shortcut-reference-link": "^1.0.0", + "remark-lint-no-table-indentation": "^1.0.0", + "remark-lint-ordered-list-marker-style": "^1.0.0", + "remark-lint-ordered-list-marker-value": "^1.0.0", + "remark-lint-rule-style": "^1.0.0", + "remark-lint-strong-marker": "^1.0.0", + "remark-lint-table-cell-padding": "^1.0.0", + "remark-lint-table-pipe-alignment": "^1.0.0", + "remark-lint-table-pipes": "^1.0.0", + "remark-lint-unordered-list-marker-style": "^1.0.0" + } + }, + "remark-preset-lint-recommended": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/remark-preset-lint-recommended/-/remark-preset-lint-recommended-3.0.3.tgz", + "integrity": "sha512-5sQ34j1Irlsj6Tt4WWRylZ7UU+1jD5es/LfDZBZp/LXDwC4ldGqKpMmCCR6Z00x1jYM1phmS4M+eGqTdah0qkQ==", + "dev": true, + "requires": { + "remark-lint": "^6.0.0", + "remark-lint-final-newline": "^1.0.0", + "remark-lint-hard-break-spaces": "^1.0.0", + "remark-lint-list-item-bullet-indent": "^1.0.0", + "remark-lint-list-item-indent": "^1.0.0", + "remark-lint-no-auto-link-without-protocol": "^1.0.0", + "remark-lint-no-blockquote-without-marker": "^2.0.0", + "remark-lint-no-duplicate-definitions": "^1.0.0", + "remark-lint-no-heading-content-indent": "^1.0.0", + "remark-lint-no-inline-padding": "^1.0.0", + "remark-lint-no-literal-urls": "^1.0.0", + "remark-lint-no-shortcut-reference-image": "^1.0.0", + "remark-lint-no-shortcut-reference-link": "^1.0.0", + "remark-lint-no-undefined-references": "^1.0.0", + "remark-lint-no-unused-definitions": "^1.0.0", + "remark-lint-ordered-list-marker-style": "^1.0.0" + } + }, + "remark-retext": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/remark-retext/-/remark-retext-3.1.3.tgz", + "integrity": "sha512-UujXAm28u4lnUvtOZQFYfRIhxX+auKI9PuA2QpQVTT7gYk1OgX6o0OUrSo1KOa6GNrFX+OODOtS5PWIHPxM7qw==", + "dev": true, + "requires": { + "mdast-util-to-nlcst": "^3.2.0" + } + }, + "remark-stringify": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-7.0.3.tgz", + "integrity": "sha512-+jgmjNjm2kR7y2Ns1BATXRlFr+iQ7sDcpSgytfU77nkw7UCd5yJNArSxB3MU3Uul7HuyYNTCjetoGfy8xLia1A==", + "dev": true, + "requires": { + "ccount": "^1.0.0", + "is-alphanumeric": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "longest-streak": "^2.0.1", + "markdown-escapes": "^1.0.0", + "markdown-table": "^1.1.0", + "mdast-util-compact": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "stringify-entities": "^2.0.0", + "unherit": "^1.0.4", + "xtend": "^4.0.1" + } + }, + "remark-validate-links": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/remark-validate-links/-/remark-validate-links-9.0.1.tgz", + "integrity": "sha512-+ZW2xzqDEujM+oPkutHm5LiTkMXeE7ldzruwi1xYVYq5xOE+zbPf0UMpc14ek2yn10T9Vvc+xLF5njZILqyAFw==", + "dev": true, + "requires": { + "github-slugger": "^1.2.0", + "hosted-git-info": "^2.5.0", + "mdast-util-to-string": "^1.0.4", + "propose": "0.0.5", + "to-vfile": "^6.0.0", + "trough": "^1.0.0", + "unist-util-visit": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "retext-contractions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/retext-contractions/-/retext-contractions-3.0.0.tgz", + "integrity": "sha512-Wn95agseXHTsoXvhavuTcnwUEb9TbL7QtnYkHeFMh8L53jdQbbooLX68cbpKyaaPbxYiomrgJpu7eB3arcr2rw==", + "dev": true, + "requires": { + "nlcst-is-literal": "^1.0.0", + "nlcst-to-string": "^2.0.0", + "unist-util-visit": "^1.1.0" + } + }, + "retext-diacritics": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/retext-diacritics/-/retext-diacritics-2.0.0.tgz", + "integrity": "sha512-wr3mqJ9whlIG/q6vP601qR+/C7AMgc7O60kebs9kvN/HtTX7CpvFsKF68+yw86drMOMVCBJP8JB1Qlnj8CkY5A==", + "dev": true, + "requires": { + "match-casing": "^1.0.0", + "nlcst-search": "^1.0.0", + "nlcst-to-string": "^2.0.0", + "quotation": "^1.0.1", + "unist-util-position": "^3.0.0" + } + }, + "retext-english": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/retext-english/-/retext-english-3.0.3.tgz", + "integrity": "sha512-qltUsSjHMvCvpAm90qRvzK1DEBOnhSK3tUQk5aHFCBtiMHccp6FhlCH0mQ9vFcBf5BsG7GEBdPysTlY3g9Lchg==", + "dev": true, + "requires": { + "parse-english": "^4.0.0", + "unherit": "^1.0.4" + } + }, + "retext-equality": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-equality/-/retext-equality-4.0.0.tgz", + "integrity": "sha512-IM0L38wMuBRDY5Pj7c4OXN0THA6I1eAqmda/H+MMyajk1fBxaGfdxrY0qm9hilyVF7XKS93uEee+V2KeNBqbmQ==", + "dev": true, + "requires": { + "lodash.difference": "^4.5.0", + "lodash.intersection": "^4.4.0", + "nlcst-normalize": "^2.0.0", + "nlcst-search": "^1.1.1", + "nlcst-to-string": "^2.0.0", + "object-keys": "^1.0.7", + "quotation": "^1.0.1", + "unist-util-is": "^3.0.0", + "unist-util-visit": "^1.0.0" + } + }, + "retext-indefinite-article": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/retext-indefinite-article/-/retext-indefinite-article-1.1.7.tgz", + "integrity": "sha512-pqvEfEHL8uoeonbEjk8+d/hmyA3ozIeNTl4t3uurMcBpoIqN3+nbuMCFQrfDy2wjaKZ40KsLmEi+Zjv7m1ejLQ==", + "dev": true, + "requires": { + "format": "^0.2.2", + "nlcst-to-string": "^2.0.0", + "number-to-words": "^1.2.3", + "unist-util-is": "^3.0.0", + "unist-util-visit": "^1.1.0" + } + }, + "retext-overuse": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/retext-overuse/-/retext-overuse-1.1.1.tgz", + "integrity": "sha1-Q+YoGzg8Byl56rqPKsCARmqPa/o=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "nlcst-search": "^1.1.1", + "nlcst-to-string": "^1.0.0", + "object-keys": "^1.0.9", + "quotation": "^1.0.1", + "stopwords": "0.0.5", + "thesaurus": "0.0.0" + }, + "dependencies": { + "nlcst-to-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-1.1.0.tgz", + "integrity": "sha1-ErLllHXsKffWGhRqebNZba/LNE0=", + "dev": true + } + } + }, + "retext-passive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/retext-passive/-/retext-passive-2.0.0.tgz", + "integrity": "sha512-IIOEH6p3Eu/sTYWEgDfdOBnEsDqxa6ZnHJjPNo6u4gfGct5rH4oaEaApTGpEIkYigUpylIHK0U6iWieqbBja0Q==", + "dev": true, + "requires": { + "lodash.difference": "^4.5.0", + "nlcst-search": "^1.0.0", + "nlcst-to-string": "^2.0.0", + "unist-util-find-before": "^2.0.0", + "unist-util-position": "^3.0.0" + } + }, + "retext-profanities": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/retext-profanities/-/retext-profanities-5.0.0.tgz", + "integrity": "sha512-zaPCKtrMDLs0U/2yN3V3rpYn1VZ3hW+AsEZdovWIRlEYZPCaUmkChOSob45LOQYJUnM+YZIahXuU9zHPm+aTKQ==", + "dev": true, + "requires": { + "cuss": "^1.15.0", + "lodash.difference": "^4.5.0", + "lodash.intersection": "^4.4.0", + "nlcst-search": "^1.0.0", + "nlcst-to-string": "^2.0.0", + "object-keys": "^1.0.9", + "pluralize": "^8.0.0", + "quotation": "^1.0.0" + } + }, + "retext-quotes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/retext-quotes/-/retext-quotes-3.0.0.tgz", + "integrity": "sha512-2htggeOFsrorhXrQvb4BI1O/r7CGVQZx/TysAT7wlVMsRUTZooiIGkBcLrcySa4sbqjsVgg1RjMy8K5O+gCQlg==", + "dev": true, + "requires": { + "nlcst-to-string": "^2.0.0", + "unist-util-is": "^3.0.0", + "unist-util-visit": "^1.1.0" + } + }, + "retext-readability": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/retext-readability/-/retext-readability-5.0.0.tgz", + "integrity": "sha512-g3AzwyfPKUH0KLP57+kpeRJFI3uxu7x+UP4NH5srtmAhyt7b45JJfzMNwt73cYraq2AG+aMlQ541cjeefjsQlg==", + "dev": true, + "requires": { + "automated-readability": "^1.0.0", + "coleman-liau": "^1.0.0", + "dale-chall": "^1.0.0", + "dale-chall-formula": "^1.0.0", + "flesch": "^1.0.0", + "gunning-fog": "^1.0.0", + "nlcst-to-string": "^2.0.0", + "smog-formula": "^1.0.0", + "spache": "^1.1.0", + "spache-formula": "^1.0.0", + "syllable": "^3.2.0", + "unist-util-visit": "^1.0.0" + } + }, + "retext-redundant-acronyms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/retext-redundant-acronyms/-/retext-redundant-acronyms-2.0.0.tgz", + "integrity": "sha512-9E62yXkDKYItNZO+lT4Pp0rAP8e/H7ppjYP681L0fk74xyItoE6okl0BMNVOa0W4XidLoGX2uWdlwWpCUeqQiw==", + "dev": true, + "requires": { + "nlcst-normalize": "^2.0.0", + "nlcst-search": "^1.0.0", + "nlcst-to-string": "^2.0.0", + "pluralize": "^8.0.0", + "quotation": "^1.0.0", + "unist-util-find-after": "^2.0.0", + "unist-util-position": "^3.0.0" + } + }, + "retext-repeated-words": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/retext-repeated-words/-/retext-repeated-words-2.0.0.tgz", + "integrity": "sha512-CGqM88ViAKtSgdWGObTU974AdmfxyiyB19MvuQTBBW3crWYIS7p21m0sJH/pCnp11gVa0YOU+vqdNaSvRiLTFA==", + "dev": true, + "requires": { + "nlcst-to-string": "^2.0.0", + "unist-util-is": "^3.0.0", + "unist-util-visit": "^1.1.0" + } + }, + "retext-sentence-spacing": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/retext-sentence-spacing/-/retext-sentence-spacing-3.0.0.tgz", + "integrity": "sha512-UWltTXZNh6kBwJJc0js3nOmbqze3LqhJg68jaRErNIPZQHtZ5hMn7h7f8kVY5OrbEL9XiY88m5DRPbFz16eTkQ==", + "dev": true, + "requires": { + "nlcst-to-string": "^2.0.0", + "unist-util-is": "^3.0.0", + "unist-util-visit": "^1.1.0" + } + }, + "retext-spell": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/retext-spell/-/retext-spell-3.0.0.tgz", + "integrity": "sha512-PvJaRhEuHOsPXX/5h3EfqEpoWZWvDBnLoopn8TGfSfPIonjwpJNvYx8qBCRp1CQlUrPPO9Vi/Hl5CvNMp7GiSA==", + "dev": true, + "requires": { + "lodash.includes": "^4.2.0", + "nlcst-is-literal": "^1.0.0", + "nlcst-to-string": "^2.0.0", + "nspell": "^2.0.0", + "quotation": "^1.1.0", + "unist-util-visit": "^1.0.0" + } + }, + "retext-syntax-urls": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/retext-syntax-urls/-/retext-syntax-urls-1.0.2.tgz", + "integrity": "sha512-Ud7i50IEP33OK9g5xCBIKh/DjoEdZi6sRJqnWDW3Wxt4B48llgfSbGLgiLeXZvJD923mOf7EAoLt/WjundXmwg==", + "dev": true, + "requires": { + "nlcst-to-string": "^2.0.0", + "unist-util-is": "^3.0.0", + "unist-util-modify-children": "^1.1.1", + "unist-util-position": "^3.0.0" + } + }, + "retext-usage": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/retext-usage/-/retext-usage-0.5.0.tgz", + "integrity": "sha1-qX3Jjn6Uf1z02Q5N1kJ1TWS6aJg=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "nlcst-search": "^1.0.0", + "nlcst-to-string": "^1.1.0", + "object-keys": "^1.0.9", + "quotation": "^1.0.0" + }, + "dependencies": { + "nlcst-to-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-1.1.0.tgz", + "integrity": "sha1-ErLllHXsKffWGhRqebNZba/LNE0=", + "dev": true + } + } + }, + "rfdc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "shellsubstitute": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shellsubstitute/-/shellsubstitute-1.2.0.tgz", + "integrity": "sha1-5PcCpQxRiw9v6YRRiQ1wWvKba3A=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=", + "dev": true + }, + "smog-formula": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/smog-formula/-/smog-formula-1.0.4.tgz", + "integrity": "sha512-Av7Dhjf+jlBnRyBjbsL3CWxjFkm3gLxhpvCLhABA5/5Q7FK2QnalHOJa+ABl4jfTtk5YP9342vXhfnqA8qgXkg==", + "dev": true + }, + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "spache": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/spache/-/spache-1.1.3.tgz", + "integrity": "sha512-wbt09O5lxUv8HSievv1zT4mZi+goVLa4r45pRxSxQXwSY1jDRvjTE36pSv/9oR/rovqcWAxzmJ2XzJgmyui1dw==", + "dev": true + }, + "spache-formula": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spache-formula/-/spache-formula-1.0.4.tgz", + "integrity": "sha512-uIjXlQzX188U556Lp5ZCGynMG/7JFSkBEqJ9Php5cnFyxtHnN5RCVSb+xXQnSNfht401KD72KUVd7ZSTR2kKog==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + }, + "state-toggle": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.2.tgz", + "integrity": "sha512-8LpelPGR0qQM4PnfLiplOQNJcIN1/r2Gy0xKB2zKnIW2YzPMt2sR4I/+gtPjhN7Svh9kw+zqEg2SFwpBO9iNiw==", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stopwords": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stopwords/-/stopwords-0.0.5.tgz", + "integrity": "sha1-Wa2dzrluoPonRZ4c7+DuDm3f1RQ=", + "dev": true + }, + "streamroller": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", + "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", + "dev": true, + "requires": { + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.14" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "string-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz", + "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^5.2.0" + } + }, + "string.prototype.trimleft": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.0.0.tgz", + "integrity": "sha1-aLaqjhYsaoDnbjqKDC50cYbicf8=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimright": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.0.0.tgz", + "integrity": "sha1-q0pW2AKgH75yk+EehPJNyBZGYd0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.0.2" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "stringify-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-2.0.0.tgz", + "integrity": "sha512-fqqhZzXyAM6pGD9lky/GOPq6V4X0SeTAFBl0iXb/BzOegl40gpf/bV3QQP7zULNYvjr6+Dx8SCaDULjVoOru0A==", + "dev": true, + "requires": { + "character-entities-html4": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.2", + "is-hexadecimal": "^1.0.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "syllable": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/syllable/-/syllable-3.6.1.tgz", + "integrity": "sha512-L2yAT4DRi9rwHpHMResxA/VKSM9T7X+eRAOEKoAFvHJxaxjtxT2Rt8qfB6pbrxeOZWsHu+ON0kTc9Oo0lU2PHA==", + "dev": true, + "requires": { + "normalize-strings": "^1.1.0", + "pluralize": "^7.0.0", + "trim": "0.0.1" + }, + "dependencies": { + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "thesaurus": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/thesaurus/-/thesaurus-0.0.0.tgz", + "integrity": "sha1-CjszVvwdgYxsFsI/Vrp/PFolyQU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "to-vfile": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/to-vfile/-/to-vfile-6.0.0.tgz", + "integrity": "sha512-i9fwXXSsHLu7mzgixc1WjgnqSe6pGpjnzCYoFmrASvEueLfyKf09QAe+XQYu8OAJ62aFqHpe2EKXojeRVvEzqA==", + "dev": true, + "requires": { + "is-buffer": "^2.0.0", + "vfile": "^4.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "too-wordy": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/too-wordy/-/too-wordy-0.1.6.tgz", + "integrity": "sha512-MV5F74YF9+UYsvwXGXTh+5YP3EqH/ivwWfyFE2/YHWQQxm9jDPmkIC23nkN133Ye4nO3HTXmiMcfGqJ5xRPfOA==", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "trim-trailing-lines": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.2.tgz", + "integrity": "sha512-MUjYItdrqqj2zpcHFTkMa9WAv4JHTI6gnRQGPFLrt5L9a6tRMiDnIqYl8JBvu2d2Tc3lWJKQwlGCp0K8AvCM+Q==", + "dev": true + }, + "trough": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.4.tgz", + "integrity": "sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, + "underscore.string": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", + "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", + "dev": true, + "requires": { + "sprintf-js": "^1.0.3", + "util-deprecate": "^1.0.2" + } + }, + "unherit": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz", + "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "xtend": "^4.0.1" + } + }, + "unified": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-8.3.2.tgz", + "integrity": "sha512-NDtUAXcd4c+mKppCbsZHzmhkKEQuhveZNBrFYmNgMIMk2K9bc8hmG3mLEGVtRmSNodobwyMePAnvIGVWZfPdzQ==", + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + } + }, + "unified-args": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/unified-args/-/unified-args-7.1.0.tgz", + "integrity": "sha512-soi9Rn7l5c1g0RfElSCHMwaxeiclSI0EsS3uZmMPUOfwMeeeZjLpNmHAowV9iSlQh59iiZhSMyQu9lB8WnIz5g==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "chalk": "^2.0.0", + "chokidar": "^3.0.0", + "fault": "^1.0.2", + "json5": "^2.0.0", + "minimist": "^1.2.0", + "text-table": "^0.2.0", + "unified-engine": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + }, + "unified-engine": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/unified-engine/-/unified-engine-7.0.0.tgz", + "integrity": "sha512-zH/MvcISpWg3JZtCoY/GYBw1WnVHkhnPoMBWpmuvAifCPSS9mzT9EbtimesJp6t2nnr/ojI0mg3TmkO1CjIwVA==", + "dev": true, + "requires": { + "concat-stream": "^2.0.0", + "debug": "^4.0.0", + "fault": "^1.0.0", + "figures": "^3.0.0", + "fn-name": "^2.0.1", + "glob": "^7.0.3", + "ignore": "^5.0.0", + "is-empty": "^1.0.0", + "is-hidden": "^1.0.1", + "is-object": "^1.0.1", + "js-yaml": "^3.6.1", + "load-plugin": "^2.0.0", + "parse-json": "^4.0.0", + "to-vfile": "^6.0.0", + "trough": "^1.0.0", + "unist-util-inspect": "^4.1.2", + "vfile-reporter": "^6.0.0", + "vfile-statistics": "^1.1.0", + "x-is-string": "^0.1.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "unified-lint-rule": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-1.0.4.tgz", + "integrity": "sha512-q9wY6S+d38xRAuWQVOMjBQYi7zGyKkY23ciNafB8JFVmDroyKjtytXHCg94JnhBCXrNqpfojo3+8D+gmF4zxJQ==", + "dev": true, + "requires": { + "wrapped": "^1.0.1" + } + }, + "unified-message-control": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unified-message-control/-/unified-message-control-1.0.4.tgz", + "integrity": "sha512-e1dEtN4Z/TvLn/qHm+xeZpzqhJTtfZusFErk336kkZVpqrJYiV9ptxq+SbRPFMlN0OkjDYHmVJ929KYjsMTo3g==", + "dev": true, + "requires": { + "trim": "0.0.1", + "unist-util-visit": "^1.0.0", + "vfile-location": "^2.0.0" + } + }, + "unist-util-find-after": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-2.0.4.tgz", + "integrity": "sha512-zo0ShIr+E/aU9xSK7JC9Kb+WP9seTFCuqVYdo5+HJSjN009XMfhiA1FIExEKzdDP1UsgvKGleGlB/pSdTSqZww==", + "dev": true, + "requires": { + "unist-util-is": "^3.0.0" + } + }, + "unist-util-find-before": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/unist-util-find-before/-/unist-util-find-before-2.0.4.tgz", + "integrity": "sha512-NzfojFvLbV+51EThEE/I5hs1NyZE71zQ5L983lENuMhwcdd8COtp4P66heK6CsjxEgjT/AXGWTD1NrAK6KOo3g==", + "dev": true, + "requires": { + "unist-util-is": "^3.0.0" + } + }, + "unist-util-generated": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.4.tgz", + "integrity": "sha512-SA7Sys3h3X4AlVnxHdvN/qYdr4R38HzihoEVY2Q2BZu8NHWDnw5OGcC/tXWjQfd4iG+M6qRFNIRGqJmp2ez4Ww==", + "dev": true + }, + "unist-util-inspect": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/unist-util-inspect/-/unist-util-inspect-4.1.4.tgz", + "integrity": "sha512-7xxyvKiZ1SC9vL5qrMqKub1T31gRHfau4242F69CcaOrXt//5PmRVOmDZ36UAEgiT+tZWzmQmbNZn+mVtnR9HQ==", + "dev": true, + "requires": { + "is-empty": "^1.0.0" + } + }, + "unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", + "dev": true + }, + "unist-util-modify-children": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.4.tgz", + "integrity": "sha512-8iey9wkoB62C7Vi/8zcRUmi4b1f5AYKTwMkyEgLduo2D8+OY65RoSvbn6k9tVNri6qumXxAwXDVlXWQi0sENTw==", + "dev": true, + "requires": { + "array-iterate": "^1.0.0" + } + }, + "unist-util-position": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.3.tgz", + "integrity": "sha512-28EpCBYFvnMeq9y/4w6pbnFmCUfzlsc41NJui5c51hOFjBA1fejcwc+5W4z2+0ECVbScG3dURS3JTVqwenzqZw==", + "dev": true + }, + "unist-util-remove-position": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.3.tgz", + "integrity": "sha512-CtszTlOjP2sBGYc2zcKA/CvNdTdEs3ozbiJ63IPBxh8iZg42SCCb8m04f8z2+V1aSk5a7BxbZKEdoDjadmBkWA==", + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "unist-util-stringify-position": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.1.tgz", + "integrity": "sha512-Zqlf6+FRI39Bah8Q6ZnNGrEHUhwJOkHde2MHVk96lLyftfJJckaPslKgzhVcviXj8KcE9UJM9F+a4JEiBUTYgA==", + "dev": true, + "requires": { + "@types/unist": "^2.0.2" + } + }, + "unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "dev": true, + "requires": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "unist-util-visit-children": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-1.1.3.tgz", + "integrity": "sha512-/GQ8KNRrG+qD30H76FZNc6Ok+8XTu8lxJByN5LnQ4eQfqxda2gP0CPsCX63BRB26ZRMNf6i1c+jlvNlqysEoFg==", + "dev": true + }, + "unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "dev": true, + "requires": { + "unist-util-is": "^3.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "untildify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz", + "integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "dev": true, + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vfile": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.0.1.tgz", + "integrity": "sha512-lRHFCuC4SQBFr7Uq91oJDJxlnftoTLQ7eKIpMdubhYcVMho4781a8MWXLy3qZrZ0/STD1kRiKc0cQOHm4OkPeA==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + } + }, + "vfile-location": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.5.tgz", + "integrity": "sha512-Pa1ey0OzYBkLPxPZI3d9E+S4BmvfVwNAAXrrqGbwTVXWaX2p9kM1zZ+n35UtVM06shmWKH4RPRN8KI80qE3wNQ==", + "dev": true + }, + "vfile-message": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.1.tgz", + "integrity": "sha512-KtasSV+uVU7RWhUn4Lw+wW1Zl/nW8JWx7JCPps10Y9JRRIDeDXf8wfBLoOSsJLyo27DqMyAi54C6Jf/d6Kr2Bw==", + "dev": true, + "requires": { + "@types/unist": "^2.0.2", + "unist-util-stringify-position": "^2.0.0" + } + }, + "vfile-reporter": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-6.0.0.tgz", + "integrity": "sha512-8Is0XxFxWJUhPJdOg3CyZTqd3ICCWg6r304PuBl818ZG91h4FMS3Q+lrOPS+cs5/DZK3H0+AkJdH0J8JEwKtDA==", + "dev": true, + "requires": { + "repeat-string": "^1.5.0", + "string-width": "^4.0.0", + "supports-color": "^6.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-sort": "^2.1.2", + "vfile-statistics": "^1.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "vfile-sort": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.1.tgz", + "integrity": "sha512-5dt7xEhC44h0uRQKhbM2JAe0z/naHphIZlMOygtMBM9Nn0pZdaX5fshhwWit9wvsuP8t/wp43nTDRRErO1WK8g==", + "dev": true + }, + "vfile-statistics": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.3.tgz", + "integrity": "sha512-CstaK/ebTz1W3Qp41Bt9Lj/2DmumFsCwC2sKahDNSPh0mPh7/UyMLCoU8ZBX34CRU0d61B4W41yIFsV0NKMZeA==", + "dev": true + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "walkdir": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.4.1.tgz", + "integrity": "sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==", + "dev": true + }, + "weasel-words": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/weasel-words/-/weasel-words-0.1.1.tgz", + "integrity": "sha1-cTeUZYXHP+RIggE4U70ADF1oek4=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrapped": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wrapped/-/wrapped-1.0.1.tgz", + "integrity": "sha1-x4PZ2Aeyc+mwHoUWgKk4yHyQckI=", + "dev": true, + "requires": { + "co": "3.1.0", + "sliced": "^1.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-good": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/write-good/-/write-good-0.11.3.tgz", + "integrity": "sha512-fDKIHO5wCzTLCOGNJl1rzzJrZlTIzfZl8msOoJQZzRhYo0X/tFTm4+2B1zTibFYK01Nnd1kLZBjj4xjcFLePNQ==", + "dev": true, + "requires": { + "adverb-where": "0.0.9", + "e-prime": "^0.10.2", + "no-cliches": "^0.1.0", + "object.assign": "^4.0.4", + "passive-voice": "^0.1.0", + "too-wordy": "^0.1.4", + "weasel-words": "^0.1.1" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", + "dev": true + }, + "xml2js": { + "version": "0.4.22", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.22.tgz", + "integrity": "sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "util.promisify": "~1.0.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", + "dev": true + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 20888161e..70c3c0c25 100644 --- a/package.json +++ b/package.json @@ -1,53 +1,53 @@ { "devDependencies": { - "coffee-script": "^1.12.7", - "dictionary-en-us": "^2.0.0", - "gaze": "^1.1.2", - "grunt": "^1.0.1", - "grunt-exec": "^2.0.0", - "jasmine": "^2.6.0", - "jasmine-core": "^2.6.4", - "jasmine-growl-reporter": "^1.0.1", + "coffeescript": "^2.4.1", + "dictionary-en-us": "^2.1.1", + "gaze": "^1.1.3", + "grunt": "^1.0.4", + "grunt-exec": "^3.0.0", + "jasmine": "^3.4.0", + "jasmine-core": "^3.4.0", + "jasmine-growl-reporter": "^2.0.0", "jasmine-node": "BrainDoctor/jasmine-node", - "jasmine-reporters": "^2.2.1", - "karma": "^1.7.0", - "karma-chrome-launcher": "^2.2.0", - "karma-coverage": "^1.1.1", - "karma-firefox-launcher": "^1.0.1", - "karma-jasmine": "^1.1.0", + "jasmine-reporters": "^2.3.2", + "karma": "^4.3.0", + "karma-chrome-launcher": "^3.1.0", + "karma-coverage": "^2.0.1", + "karma-firefox-launcher": "^1.2.0", + "karma-jasmine": "^2.0.1", "minimist": "^1.2.0", "mkdirp": "^0.5.1", - "remark-cli": "^6.0.1", - "remark-frontmatter": "^1.3.1", + "remark-cli": "^7.0.0", + "remark-frontmatter": "^1.3.2", "remark-lint-heading-whitespace": "^1.0.0", - "remark-lint-no-dead-urls": "^0.4.1", - "remark-lint-unordered-list-marker-style": "^1.0.2", + "remark-lint-no-dead-urls": "^0.5.0", + "remark-lint-unordered-list-marker-style": "^1.0.3", "remark-lint-write-good": "^1.1.0", - "remark-preset-lint-consistent": "^2.0.2", - "remark-preset-lint-markdown-style-guide": "^2.1.2", - "remark-preset-lint-recommended": "^3.0.2", - "remark-retext": "^3.1.2", - "remark-stringify": "^6.0.4", - "remark-validate-links": "^8.0.2", - "retext-contractions": "^2.1.3", - "retext-diacritics": "^1.2.2", - "retext-english": "^3.0.2", - "retext-equality": "^3.9.1", - "retext-indefinite-article": "^1.1.6", + "remark-preset-lint-consistent": "^2.0.3", + "remark-preset-lint-markdown-style-guide": "^2.1.3", + "remark-preset-lint-recommended": "^3.0.3", + "remark-retext": "^3.1.3", + "remark-stringify": "^7.0.3", + "remark-validate-links": "^9.0.1", + "retext-contractions": "^3.0.0", + "retext-diacritics": "^2.0.0", + "retext-english": "^3.0.3", + "retext-equality": "^4.0.0", + "retext-indefinite-article": "^1.1.7", "retext-overuse": "^1.1.1", - "retext-passive": "^1.3.2", - "retext-profanities": "^4.6.0", - "retext-quotes": "^2.0.3", - "retext-readability": "^4.2.1", - "retext-redundant-acronyms": "^1.2.2", - "retext-repeated-words": "^1.2.2", - "retext-sentence-spacing": "^2.1.0", - "retext-spell": "^2.4.0", - "retext-syntax-urls": "^1.0.1", + "retext-passive": "^2.0.0", + "retext-profanities": "^5.0.0", + "retext-quotes": "^3.0.0", + "retext-readability": "^5.0.0", + "retext-redundant-acronyms": "^2.0.0", + "retext-repeated-words": "^2.0.0", + "retext-sentence-spacing": "^3.0.0", + "retext-spell": "^3.0.0", + "retext-syntax-urls": "^1.0.2", "retext-usage": "^0.5.0", - "underscore": "^1.8.3", - "walkdir": "^0.0.11", - "xml2js": "^0.4.17" + "underscore": "^1.9.1", + "walkdir": "^0.4.1", + "xml2js": "^0.4.22" }, "scripts": { "lint-md": "remark .", diff --git a/packaging/DISTRIBUTIONS.md b/packaging/DISTRIBUTIONS.md index 286e2dd10..dcf975dea 100644 --- a/packaging/DISTRIBUTIONS.md +++ b/packaging/DISTRIBUTIONS.md @@ -37,15 +37,15 @@ have complete visibility over the range of support. | Versions 6.* | RHEL | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? | Versions 7.* | RHEL | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? | Versions 8.* | RHEL | ? | ? | ? | N/A | ✗ | ? | ? | ✔ | ? -| Fedora 28 | Fedora | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? -| Fedora 29 | Fedora | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? -| Fedora 30 | Fedora | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? +| Fedora 28 | Fedora | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? +| Fedora 29 | Fedora | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? +| Fedora 30 | Fedora | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? | Fedora 31 | Fedora | ? | ? | ? | N/A | ✗ | ? | ? | ✔ | ? | CentOS 6.* | Cent OS | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? | CentOS 7.* | Cent OS | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? | CentOS 8.* | Cent OS | ? | ? | ? | N/A | ✗ | ? | ? | ✔ | ? -| OpenSuSE Leap 15.0 | Open SuSE | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? -| OpenSuSE Leap 15.1 | Open SuSE | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? +| OpenSuSE Leap 15.0 | Open SuSE | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? +| OpenSuSE Leap 15.1 | Open SuSE | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? | OpenSuSE Tumbleweed | Open SuSE | ✔ | ? | ? | N/A | ✗ | ✔ | ? | ✔ | ? | SLES 11 | SLES | ? | ? | ? | N/A | ✗ | ? | ? | ✔ | ? | SLES 12 | SLES | ? | ? | ? | N/A | ✗ | ? | ? | ✔ | ? @@ -58,8 +58,8 @@ have complete visibility over the range of support. | Version | Family | CI: Smoke testing | CI: Testing | CD | .DEB | .RPM | Installer | Kickstart | Kickstart64 | Community :------------------: | :------------------: | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: -| 14.04.6 LTS (Trusty Tahr) | Ubuntu | ✔ | ? | ✔ | ✗ | N/A | ✔ | ✔ | ✔ | ? -| 16.04.6 LTS (Xenial Xerus) | Ubuntu | ✔ | ? | ✔ | ✗ | N/A | ✔ | ✔ | ✔ | ? +| 14.04.6 LTS (Trusty Tahr) | Ubuntu | ✔ | ? | ✔ | ✔ | N/A | ✔ | ✔ | ✔ | ? +| 16.04.6 LTS (Xenial Xerus) | Ubuntu | ✔ | ? | ✔ | ✔ | N/A | ✔ | ✔ | ✔ | ? | 18.04.2 LTS (Bionic Beaver) | Ubuntu | ✔ | ? | ✔ | ✔ | N/A | ✔ | ✔ | ✔ | ? | 19.04 (Disco Dingo) Latest | Ubuntu | ✔ | ? | ✔ | ✔ | N/A | ✔ | ✔ | ✔ | ? | Debian 7 (Wheezy) | Debian | ✔ | ? | ✔ | ✗ | N/A | ✔ | ✔ | ✔ | ? @@ -67,17 +67,17 @@ have complete visibility over the range of support. | Debian 9 (Stretch) | Debian | ✔ | ? | ✔ | ✔ | N/A | ✔ | ✔ | ✔ | ? | Debian 10 (Buster) | Debian | ✔ | ? | ✔ | ✔ | N/A | ✔ | ✔ | ✔ | ? | Versions 6.* | RHEL | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? -| Versions 7.* | RHEL | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? +| Versions 7.* | RHEL | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? | Versions 8.* | RHEL | ? | ? | ? | N/A | ✗ | ? | ? | ✔ | ? -| Fedora 28 | Fedora | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? -| Fedora 29 | Fedora | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? -| Fedora 30 | Fedora | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? +| Fedora 28 | Fedora | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? +| Fedora 29 | Fedora | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? +| Fedora 30 | Fedora | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? | Fedora 31 | Fedora | ? | ? | ? | N/A | ✗ | ? | ? | ✔ | ? | CentOS 6.* | Cent OS | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? -| CentOS 7.* | Cent OS | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? +| CentOS 7.* | Cent OS | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? | CentOS 8.* | Cent OS | ? | ? | ? | N/A | ✗ | ? | ? | ✔ | ? -| OpenSuSE Leap 15.0 | Open SuSE | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? -| OpenSuSE Leap 15.1 | Open SuSE | ✔ | ? | ✔ | N/A | ✔ | ✔ | ✔ | ✔ | ? +| OpenSuSE Leap 15.0 | Open SuSE | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? +| OpenSuSE Leap 15.1 | Open SuSE | ✔ | ? | ✔ | N/A | ✗ | ✔ | ✔ | ✔ | ? | OpenSuSE Tumbleweed | Open SuSE | ✔ | ? | ? | N/A | ✗ | ✔ | ? | ✔ | ? | SLES 11 | SLES | ? | ? | ? | N/A | ✗ | ? | ? | ✔ | ? | SLES 12 | SLES | ? | ? | ? | N/A | ✗ | ? | ? | ✔ | ? @@ -199,7 +199,7 @@ This is Netdata's TLS capability that incorporates encryption on the web server - **Flags/instructions to enable**: None - **Flags to disable from source**: --disable-plugin-cups -- **What packages required for auto-detect?**: `cups-devel` +- **What packages required for auto-detect?**: `cups-devel >= 1.7` #### FPING diff --git a/packaging/go.d.checksums b/packaging/go.d.checksums index 964a09b7a..943710426 100644 --- a/packaging/go.d.checksums +++ b/packaging/go.d.checksums @@ -1,16 +1,16 @@ -bd5e9f2e2677413eeb1390c750fcafa83875dbe6890de4d501db98d06640a0fe *config.tar.gz -941e6319798a5eea2ddabb3c9b40e06830e2aee5758708c182c4072de720be4e *go.d.plugin-v0.8.0.darwin-386.tar.gz -96b0d2c39854c3d4a3636b68a98f7d8d1b05754599499c456c2af0a6c477cea8 *go.d.plugin-v0.8.0.darwin-amd64.tar.gz -351051a43e5d4059ffb8f91e95a64310f3342420bd058bf120ae84c900ef75c9 *go.d.plugin-v0.8.0.freebsd-386.tar.gz -5b30abb8373956e3330202259cef7b0058a284f21367e573542901b8d1572a36 *go.d.plugin-v0.8.0.freebsd-amd64.tar.gz -ba90aeae716f66bb6cd4306134e8151de749fd2259b9fc99d57e4b41fc36c6ef *go.d.plugin-v0.8.0.freebsd-arm.tar.gz -9fcf0a2e4592eda0b6e7c8e4045ba2995239e41d910ef1ad9e48621e1ac2c98a *go.d.plugin-v0.8.0.linux-386.tar.gz -f92efd1895fb54289c651955ad45627ad3c8a6c725915ac84c0223726a7fe153 *go.d.plugin-v0.8.0.linux-amd64.tar.gz -60bb3636db91ba7b188d73fc7eeb97bbfab7a77b3eb8a91c456a173ef5982729 *go.d.plugin-v0.8.0.linux-arm.tar.gz -062049e378349c98a2f629dc33bb44117e2f7dc60aa47a9d83660193850990bd *go.d.plugin-v0.8.0.linux-arm64.tar.gz -ef57c14d3ca9ec7dca1b60d4d3bfb5cf04399139b1073f9713bb0536fadf9276 *go.d.plugin-v0.8.0.linux-mips.tar.gz -735c4b3cfff31f1ffdf60ff35cc617914641e22406e70c92a884270f77c9001e *go.d.plugin-v0.8.0.linux-mips64.tar.gz -3cafad1d94f7001d0c9aff9d60a384fb477210af2967cc7145572b635e180a7a *go.d.plugin-v0.8.0.linux-mips64le.tar.gz -f1099a482bedcb92e3ac8857a06adbc55d9e612838cbc79d3c04b616af1d1ca3 *go.d.plugin-v0.8.0.linux-mipsle.tar.gz -978f31c64215193b228c3ee9fc7c3fdf324ca4b543207fbe8e459730ae6409b2 *go.d.plugin-v0.8.0.linux-ppc64.tar.gz -b5566fc280e4b9e7b07c3ae1f1296f232530c29eb2635398b7124c2caf14e53a *go.d.plugin-v0.8.0.linux-ppc64le.tar.gz +e99a297521e8420fe9fca440d58c666df5c5498c82a980ca5ac3411e0cbf6e0d *config.tar.gz +8b8d8f99d8649537185b91f85aebd1d088a30ccd2136bec19dee3f19592234f7 *go.d.plugin-v0.10.0.darwin-386.tar.gz +335c5e417f4bbf7cf3a5d7cacc934885fc8fb6d9831d19179d0ea99f0fb8d53d *go.d.plugin-v0.10.0.darwin-amd64.tar.gz +753b47e291985c1864f242cd3de555f702b7975b0890303abaf64913a4658d2a *go.d.plugin-v0.10.0.freebsd-386.tar.gz +25dacbb8c14469c50ee8ae353803630732ffc6caca7a94603cd98e946a861788 *go.d.plugin-v0.10.0.freebsd-amd64.tar.gz +4382862045849d242f1d92dc1596eea729714d8f6ee21a61305691f1260d23c4 *go.d.plugin-v0.10.0.freebsd-arm.tar.gz +fc2413d59bfa80509db6b6bfd11fba3b232b504e9865e4a7a4555d7cec68fb5e *go.d.plugin-v0.10.0.linux-386.tar.gz +e027831ba0108260ceead05df991dac008693195699df3d195c403c8dd29ae49 *go.d.plugin-v0.10.0.linux-amd64.tar.gz +9221283f0fccb7940f4b40852430965c9a2186255119c9dfec4e634099c36893 *go.d.plugin-v0.10.0.linux-arm.tar.gz +8f88c4ecdde55408a3b38c6dab801ab63057e1d4efbe1a0ba25aeaa69c90e491 *go.d.plugin-v0.10.0.linux-arm64.tar.gz +e41b1c0c7bb09a816798428659d8e0b4e6ff5194f1741fc3e304e0e841561c53 *go.d.plugin-v0.10.0.linux-mips.tar.gz +2d3d9ca920b8207482229abad43caa58f5c17e36beac5e59b5a6d52289741576 *go.d.plugin-v0.10.0.linux-mips64.tar.gz +9d4e5bdb4c0b51c37938d8f4559ed553fbd0e87357433a4fd5ced1aae93114ca *go.d.plugin-v0.10.0.linux-mips64le.tar.gz +7244bf058cd8e7163324dbcf263ec13021f202cca6c6ed24b6611d62523fcdfe *go.d.plugin-v0.10.0.linux-mipsle.tar.gz +9637bfe94f7622752a558674c446077f2c7bb1b87d33e807efe624e78d5500ca *go.d.plugin-v0.10.0.linux-ppc64.tar.gz +a151fcc992b9cab53a92ae6fa64cafe9d9bd52c37838400433acd1ad98ff9a96 *go.d.plugin-v0.10.0.linux-ppc64le.tar.gz diff --git a/packaging/go.d.version b/packaging/go.d.version index b19b52118..bf057dbfd 100644 --- a/packaging/go.d.version +++ b/packaging/go.d.version @@ -1 +1 @@ -v0.8.0 +v0.10.0 diff --git a/packaging/installer/README.md b/packaging/installer/README.md index 3d404e779..22633895f 100644 --- a/packaging/installer/README.md +++ b/packaging/installer/README.md @@ -33,7 +33,7 @@ This method is **fully automatic on all Linux distributions**. FreeBSD and MacOS To install Netdata from source, and keep it up to date with our **nightly releases** automatically, run the following: ```bash -$ bash <(curl -Ss https://my-netdata.io/kickstart.sh) +bash <(curl -Ss https://my-netdata.io/kickstart.sh) ``` !!! note @@ -48,7 +48,7 @@ To learn more about the pros and cons of using *nightly* vs. *stable* releases, Verify the integrity of the script with this: ```bash -[ "b6d16c171ccad073b86327246151d875" = "$(curl -Ss https://my-netdata.io/kickstart.sh | md5sum | cut -d ' ' -f 1)" ] && echo "OK, VALID" || echo "FAILED, INVALID" +[ "735e9966a4cf0187863e06a5282b34a7" = "$(curl -Ss https://my-netdata.io/kickstart.sh | md5sum | cut -d ' ' -f 1)" ] && echo "OK, VALID" || echo "FAILED, INVALID" ``` _It should print `OK, VALID` if the script is the one we ship._ @@ -67,16 +67,17 @@ The `kickstart.sh` script passes all its parameters to `netdata-installer.sh`, s - `--dont-start-it`: Prevent the installer from starting Netdata automatically. - `--stable-channel`: Automatically update only on the release of new major versions. - `--no-updates`: Prevent automatic updates of any kind. +- `--local-files`: Used for offline installations. Pass four file paths: the Netdata tarball, the checksum file, the go.d plugin tarball, and the go.d plugin config tarball, to force kickstart run the process using those files. Example using all the above parameters: ```bash -$ bash <(curl -Ss https://my-netdata.io/kickstart.sh) --dont-wait --dont-start-it --no-updates --stable-channel +bash <(curl -Ss https://my-netdata.io/kickstart.sh) --dont-wait --dont-start-it --no-updates --stable-channel --local-files /tmp/my-selfdownloaded-tarball.tar.gz /tmp/checksums.txt /tmp/manually.downloaded.go.d.binary.tar.gz /tmp/manually.downloaded.go.d.config.tar.gz ``` - +Note: `--stable-channel` and `--local-files` overlap, if you use the tarball override the stable channel option is not effective </details> -Once Netdata is installed, see [Getting Started](../../docs/GettingStarted.md). +Once Netdata is installed, see [Getting Started](../../docs/getting-started.md). --- @@ -89,7 +90,7 @@ You can install a pre-compiled static binary of Netdata on any Intel/AMD 64bit L To install Netdata from a binary package on any Linux distro and any kernel version on **Intel/AMD 64bit** systems, and keep it up to date with our **nightly releases** automatically, run the following: ```bash -$ bash <(curl -Ss https://my-netdata.io/kickstart-static64.sh) +bash <(curl -Ss https://my-netdata.io/kickstart-static64.sh) ``` !!! note @@ -108,7 +109,7 @@ This script installs Netdata at `/opt/netdata`. Verify the integrity of the script with this: ```bash -[ "4415e8c13e529a795abb953a9be14ad5" = "$(curl -Ss https://my-netdata.io/kickstart-static64.sh | md5sum | cut -d ' ' -f 1)" ] && echo "OK, VALID" || echo "FAILED, INVALID" +[ "c529e4eb7ce201845cef605d450f8380" = "$(curl -Ss https://my-netdata.io/kickstart-static64.sh | md5sum | cut -d ' ' -f 1)" ] && echo "OK, VALID" || echo "FAILED, INVALID" ``` *It should print `OK, VALID` if the script is the one we ship.* @@ -119,12 +120,14 @@ The `kickstart-static64.sh` script passes all its parameters to `netdata-install - `--dont-start-it`: Prevent the installer from starting Netdata automatically. - `--stable-channel`: Automatically update only on the release of new major versions. - `--no-updates`: Prevent automatic updates of any kind. +- `--local-files`: Used for offline installations. Pass two file paths, one for the tarball and one fir the checksum file, to force kickstart run the process using those files. Example using all the above parameters: ```sh -$ bash <(curl -Ss https://my-netdata.io/kickstart-static64.sh) --dont-wait --dont-start-it --no-updates --stable-channel +bash <(curl -Ss https://my-netdata.io/kickstart-static64.sh) --dont-wait --dont-start-it --no-updates --stable-channel --local-files /tmp/my-selfdownloaded-tarball.tar.gz /tmp/checksums.txt ``` +Note: `--stable-channel` and `--local-files` overlap, if you use the tarball override the stable channel option is not effective If your shell fails to handle the above one liner, do this: @@ -146,7 +149,7 @@ sh /tmp/kickstart-static64.sh </details> -Once Netdata is installed, see [Getting Started](../../docs/GettingStarted.md). +Once Netdata is installed, see [Getting Started](../../docs/getting-started.md). --- @@ -469,9 +472,9 @@ When Netdata is first installed, it will run as *root*. This may or may not be a 3. Change ownership of the following directories, as defined in [Netdata Security](../../docs/netdata-security.md#security-design): ```sh -$ chown -R root:netdata /opt/netdata/usr/share/netdata -$ chown -R netdata:netdata /opt/netdata/var/lib/netdata /opt/netdata/var/cache/netdata -$ chown -R netdata:root /opt/netdata/var/log/netdata +chown -R root:netdata /opt/netdata/usr/share/netdata +chown -R netdata:netdata /opt/netdata/var/lib/netdata /opt/netdata/var/cache/netdata +chown -R netdata:root /opt/netdata/var/log/netdata ``` Additionally, as of 2018/06/24, the Netdata installer doesn't recognize DSM as an operating system, so no init script is installed. You'll have to do this manually: @@ -504,6 +507,86 @@ The Netdata team maintains two releases of the Netdata agent: **nightly** and ** - Protect yourself from the rare instance when major bugs slip through our testing and negatively affect a Netdata installation - Retain more control over the Netdata version you use +## Offline installations + +You can install Netdata on systems without internet access, but you need to take +a few extra steps to make it work. + +By default, the `kickstart.sh` and `kickstart-static64.sh` download Netdata +assets, like the precompiled binary and a few dependencies, using the system's +internet connection, but you can also supply these files from the local filesystem. + +First, download the required files. If you're using `kickstart.sh`, you need the +Netdata tarball, the checksums, the go.d plugin binary, and the go.d plugin +configuration. If you're using `kickstart-static64.sh`, you need only the +Netdata tarball and checksums. + +Download the files you need to a system of yours that's connected to the +internet. You can use the commands below, or visit the [latest Netdata release +page](https://github.com/netdata/netdata/releases/latest) and [latest go.d +plugin release page](https://github.com/netdata/go.d.plugin/releases) to +download the required files manually. + +#### kickstart.sh +```bash +cd /tmp + +curl -s https://my-netdata.io/kickstart.sh > kickstart.sh + +# Netdata tarball +curl -s https://api.github.com/repos/netdata/netdata/releases/latest | grep "browser_download_url.*tar.gz" | cut -d '"' -f 4 | wget -qi - + +# Netdata checksums +curl -s https://api.github.com/repos/netdata/netdata/releases/latest | grep "browser_download_url.*txt" | cut -d '"' -f 4 | wget -qi - + +# Netdata dependency handling script +curl -s https://raw.githubusercontent.com/netdata/netdata-demo-site/master/install-required-packages.sh | wget -qi - + +# go.d plugin +# For binaries for OS types and architectures not listed on [go.d releases](https://github.com/netdata/go.d.plugin/releases/latest), kindly open a github issue and we will do our best to serve your request +export OS=$(uname -s | tr '[:upper:]' '[:lower:]') ARCH=$(uname -m | sed -e 's/i386/386/g' -e 's/i686/386/g' -e 's/x86_64/amd64/g' -e 's/aarch64/arm64/g' -e 's/armv64/arm64/g' -e 's/armv6l/arm/g' -e 's/armv7l/arm/g' -e 's/armv5tel/arm/g') && curl -s https://api.github.com/repos/netdata/go.d.plugin/releases/latest | grep "browser_download_url.*${OS}-${ARCH}.tar.gz" | cut -d '"' -f 4 | wget -qi - + +# go.d configuration +curl -s https://api.github.com/repos/netdata/go.d.plugin/releases/latest | grep "browser_download_url.*config.tar.gz" | cut -d '"' -f 4 | wget -qi - +``` + +#### kickstart-static64.sh +```bash +cd /tmp + +curl -s https://my-netdata.io/kickstart-static64.sh > kickstart-static64.sh + +# Netdata static64 tarball +curl -s https://api.github.com/repos/netdata/netdata/releases/latest | grep "browser_download_url.*gz.run" | cut -d '"' -f 4 | wget -qi - + +# Netdata checksums +curl -s https://api.github.com/repos/netdata/netdata/releases/latest | grep "browser_download_url.*txt" | cut -d '"' -f 4 | wget -qi - +``` + +Move downloaded files to the `/tmp` directory on the offline system in whichever way +your defined policy allows (if any). + +Now you can run either the `kickstart.sh` or `kickstart-static64.sh` scripts +using the `--local-files` option. This option requires you to specify +the location and names of the files you just downloaded. + +!!! note When using `--local-files`, the `kickstart.sh` or + `kickstart-static64.sh` scripts won't download any Netdata assets from the + internet. But, you may still need a connection to install dependencies using + your system's package manager. The scripts will warn you if your system + doesn't have all the dependencies. + +```bash +# kickstart.sh +bash kickstart.sh --local-files /tmp/netdata-version-number-here.tar.gz /tmp/sha256sums.txt /tmp/go.d-binary-filename.tar.gz /tmp/config.tar.gz /tmp/install-required-packages.sh + +# kickstart-static64.sh +bash kickstart-static64.sh --local-files /tmp/netdata-version-number-here.gz.run /tmp/sha256sums.txt +``` + +Now that you're finished with your offline installation, you can move on to our +[getting started guide](../../docs/getting-started.md)! + ## Automatic updates By default, Netdata's installation scripts enable automatic updates for both nightly and stable release channels. diff --git a/packaging/installer/UNINSTALL.md b/packaging/installer/UNINSTALL.md index b8e5bd9e3..d2bd1ebd9 100644 --- a/packaging/installer/UNINSTALL.md +++ b/packaging/installer/UNINSTALL.md @@ -1,8 +1,14 @@ # Uninstalling Netdata -Our self-contained uninstaller is able to remove Netdata installations created with shell installer. It doesn't need any other Netdata repository files to be run. All it needs is an .environment file, which is created during installation (with shell installer) and put in ${NETDATA_USER_CONFIG_DIR}/.environment (by default /etc/netdata/.environment). That file contains some parameters which are passed to our installer and which are needed during uninstallation process. Mainly two parameters are needed: +Our self-contained uninstaller is able to remove Netdata installations created with shell installer. +It doesn't need any other Netdata repository files to be run. +All it needs is an `.environment` file, which is created during installation (with shell installer) +and put in `${NETDATA_USER_CONFIG_DIR}/.environment` (by default `/etc/netdata/.environment`). +That file contains some parameters which are passed to our installer +and which are needed during uninstallation process. +Mainly two parameters are needed: -``` +```sh NETDATA_PREFIX NETDATA_ADDED_TO_GROUPS ``` @@ -10,16 +16,16 @@ NETDATA_ADDED_TO_GROUPS A workflow for uninstallation looks like this: 1. Find your `.environment` file, which is usually `/etc/netdata/.environment` in a default installation. -2. If you cannot find that file and would like to uninstall Netdata, then create new file with following content: +2. If you cannot find that file and would like to uninstall Netdata, then create a new file with the following content: -``` +```sh NETDATA_PREFIX="<installation prefix>" # put what you used as a parameter to shell installed `--install` flag. Otherwise it should be empty NETDATA_ADDED_TO_GROUPS="<additional groups>" # Additional groups for a user running the Netdata process ``` 3. Run `netdata-uninstaller.sh` as follows -``` +```sh ${NETDATA_PREFIX}/usr/libexec/netdata/netdata-uninstaller.sh --yes --env <environment_file> ``` @@ -34,6 +40,7 @@ chmod +x ./netdata-uninstaller.sh The default `environment_file` is `/etc/netdata/.environment`. -Note: This uninstallation method assumes previous installation with `netdata-installer.sh` or the kickstart script. Currently using it when Netdata was installed by a package manager can work or cause unexpected results. +Note: This uninstallation method assumes previous installation with `netdata-installer.sh` or the kickstart script. +Currently using it when Netdata was installed by a package manager can work or cause unexpected results. [![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Finstaller%2FUNINSTALL&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/packaging/installer/kickstart-static64.sh b/packaging/installer/kickstart-static64.sh index 34ca116da..a988e4f62 100755 --- a/packaging/installer/kickstart-static64.sh +++ b/packaging/installer/kickstart-static64.sh @@ -1,7 +1,15 @@ #!/usr/bin/env sh +# # SPDX-License-Identifier: GPL-3.0-or-later # shellcheck disable=SC1117,SC2039,SC2059,SC2086 - +# +# Options to run +# --dont-wait do not wait for input +# --non-interactive do not wait for input +# --dont-start-it do not start netdata after install +# --stable-channel Use the stable release channel, rather than the nightly to fetch sources +# --local-files Use a manually provided tarball for the installation +# # --------------------------------------------------------------------------------------------------------------------- # library functions copied from packaging/installer/functions.sh @@ -127,6 +135,11 @@ download() { } set_tarball_urls() { + if [ -n "${NETDATA_LOCAL_TARBALL_OVERRIDE}" ]; then + progress "Not fetching remote tarballs, local override was given" + return + fi + if [ "$1" = "stable" ]; then local latest # Simple version @@ -175,15 +188,31 @@ RELEASE_CHANNEL="nightly" while [ -n "${1}" ]; do if [ "${1}" = "--dont-wait" ] || [ "${1}" = "--non-interactive" ] || [ "${1}" = "--accept" ]; then opts="${opts} --accept" + shift 1 elif [ "${1}" = "--dont-start-it" ]; then inner_opts="${inner_opts} ${1}" + shift 1 elif [ "${1}" = "--stable-channel" ]; then RELEASE_CHANNEL="stable" + shift 1 + elif [ "${1}" = "--local-files" ]; then + shift 1 + if [ -z "${1}" ]; then + fatal "Option --local-files requires extra information. The desired tarball full filename is needed" + fi + + NETDATA_LOCAL_TARBALL_OVERRIDE="${1}" + shift 1 + if [ -z "${1}" ]; then + fatal "Option --local-files requires a pair of the tarball source and the checksum file" + fi + + NETDATA_LOCAL_TARBALL_OVERRIDE_CHECKSUM="${1}" + shift 1 else - echo >&2 "Unknown option '${1}'" + echo >&2 "Unknown option '${1}' or invalid number of arguments. Please check the README for the available arguments of ${0} and try again" exit 1 fi - shift done [ -n "${inner_opts}" ] && inner_opts="-- ${inner_opts}" @@ -191,11 +220,18 @@ done TMPDIR=$(create_tmp_directory) cd "${TMPDIR}" -set_tarball_urls "${RELEASE_CHANNEL}" -progress "Downloading static netdata binary: ${NETDATA_TARBALL_URL}" +if [ -z "${NETDATA_LOCAL_TARBALL_OVERRIDE}" ]; then + set_tarball_urls "${RELEASE_CHANNEL}" + progress "Downloading static netdata binary: ${NETDATA_TARBALL_URL}" + + download "${NETDATA_TARBALL_CHECKSUM_URL}" "${TMPDIR}/sha256sum.txt" + download "${NETDATA_TARBALL_URL}" "${TMPDIR}/netdata-latest.gz.run" +else + progress "Installation sources were given as input, running installation using \"${NETDATA_LOCAL_TARBALL_OVERRIDE}\"" + run cp "${NETDATA_LOCAL_TARBALL_OVERRIDE}" "${TMPDIR}/netdata-latest.gz.run" + run cp "${NETDATA_LOCAL_TARBALL_OVERRIDE_CHECKSUM}" "${TMPDIR}/sha256sum.txt" +fi -download "${NETDATA_TARBALL_CHECKSUM_URL}" "${TMPDIR}/sha256sum.txt" -download "${NETDATA_TARBALL_URL}" "${TMPDIR}/netdata-latest.gz.run" if ! grep netdata-latest.gz.run "${TMPDIR}/sha256sum.txt" | safe_sha256sum -c - >/dev/null 2>&1; then fatal "Static binary checksum validation failed. Stopping netdata installation and leaving binary in ${TMPDIR}" fi diff --git a/packaging/installer/kickstart.sh b/packaging/installer/kickstart.sh index bab95fda2..1612d5614 100755 --- a/packaging/installer/kickstart.sh +++ b/packaging/installer/kickstart.sh @@ -10,9 +10,10 @@ # bash <(curl -Ss https://my-netdata.io/kickstart.sh) all # # Other options: -# --dont-wait do not prompt for user input -# --non-interactive do not prompt for user input -# --no-updates do not install script for daily updates +# --dont-wait do not prompt for user input +# --non-interactive do not prompt for user input +# --no-updates do not install script for daily updates +# --local-files set the full path of the desired tarball to run install with # # This script will: # @@ -163,6 +164,11 @@ download() { } set_tarball_urls() { + if [ -n "${NETDATA_LOCAL_TARBALL_OVERRIDE}" ]; then + progress "Not fetching remote tarballs, local override was given" + return + fi + if [ "$1" = "stable" ]; then local latest # Simple version @@ -216,8 +222,17 @@ dependencies() { if ! detect_bash4 "${bash}"; then warning "Cannot detect packages to be installed in this system, without BASH v4+." else - progress "Downloading script to detect required packages..." - download "${PACKAGES_SCRIPT}" "${TMPDIR}/install-required-packages.sh" + progress "Fetching script to detect required packages..." + if [ -n "${NETDATA_LOCAL_TARBALL_OVERRIDE_DEPS_SCRIPT}" ]; then + if [ -f "${NETDATA_LOCAL_TARBALL_OVERRIDE_DEPS_SCRIPT}" ]; then + run cp "${NETDATA_LOCAL_TARBALL_OVERRIDE_DEPS_SCRIPT}" "${TMPDIR}/install-required-packages.sh" + else + fatal "Invalid given dependency file, please check your --local-files parameter options and try again" + fi + else + download "${PACKAGES_SCRIPT}" "${TMPDIR}/install-required-packages.sh" + fi + if [ ! -s "${TMPDIR}/install-required-packages.sh" ]; then warning "Downloaded dependency installation script is empty." else @@ -293,6 +308,42 @@ while [ -n "${1}" ]; do elif [ "${1}" = "--stable-channel" ]; then RELEASE_CHANNEL="stable" shift 1 + elif [ "${1}" = "--local-files" ]; then + shift 1 + if [ -z "${1}" ]; then + fatal "Missing netdata: Option --local-files requires extra information. The desired tarball for netdata, the checksum, the go.d plugin tarball , the go.d plugin config tarball and the dependency management script, in this particular order" + fi + + export NETDATA_LOCAL_TARBALL_OVERRIDE="${1}" + shift 1 + + if [ -z "${1}" ]; then + fatal "Missing checksum file: Option --local-files requires extra information. The desired tarball for netdata, the checksum, the go.d plugin tarball , the go.d plugin config tarball and the dependency management script, in this particular order" + fi + + export NETDATA_LOCAL_TARBALL_OVERRIDE_CHECKSUM="${1}" + shift 1 + + if [ -z "${1}" ]; then + fatal "Missing go.d tarball: Option --local-files requires extra information. The desired tarball for netdata, the checksum, the go.d plugin tarball , the go.d plugin config tarball and the dependency management script, in this particular order" + fi + + export NETDATA_LOCAL_TARBALL_OVERRIDE_GO_PLUGIN="${1}" + shift 1 + + if [ -z "${1}" ]; then + fatal "Missing go.d config tarball: Option --local-files requires extra information. The desired tarball for netdata, the checksum, the go.d plugin tarball , the go.d plugin config tarball and the dependency management script, in this particular order" + fi + + export NETDATA_LOCAL_TARBALL_OVERRIDE_GO_PLUGIN_CONFIG="${1}" + shift 1 + + if [ -z "${1}" ]; then + fatal "Missing dependencies management scriptlet: Option --local-files requires extra information. The desired tarball for netdata, the checksum, the go.d plugin tarball , the go.d plugin config tarball and the dependency management script, in this particular order" + fi + + export NETDATA_LOCAL_TARBALL_OVERRIDE_DEPS_SCRIPT="${1}" + shift 1 else break fi @@ -311,10 +362,17 @@ dependencies # --------------------------------------------------------------------------------------------------------------------- # download netdata package -set_tarball_urls "${RELEASE_CHANNEL}" +if [ -z "${NETDATA_LOCAL_TARBALL_OVERRIDE}" ]; then + set_tarball_urls "${RELEASE_CHANNEL}" + + download "${NETDATA_TARBALL_CHECKSUM_URL}" "${TMPDIR}/sha256sum.txt" + download "${NETDATA_TARBALL_URL}" "${TMPDIR}/netdata-latest.tar.gz" +else + progress "Installation sources were given as input, running installation using \"${NETDATA_LOCAL_TARBALL_OVERRIDE}\"" + run cp "${NETDATA_LOCAL_TARBALL_OVERRIDE_CHECKSUM}" "${TMPDIR}/sha256sum.txt" + run cp "${NETDATA_LOCAL_TARBALL_OVERRIDE}" "${TMPDIR}/netdata-latest.tar.gz" +fi -download "${NETDATA_TARBALL_CHECKSUM_URL}" "${TMPDIR}/sha256sum.txt" -download "${NETDATA_TARBALL_URL}" "${TMPDIR}/netdata-latest.tar.gz" if ! grep netdata-latest.tar.gz "${TMPDIR}/sha256sum.txt" | safe_sha256sum -c - >/dev/null 2>&1; then fatal "Tarball checksum validation failed. Stopping netdata installation and leaving tarball in ${TMPDIR}" fi diff --git a/packaging/installer/netdata-uninstaller.sh b/packaging/installer/netdata-uninstaller.sh index 41ada6234..5c8caeaf3 100755 --- a/packaging/installer/netdata-uninstaller.sh +++ b/packaging/installer/netdata-uninstaller.sh @@ -158,7 +158,12 @@ portable_del_group() { # Linux if command -v groupdel 1>/dev/null 2>&1; then - run groupdel -f "${groupname}" && return 0 + if grep -q "${groupname}" /etc/group; then + run groupdel -f "${groupname}" && return 0 + else + echo >&2 "Group ${groupname} already removed in a previous step." + run_ok + fi fi # mac OS diff --git a/packaging/version b/packaging/version index 7893098b6..f72019128 100644 --- a/packaging/version +++ b/packaging/version @@ -1 +1 @@ -v1.17.1 +v1.18.0 diff --git a/tests/Makefile.am b/tests/Makefile.am index 179b04864..c549cbd47 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -8,6 +8,7 @@ CLEANFILES = \ acls/acl.sh \ urls/request.sh \ alarm_repetition/alarm.sh \ + template_dimension/template_dim.sh \ $(NULL) include $(top_srcdir)/build/subst.inc @@ -28,6 +29,7 @@ dist_noinst_DATA = \ acls/acl.sh.in \ urls/request.sh.in \ alarm_repetition/alarm.sh.in \ + template_dimension/template_dim.sh.in \ $(NULL) dist_plugins_SCRIPTS = \ @@ -35,6 +37,7 @@ dist_plugins_SCRIPTS = \ acls/acl.sh \ urls/request.sh \ alarm_repetition/alarm.sh \ + template_dimension/template_dim.sh \ $(NULL) dist_noinst_SCRIPTS = \ diff --git a/tests/acls/acl.sh.in b/tests/acls/acl.sh.in index 772d66408..9ac404c07 100644 --- a/tests/acls/acl.sh.in +++ b/tests/acls/acl.sh.in @@ -8,6 +8,7 @@ NETDATA_VARLIB_DIR="/var/lib/netdata" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;43m' +NOCOLOR='\033[0m' #change the previous acl file and with a new #and store it on a new file @@ -15,6 +16,8 @@ change_file(){ sed "s/$1/$2/g" netdata.cfg > "$4" } +NETDATAPID="" + change_ssl_file(){ KEYROW="ssl key = $3/key.pem" CERTROW="ssl certificate = $3/cert.pem" @@ -35,24 +38,24 @@ run_acl_tests() { TOT=$(grep -c "HTTP/1.1 301" log_*.txt | cut -d: -f2| grep -c 1) if [ "$TOT" -ne "$4" ]; then - echo -e "${RED}I got a wrong number of redirects($TOT) when SSL is activated, It was expected $4" + echo -e "${RED}I got a wrong number of redirects($TOT) when SSL is activated, It was expected $4 ${NOCOLOR}" rm log_* netdata.conf.test* netdata.txt health.csv index.html badge.csv tmp* key.pem cert.pem info.txt - killall netdata + kill $NETDATAPID exit 1 elif [ "$TOT" -eq "$4" ] && [ "$4" -ne "0" ]; then - echo -e "${YELLOW}I got the correct number of redirects($4) when SSL is activated and I try to access with HTTP." + echo -e "${YELLOW}I got the correct number of redirects($4) when SSL is activated and I try to access with HTTP. ${NOCOLOR}" return fi TOT=$(grep -c "HTTP/1.1 200 OK" log_* | cut -d: -f2| grep -c 1) if [ "$TOT" -ne "$3" ]; then - echo -e "${RED}I got a wrong number of \"200 OK\" from the queries, it was expected $3." - killall netdata + echo -e "${RED}I got a wrong number of \"200 OK\" from the queries, it was expected $3. ${NOCOLOR}" + kill $NETDATAPID rm log_* netdata.conf.test* netdata.txt health.csv index.html badge.csv tmp* key.pem cert.pem info.txt exit 1 fi - echo -e "${GREEN}ACLs were applied correctly" + echo -e "${GREEN}ACLs were applied correctly ${NOCOLOR}" } CONF=$(grep "bind" netdata.cfg) @@ -69,12 +72,14 @@ else fi change_file "$CONF" " bind to = *" "$CWD" "netdata.conf.test0" -netdata -c "netdata.conf.test0" +netdata -c "netdata.conf.test0" -D & +NETDATAPID=$! run_acl_tests $TOKEN "$BASICURL:19999" 5 0 -killall netdata +kill $NETDATAPID change_ssl_file "$CONF" " bind to = *=dashboard|registry|badges|management|netdata.conf *:20000=dashboard|registry|badges|management *:20001=dashboard|registry|netdata.conf^SSL=optional *:20002=dashboard|registry" "$CWD" "netdata.conf.test1" -netdata -c "netdata.conf.test1" +netdata -c "netdata.conf.test1" -D & +NETDATAPID=$! run_acl_tests $TOKEN "$BASICURL:19999" 5 5 run_acl_tests $TOKEN "$BASICURLS:19999" 5 0 @@ -86,10 +91,11 @@ run_acl_tests $TOKEN "$BASICURLS:20001" 4 0 run_acl_tests $TOKEN "$BASICURL:20002" 3 5 run_acl_tests $TOKEN "$BASICURLS:20002" 3 0 -killall netdata +kill $NETDATAPID change_ssl_file "$CONF" " bind to = *=dashboard|registry|badges|management|netdata.conf *:20000=dashboard|registry|badges|management *:20001=dashboard|registry|netdata.conf^SSL=force *:20002=dashboard|registry" "$CWD" "netdata.conf.test2" -netdata -c "netdata.conf.test2" +netdata -c "netdata.conf.test2" -D & +NETDATAPID=$! run_acl_tests $TOKEN "$BASICURL:19999" 5 5 run_acl_tests $TOKEN "$BASICURLS:19999" 5 0 @@ -101,10 +107,11 @@ run_acl_tests $TOKEN "$BASICURLS:20001" 4 0 run_acl_tests $TOKEN "$BASICURL:20002" 3 5 run_acl_tests $TOKEN "$BASICURLS:20002" 3 0 -killall netdata +kill $NETDATAPID change_ssl_file "$CONF" " bind to = *=dashboard|registry|badges|management|netdata.conf *:20000=dashboard|registry|badges|management^SSL=optional *:20001=dashboard|registry|netdata.conf^SSL=force" "$CWD" "netdata.conf.test3" -netdata -c "netdata.conf.test3" +netdata -c "netdata.conf.test3" -D & +NETDATAPID=$! run_acl_tests $TOKEN "$BASICURL:19999" 5 5 run_acl_tests $TOKEN "$BASICURLS:19999" 5 0 @@ -113,7 +120,7 @@ run_acl_tests $TOKEN "$BASICURLS:20000" 4 0 run_acl_tests $TOKEN "$BASICURL:20001" 4 5 run_acl_tests $TOKEN "$BASICURLS:20001" 4 0 -killall netdata +kill $NETDATAPID rm log_* netdata.conf.test* netdata.txt health.csv index.html badge.csv tmp* key.pem cert.pem info.txt -echo "All the tests were successful" +echo "All the tests were successful ${NOCOLOR}" diff --git a/tests/alarm_repetition/alarm.sh.in b/tests/alarm_repetition/alarm.sh.in index 8555e0a3c..09d6aaf46 100644 --- a/tests/alarm_repetition/alarm.sh.in +++ b/tests/alarm_repetition/alarm.sh.in @@ -7,7 +7,8 @@ HEALTHDIR="@configdir_POST@/health.d/" OUTDIR="workdir/" #url to do download -MURL="http://localhost:19999/api/v1/alarms?active" +QUERY="/api/v1/alarms?active" +MURL="http://localhost:19999$QUERY" #error messages RED='\033[0;31m' @@ -35,24 +36,26 @@ netdata_test_download() { grep "HTTP/1.1 200 OK" "$1" 2>/dev/null 1>/dev/null TEST="$?" if [ "$TEST" -ne "0" ]; then - echo -e "${RED} Error to get the alarms" - killall netdata + echo -e "${RED} Error to get the alarms. ${NOCOLOR}" + kill "$5" + rm "$HEALTHDIR/ram.conf" exit 1 fi COUNT=$(grep -w "\"last_repeat\":" "$2" | grep -c "$OPT" "\"0\"") if [ "$COUNT" -eq "0" ]; then - echo -e "${RED} Netdata gave an unexpected result when alarm repetition is $4" - killall netdata + echo -e "${RED} Netdata gave an unexpected result when alarm repetition is $4 ${NOCOLOR}" + killall "$5" + rm "$HEALTHDIR/ram.conf" exit 1 fi - echo -e "${GREEN} I got the expected result" + echo -e "${GREEN} I got the expected result ${NOCOLOR}" } get_the_logs() { curl -v -k --create-dirs -o "$OUTDIR/$1.out" "$MURL" 2> "$OUTDIR/$1.err" - netdata_test_download "$OUTDIR/$1.err" "$OUTDIR/$1.out" "$2" "$3" + netdata_test_download "$OUTDIR/$1.err" "$OUTDIR/$1.out" "$2" "$3" "$4" } process_data() { @@ -61,14 +64,14 @@ process_data() { NETDATAPID=$! echo -e "${NOCOLOR}Sleeping during $SEC seconds to create alarm entries" sleep $SEC - get_the_logs "$1" "$2" "$3" + get_the_logs "$1" "$2" "$3" "$NETDATAPID" kill $NETDATAPID } mkdir "$OUTDIR" CREATEDIR="$?" if [ "$CREATEDIR" -ne "0" ]; then - echo -e "${RED}Cannot create the output directory, it already exists. The test will overwrite previous results." + echo -e "${RED}Cannot create the output directory, it already exists. The test will overwrite previous results. ${NOCOLOR}" fi change_alarm_file "./0" "ram_without_repetition.conf" "$HEALTHDIR/ram.conf" @@ -81,6 +84,6 @@ cp -a netdata.conf_with_repetition netdata.conf process_data "ram_with" "I" "activated." rm netdata.conf -echo -e "${GREEN} all the tests were sucessful" +echo -e "${GREEN} all the tests were sucessful ${NOCOLOR}" rm "$HEALTHDIR/ram.conf" rm -rf $OUTDIR diff --git a/tests/profile/benchmark-line-parsing.c b/tests/profile/benchmark-line-parsing.c index c07d1d857..1d47cc83a 100644 --- a/tests/profile/benchmark-line-parsing.c +++ b/tests/profile/benchmark-line-parsing.c @@ -643,11 +643,6 @@ void main(void) total_active_file_hash = simple_hash("total_active_file"); total_unevictable_hash = simple_hash("total_unevictable"); - // cache functions - (void)simple_hash2("hello world"); - (void)strcmp("1", "2"); - (void)strtoull("123", NULL, 0); - unsigned long i, c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0, c7; unsigned long max = 1000000; diff --git a/tests/stress.sh b/tests/stress.sh index 9c9393d3b..97cced032 100755 --- a/tests/stress.sh +++ b/tests/stress.sh @@ -1,8 +1,14 @@ #!/bin/bash # SPDX-License-Identifier: GPL-3.0-or-later +if ! hash curl 2>/dev/null +then + 1>&2 echo "'curl' not found on system. Please install 'curl'." + exit 1 +fi + # set the host to connect to -if [ ! -z "$1" ] +if [ -n "$1" ] then host="$1" else @@ -11,17 +17,17 @@ fi echo "using netdata server at: $host" # shellcheck disable=SC2207 disable=SC1117 -charts=($(curl "$host/netdata.conf" 2>/dev/null | grep "^\[" | cut -d '[' -f 2 | cut -d ']' -f 1 | grep -v ^global$ | grep -v "^plugin" | sort -u)) +charts=($(curl -k "$host/netdata.conf" 2>/dev/null | grep "^\[" | cut -d '[' -f 2 | cut -d ']' -f 1 | grep -v ^global$ | grep -v "^plugin" | sort -u)) if [ "${#charts[@]}" -eq 0 ] then echo "Cannot download charts from server: $host" exit 1 fi -update_every="$(curl "$host/netdata.conf" 2>/dev/null | grep "update every = " | head -n 1 | cut -d '=' -f 2)" +update_every="$(curl -k "$host/netdata.conf" 2>/dev/null | grep "update every = " | head -n 1 | cut -d '=' -f 2)" [ $(( update_every + 1 - 1)) -eq 0 ] && update_every=1 -entries="$(curl "$host/netdata.conf" 2>/dev/null | grep "history = " | head -n 1 | cut -d '=' -f 2)" +entries="$(curl -k "$host/netdata.conf" 2>/dev/null | grep "history = " | head -n 1 | cut -d '=' -f 2)" [ $(( entries + 1 - 1)) -eq 0 ] && entries=3600 # to compare equal things, set the entries to 3600 max @@ -49,7 +55,7 @@ trap cleanup EXIT while true do - echo "curl --compressed --keepalive-time 120 --header \"Connection: keep-alive\" \\" >"$file" + echo "curl -k --compressed --keepalive-time 120 --header \"Connection: keep-alive\" \\" >"$file" # shellcheck disable=SC2034 for x in {1..100} do diff --git a/tests/template_dimension/system_cpu.conf.alarm_foreach b/tests/template_dimension/system_cpu.conf.alarm_foreach new file mode 100644 index 000000000..21a8cbb72 --- /dev/null +++ b/tests/template_dimension/system_cpu.conf.alarm_foreach @@ -0,0 +1,8 @@ + alarm: dev_dim_template + on: system.cpu + os: linux +lookup: sum -3s at 0 every 3 percentage foreach system,user,nice + units: % + every: 1s + warn: $this > 1 + crit: $this > 4 diff --git a/tests/template_dimension/system_cpu.conf.alarm_foreach_sp b/tests/template_dimension/system_cpu.conf.alarm_foreach_sp new file mode 100644 index 000000000..fdd19e813 --- /dev/null +++ b/tests/template_dimension/system_cpu.conf.alarm_foreach_sp @@ -0,0 +1,8 @@ + alarm: dev_dim_template + on: system.cpu + os: linux +lookup: sum -3s at 0 every 3 percentage foreach * + units: % + every: 1s + warn: $this > 1 + crit: $this > 4 diff --git a/tests/template_dimension/system_cpu.conf.template_alarm b/tests/template_dimension/system_cpu.conf.template_alarm new file mode 100644 index 000000000..2bd12a101 --- /dev/null +++ b/tests/template_dimension/system_cpu.conf.template_alarm @@ -0,0 +1,26 @@ +template: dev_dim_template_system + on: system.cpu + os: linux + lookup: sum -3s at 0 every 3 percentage of system + units: % + every: 1s + warn: $this > 1 + crit: $this > 4 + +template: dev_dim_template_user + on: system.cpu + os: linux + lookup: sum -3s at 0 every 3 percentage of user + units: % + every: 1s + warn: $this > 1 + crit: $this > 4 + +template: dev_dim_template_nice + on: system.cpu + os: linux + lookup: sum -3s at 0 every 3 percentage of nice + units: % + every: 1s + warn: $this > 1 + crit: $this > 4 diff --git a/tests/template_dimension/system_cpu.conf.template_foreach b/tests/template_dimension/system_cpu.conf.template_foreach new file mode 100644 index 000000000..c75c15b2a --- /dev/null +++ b/tests/template_dimension/system_cpu.conf.template_foreach @@ -0,0 +1,8 @@ +template: dev_dim_template + on: system.cpu + os: linux + lookup: sum -3s at 0 every 3 percentage foreach system,user,nice + units: % + every: 1s + warn: $this > 1 + crit: $this > 4 diff --git a/tests/template_dimension/system_cpu.conf.template_foreach_sp b/tests/template_dimension/system_cpu.conf.template_foreach_sp new file mode 100644 index 000000000..f50a832c9 --- /dev/null +++ b/tests/template_dimension/system_cpu.conf.template_foreach_sp @@ -0,0 +1,8 @@ + template: dev_dim_template + on: system.cpu + os: linux + lookup: sum -3s at 0 every 3 percentage foreach * + units: % + every: 1s + warn: $this > 1 + crit: $this > 4 diff --git a/tests/template_dimension/system_cpu.conf.unique_alarm b/tests/template_dimension/system_cpu.conf.unique_alarm new file mode 100644 index 000000000..0f38b6e12 --- /dev/null +++ b/tests/template_dimension/system_cpu.conf.unique_alarm @@ -0,0 +1,26 @@ + alarm: dev_dim_template_system + on: system.cpu + os: linux +lookup: sum -3s at 0 every 3 percentage of system + units: % + every: 1s + warn: $this > 1 + crit: $this > 4 + + alarm: dev_dim_template_user + on: system.cpu + os: linux +lookup: sum -3s at 0 every 3 percentage of user + units: % + every: 1s + warn: $this > 1 + crit: $this > 4 + + alarm: dev_dim_template_nice + on: system.cpu + os: linux +lookup: sum -3s at 0 every 3 percentage of nice + units: % + every: 1s + warn: $this > 1 + crit: $this > 4 diff --git a/tests/template_dimension/template_dim.sh.in b/tests/template_dimension/template_dim.sh.in new file mode 100644 index 000000000..88978fd84 --- /dev/null +++ b/tests/template_dimension/template_dim.sh.in @@ -0,0 +1,88 @@ +#!/bin/bash + +#The health directory to put the alarms +HEALTHDIR="@configdir_POST@/health.d/" + +#the current time +OUTDIR="alarms" +QUERY="/api/v1/alarms?all" +MURL="http://localhost:19999$QUERY" + +#error messages +RED='\033[0;31m' +GREEN='\033[0;32m' +NOCOLOR='\033[0m' + +ALARMTEST="dev_dim_template" + +change_alarm_file() { + if [ -f "$1" ]; then + rm "$1" + fi + + #copy keeping the permissions + cp -a "$2" "$3" +} + +netdata_test_download() { + grep "HTTP/1.1 200 OK" "$1" 2>/dev/null 1>/dev/null + TEST="$?" + if [ "$TEST" -ne "0" ]; then + echo -e "${RED} Error to get the alarm log. ${NOCOLOR}" + exit 1 + fi + + TOTALARM=$(grep "$ALARMTEST" "$2" | grep name | cut -d: -f2 | grep -c "$ALARMTEST") + + if [ "$TOTALARM" -ne "$3" ]; then + echo -e "${RED} The number of actives alarms with the name $SYSTEMALARM is wrong ${NOCOLOR}" + exit 1 + fi +} + +get_the_logs() { + curl -v -k --create-dirs -o "$OUTDIR/$1.out" "$MURL" 2> "$OUTDIR/$1.err" + netdata_test_download "$OUTDIR/$1.err" "$OUTDIR/$1.out" "$2" +} + +process_data() { + netdata -D & + NETDATAPID=$! + echo -e "${NOCOLOR}Sleeping during 15 seconds to create alarms" + sleep 15 + kill $NETDATAPID + get_the_logs "$1" "$2" +} + +mkdir "$OUTDIR" +CREATEDIR="$?" +if [ "$CREATEDIR" -ne "0" ]; then + echo -e "${RED}Cannot create the output directory, it already exists. The test will overwrite previous results. ${NOCOLOR}" +fi + +if [ -n "$1" ]; then + MURL="$1$QUERY" +fi + +change_alarm_file "./0" "system_cpu.conf.unique_alarm" "$HEALTHDIR/dim_double_without_template.conf" +process_data "double_without_template" 3 "$HEALTHDIR/dim_double_without_template.conf" + +change_alarm_file "$HEALTHDIR/dim_double_without_template.conf" "system_cpu.conf.alarm_foreach" "$HEALTHDIR/dim_foreach_without_template.conf" +process_data "foreach_without_template" 3 "$HEALTHDIR/dim_foreach_without_template.conf" + +change_alarm_file "$HEALTHDIR/dim_foreach_without_template.conf" "system_cpu.conf.alarm_foreach_sp" "$HEALTHDIR/dim_foreach_without_template_sp.conf" +process_data "foreach_without_template" 10 "$HEALTHDIR/dim_foreach_without_template_sp.conf" + +change_alarm_file "$HEALTHDIR/dim_foreach_without_template_sp.conf" "system_cpu.conf.template_alarm" "$HEALTHDIR/dim_double_with_template.conf" +process_data "double_with_template" 3 "$HEALTHDIR/dim_double_with_template.conf" + +change_alarm_file "$HEALTHDIR/dim_double_with_template.conf" "system_cpu.conf.template_foreach" "$HEALTHDIR/dim_foreach_with_template.conf" +process_data "foreach_with_template" 3 "$HEALTHDIR/dim_foreach_with_template.conf" + +change_alarm_file "$HEALTHDIR/dim_foreach_with_template.conf" "system_cpu.conf.template_foreach_sp" "$HEALTHDIR/dim_foreach_with_template_sp.conf" +process_data "foreach_with_template" 10 "$HEALTHDIR/dim_foreach_with_template_sp.conf" + +rm "$HEALTHDIR/dim_foreach_with_template_sp.conf" +rm -rf "$OUTDIR" + +echo -e "${GREEN} all the tests were sucessful ${NOCOLOR}" diff --git a/tests/urls/request.sh.in b/tests/urls/request.sh.in index 6cbe77384..ebdfc094c 100644 --- a/tests/urls/request.sh.in +++ b/tests/urls/request.sh.in @@ -18,6 +18,9 @@ OUTDIR="tests" OUTEDIR="encoded_tests" OUTOPTDIR="options" ERRDIR="etests" +NOCOLOR='\033[0' +RED='\033[0;31m' +GREEN='\033[0;32m' ################################################################################################ #### #### @@ -27,7 +30,7 @@ ERRDIR="etests" # Print error message and close script netdata_print_error(){ - echo "Closing due error \"$1\" code \"$2\"" + echo "${RED} Closing due error \"$1\" code \"$2\" ${NOCOLOR}" exit 1 } @@ -200,36 +203,40 @@ netdata_download_allmetrics() { } -################################################################################################ +#################################################### #### #### -#### MAIN ROUTINE #### +#### MAIN ROUTINE #### #### #### -################################################################################################ +#################################################### MURL="http://127.0.0.1:19999" +if [ -n "$1" ]; then + MURL="$1" +fi + netdata_create_directory $OUTDIR netdata_create_directory $OUTEDIR netdata_create_directory $OUTOPTDIR netdata_create_directory $ERRDIR -wget --no-check-certificate --execute="robots = off" --mirror --convert-links --no-parent $MURL +wget --no-check-certificate --execute="robots = off" --mirror --convert-links --no-parent "$MURL" TEST=$? if [ $TEST -ne "0" ] ; then echo "Cannot connect to Netdata" exit 1 fi -netdata_download_various $MURL "netdata.conf" "netdata.conf" +netdata_download_various "$MURL" "netdata.conf" "netdata.conf" -netdata_download_various_with_options $MURL "netdata.conf" "netdata.conf" +netdata_download_various_with_options "$MURL" "netdata.conf" "netdata.conf" -netdata_wrong_request_various $MURL "api/v15/info?this%20could%20not%20be%20here" "err_version" +netdata_wrong_request_various "$MURL" "api/v15/info?this%20could%20not%20be%20here" "err_version" -netdata_wrong_request_various $MURL "api/v1/\(*@&$\!$%%5E\)\!$*%&\)\!$*%%5E*\!%5E%\!%5E$%\!%5E%\(\!*%5E*%5E%\(*@&$%5E%\(\!%5E#*&\!^#$*&\!^%\)@\($%^\)\!*&^\(\!*&^#$&#$\)\!$%^\)\!$*%&\)#$\!^#*$^\!\(*#^#\)\!%^\!\)$*%&\!\(*&$\!^#$*&^\!*#^$\!*^\)%\(\!*&$%\)\(\!&#$\!^*#&$^\!*^%\)\!$%\)\!\(&#$\!^#*&^$" "err_version2" +netdata_wrong_request_various "$MURL" "api/v1/\(*@&$\!$%%5E\)\!$*%&\)\!$*%%5E*\!%5E%\!%5E$%\!%5E%\(\!*%5E*%5E%\(*@&$%5E%\(\!%5E#*&\!^#$*&\!^%\)@\($%^\)\!*&^\(\!*&^#$&#$\)\!$%^\)\!$*%&\)#$\!^#*$^\!\(*#^#\)\!%^\!\)$*%&\!\(*&$\!^#$*&^\!*#^$\!*^\)%\(\!*&$%\)\(\!&#$\!^*#&$^\!*^%\)\!$%\)\!\(&#$\!^#*&^$" "err_version2" -netdata_download_various $MURL "api/v1/info" "info" -netdata_download_various_with_options $MURL "api/v1/info" "info" -netdata_download_various $MURL "api/v1/info?this%20could%20not%20be%20here" "err_info" +netdata_download_various "$MURL" "api/v1/info" "info" +netdata_download_various_with_options "$MURL" "api/v1/info" "info" +netdata_download_various "$MURL" "api/v1/info?this%20could%20not%20be%20here" "err_info" netdata_print_header "Getting all the netdata charts" CHARTS=$( netdata_download_charts "$MURL" "api/v1/charts" ) @@ -244,58 +251,57 @@ elif [ ${#CHARTS[@]} -ne ${#WCHARTS2[@]} ]; then exit 3; fi -netdata_wrong_request_various $MURL "api/v1/chart" "err_chart_without_chart" -netdata_wrong_request_various $MURL "api/v1/chart?_=234231424242" "err_chart_arg" +netdata_wrong_request_various "$MURL" "api/v1/chart" "err_chart_without_chart" +netdata_wrong_request_various "$MURL" "api/v1/chart?_=234231424242" "err_chart_arg" -netdata_download_various $MURL "api/v1/chart?chart=cpu.cpu0_interrupts&_=234231424242" "chart_cpu_with_more_args" -netdata_download_various_with_options $MURL "api/v1/chart?chart=cpu.cpu0_interrupts&_=234231424242" "chart_cpu_with_more_args" +netdata_download_various "$MURL" "api/v1/chart?chart=cpu.cpu0_interrupts&_=234231424242" "chart_cpu_with_more_args" +netdata_download_various_with_options "$MURL" "api/v1/chart?chart=cpu.cpu0_interrupts&_=234231424242" "chart_cpu_with_more_args" -netdata_download_various $MURL "api/v1/chart%3Fchart=cpu.cpu0_interrupts&_=234231424242" "chart_cpu_with_more_args_encoded" -netdata_download_various_with_options $MURL "api/v1/chart%3Fchart=cpu.cpu0_interrupts&_=234231424242" "chart_cpu_with_more_args_encoded" -netdata_download_various $MURL "api/v1/chart%3Fchart=cpu.cpu0_interrupts%26_=234231424242" "chart_cpu_with_more_args_encoded2" -netdata_download_various $MURL "api/v1/chart%3Fchart%3Dcpu.cpu0_interrupts%26_%3D234231424242" "chart_cpu_with_more_args_encoded3" +netdata_download_various "$MURL" "api/v1/chart%3Fchart=cpu.cpu0_interrupts&_=234231424242" "chart_cpu_with_more_args_encoded" +netdata_download_various_with_options "$MURL" "api/v1/chart%3Fchart=cpu.cpu0_interrupts&_=234231424242" "chart_cpu_with_more_args_encoded" +netdata_download_various "$MURL" "api/v1/chart%3Fchart=cpu.cpu0_interrupts%26_=234231424242" "chart_cpu_with_more_args_encoded2" +netdata_download_various "$MURL" "api/v1/chart%3Fchart%3Dcpu.cpu0_interrupts%26_%3D234231424242" "chart_cpu_with_more_args_encoded3" netdata_create_directory "$OUTDIR/chart" for I in $CHARTS ; do NAME=${I//\"/} - netdata_download_various $MURL "api/v1/chart?chart=$NAME" "chart/$NAME" + netdata_download_various "$MURL" "api/v1/chart?chart=$NAME" "chart/$NAME" done -netdata_wrong_request_various $MURL "api/v1/alarm_variables" "err_alarm_variables_without_chart" -netdata_wrong_request_various $MURL "api/v1/alarm_variables?_=234231424242" "err_alarm_variables_arg" -netdata_download_various $MURL "api/v1/alarm_variables?chart=cpu.cpu0_interrupts&_=234231424242" "alarm_cpu_with_more_args" +netdata_wrong_request_various "$MURL" "api/v1/alarm_variables" "err_alarm_variables_without_chart" +netdata_wrong_request_various "$MURL" "api/v1/alarm_variables?_=234231424242" "err_alarm_variables_arg" +netdata_download_various "$MURL" "api/v1/alarm_variables?chart=cpu.cpu0_interrupts&_=234231424242" "alarm_cpu_with_more_args" netdata_create_directory "$OUTDIR/alarm_variables" for I in $CHARTS ; do NAME=${I//\"/} - netdata_download_various $MURL "api/v1/alarm_variables?chart=$NAME" "alarm_variables/$NAME" + netdata_download_various "$MURL" "api/v1/alarm_variables?chart=$NAME" "alarm_variables/$NAME" done netdata_create_directory "$OUTDIR/badge" netdata_create_directory "$OUTEDIR/badge" for I in $CHARTS ; do - netdata_download_chart $MURL "api/v1/badge.svg?chart" "$I" "badge" + netdata_download_chart "$MURL" "api/v1/badge.svg?chart" "$I" "badge" done netdata_create_directory "$OUTDIR/allmetrics" -netdata_download_allmetrics $MURL "allmetrics" +netdata_download_allmetrics "$MURL" "allmetrics" -netdata_download_various $MURL "api/v1/alarms?all" "alarms_all" -netdata_download_various $MURL "api/v1/alarms?active" "alarms_active" -netdata_download_various $MURL "api/v1/alarms" "alarms_nothing" +netdata_download_various "$MURL" "api/v1/alarms?all" "alarms_all" +netdata_download_various "$MURL" "api/v1/alarms?active" "alarms_active" +netdata_download_various "$MURL" "api/v1/alarms" "alarms_nothing" -netdata_download_various $MURL "api/v1/alarm_log?after" "alarm_without" -netdata_download_various $MURL "api/v1/alarm_log" "alarm_nothing" -netdata_download_various $MURL "api/v1/alarm_log?after&_=$PT" "alarm_log" +netdata_download_various "$MURL" "api/v1/alarm_log?after" "alarm_without" +netdata_download_various "$MURL" "api/v1/alarm_log" "alarm_nothing" +netdata_download_various "$MURL" "api/v1/alarm_log?after&_=$PT" "alarm_log" netdata_create_directory "$OUTDIR/data" netdata_create_directory "$OUTEDIR/data" for I in $CHARTS ; do - netdata_download_chart $MURL "api/v1/data?chart" "$I" "data" + netdata_download_chart "$MURL" "api/v1/data?chart" "$I" "data" break; done -WHITE='\033[0;37m' -echo -e "${WHITE}ALL the URLS got 200 as answer!" +echo -e "${GREEN}ALL the URLS got 200 as answer! ${NOCOLOR}" exit 0 diff --git a/web/README.md b/web/README.md index 2636323af..f37d7f51a 100644 --- a/web/README.md +++ b/web/README.md @@ -43,7 +43,7 @@ analysis. Whenever you use a chart in this way, Netdata synchronizes all the other charts to match it. Chart synchronization even works between separate Netdata agents if you connect -them using the [node menu](../registry)! +them using the [**My nodes** menu](../registry)! You can change how charts show their metrics in a few different ways, each of which have a few methods: diff --git a/web/api/badges/README.md b/web/api/badges/README.md index 75c30abff..f199c5802 100644 --- a/web/api/badges/README.md +++ b/web/api/badges/README.md @@ -214,6 +214,14 @@ These are options dedicated to badges: <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&after=-60&scale=175"></img> `scale=175`<br/> <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&after=-60&scale=200"></img> `scale=200` +- `fixed_width_lbl=NUMBER` and `fixed_width_val=NUMBER` + + This parameter overrides auto-sizing of badges and displays them at fixed widths. `fixed_width_lbl` determines the size of the label's left side (label/name). `fixed_width_val` determines the size of the the label's right side (value). You must set both parameters together, or they will be ignored. + + You should set the label/value widths wide enough to provide space for all the possible values/contents of the badge you're requesting. In case the text cannot fit the space given it will be clipped. + + The `scale` parameter still applies on the values you give to `fixed_width_lbl` and `fixed_width_val`. + - `refresh=auto` or `refresh=SECONDS` This option enables auto-refreshing of images. Netdata will send the HTTP header `Refresh: SECONDS` to the web browser, thus requesting automatic refresh of the images at regular intervals. diff --git a/web/api/badges/web_buffer_svg.c b/web/api/badges/web_buffer_svg.c index 143fc0f3c..ea07c894d 100644 --- a/web/api/badges/web_buffer_svg.c +++ b/web/api/badges/web_buffer_svg.c @@ -688,7 +688,7 @@ static inline void calc_colorz(const char *color, char *final, size_t len, calcu // colors #define COLOR_STRING_SIZE 100 -void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options) { +void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options, int fixed_width_lbl, int fixed_width_val) { char value_color_buffer[COLOR_STRING_SIZE + 1] , value_string[VALUE_STRING_SIZE + 1] , label_escaped[LABEL_STRING_SIZE + 1] @@ -696,7 +696,8 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch , label_color_escaped[COLOR_STRING_SIZE + 1] , value_color_escaped[COLOR_STRING_SIZE + 1]; - double label_width, value_width, total_width, height = 20.0, font_size = 11.0, text_offset = 5.8, round_corner = 3.0; + double label_width = (double)fixed_width_lbl, value_width = (double)fixed_width_val, total_width; + double height = 20.0, font_size = 11.0, text_offset = 5.8, round_corner = 3.0; if(scale < 100) scale = 100; @@ -709,8 +710,10 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch calc_colorz(value_color, value_color_buffer, COLOR_STRING_SIZE, value); format_value_and_unit(value_string, VALUE_STRING_SIZE, (options & RRDR_OPTION_DISPLAY_ABS)?calculated_number_fabs(value):value, units, precision); - label_width = verdana11_width(label, font_size) + (BADGE_HORIZONTAL_PADDING * 2); - value_width = verdana11_width(value_string, font_size) + (BADGE_HORIZONTAL_PADDING * 2); + if(fixed_width_lbl <= 0 || fixed_width_val <= 0) { + label_width = verdana11_width(label, font_size) + (BADGE_HORIZONTAL_PADDING * 2); + value_width = verdana11_width(value_string, font_size) + (BADGE_HORIZONTAL_PADDING * 2); + } total_width = label_width + value_width; escape_xmlz(label_escaped, label, LABEL_STRING_SIZE); @@ -740,16 +743,49 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch "<rect class=\"bdge-ttl-width\" width=\"%0.2f\" height=\"%0.2f\" rx=\"%0.2f\" fill=\"#fff\"/>" "</mask>" "<g mask=\"url(#round)\">" - "<rect class=\"bdge-rect-lbl\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>" - "<rect class=\"bdge-rect-val\" x=\"%0.2f\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>" + "<rect class=\"bdge-rect-lbl\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>", + total_width, height, + total_width, height, round_corner, + label_width, height, label_color_escaped); //<rect class="bdge-rect-lbl" + + if(fixed_width_lbl > 0 && fixed_width_val > 0) { + buffer_sprintf(wb, + "<clipPath id=\"lbl-rect\">" + "<rect class=\"bdge-rect-lbl\" width=\"%0.2f\" height=\"%0.2f\"/>" + "</clipPath>", + label_width, height); //<clipPath id="lbl-rect"> <rect class="bdge-rect-lbl" + } + + buffer_sprintf(wb, + "<rect class=\"bdge-rect-val\" x=\"%0.2f\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>", + label_width, value_width, height, value_color_escaped); + + if(fixed_width_lbl > 0 && fixed_width_val > 0) { + buffer_sprintf(wb, + "<clipPath id=\"val-rect\">" + "<rect class=\"bdge-rect-val\" x=\"%0.2f\" width=\"%0.2f\" height=\"%0.2f\"/>" + "</clipPath>", + label_width, value_width, height); + } + + buffer_sprintf(wb, "<rect class=\"bdge-ttl-width\" width=\"%0.2f\" height=\"%0.2f\" fill=\"url(#smooth)\"/>" "</g>" "<g fill=\"#fff\" text-anchor=\"middle\" font-family=\"DejaVu Sans,Verdana,Geneva,sans-serif\" font-size=\"%0.2f\">" - "<text class=\"bdge-lbl-lbl\" x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\">%s</text>" - "<text class=\"bdge-lbl-lbl\" x=\"%0.2f\" y=\"%0.0f\">%s</text>" - "<text class=\"bdge-lbl-val\" x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\">%s</text>" - "<text class=\"bdge-lbl-val\" x=\"%0.2f\" y=\"%0.0f\">%s</text>" - "</g>" + "<text class=\"bdge-lbl-lbl\" x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\" clip-path=\"url(#lbl-rect)\">%s</text>" + "<text class=\"bdge-lbl-lbl\" x=\"%0.2f\" y=\"%0.0f\" clip-path=\"url(#lbl-rect)\">%s</text>" + "<text class=\"bdge-lbl-val\" x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\" clip-path=\"url(#val-rect)\">%s</text>" + "<text class=\"bdge-lbl-val\" x=\"%0.2f\" y=\"%0.0f\" clip-path=\"url(#val-rect)\">%s</text>" + "</g>", + total_width, height, + font_size, + label_width / 2, ceil(height - text_offset), label_escaped, + label_width / 2, ceil(height - text_offset - 1.0), label_escaped, + label_width + value_width / 2 -1, ceil(height - text_offset), value_escaped, + label_width + value_width / 2 -1, ceil(height - text_offset - 1.0), value_escaped); + + if(fixed_width_lbl <= 0 || fixed_width_val <= 0){ + buffer_sprintf(wb, "<script type=\"text/javascript\">" "var bdg_horiz_padding = %d;" "function netdata_bdge_each(list, attr, value){" @@ -773,19 +809,10 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch "var width_update_elems = this_svg.getElementsByClassName(\"bdge-ttl-width\");" "netdata_bdge_each(width_update_elems, \"width\", width_total);" "this_svg.setAttribute(\"width\", width_total);" - "</script>" - "</svg>", - total_width, height, - total_width, height, round_corner, - label_width, height, label_color_escaped, - label_width, value_width, height, value_color_escaped, - total_width, height, - font_size, - label_width / 2, ceil(height - text_offset), label_escaped, - label_width / 2, ceil(height - text_offset - 1.0), label_escaped, - label_width + value_width / 2 -1, ceil(height - text_offset), value_escaped, - label_width + value_width / 2 -1, ceil(height - text_offset - 1.0), value_escaped, - BADGE_HORIZONTAL_PADDING ); + "</script>", + BADGE_HORIZONTAL_PADDING); + } + buffer_sprintf(wb, "</svg>"); } int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) { @@ -807,7 +834,9 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u , *refresh_str = NULL , *precision_str = NULL , *scale_str = NULL - , *alarm = NULL; + , *alarm = NULL + , *fixed_width_lbl_str = NULL + , *fixed_width_val_str = NULL; int group = RRDR_GROUPING_AVERAGE; uint32_t options = 0x00000000; @@ -851,9 +880,20 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u else if(!strcmp(name, "refresh")) refresh_str = value; else if(!strcmp(name, "precision")) precision_str = value; else if(!strcmp(name, "scale")) scale_str = value; + else if(!strcmp(name, "fixed_width_lbl")) fixed_width_lbl_str = value; + else if(!strcmp(name, "fixed_width_val")) fixed_width_val_str = value; else if(!strcmp(name, "alarm")) alarm = value; } + int fixed_width_lbl = -1; + int fixed_width_val = -1; + + if(fixed_width_lbl_str && *fixed_width_lbl_str + && fixed_width_val_str && *fixed_width_val_str) { + fixed_width_lbl = str2i(fixed_width_lbl_str); + fixed_width_val = str2i(fixed_width_val_str); + } + if(!chart || !*chart) { buffer_no_cacheable(w->response.data); buffer_sprintf(w->response.data, "No chart id is given at the request."); @@ -866,7 +906,7 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u if(!st) st = rrdset_find_byname(host, chart); if(!st) { buffer_no_cacheable(w->response.data); - buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, scale, 0); + buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, scale, 0, -1, -1); ret = HTTP_RESP_OK; goto cleanup; } @@ -877,7 +917,7 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u rc = rrdcalc_find(st, alarm); if (!rc) { buffer_no_cacheable(w->response.data); - buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, scale, 0); + buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, scale, 0, -1, -1); ret = HTTP_RESP_OK; goto cleanup; } @@ -995,7 +1035,9 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u value_color, precision, scale, - options + options, + fixed_width_lbl, + fixed_width_val ); ret = HTTP_RESP_OK; } @@ -1032,7 +1074,9 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u value_color, precision, scale, - options + options, + fixed_width_lbl, + fixed_width_val ); } diff --git a/web/api/badges/web_buffer_svg.h b/web/api/badges/web_buffer_svg.h index f75677bf9..f0558c078 100644 --- a/web/api/badges/web_buffer_svg.h +++ b/web/api/badges/web_buffer_svg.h @@ -6,7 +6,7 @@ #include "libnetdata/libnetdata.h" #include "web/server/web_client.h" -extern void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options); +extern void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options, int fixed_width_lbl, int fixed_width_val); extern char *format_value_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision); extern int web_client_api_request_v1_badge(struct rrdhost *host, struct web_client *w, char *url); diff --git a/web/api/exporters/shell/allmetrics_shell.c b/web/api/exporters/shell/allmetrics_shell.c index 9a18b92dc..90c63d443 100644 --- a/web/api/exporters/shell/allmetrics_shell.c +++ b/web/api/exporters/shell/allmetrics_shell.c @@ -108,6 +108,7 @@ void rrd_stats_api_v1_charts_allmetrics_json(RRDHOST *host, BUFFER *wb) { buffer_sprintf(wb, "%s\n" "\t\"%s\": {\n" "\t\t\"name\":\"%s\",\n" + "\t\t\"family\":\"%s\",\n" "\t\t\"context\":\"%s\",\n" "\t\t\"units\":\"%s\",\n" "\t\t\"last_updated\": %ld,\n" @@ -115,6 +116,7 @@ void rrd_stats_api_v1_charts_allmetrics_json(RRDHOST *host, BUFFER *wb) { , chart_counter?",":"" , st->id , st->name + , st->family , st->context , st->units , rrdset_last_entry_t(st) diff --git a/web/api/formatters/json/README.md b/web/api/formatters/json/README.md index 8a0e37bfc..2bd37bc7d 100644 --- a/web/api/formatters/json/README.md +++ b/web/api/formatters/json/README.md @@ -103,7 +103,7 @@ callback({ > Using `format=datatable` and `options=` ```bash -$ curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=nginx_local.connections&after=-3600&points=6&group=average&formdatatable&options=' +curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=nginx_local.connections&after=-3600&points=6&group=average&formdatatable&options=' { "cols": [ diff --git a/web/api/queries/query.c b/web/api/queries/query.c index af3bcfe38..6f186d3ac 100644 --- a/web/api/queries/query.c +++ b/web/api/queries/query.c @@ -731,6 +731,7 @@ static void rrd2rrdr_log_request_response_metdata(RRDR *r static int rrdr_convert_before_after_to_absolute( long long *after_requestedp , long long *before_requestedp + , int update_every , time_t first_entry_t , time_t last_entry_t ) { @@ -749,6 +750,12 @@ static int rrdr_convert_before_after_to_absolute( // allow relative for before (smaller than API_RELATIVE_TIME_MAX) if(abs(before_requested) <= API_RELATIVE_TIME_MAX) { + if(abs(before_requested) % update_every) { + // make sure it is multiple of st->update_every + if(before_requested < 0) before_requested = before_requested - update_every - + before_requested % update_every; + else before_requested = before_requested + update_every - before_requested % update_every; + } if(before_requested > 0) before_requested = first_entry_t + before_requested; else before_requested = last_entry_t + before_requested; //last_entry_t is not really now_t //TODO: fix before_requested to be relative to now_t @@ -757,6 +764,12 @@ static int rrdr_convert_before_after_to_absolute( // allow relative for after (smaller than API_RELATIVE_TIME_MAX) if(abs(after_requested) <= API_RELATIVE_TIME_MAX) { + if(after_requested == 0) after_requested = -update_every; + if(abs(after_requested) % update_every) { + // make sure it is multiple of st->update_every + if(after_requested < 0) after_requested = after_requested - update_every - after_requested % update_every; + else after_requested = after_requested + update_every - after_requested % update_every; + } after_requested = before_requested + after_requested; absolute_period_requested = 0; } @@ -800,28 +813,6 @@ static RRDR *rrd2rrdr_fixedstep( ) { int aligned = !(options & RRDR_OPTION_NOT_ALIGNED); - if(!absolute_period_requested) { - if(before_requested % update_every) { - // make sure it is multiple of update_every - if(before_requested > 0) - before_requested = before_requested - update_every + before_requested % update_every; - #ifdef NETDATA_INTERNAL_CHECKS - else - error("INTERNAL ERROR: rrd2rrdr() on %s, negative or zero before_requested", st->name); - #endif - } - if(after_requested % update_every) { - // make sure it is multiple of update_every - if(after_requested < 0) - after_requested = after_requested - update_every + after_requested % update_every; - #ifdef NETDATA_INTERNAL_CHECKS - else - error("INTERNAL ERROR: rrd2rrdr() on %s, negative or zero after_requested", st->name); - #endif - } - if(after_requested == before_requested) after_requested -= update_every; - } - // the duration of the chart time_t duration = before_requested - after_requested; long available_points = duration / update_every; @@ -1190,28 +1181,6 @@ static RRDR *rrd2rrdr_variablestep( ) { int aligned = !(options & RRDR_OPTION_NOT_ALIGNED); - if(!absolute_period_requested) { - if(before_requested % update_every) { - // make sure it is multiple of update_every - if(before_requested > 0) - before_requested = before_requested - before_requested % update_every; - #ifdef NETDATA_INTERNAL_CHECKS - else - error("INTERNAL ERROR: rrd2rrdr() on %s, negative or zero before_requested", st->name); - #endif - } - if(after_requested % update_every) { - // make sure it is multiple of update_every - if(after_requested < 0) - after_requested = after_requested - after_requested % update_every; - #ifdef NETDATA_INTERNAL_CHECKS - else - error("INTERNAL ERROR: rrd2rrdr() on %s, negative or zero after_requested", st->name); - #endif - } - if(after_requested == before_requested) after_requested -= update_every; - } - // the duration of the chart time_t duration = before_requested - after_requested; long available_points = duration / update_every; @@ -1585,9 +1554,10 @@ RRDR *rrd2rrdr( time_t first_entry_t = rrdset_first_entry_t(st); time_t last_entry_t = rrdset_last_entry_t(st); + rrd_update_every = st->update_every; absolute_period_requested = rrdr_convert_before_after_to_absolute(&after_requested, &before_requested, - first_entry_t, last_entry_t); - + rrd_update_every, first_entry_t, + last_entry_t); #ifdef ENABLE_DBENGINE if ((st->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)) { struct rrdeng_region_info *region_info_array; @@ -1597,24 +1567,33 @@ RRDR *rrd2rrdr( regions = rrdeng_variable_step_boundaries(st, after_requested, before_requested, ®ion_info_array, &max_interval); if (1 == regions) { - if (region_info_array) - rrd_update_every = region_info_array[0].update_every; - else - rrd_update_every = st->update_every; - if (region_info_array) - freez(region_info_array); + if (region_info_array) { + if (rrd_update_every != region_info_array[0].update_every) { + rrd_update_every = region_info_array[0].update_every; + /* recalculate query alignment */ + absolute_period_requested = + rrdr_convert_before_after_to_absolute(&after_requested, &before_requested, rrd_update_every, + first_entry_t, last_entry_t); + } + freez(region_info_array); + } return rrd2rrdr_fixedstep(st, points_requested, after_requested, before_requested, group_method, resampling_time_requested, options, dimensions, rrd_update_every, first_entry_t, last_entry_t, absolute_period_requested); } else { - rrd_update_every = (uint16_t)max_interval; + if (rrd_update_every != (uint16_t)max_interval) { + rrd_update_every = (uint16_t) max_interval; + /* recalculate query alignment */ + absolute_period_requested = rrdr_convert_before_after_to_absolute(&after_requested, &before_requested, + rrd_update_every, first_entry_t, + last_entry_t); + } return rrd2rrdr_variablestep(st, points_requested, after_requested, before_requested, group_method, resampling_time_requested, options, dimensions, rrd_update_every, first_entry_t, last_entry_t, absolute_period_requested, region_info_array); } } #endif - rrd_update_every = st->update_every; return rrd2rrdr_fixedstep(st, points_requested, after_requested, before_requested, group_method, resampling_time_requested, options, dimensions, rrd_update_every, first_entry_t, last_entry_t, absolute_period_requested); diff --git a/web/gui/README.md b/web/gui/README.md index 876d499fc..cb7dc8987 100644 --- a/web/gui/README.md +++ b/web/gui/README.md @@ -7,7 +7,7 @@ toolkit. You've probably seen it before: dashboard](https://user-images.githubusercontent.com/2662304/48307727-9175c800-e55b-11e8-92d8-a581d60a4889.gif) Learn more about how dashboards work and how they're populated using the -`dashboards.js` file in our [web dashboards overview](../README.md). +`dashboards.js` file in our [web dashboards overview](../). By default, Netdata starts a web server for its dashboard at port `19999`. Open up your web browser of choice and navigate to `http://SERVER-IP:19999`, or @@ -34,8 +34,8 @@ dashboard](https://user-images.githubusercontent.com/1153921/62810777-ef681980-b Netdata is broken up into multiple **sections**, such as **System Overview**, **CPU**, **Disk**, and more. Inside each section you'll find a number of charts, -broken down into [contexts](../README.md#contexts) and -[families](../README.md#families). +broken down into [contexts](../#contexts) and +[families](../#families). An example of the **Memory** section on a Linux desktop system. @@ -56,7 +56,7 @@ associated with. menu](https://user-images.githubusercontent.com/1153921/62811361-38b96880-bab6-11e9-8d41-4d9b29778e86.png) Most menu items will contain several **submenu** entries, which represent any -[families](../README.md#families) from that section. Netdata automatically +[families](../#families) from that section. Netdata automatically generates these submenu entries. Here's a **Disks** menu with several submenu entries for each disk drive and @@ -129,11 +129,11 @@ Edit the file with your customizations. For example: ```javascript customDashboard.menu = { - 'system': { - title: 'Testing, testing, 1 2 3', + system: { + title: "Testing, testing, 1 2 3", icon: '<i class="fas fa-thumbs-up"></i>', - info: 'This is overwritten info for the system overview section!' - }, + info: "This is overwritten info for the system overview section!" + } }; ``` @@ -156,4 +156,4 @@ file](https://user-images.githubusercontent.com/1153921/62798924-570e6c80-ba94-1 For information on creating custom dashboards from scratch, see the [custom dashboards](custom/) or [Atlassian Confluence dashboards](confluence/) guides. -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fgui%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fgui%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/gui/dash-example.html b/web/gui/dash-example.html index 55cd6400c..231fec8ce 100644 --- a/web/gui/dash-example.html +++ b/web/gui/dash-example.html @@ -412,8 +412,6 @@ class PickNSort { constructor (base_url, link_base_url) { this.base_url = base_url; // URL of netdata host, with port this.link_base_url = link_base_url || base_url; // Reverse proxy URL (Optional) - this.link_base_url; - this.netdata_info; this.current_alarms = {}; this.new_alarms = {}; this.first_build = true; diff --git a/web/gui/dashboard_info.js b/web/gui/dashboard_info.js index 130162be3..774577a04 100644 --- a/web/gui/dashboard_info.js +++ b/web/gui/dashboard_info.js @@ -213,6 +213,12 @@ netdataDashboard.menu = { info: 'Network latency statistics, via <b>fping</b>. <b>fping</b> is a program to send ICMP echo probes to network hosts, similar to <code>ping</code>, but much better performing when pinging multiple hosts. fping versions after 3.15 can be directly used as netdata plugins.' }, + 'gearman': { + title: 'Gearman', + icon: '<i class="fas fa-tasks"></i>', + info: 'Gearman is a job server that allows you to do work in parallel, to load balance processing, and to call functions between languages.' + }, + 'ioping': { title: 'ioping', icon: '<i class="fas fa-exchange-alt"></i>', @@ -492,6 +498,24 @@ netdataDashboard.menu = { title: 'vSphere', icon: '<i class="fas fa-server"></i>', info: 'Performance statistics for ESXI hosts and virtual machines. Data collected from <a href="https://www.vmware.com/products/vcenter-server.html">VMware vCenter Server</a> using <code><a href="https://github.com/vmware/govmomi"> govmomi</a></code> library.' + }, + + 'vcsa': { + title: 'VCSA', + icon: '<i class="fas fa-server"></i>', + info: 'vCenter Server Appliance health statistics. Data collected from <a href="https://vmware.github.io/vsphere-automation-sdk-rest/vsphere/index.html#SVC_com.vmware.appliance.health">Health API</a>.' + }, + + 'zookeeper': { + title: 'Zookeeper', + icon: '<i class="fas fa-database"></i>', + info: 'Provides health statistics for <b><a href="https://zookeeper.apache.org/">Zookeeper</a></b> server. Data collected through the command port using <code><a href="https://zookeeper.apache.org/doc/r3.5.5/zookeeperAdmin.html#sc_zkCommands">mntr</a></code> command.' + }, + + 'hdfs': { + title: 'HDFS', + icon: '<i class="fas fa-folder-open"></i>', + info: 'Provides <b><a href="https://hadoop.apache.org/docs/r3.2.0/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html">Hadoop Distributed File System</a></b> performance statistics. Module collects metrics over <code>Java Management Extensions</code> through the web interface of an <code>HDFS</code> daemon.' } }; @@ -1236,6 +1260,39 @@ netdataDashboard.context = { info: 'A deadlock happens when two or more transactions mutually hold and request for locks, creating a cycle of dependencies. For more information about <a href="https://dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks-handling.html" target="_blank">how to minimize and handle deadlocks</a>.' }, + 'mysql.galera_cluster_status': { + info: + '<code>-1</code>: unknown, ' + + '<code>0</code>: primary (primary group configuration, quorum present), ' + + '<code>1</code>: non-primary (non-primary group configuration, quorum lost), ' + + '<code>2</code>: disconnected(not connected to group, retrying).' + }, + + 'mysql.galera_cluster_state': { + info: + '<code>0</code>: undefined, ' + + '<code>1</code>: joining, ' + + '<code>2</code>: donor/desynced, ' + + '<code>3</code>: joined, ' + + '<code>4</code>: synced.' + }, + + 'mysql.galera_cluster_weight': { + info: 'The value is counted as a sum of <code>pc.weight</code> of the nodes in the current Primary Component.' + }, + + 'mysql.galera_connected': { + info: '<code>0</code> means that the node has not yet connected to any of the cluster components. ' + + 'This may be due to misconfiguration.' + }, + + 'mysql.open_transactions': { + info: 'The number of locally running transactions which have been registered inside the wsrep provider. ' + + 'This means transactions which have made operations which have caused write set population to happen. ' + + 'Transactions which are read only are not counted.' + }, + + // ------------------------------------------------------------------------ // POSTGRESQL @@ -2581,5 +2638,49 @@ netdataDashboard.context = { 'vsphere.overall_status': { info: '<code>0</code> is unknown, <code>1</code> is OK, <code>2</code> is might have a problem, <code>3</code> is definitely has a problem.' - } + }, + + // ------------------------------------------------------------------------ + // VCSA + 'vcsa.system_health': { + info: + '<code>-1</code>: unknown; ' + + '<code>0</code>: all components are healthy; ' + + '<code>1</code>: one or more components might become overloaded soon; ' + + '<code>2</code>: one or more components in the appliance might be degraded; ' + + '<code>3</code>: one or more components might be in an unusable status and the appliance might become unresponsive soon; ' + + '<code>4</code>: no health data is available.' + }, + + 'vcsa.components_health': { + info: + '<code>-1</code>: unknown; ' + + '<code>0</code>: healthy; ' + + '<code>1</code>: healthy, but may have some problems; ' + + '<code>2</code>: degraded, and may have serious problems; ' + + '<code>3</code>: unavailable, or will stop functioning soon; ' + + '<code>4</code>: no health data is available.' + }, + + 'vcsa.software_updates_health': { + info: + '<code>softwarepackages</code> represents information on available software updates available in the remote vSphere Update Manager repository.<br>' + + '<code>-1</code>: unknown; ' + + '<code>0</code>: no updates available; ' + + '<code>2</code>: non-security updates are available; ' + + '<code>3</code>: security updates are available; ' + + '<code>4</code>: an error retrieving information on software updates.' + }, + + // ------------------------------------------------------------------------ + // Zookeeper + + 'zookeeper.server_state': { + info: + '<code>0</code>: unknown, ' + + '<code>1</code>: leader, ' + + '<code>2</code>: follower, ' + + '<code>3</code>: observer, ' + + '<code>4</code>: standalone.' + } }; diff --git a/web/gui/goto-host-from-alarm.html b/web/gui/goto-host-from-alarm.html index ec53df084..7d12f8480 100644 --- a/web/gui/goto-host-from-alarm.html +++ b/web/gui/goto-host-from-alarm.html @@ -69,6 +69,7 @@ var urlOptions = { alarm_unique_id: 0, alarm_id: 0, alarm_event_id: 0, + alarm_when: 0, hasProperty: function(property) { return typeof this[property] !== 'undefined'; } @@ -101,6 +102,7 @@ function netdataURL(url) { + ';alarm_unique_id=' + urlOptions.alarm_unique_id.toString() + ';alarm_id=' + urlOptions.alarm_id.toString() + ';alarm_event_id=' + urlOptions.alarm_event_id.toString() + + ';alarm_when=' + urlOptions.alarm_when.toString() ; } diff --git a/web/gui/main.css b/web/gui/main.css index b6ba95910..870a1fdd4 100644 --- a/web/gui/main.css +++ b/web/gui/main.css @@ -383,6 +383,10 @@ body.modal-open { /* -------------------------------------------------------------------------- */ +#alarms_log_table tbody tr { + cursor: pointer; +} + #my-netdata-dropdown-content { width: 500px; } diff --git a/web/gui/main.js b/web/gui/main.js index 71af6b59d..0635b07a7 100644 --- a/web/gui/main.js +++ b/web/gui/main.js @@ -71,6 +71,7 @@ var urlOptions = { alarm_unique_id: 0, alarm_id: 0, alarm_event_id: 0, + alarm_when: 0, hasProperty: function (property) { // console.log('checking property ' + property + ' of type ' + typeof(this[property])); @@ -139,7 +140,7 @@ var urlOptions = { } } - var numeric = ['after', 'before', 'highlight_after', 'highlight_before']; + var numeric = ['after', 'before', 'highlight_after', 'highlight_before', 'alarm_when']; len = numeric.length; while (len--) { if (typeof urlOptions[numeric[len]] === 'string') { @@ -153,6 +154,22 @@ var urlOptions = { } } + if (urlOptions.alarm_when) { + // if alarm_when exists, create after/before params + // -/+ 2 minutes from the alarm, and reload the page + const alarmTime = new Date(urlOptions.alarm_when * 1000).valueOf(); + const timeMarginMs = 120000; // 2 mins + + const after = alarmTime - timeMarginMs; + const before = alarmTime + timeMarginMs; + const newHash = document.location.hash.replace( + /;alarm_when=[0-9]*/i, + ";after=" + after + ";before=" + before, + ); + history.replaceState(null, '', newHash); + location.reload(); + } + if (urlOptions.server !== null && urlOptions.server !== '') { netdataServerStatic = document.location.origin.toString() + document.location.pathname.toString(); netdataServer = urlOptions.server; @@ -708,7 +725,7 @@ function openAuthenticatedUrl(url) { if (isSignedIn()) { window.open(url); } else { - window.open(`${NETDATA.registry.cloudBaseURL}/account/sign-in-agent?id=${NETDATA.registry.machine_guid}&name=${encodeURIComponent(NETDATA.registry.hostname)}&origin=${encodeURIComponent(window.location.origin + "/")}&redirectUrl=${encodeURIComponent(window.location.origin + "/" + url)}`); + window.open(`${NETDATA.registry.cloudBaseURL}/account/sign-in-agent?id=${NETDATA.registry.machine_guid}&name=${encodeURIComponent(NETDATA.registry.hostname)}&origin=${encodeURIComponent(window.location.origin + "/")}&redirect_uri=${encodeURIComponent(window.location.origin + "/" + url)}`); } } @@ -2094,7 +2111,7 @@ function alarmsUpdateModal() { var badge_url = NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto'; var action_buttons = '<br/> <br/>role: <b>' + alarm.recipient + '</b><br/> <br/>' - + '<div class="action-button ripple" title="click to scroll the dashboard to the chart of this alarm" data-toggle="tooltip" data-placement="bottom" onClick="scrollToChartAfterHidingModal(\'' + alarm.chart + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;"><i class="fab fa-periscope"></i></div>' + + '<div class="action-button ripple" title="click to scroll the dashboard to the chart of this alarm" data-toggle="tooltip" data-placement="bottom" onClick="scrollToChartAfterHidingModal(\'' + alarm.chart + '\', ' + alarm.last_status_change * 1000 + ', \'' + alarm.status + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;"><i class="fab fa-periscope"></i></div>' + '<div class="action-button ripple" title="click to copy to the clipboard the URL of this badge" data-toggle="tooltip" data-placement="bottom" onClick="clipboardCopy(\'' + badge_url + '\'); return false;"><i class="far fa-copy"></i></div>' + '<div class="action-button ripple" title="click to copy to the clipboard an auto-refreshing <code>embed</code> html element for this badge" data-toggle="tooltip" data-placement="bottom" onClick="clipboardCopyBadgeEmbed(\'' + badge_url + '\'); return false;"><i class="fas fa-copy"></i></div>'; @@ -2335,6 +2352,18 @@ function alarmsUpdateModal() { exportOptions: { fileName: 'netdata_alarm_log' }, + onClickRow: function (row, $element,field) { + void (field); + void ($element); + let main_url; + let common_url = "&host=" + encodeURIComponent(row['hostname']) + "&chart=" + encodeURIComponent(row['chart']) + "&family=" + encodeURIComponent(row['family']) + "&alarm=" + encodeURIComponent(row['name']) + "&alarm_unique_id=" + row['unique_id'] + "&alarm_id=" + row['alarm_id'] + "&alarm_event_id=" + row['alarm_event_id'] + "&alarm_when=" + row['when']; + if (NETDATA.registry.isUsingGlobalRegistry() && NETDATA.registry.machine_guid != null) { + main_url = "https://netdata.cloud/alarms/redirect?agentID=" + NETDATA.registry.machine_guid + common_url; + } else { + main_url = NETDATA.registry.server + "/goto-host-from-alarm.html?" + common_url ; + } + window.open(main_url,"_blank"); + }, rowStyle: function (row, index) { void (index); @@ -3965,9 +3994,21 @@ function scrollDashboardTo() { var modalHiddenCallback = null; -function scrollToChartAfterHidingModal(chart) { +function scrollToChartAfterHidingModal(chart, alarmDate, alarmStatus) { modalHiddenCallback = function () { - NETDATA.alarms.scrollToChart(chart); + NETDATA.alarms.scrollToChart(chart, alarmDate); + + if (['WARNING', 'CRITICAL'].includes(alarmStatus)) { + const currentChartState = NETDATA.options.targets.find( + (chartState) => chartState.id === chart, + ) + const twoMinutes = 2 * 60 * 1000 + NETDATA.globalPanAndZoom.setMaster( + currentChartState, + alarmDate - twoMinutes, + alarmDate + twoMinutes, + ) + } }; } @@ -4914,8 +4955,8 @@ function handleSignInMessage(e) { cloudToken = e.data.token; netdataRegistryCallback(registryAgents); - if (e.data.redirectUrl) { - window.location.replace(e.data.redirectUrl); + if (e.data.redirectURI && !window.location.href.includes(e.data.redirectURI)) { + window.location.replace(e.data.redirectURI); } } diff --git a/web/server/README.md b/web/server/README.md index 30cb00699..9f47cb8d9 100644 --- a/web/server/README.md +++ b/web/server/README.md @@ -33,7 +33,7 @@ The ports to bind are controlled via `[web].bind to`, like this: ``` [web] default port = 19999 - bind to = 127.0.0.1=dashboard^SSL=optional 10.1.1.1:19998=management|netdata.conf hostname:19997=badges [::]:19996=streaming^SSL=force localhost:19995=registry *:http=dashboard unix:/tmp/netdata.sock + bind to = 127.0.0.1=dashboard^SSL=optional 10.1.1.1:19998=management|netdata.conf hostname:19997=badges [::]:19996=streaming^SSL=force localhost:19995=registry *:http=dashboard unix:/run/netdata/netdata.sock ``` Using the above, Netdata will bind to: @@ -44,7 +44,7 @@ Using the above, Netdata will bind to: - All IPv6 IPs at port 19996. Only metric streaming requests from other Netdata agents will be accepted on this port. Only encrypted streams will be allowed (i.e. slaves also need to be [configured for TLS](../../streaming). - All the IPs `localhost` resolves to (both IPv4 and IPv6 depending the resolved IPs) at port 19996. This port will only accept registry API requests. - All IPv4 and IPv6 IPs at port `http` as set in `/etc/services`. Only the UI (dashboard) and the read API will be accessible on this port. -- Unix domain socket `/tmp/netdata.sock`. All requests are serviceable on this socket. +- Unix domain socket `/run/netdata/netdata.sock`. All requests are serviceable on this socket. Note that in some OSs like Fedora, every service sees a different `/tmp`, so don't create a Unix socket under `/tmp`. `/run` or `/var/run` is suggested. The option `[web].default port` is used when an entries in `[web].bind to` do not specify a port. @@ -79,14 +79,14 @@ Both files must be readable by the `netdata` user. If either of these files do n For test purposes, you can generate self-signed certificates with the following command: ```bash -$ openssl req -newkey rsa:2048 -nodes -sha512 -x509 -days 365 -keyout key.pem -out cert.pem +openssl req -newkey rsa:2048 -nodes -sha512 -x509 -days 365 -keyout key.pem -out cert.pem ``` !!! note If you use 4096 bits for your key and the certificate, Netdata will need more CPU to process the communication. `rsa4096` can be up to 4 times slower than `rsa2048`, so we recommend using 2048 bits. You can verify the difference by running: ```sh -$ openssl speed rsa2048 rsa4096 +openssl speed rsa2048 rsa4096 ``` #### TLS/SSL enforcement @@ -98,11 +98,11 @@ When the certificates are defined and unless any other options are provided, a N To change this behavior, you need to modify the `bind to` setting in the `[web]` section of `netdata.conf`. At the end of each port definition, you can append `^SSL=force` or `^SSL=optional`. What happens with these settings differs, depending on whether the port is used for HTTP/S requests, or for streaming. -|SSL setting|HTTP requests|HTTPS requests|Unencrypted Streams|Encrypted Streams| +| SSL setting | HTTP requests|HTTPS requests|Unencrypted Streams|Encrypted Streams| |:---------:|:-----------:|:------------:|:-----------------:|:----------------| -|none|Redirected to HTTPS|Accepted|Accepted|Accepted| -|`force`|Redirected to HTTPS|Accepted|Denied|Accepted| -|`optional`|Accepted|Accepted|Accepted|Accepted| +| none | Redirected to HTTPS|Accepted|Accepted|Accepted| +| `force`| Redirected to HTTPS|Accepted|Denied|Accepted| +| `optional`| Accepted|Accepted|Accepted|Accepted| Example: diff --git a/web/server/static/static-threaded.c b/web/server/static/static-threaded.c index 5dda27000..c432b9bf3 100644 --- a/web/server/static/static-threaded.c +++ b/web/server/static/static-threaded.c @@ -7,23 +7,26 @@ int web_client_timeout = DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS; int web_client_first_request_timeout = DEFAULT_TIMEOUT_TO_RECEIVE_FIRST_WEB_REQUEST; long web_client_streaming_rate_t = 0L; -// ---------------------------------------------------------------------------- -// high level web clients connection management - -static struct web_client *web_client_create_on_fd(int fd, const char *client_ip, const char *client_port, int port_acl) { +/* + * -------------------------------------------------------------------------------------------------------------------- + * Build web_client state from the pollinfo that describes an accepted connection. + */ +static struct web_client *web_client_create_on_fd(POLLINFO *pi) { struct web_client *w; w = web_client_get_from_cache_or_allocate(); - w->ifd = w->ofd = fd; + w->ifd = w->ofd = pi->fd; - strncpyz(w->client_ip, client_ip, sizeof(w->client_ip) - 1); - strncpyz(w->client_port, client_port, sizeof(w->client_port) - 1); + strncpyz(w->client_ip, pi->client_ip, sizeof(w->client_ip) - 1); + strncpyz(w->client_port, pi->client_port, sizeof(w->client_port) - 1); + strncpyz(w->client_host, pi->client_host, sizeof(w->client_host) - 1); if(unlikely(!*w->client_ip)) strcpy(w->client_ip, "-"); if(unlikely(!*w->client_port)) strcpy(w->client_port, "-"); - w->port_acl = port_acl; + w->port_acl = pi->port_acl; web_client_initialize_connection(w); + w->pollinfo_slot = pi->slot; return(w); } @@ -76,7 +79,7 @@ static void *web_server_file_add_callback(POLLINFO *pi, short int *events, void return w; } -static void web_werver_file_del_callback(POLLINFO *pi) { +static void web_server_file_del_callback(POLLINFO *pi) { struct web_client *w = (struct web_client *)pi->data; debug(D_WEB_CLIENT, "%llu: RELEASE FILE READ ON FD %d", w->id, pi->fd); @@ -138,7 +141,7 @@ static int web_server_file_write_callback(POLLINFO *pi, short int *events) { // web server clients static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data) { - (void)data; + (void)data; // Supress warning on unused argument worker_private->connected++; @@ -149,10 +152,9 @@ static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data *events = POLLIN; debug(D_WEB_CLIENT_ACCESS, "LISTENER on %d: new connection.", pi->fd); - struct web_client *w = web_client_create_on_fd(pi->fd, pi->client_ip, pi->client_port, pi->port_acl); - w->pollinfo_slot = pi->slot; + struct web_client *w = web_client_create_on_fd(pi); - if ( !strncmp(pi->client_port,"UNIX",4)){ + if (!strncmp(pi->client_port, "UNIX", 4)) { web_client_set_unix(w); } else { web_client_set_tcp(w); @@ -270,8 +272,9 @@ static int web_server_rcv_callback(POLLINFO *pi, short int *events) { , POLLINFO_FLAG_CLIENT_SOCKET , "FILENAME" , "" + , "" , web_server_file_add_callback - , web_werver_file_del_callback + , web_server_file_del_callback , web_server_file_read_callback , web_server_file_write_callback , (void *) w diff --git a/web/server/web_client.c b/web/server/web_client.c index 908e3a6a9..53a5944ce 100644 --- a/web/server/web_client.c +++ b/web/server/web_client.c @@ -791,7 +791,7 @@ static inline char *http_header_parse(struct web_client *w, char *s, int parse_u w->auth_bearer_token = strdupz(v); } else if(hash == hash_host && !strcasecmp(s, "Host")){ - strncpyz(w->host, v, (ve - v)); + strncpyz(w->server_host, v, ((size_t)(ve - v) < sizeof(w->server_host)-1 ? (size_t)(ve - v) : sizeof(w->server_host)-1)); } #ifdef NETDATA_WITH_ZLIB else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) { @@ -1147,8 +1147,8 @@ static inline void web_client_send_http_header(struct web_client *w) { char headerbegin[8328]; if (w->response.code == HTTP_RESP_MOVED_PERM) { memcpy(headerbegin,"\r\nLocation: https://",20); - size_t headerlength = strlen(w->host); - memcpy(&headerbegin[20],w->host,headerlength); + size_t headerlength = strlen(w->server_host); + memcpy(&headerbegin[20],w->server_host,headerlength); headerlength += 20; size_t tmp = strlen(w->last_url); memcpy(&headerbegin[headerlength],w->last_url,tmp); @@ -1212,7 +1212,7 @@ static inline void web_client_send_http_header(struct web_client *w) { if(w->mode == WEB_CLIENT_MODE_OPTIONS) { buffer_strcat(w->response.header_output, "Access-Control-Allow-Methods: GET, OPTIONS\r\n" - "Access-Control-Allow-Headers: accept, x-requested-with, origin, content-type, cookie, pragma, cache-control\r\n" + "Access-Control-Allow-Headers: accept, x-requested-with, origin, content-type, cookie, pragma, cache-control, x-auth-token\r\n" "Access-Control-Max-Age: 1209600\r\n" // 86400 * 14 ); } diff --git a/web/server/web_client.h b/web/server/web_client.h index 38a433523..c785a7fda 100644 --- a/web/server/web_client.h +++ b/web/server/web_client.h @@ -154,13 +154,14 @@ struct web_client { int ifd; int ofd; - char client_ip[NI_MAXHOST+1]; - char client_port[NI_MAXSERV+1]; + char client_ip[INET6_ADDRSTRLEN]; // Defined buffer sizes include null-terminators + char client_port[NI_MAXSERV]; + char server_host[NI_MAXHOST]; + char client_host[NI_MAXHOST]; char decoded_url[NETDATA_WEB_REQUEST_URL_SIZE + 1]; // we decode the URL in this buffer char decoded_query_string[NETDATA_WEB_REQUEST_URL_SIZE + 1]; // we decode the Query String in this buffer char last_url[NETDATA_WEB_REQUEST_URL_SIZE+1]; // we keep a copy of the decoded URL here - char host[256]; size_t url_path_length; char separator; // This value can be either '?' or 'f' char *url_search_path; //A pointer to the search path sent by the client diff --git a/web/server/web_server.c b/web/server/web_server.c index 9e51c81fe..b8b84bc36 100644 --- a/web/server/web_server.c +++ b/web/server/web_server.c @@ -86,22 +86,34 @@ SIMPLE_PATTERN *web_allow_netdataconf_from = NULL; void web_client_update_acl_matches(struct web_client *w) { w->acl = WEB_CLIENT_ACL_NONE; - if(!web_allow_dashboard_from || simple_pattern_matches(web_allow_dashboard_from, w->client_ip)) + if (!web_allow_dashboard_from || + connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host), + web_allow_dashboard_from, "dashboard")) w->acl |= WEB_CLIENT_ACL_DASHBOARD; - if(!web_allow_registry_from || simple_pattern_matches(web_allow_registry_from, w->client_ip)) + if (!web_allow_registry_from || + connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host), + web_allow_registry_from, "registry")) w->acl |= WEB_CLIENT_ACL_REGISTRY; - if(!web_allow_badges_from || simple_pattern_matches(web_allow_badges_from, w->client_ip)) + if (!web_allow_badges_from || + connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host), + web_allow_badges_from, "badges")) w->acl |= WEB_CLIENT_ACL_BADGE; - if(!web_allow_mgmt_from || simple_pattern_matches(web_allow_mgmt_from, w->client_ip)) + if (!web_allow_mgmt_from || + connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host), + web_allow_mgmt_from, "management")) w->acl |= WEB_CLIENT_ACL_MGMT; - if(!web_allow_streaming_from || simple_pattern_matches(web_allow_streaming_from, w->client_ip)) + if (!web_allow_streaming_from || + connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host), + web_allow_streaming_from, "streaming")) w->acl |= WEB_CLIENT_ACL_STREAMING; - if(!web_allow_netdataconf_from || simple_pattern_matches(web_allow_netdataconf_from, w->client_ip)) + if (!web_allow_netdataconf_from || + connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host), + web_allow_netdataconf_from, "netdata.conf")) w->acl |= WEB_CLIENT_ACL_NETDATACONF; w->acl &= w->port_acl; |