From 2b404742e2d772b2e8f8f8452749e0f6606ec263 Mon Sep 17 00:00:00 2001 From: Fred Navruzov Date: Mon, 8 Jan 2024 10:31:36 +0100 Subject: [PATCH] docs: vmanomaly part 1 (#5558) * add `AD` section, fix links, release docs and changelog * - connect sections, refactor structure * - resolve suggestions - add FAQ section - fix dead links * - fix incorrect render of tables for Writer - comment out internal readers/writers - fix page ordering to some extent * - link licensing requirements from v1.5.0 to main page --------- Co-authored-by: Artem Navoiev --- docs/.jekyll-metadata | Bin 0 -> 2277159 bytes docs/anomaly-detection/CHANGELOG.md | 124 ++++++ docs/anomaly-detection/FAQ.md | 55 +++ docs/anomaly-detection/README.md | 60 +++ docs/anomaly-detection/components/README.md | 27 ++ .../components/models/README.md | 20 + .../components/models/custom_model.md | 174 +++++++++ .../components/models/models.md | 323 ++++++++++++++++ .../components/monitoring.md | 297 +++++++++++++++ docs/anomaly-detection/components/reader.md | 262 +++++++++++++ .../anomaly-detection/components/scheduler.md | 354 ++++++++++++++++++ docs/anomaly-detection/components/writer.md | 270 +++++++++++++ docs/anomaly-detection/guides/README.md | 17 + .../guides/guide-vmanomaly-vmalert.md | 9 +- .../guide-vmanomaly-vmalert_alert-rule.webp | Bin ...guide-vmanomaly-vmalert_alerts-firing.webp | Bin ...guide-vmanomaly-vmalert_anomaly-score.webp | Bin ...uide-vmanomaly-vmalert_docker-compose.webp | Bin .../guides/guide-vmanomaly-vmalert_files.webp | Bin ...vmanomaly-vmalert_node-cpu-rate-graph.webp | Bin ...de-vmanomaly-vmalert_yhat-lower-upper.webp | Bin .../guides/guide-vmanomaly-vmalert_yhat.webp | Bin docs/vmanomaly.md | 45 ++- 23 files changed, 2016 insertions(+), 21 deletions(-) create mode 100644 docs/.jekyll-metadata create mode 100644 docs/anomaly-detection/CHANGELOG.md create mode 100644 docs/anomaly-detection/FAQ.md create mode 100644 docs/anomaly-detection/README.md create mode 100644 docs/anomaly-detection/components/README.md create mode 100644 docs/anomaly-detection/components/models/README.md create mode 100644 docs/anomaly-detection/components/models/custom_model.md create mode 100644 docs/anomaly-detection/components/models/models.md create mode 100644 docs/anomaly-detection/components/monitoring.md create mode 100644 docs/anomaly-detection/components/reader.md create mode 100644 docs/anomaly-detection/components/scheduler.md create mode 100644 docs/anomaly-detection/components/writer.md create mode 100644 docs/anomaly-detection/guides/README.md rename docs/{ => anomaly-detection}/guides/guide-vmanomaly-vmalert.md (99%) rename docs/{ => anomaly-detection}/guides/guide-vmanomaly-vmalert_alert-rule.webp (100%) rename docs/{ => anomaly-detection}/guides/guide-vmanomaly-vmalert_alerts-firing.webp (100%) rename docs/{ => anomaly-detection}/guides/guide-vmanomaly-vmalert_anomaly-score.webp (100%) rename docs/{ => anomaly-detection}/guides/guide-vmanomaly-vmalert_docker-compose.webp (100%) rename docs/{ => anomaly-detection}/guides/guide-vmanomaly-vmalert_files.webp (100%) rename docs/{ => anomaly-detection}/guides/guide-vmanomaly-vmalert_node-cpu-rate-graph.webp (100%) rename docs/{ => anomaly-detection}/guides/guide-vmanomaly-vmalert_yhat-lower-upper.webp (100%) rename docs/{ => anomaly-detection}/guides/guide-vmanomaly-vmalert_yhat.webp (100%) diff --git a/docs/.jekyll-metadata b/docs/.jekyll-metadata new file mode 100644 index 0000000000000000000000000000000000000000..0a179684dab0a41b6ad1fc3ad18284df7bdcfa16 GIT binary patch literal 2277159 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

mJ{Mp=@{MGehFvG!!4DN2W+(ZXpL{Fn+gvqtmX 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 X7_6ci!S|p literal 0 HcmV?d00001 diff --git a/docs/anomaly-detection/CHANGELOG.md b/docs/anomaly-detection/CHANGELOG.md new file mode 100644 index 0000000000..c59f5989d0 --- /dev/null +++ b/docs/anomaly-detection/CHANGELOG.md @@ -0,0 +1,124 @@ +--- +# sort: 4 +weight: 4 +title: CHANGELOG +menu: + docs: + identifier: "vmanomaly-changelog" + parent: "anomaly-detection" + sort: 4 + weight: 4 +aliases: +- /anomaly-detection/CHANGELOG.html +--- + +# CHANGELOG + +Please find the changelog for VictoriaMetrics Anomaly Detection below. + +The following `tip` changes can be tested by building from the `latest` tag: +```bash +docker pull us-docker.pkg.dev/victoriametrics-test/public/vmanomaly-trial:latest +``` + +Please find [launch instructions here](/vmanomaly.html#run-vmanomaly-docker-container). + +# tip + + +## v1.7.2 +Released: 2023-12-21 +- FIX: fit/infer calls are now skipped if we have insufficient *valid* data to run on. +- FIX: proper handling of `inf` and `NaN` in fit/infer calls. +- FEATURE: add counter of skipped model runs `vmanomaly_model_runs_skipped` to healthcheck metrics. +- FEATURE: add exponential retries wrapper to VmReader's `read_metrics()`. +- FEATURE: add `BacktestingScheduler` for consecutive retrospective fit/infer calls. +- FEATURE: add improved & numerically stable anomaly scores. +- IMPROVEMENT: add full config validation. The probability of getting errors in later stages (say, model fit) is greatly reduced now. All the config validation errors that needs to be fixed are now a part of logging. + > **note**: this is an backward-incompatible change, as `model` config section now expects key-value args for internal model defined in nested `args`. +- IMPROVEMENT: add explicit support of `gzip`-ed responses from vmselect in VmReader. + + +## v1.6.0 +Released: 2023-10-30 +- IMPROVEMENT: + - now all the produced healthcheck metrics have `vmanomaly_` prefix for easier accessing. + - updated docs for monitoring. + > **note**: this is an backward-incompatible change, as metric names will be changed, resulting in new metrics creation, i.e. `model_datapoints_produced` will become `vmanomaly_model_datapoints_produced` +- IMPROVEMENT: Set default value for `--log_level` from `DEBUG` to `INFO` to reduce logs verbosity. +- IMPROVEMENT: Add alias `--log-level` to `--log_level`. +- FEATURE: Added `extra_filters` parameter to reader. It allows to apply global filters to all queries. +- FEATURE: Added `verify_tls` parameter to reader and writer. It allows to disable TLS verification for remote endpoint. +- FEATURE: Added `bearer_token` parameter to reader and writer. It allows to pass bearer token for remote endpoint for authentication. +- BUGFIX: Fixed passing `workers` parameter for reader. Previously it would throw a runtime error if `workers` was specified. + +## v1.5.1 +Released: 2023-09-18 +- IMPROVEMENT: Infer from the latest seen datapoint for each query. Handles the case datapoints arrive late. + + +## v1.5.0 +Released: 2023-08-11 +- FEATURE: add `--license` and `--license-file` command-line flags for license code verification. +- IMPROVEMENT: Updated Python to 3.11.4 and updated dependencies. +- IMPROVEMENT: Guide documentation for Custom Model usage. + + +## v1.4.2 +Released: 2023-06-09 +- FIX: Fix case with received metric labels overriding generated. + + +## v1.4.1 +Released: 2023-06-09 +- IMPROVEMENT: Update dependencies. + + +## v1.4.0 +Released: 2023-05-06 +- FEATURE: Reworked self-monitoring grafana dashboard for vmanomaly. +- IMPROVEMENT: Update python version and dependencies. + + +## v1.3.0 +Released: 2023-03-21 +- FEATURE: Parallelized queries. See `reader.workers` param to control parallelism. By default it's value is equal to number of queries (sends all the queries at once). +- IMPROVEMENT: Updated self-monitoring dashboard. +- IMPROVEMENT: Reverted back default bind address for /metrics server to 0.0.0.0, as vmanomaly is distributed in Docker images. +- IMPROVEMENT: Silenced Prophet INFO logs about yearly seasonality. + +## v1.2.2 +Released: 2023-03-19 +- FIX: Fix `for` metric label to pass QUERY_KEY. +- FEATURE: Added `timeout` config param to reader, writer, monitoring.push. +- FIX: Don't hang if scheduler-model thread exits. +- FEATURE: Now reader, writer and monitoring.push will not halt the process if endpoint is inaccessible or times out, instead they will increment metrics `*_response_count{code=~"timeout|connection_error"}`. + +## v1.2.1 +Released: 2023-02-18 +- FIX: Fixed scheduler thread starting. +- FIX: Fix rolling model fit+infer. +- BREAKING CHANGE: monitoring.pull server now binds by default on 127.0.0.1 instead of 0.0.0.0. Please specify explicitly in monitoring.pull.addr what IP address it should bind to for serving /metrics. + +## v1.2.0 +Released: 2023-02-04 +- FEATURE: With arg `--watch` watches for config(s) changes and reloads the service automatically. +- IMPROVEMENT: Remove "provide_series" from HoltWinters model. Only Prophet model now has it, because it may produce a lot of series if "holidays" is on. +- IMPROVEMENT: if Prophet's "provide_series" is omitted, then all series are returned. +- DEPRECATION: Config monitoring.endpount_url is deprecated in favor of monitoring.url. +- DEPRECATION: Remove 'enable' param from config monitoring.pull. Now /metrics server is started whenever monitoring.pull is present. +- IMPROVEMENT: include example configs into the docker image at /vmanomaly/config/* +- IMPROVEMENT: include self-monitoring grafana dashboard into the docker image under /vmanomaly/dashboard/vmanomaly_grafana_dashboard.json + +## v1.1.0 +Released: 2023-01-23 +- IMPROVEMENT: update Python dependencies +- FEATURE: Add _multivariate_ IsolationForest model. + +## v1.0.1 +Released: 2023-01-06 +- FIX: prophet model incorrectly predicted two points in case of only one + +## v1.0.0-beta +Released: 2022-12-08 +- First public release is available \ No newline at end of file diff --git a/docs/anomaly-detection/FAQ.md b/docs/anomaly-detection/FAQ.md new file mode 100644 index 0000000000..a1933888fc --- /dev/null +++ b/docs/anomaly-detection/FAQ.md @@ -0,0 +1,55 @@ +--- +# sort: 3 +weight: 3 +title: FAQ +menu: + docs: + identifier: "vmanomaly-faq" + parent: "anomaly-detection" + weight: 3 + sort: 3 +aliases: +- /anomaly-detection/FAQ.html +--- + +# FAQ - VictoriaMetrics Anomaly Detection + +## What is VictoriaMetrics Anomaly Detection (vmanomaly)? +VictoriaMetrics Anomaly Detection, also known as `vmanomaly`, is a service for detecting unexpected changes in time series data. Utilizing machine learning models, it computes and pushes back an ["anomaly score"](/anomaly-detection/components/models/models.html#vmanomaly-output) for user-specified metrics. This hands-off approach to anomaly detection reduces the need for manual alert setup and can adapt to various metrics, improving your observability experience. + +Please refer to [our guide section](/anomaly-detection/#practical-guides-and-installation) to find out more. + +## How Does vmanomaly Work? +`vmanomaly` applies built-in (or custom) [anomaly detection algorithms](/anomaly-detection/components/models), specified in a config file. Although a single config file supports one model, running multiple instances of `vmanomaly` with different configs is possible and encouraged for parallel processing or better support for your use case (i.e. simpler model for simple metrics, more sophisticated one for metrics with trends and seasonalities). + +Please refer to [about](/vmanomaly.html#about) section to find out more. + +## What Data Does vmanomaly Operate On? +`vmanomaly` operates on data fetched from VictoriaMetrics, where you can leverage full power of [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html) for data selection, sampling, and processing. Users can also [apply global filters](https://docs.victoriametrics.com/#prometheus-querying-api-enhancements) for more targeted data analysis, enhancing scope limitation and tenant visibility. + +Respective config is defined in a [`reader`](/anomaly-detection/components/reader.html#vm-reader) section. + +## Handling Noisy Input Data +`vmanomaly` operates on data fetched from VictoriaMetrics using [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html) queries, so the initial data quality can be fine-tuned with aggregation, grouping, and filtering to reduce noise and improve anomaly detection accuracy. + +## Output Produced by vmanomaly +`vmanomaly` models generate [metrics](/anomaly-detection/components/models/models.html#vmanomaly-output) like `anomaly_score`, `yhat`, `yhat_lower`, `yhat_upper`, and `y`. These metrics provide a comprehensive view of the detected anomalies. The service also produces [health check metrics](/anomaly-detection/components/monitoring.html#metrics-generated-by-vmanomaly) for monitoring its performance. + +## Choosing the Right Model for vmanomaly +Selecting the best model for `vmanomaly` depends on the data's nature and the types of anomalies to detect. For instance, [Z-score](anomaly-detection/components/models/models.html#z-score) is suitable for data without trends or seasonality, while more complex patterns might require models like [Prophet](anomaly-detection/components/models/models.html#prophet). + +Please refer to [respective blogpost on anomaly types and alerting heuristics](https://victoriametrics.com/blog/victoriametrics-anomaly-detection-handbook-chapter-2/) for more details. + +Still not 100% sure what to use? We are [here to help](/anomaly-detection/#get-in-touch). + +## Alert Generation in vmanomaly +While `vmanomaly` detects anomalies and produces scores, it *does not directly generate alerts*. The anomaly scores are written back to VictoriaMetrics, where an external alerting tool, like [`vmalert`](/vmalert.html), can be used to create alerts based on these scores for integrating it with your alerting management system. + +## Preventing Alert Fatigue +Produced anomaly scores are designed in such a way that values from 0.0 to 1.0 indicate non-anomalous data, while a value greater than 1.0 is generally classified as an anomaly. However, there are no perfect models for anomaly detection, that's why reasonable defaults expressions like `anomaly_score > 1` may not work 100% of the time. However, anomaly scores, produced by `vmanomaly` are written back as metrics to VictoriaMetrics, where tools like [`vmalert`](/vmalert.html) can use [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html) expressions to fine-tune alerting thresholds and conditions, balancing between avoiding [false negatives](https://victoriametrics.com/blog/victoriametrics-anomaly-detection-handbook-chapter-1/#false-negative) and reducing [false positives](https://victoriametrics.com/blog/victoriametrics-anomaly-detection-handbook-chapter-1/#false-positive). + +## Resource Consumption of vmanomaly +`vmanomaly` itself is a lightweight service, resource usage is primarily dependent on [scheduling](/anomaly-detection/components/scheduler.html) (how often and on what data to fit/infer your models), [# and size of timeseries returned by your queries](/anomaly-detection/components/reader.html#vm-reader), and the complexity of the employed [models](anomaly-detection/components/models). Its resource usage is directly related to these factors, making it adaptable to various operational scales. + +## Scaling vmanomaly +`vmanomaly` can be scaled horizontally by launching multiple independent instances, each with its own [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html) queries and [configurations](/anomaly-detection/components/). This flexibility allows it to handle varying data volumes and throughput demands efficiently. \ No newline at end of file diff --git a/docs/anomaly-detection/README.md b/docs/anomaly-detection/README.md new file mode 100644 index 0000000000..44d3089690 --- /dev/null +++ b/docs/anomaly-detection/README.md @@ -0,0 +1,60 @@ +--- +# sort: 14 +title: VictoriaMetrics Anomaly Detection +weight: 0 +disableToc: true + +menu: + docs: + parent: 'victoriametrics' + sort: 0 + weight: 0 + +aliases: +- /anomaly-detection.html +--- + +# VictoriaMetrics Anomaly Detection + +In the dynamic and complex world of system monitoring, VictoriaMetrics Anomaly Detection, being a part of our [Enterprise offering](https://victoriametrics.com/products/enterprise/), stands as a pivotal tool for achieving advanced observability. It empowers SREs and DevOps teams by automating the intricate task of identifying abnormal behavior in time-series data. It goes beyond traditional threshold-based alerting, utilizing machine learning techniques to not only detect anomalies but also minimize false positives, thus reducing alert fatigue. By providing simplified alerting mechanisms atop of [unified anomaly scores](/anomaly-detection/components/models/models.html#vmanomaly-output), it enables teams to spot and address potential issues faster, ensuring system reliability and operational efficiency. + +## Key Components +Explore the integral components that configure VictoriaMetrics Anomaly Detection: +* [Get familiar with components](/anomaly-detection/components) + - [Models](/anomaly-detection/components/models) + - [Reader](/anomaly-detection/components/reader.html) + - [Scheduler](/anomaly-detection/components/scheduler.html) + - [Writer](/anomaly-detection/components/writer.html) + - [Monitoring](/anomaly-detection/components/monitoring.html) + +## Practical Guides and Installation +Begin your VictoriaMetrics Anomaly Detection journey with ease using our guides and installation instructions: + +- **Quick Start Guide**: Jumpstart your anomaly detection setup to simplify the process of integrating anomaly detection into your observability ecosystem. Get started [**here**](/anomaly-detection/guides/guide-vmanomaly-vmalert.html). + +- **Installation Options**: Choose the method that best fits your environment: + - **Docker Installation**: Ideal for containerized environments. Follow our [Docker guide](../vmanomaly.md#run-vmanomaly-docker-container) for a smooth setup. + - **Helm Chart Installation**: Perfect for Kubernetes users. Deploy using our [Helm charts](https://github.com/VictoriaMetrics/helm-charts/tree/master/charts/victoria-metrics-anomaly) for an efficient integration. + +> Note: starting from [v1.5.0](./CHANGELOG.md#v150) `vmanomaly` requires a [license key](/vmanomaly.html#licensing) to run. You can obtain a trial license key [**here**](https://victoriametrics.com/products/enterprise/trial/index.html). + +## Deep Dive into Anomaly Detection +Enhance your knowledge with our handbook on Anomaly Detection & Root Cause Analysis and stay updated: +* Anomaly Detection Handbook + - [Introduction to Time Series Anomaly Detection](https://victoriametrics.com/blog/victoriametrics-anomaly-detection-handbook-chapter-1/) + - [Types of Anomalies in Time Series Data](https://victoriametrics.com/blog/victoriametrics-anomaly-detection-handbook-chapter-2/) + - [Techniques and Models for Anomaly Detection](https://victoriametrics.com/blog/victoriametrics-anomaly-detection-handbook-chapter-3/) +* Follow the [`#anomaly-detection`](https://victoriametrics.com/blog/tags/anomaly-detection/) tag in our blog + +## Frequently Asked Questions (FAQ) +Got questions about VictoriaMetrics Anomaly Detection? Chances are, we've got the answers ready for you. + +Dive into [our FAQ section](/anomaly-detection/FAQ.html) to find responses to common questions. + +## Get in Touch +We're eager to connect with you and tailor our solutions to your specific needs. Here's how you can engage with us: +* [Book a Demo](https://calendly.com/fred-navruzov/) to discover what our product can do. +* Interested in exploring our [Enterprise features](https://new.victoriametrics.com/products/enterprise), including Anomaly Detection? [Request your trial license](https://new.victoriametrics.com/products/enterprise/trial/) today and take the first step towards advanced system observability. + +--- +Our [CHANGELOG is just a click away](./CHANGELOG.md), keeping you informed about the latest updates and enhancements. \ No newline at end of file diff --git a/docs/anomaly-detection/components/README.md b/docs/anomaly-detection/components/README.md new file mode 100644 index 0000000000..6e51feaf75 --- /dev/null +++ b/docs/anomaly-detection/components/README.md @@ -0,0 +1,27 @@ +--- +# sort: 1 +title: Components +weight: 0 +menu: + docs: + identifier: "vmanomaly-components" + parent: "anomaly-detection" + weight: 0 + sort: 1 +aliases: + - /anomaly-detection/components/ + - /anomaly-detection/components/index.html +--- + +# Components + +This chapter describes different components, that correspond to respective sections of a config to launch VictoriaMetrics Anomaly Detection (or simply [`vmanomaly`](/vmanomaly.html)) service: + +- [Model(s) section](models/README.md) - Required +- [Reader section](reader.html) - Required +- [Scheduler section](scheduler.html) - Required +- [Writer section](writer.html) - Required +- [Monitoring section](monitoring.html) - Optional + + +> **Note**: starting from [v1.7.0](../CHANGELOG.md#v172), once the service starts, automated config validation is performed. Please see container logs for errors that need to be fixed to create fully valid config, visiting sections above for examples and documentation. \ No newline at end of file diff --git a/docs/anomaly-detection/components/models/README.md b/docs/anomaly-detection/components/models/README.md new file mode 100644 index 0000000000..9b65f96a9c --- /dev/null +++ b/docs/anomaly-detection/components/models/README.md @@ -0,0 +1,20 @@ +--- +title: Models +weight: 1 +# sort: 1 +menu: + docs: + identifier: "vmanomaly-models" + parent: "vmanomaly-components" + weight: 1 + # sort: 1 +aliases: + - /anomaly-detection/components/models.html +--- + +# Models + +This section describes `Model` component of VictoriaMetrics Anomaly Detection (or simply [`vmanomaly`](/vmanomaly.html)) and the guide of how to define respective section of a config to launch the service. + + +Please find a guide of how to use [built-in models](/anomaly-detection/docs/models/models.html) for anomaly detection, as well as how to define and use your own [custom model](/anomaly-detection/docs/models/custom_model.html). \ No newline at end of file diff --git a/docs/anomaly-detection/components/models/custom_model.md b/docs/anomaly-detection/components/models/custom_model.md new file mode 100644 index 0000000000..de55c66594 --- /dev/null +++ b/docs/anomaly-detection/components/models/custom_model.md @@ -0,0 +1,174 @@ +--- +# sort: 2 +weight: 2 +title: Custom Model Guide +# disableToc: true +menu: + docs: + parent: "vmanomaly-models" + weight: 2 + # sort: 2 +aliases: + - /anomaly-detection/components/models/custom_model.html +--- + +# Custom Model Guide +**Note**: vmanomaly is a part of [enterprise package](https://docs.victoriametrics.com/enterprise.html). Please [contact us](https://victoriametrics.com/contact-us/) to find out more. + +Apart from vmanomaly predefined models, users can create their own custom models for anomaly detection. + +Here in this guide, we will +- Make a file containing our custom model definition +- Define VictoriaMetrics Anomaly Detection config file to use our custom model +- Run service + +**Note**: The file containing the model should be written in [Python language](https://www.python.org/) (3.11+) + +## 1. Custom model +We'll create `custom_model.py` file with `CustomModel` class that will inherit from vmanomaly `Model` base class. +In the `CustomModel` class there should be three required methods - `__init__`, `fit` and `infer`: +* `__init__` method should initiate parameters for the model. + + **Note**: if your model relies on configs that have `arg` [key-value pair argument](./models.md#section-overview), do not forget to use Python's `**kwargs` in method's signature and to explicitly call + ```python + super().__init__(**kwargs) + ``` + to initialize the base class each model derives from +* `fit` method should contain the model training process. +* `infer` should return Pandas.DataFrame object with model's inferences. + +For the sake of simplicity, the model in this example will return one of two values of `anomaly_score` - 0 or 1 depending on input parameter `percentage`. + +

+ + +## 2. Configuration file +Next, we need to create `config.yaml` file with VM Anomaly Detection configuration and model input parameters. +In the config file `model` section we need to put our model class `model.custom.CustomModel` and all parameters used in `__init__` method. +You can find out more about configuration parameters in vmanomaly docs. + +
+ +```yaml +scheduler: + infer_every: "1m" + fit_every: "1m" + fit_window: "1d" + +model: + # note: every custom model should implement this exact path, specified in `class` field + class: "model.model.CustomModel" + # custom model params are defined here + percentage: 0.9 + +reader: + datasource_url: "http://localhost:8428/" + queries: + ingestion_rate: 'sum(rate(vm_rows_inserted_total)) by (type)' + churn_rate: 'sum(rate(vm_new_timeseries_created_total[5m]))' + +writer: + datasource_url: "http://localhost:8428/" + metric_format: + __name__: "custom_$VAR" + for: "$QUERY_KEY" + model: "custom" + run: "test-format" + +monitoring: + # /metrics server. + pull: + port: 8080 + push: + url: "http://localhost:8428/" + extra_labels: + job: "vmanomaly-develop" + config: "custom.yaml" +``` + +
+ +## 3. Running model +Let's pull the docker image for vmanomaly: + +
+ +```sh +docker pull us-docker.pkg.dev/victoriametrics-test/public/vmanomaly-trial:latest +``` + +
+ +Now we can run the docker container putting as volumes both config and model file: + +**Note**: place the model file to `/model/custom.py` path when copying +
+ +```sh +docker run -it \ +--net [YOUR_NETWORK] \ +-v [YOUR_LICENSE_FILE_PATH]:/license.txt \ +-v $(PWD)/custom_model.py:/vmanomaly/src/model/custom.py \ +-v $(PWD)/custom.yaml:/config.yaml \ +us-docker.pkg.dev/victoriametrics-test/public/vmanomaly-trial:latest /config.yaml \ +--license-file=/license.txt +``` +
+ +Please find more detailed instructions (license, etc.) [here](/vmanomaly.html#run-vmanomaly-docker-container) + + +## Output +As the result, this model will return metric with labels, configured previously in `config.yaml`. +In this particular example, 2 metrics will be produced. Also, there will be added other metrics from input query result. + +``` +{__name__="custom_anomaly_score", for="ingestion_rate", model="custom", run="test-format"} + +{__name__="custom_anomaly_score", for="churn_rate", model="custom", run="test-format"} +``` diff --git a/docs/anomaly-detection/components/models/models.md b/docs/anomaly-detection/components/models/models.md new file mode 100644 index 0000000000..797fb8c735 --- /dev/null +++ b/docs/anomaly-detection/components/models/models.md @@ -0,0 +1,323 @@ +--- +# sort: 1 +weight: 1 +title: Built-in Models +# disableToc: true +menu: + docs: + parent: "vmanomaly-models" + # sort: 1 + weight: 1 +aliases: + - /anomaly-detection/components/models/models.html +--- + +# Models config parameters + +## Section Overview +VM Anomaly Detection (`vmanomaly` hereinafter) models support 2 groups of parameters: + +- **`vmanomaly`-specific** arguments - please refer to *Parameters specific for vmanomaly* and *Default model parameters* subsections for each of the models below. +- Arguments to **inner model** (say, [Facebook's Prophet](https://facebook.github.io/prophet/docs/quick_start.html#python-api)), passed in a `args` argument as key-value pairs, that will be directly given to the model during initialization to allow granular control. Optional. + +**Note**: For users who may not be familiar with Python data types such as `list[dict]`, a [dictionary](https://www.w3schools.com/python/python_dictionaries.asp) in Python is a data structure that stores data values in key-value pairs. This structure allows for efficient data retrieval and management. + + +**Models**: +* [ARIMA](#arima) +* [Holt-Winters](#holt-winters) +* [Prophet](#prophet) +* [Rolling Quantile](#rolling-quantile) +* [Seasonal Trend Decomposition](#seasonal-trend-decomposition) +* [Z-score](#z-score) +* [MAD (Median Absolute Deviation)](#mad-median-absolute-deviation) +* [Isolation forest (Multivariate)](#isolation-forest-multivariate) +* [Custom model](#custom-model) + +--- +## [ARIMA](https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average) +Here we use ARIMA implementation from `statsmodels` [library](https://www.statsmodels.org/dev/generated/statsmodels.tsa.arima.model.ARIMA.html) + +*Parameters specific for vmanomaly*: + +\* - mandatory parameters. +* `class`\* (string) - model class name `"model.arima.ArimaModel"` + +* `z_threshold` (float) - [standard score](https://en.wikipedia.org/wiki/Standard_score) for calculating boundaries to define anomaly score. Defaults to 2.5. + +* `provide_series` (list[string]) - List of columns to be produced and returned by the model. Defaults to `["anomaly_score", "yhat", "yhat_lower" "yhat_upper", "y"]`. Output can be **only a subset** of a given column list. + +* `resample_freq` (string) = Frequency to resample input data into, e.g. data comes at 15 seconds resolution, and resample_freq is '1m'. Then fitting data will be downsampled to '1m' and internal model is trained at '1m' intervals. So, during inference, prediction data would be produced at '1m' intervals, but interpolated to "15s" to match with expected output, as output data must have the same timestamps. + +*Default model parameters*: + +* `order`\* (list[int]) - ARIMA's (p,d,q) order of the model for the autoregressive, differences, and moving average components, respectively. + +* `args`: (dict) - Inner model args (key-value pairs). See accepted params in [model documentation](https://www.statsmodels.org/dev/generated/statsmodels.tsa.arima.model.ARIMA.html). Defaults to empty (not provided). Example: {"trend": "c"} + +*Config Example* +
+ +```yaml +model: + class: "model.arima.ArimaModel" + # ARIMA's (p,d,q) order + order: + - 1 + - 1 + - 0 + z_threshold: 2.7 + resample_freq: '1m' + # Inner model args (key-value pairs) accepted by statsmodels.tsa.arima.model.ARIMA + args: + trend: 'c' +``` +
+ +--- +## [Holt-Winters](https://en.wikipedia.org/wiki/Exponential_smoothing) +Here we use Holt-Winters Exponential Smoothing implementation from `statsmodels` [library](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing.html). All parameters from this library can be passed to the model. + +*Parameters specific for vmanomaly*: + +\* - mandatory parameters. +* `class`\* (string) - model class name `"model.holtwinters.HoltWinters"` + +* `frequency`\* (string) - Must be set equal to sampling_period. Model needs to know expected data-points frequency (e.g. '10m'). +If omitted, frequency is guessed during fitting as **the median of intervals between fitting data timestamps**. During inference, if incoming data doesn't have the same frequency, then it will be interpolated. + +E.g. data comes at 15 seconds resolution, and our resample_freq is '1m'. Then fitting data will be downsampled to '1m' and internal model is trained at '1m' intervals. So, during inference, prediction data would be produced at '1m' intervals, but interpolated to "15s" to match with expected output, as output data must have the same timestamps. + +As accepted by pandas.Timedelta (e.g. '5m'). + +* `seasonality` (string) - As accepted by pandas.Timedelta. +If `seasonal_periods` is not specified, it is calculated as `seasonality` / `frequency` +Used to compute "seasonal_periods" param for the model (e.g. '1D' or '1W'). + +* `z_threshold` (float) - [standard score](https://en.wikipedia.org/wiki/Standard_score) for calculating boundaries to define anomaly score. Defaults to 2.5. + + +*Default model parameters*: + +* If [parameter](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing.html#statsmodels.tsa.holtwinters.ExponentialSmoothing-parameters) `seasonal` is not specified, default value will be `add`. + +* If [parameter](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing.html#statsmodels.tsa.holtwinters.ExponentialSmoothing-parameters) `initialization_method` is not specified, default value will be `estimated`. + +* `args`: (dict) - Inner model args (key-value pairs). See accepted params in [model documentation](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing.html#statsmodels.tsa.holtwinters.ExponentialSmoothing-parameters). Defaults to empty (not provided). Example: {"seasonal": "add", "initialization_method": "estimated"} + +*Config Example* +
+ +```yaml +model: + class: "model.holtwinters.HoltWinters" + seasonality: '1d' + frequency: '1h' + # Inner model args (key-value pairs) accepted by statsmodels.tsa.holtwinters.ExponentialSmoothing + args: + seasonal: 'add' + initialization_method: 'estimated' +``` +
+ +Resulting metrics of the model are described [here](#vmanomaly-output). + +--- +## [Prophet](https://facebook.github.io/prophet/) +Here we utilize the Facebook Prophet implementation, as detailed in their [library documentation](https://facebook.github.io/prophet/docs/quick_start.html#python-api). All parameters from this library are compatible and can be passed to the model. + +*Parameters specific for vmanomaly*: + +\* - mandatory parameters. +* `class`\* (string) - model class name `"model.prophet.ProphetModel"` +* `seasonalities` (list[dict]) - Extra seasonalities to pass to Prophet. See [`add_seasonality()`](https://facebook.github.io/prophet/docs/seasonality,_holiday_effects,_and_regressors.html#modeling-holidays-and-special-events:~:text=modeling%20the%20cycle-,Specifying,-Custom%20Seasonalities) Prophet param. +* `provide_series` - model resulting metrics. If not specified [standard metrics](#vmanomaly-output) will be provided. + +**Note**: Apart from standard vmanomaly output Prophet model can provide [additional metrics](#additional-output-metrics-produced-by-fb-prophet). + +**Additional output metrics produced by FB Prophet** +Depending on chosen `seasonality` parameter FB Prophet can return additional metrics such as: +- `trend`, `trend_lower`, `trend_upper` +- `additive_terms`, `additive_terms_lower`, `additive_terms_upper`, +- `multiplicative_terms`, `multiplicative_terms_lower`, `multiplicative_terms_upper`, +- `daily`, `daily_lower`, `daily_upper`, +- `hourly`, `hourly_lower`, `hourly_upper`, +- `holidays`, `holidays_lower`, `holidays_upper`, +- and a number of columns for each holiday if `holidays` param is set + +*Config Example* +
+ +```yaml +model: + class: "model.prophet.ProphetModel" + seasonalities: + - name: 'hourly' + period: 0.04166666666 + fourier_order: 30 + # Inner model args (key-value pairs) accepted by + # https://facebook.github.io/prophet/docs/quick_start.html#python-api + args: + # See https://facebook.github.io/prophet/docs/uncertainty_intervals.html + interval_width: 0.98 + country_holidays: 'US' +``` +
+ +Resulting metrics of the model are described [here](#vmanomaly-output) + +--- +## [Rolling Quantile](https://en.wikipedia.org/wiki/Quantile) + +*Parameters specific for vmanomaly*: + +\* - mandatory parameters. + +* `class`\* (string) - model class name `"model.rolling_quantile.RollingQuantileModel"` +* `quantile`\* (float) - quantile value, from 0.5 to 1.0. This constraint is implied by 2-sided confidence interval. +* `window_steps`\* (integer) - size of the moving window. (see 'sampling_period') + +*Config Example* +
+ +```yaml +model: + class: "model.rolling_quantile.RollingQuantileModel" + quantile: 0.9 + window_steps: 96 +``` +
+ +Resulting metrics of the model are described [here](#vmanomaly-output). + +--- +## [Seasonal Trend Decomposition](https://en.wikipedia.org/wiki/Seasonal_adjustment) +Here we use Seasonal Decompose implementation from `statsmodels` [library](https://www.statsmodels.org/dev/generated/statsmodels.tsa.seasonal.seasonal_decompose.html). Parameters from this library can be passed to the model. Some parameters are specifically predefined in vmanomaly and can't be changed by user(`model`='additive', `two_sided`=False). + +*Parameters specific for vmanomaly*: + +\* - mandatory parameters. +* `class`\* (string) - model class name `"model.std.StdModel"` +* `period`\* (integer) - Number of datapoints in one season. +* `z_threshold` (float) - [standard score](https://en.wikipedia.org/wiki/Standard_score) for calculating boundaries to define anomaly score. Defaults to 2.5. + + +*Config Example* +
+ +```yaml +model: + class: "model.std.StdModel" + period: 2 +``` +
+ +Resulting metrics of the model are described [here](#vmanomaly-output). + +**Additional output metrics produced by Seasonal Trend Decomposition model** +* `resid` - The residual component of the data series. +* `trend` - The trend component of the data series. +* `seasonal` - The seasonal component of the data series. + +--- +## [MAD (Median Absolute Deviation)](https://en.wikipedia.org/wiki/Median_absolute_deviation) +The MAD model is a robust method for anomaly detection that is *less sensitive* to outliers in data compared to standard deviation-based models. It considers a point as an anomaly if the absolute deviation from the median is significantly large. + +*Parameters specific for vmanomaly*: + +\* - mandatory parameters. +* `class`\* (string) - model class name `"model.mad.MADModel"` +* `threshold` (float) - The threshold multiplier for the MAD to determine anomalies. Defaults to 2.5. Higher values will identify fewer points as anomalies. + +*Config Example* +
+ +```yaml +model: + class: "model.mad.MADModel" + threshold: 2.5 +``` +Resulting metrics of the model are described [here](#vmanomaly-output). + +--- +## [Z-score](https://en.wikipedia.org/wiki/Standard_score) +*Parameters specific for vmanomaly*: +\* - mandatory parameters. +* `class`\* (string) - model class name `"model.zscore.ZscoreModel"` +* `z_threshold` (float) - [standard score](https://en.wikipedia.org/wiki/Standard_score) for calculation boundaries and anomaly score. Defaults to 2.5. + +*Config Example* +
+ +```yaml +model: + class: "model.zscore.ZscoreModel" + z_threshold: 2.5 +``` +
+ +Resulting metrics of the model are described [here](#vmanomaly-output). + +## [Isolation forest](https://en.wikipedia.org/wiki/Isolation_forest) (Multivariate) +Detects anomalies using binary trees. The algorithm has a linear time complexity and a low memory requirement, which works well with high-volume data. It can be used on both univatiate and multivariate data, but it is more effective in multivariate case. + +**Important**: Be aware of [the curse of dimensionality](https://en.wikipedia.org/wiki/Curse_of_dimensionality). Don't use single multivariate model if you expect your queries to return many time series of less datapoints that the number of metrics. In such case it is hard for a model to learn meaningful dependencies from too sparse data hypercube. + +Here we use Isolation Forest implementation from `scikit-learn` [library](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html). All parameters from this library can be passed to the model. + +*Parameters specific for vmanomaly*: + +\* - mandatory parameters. +* `class`\* (string) - model class name `"model.isolation_forest.IsolationForestMultivariateModel"` + +* `contamination` - The amount of contamination of the data set, i.e. the proportion of outliers in the data set. Used when fitting to define the threshold on the scores of the samples. Default value - "auto". Should be either `"auto"` or be in the range (0.0, 0.5]. + +* `args`: (dict) - Inner model args (key-value pairs). See accepted params in [model documentation](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html). Defaults to empty (not provided). Example: {"random_state": 42, "n_estimators": 100} + +*Config Example* +
+ +```yaml +model: + # To use univariate model, substitute class argument with "model.isolation_forest.IsolationForestModel". + class: "model.isolation_forest.IsolationForestMultivariateModel" + contamination: "auto" + args: + n_estimators: 100 + # i.e. to assure reproducibility of produced results each time model is fit on the same input + random_state: 42 +``` +
+ +Resulting metrics of the model are described [here](#vmanomaly-output). + +--- +## Custom model +You can find a guide on setting up a custom model [here](./custom_model.md). + +## vmanomaly output + +When vmanomaly is executed, it generates various metrics, the specifics of which depend on the model employed. +These metrics can be renamed in the writer's section. + +The default metrics produced by vmanomaly include: + +- `anomaly_score`: This is the *primary* metric. + - It is designed in such a way that values from 0.0 to 1.0 indicate non-anomalous data. + - A value greater than 1.0 is generally classified as an anomaly, although this threshold can be adjusted in the alerting configuration. + - The decision to set the changepoint at 1 was made to ensure consistency across various models and alerting configurations, such that a score above 1 consistently signifies an anomaly. + +- `yhat`: This represents the predicted expected value. + +- `yhat_lower`: This indicates the predicted lower boundary. + +- `yhat_upper`: This refers to the predicted upper boundary. + +- `y`: This is the original value obtained from the query result. + +**Important**: Be aware that if `NaN` (Not a Number) or `Inf` (Infinity) values are present in the input data during `infer` model calls, the model will produce `NaN` as the `anomaly_score` for these particular instances. + + +## Healthcheck metrics + +Each model exposes [several healthchecks metrics](./../monitoring.html#models-behaviour-metrics) to its `health_path` endpoint: \ No newline at end of file diff --git a/docs/anomaly-detection/components/monitoring.md b/docs/anomaly-detection/components/monitoring.md new file mode 100644 index 0000000000..546d6ecb15 --- /dev/null +++ b/docs/anomaly-detection/components/monitoring.md @@ -0,0 +1,297 @@ +--- +# sort: 5 +title: Monitoring +weight: 5 +menu: + docs: + parent: "vmanomaly-components" + weight: 5 + # sort: 5 +aliases: + - /anomaly-detection/components/monitoring.html +--- + +# Monitoring + +There are 2 models to monitor VictoriaMetrics Anomaly Detection behavior - [push](https://docs.victoriametrics.com/keyConcepts.html#push-model) and [pull](https://docs.victoriametrics.com/keyConcepts.html#pull-model). Parameters for each of them should be specified in the config file, `monitoring` section. + +## Pull Model Config parameters + + + + + + + + + + + + + + + + + + + + + +
ParameterDefaultDescription
addr"0.0.0.0"Server IP Address
port8080Port
+ +## Push Config parameters + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDefaultDescription
urlLink where to push metrics to. Example: "http://localhost:8480/"
tenant_idTenant ID for cluster version. Example: "0:0"
health_path"health"Absolute, to override /health path
userBasicAuth username
passwordBasicAuth password
timeout"5s"Stop waiting for a response after a given number of seconds.
extra_labelsSection for custom labels specified by user.
+ +## Monitoring section config example + +
+ +``` yaml +monitoring: + pull: # Enable /metrics endpoint. + addr: "0.0.0.0" + port: 8080 + push: + url: "http://localhost:8480/" + tenant_id: "0:0" # For cluster version only + health_path: "health" + user: "USERNAME" + password: "PASSWORD" + timeout: "5s" + extra_labels: + job: "vmanomaly-push" + test: "test-1" +``` +
+ +## Metrics generated by vmanomaly + + + + + + + + + + + + + + + + +
MetricTypeDescription
vmanomaly_start_time_secondsGaugevmanomaly start time in UNIX time
+ +### Models Behaviour Metrics +Label names [description](#labelnames) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MetricTypeDescriptionLabelnames
vmanomaly_model_runsCounterHow many times models ran (per model)stage, query_key
vmanomaly_model_run_duration_secondsSummaryHow much time (in seconds) model invocations tookstage, query_key
vmanomaly_model_datapoints_acceptedCounterHow many datapoints did models acceptstage, query_key
vmanomaly_model_datapoints_producedCounterHow many datapoints were generated by modelsstage, query_key
vmanomaly_models_activeGaugeHow many models are currently inferringquery_key
vmanomaly_model_runs_skippedCounterHow many times a run was skipped (per model)stage, query_key
+ +### Writer Behaviour Metrics +Label names [description](#labelnames) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MetricTypeDescriptionLabelnames
vmanomaly_writer_request_duration_secondsSummaryHow much time (in seconds) did requests to VictoriaMetrics takeurl, query_key
vmanomaly_writer_response_countCounterResponse code counts we got from VictoriaMetricsurl, query_key, code
vmanomaly_writer_sent_bytesCounterHow much bytes were sent to VictoriaMetricsurl, query_key
vmanomaly_writer_request_serialize_secondsSummaryHow much time (in seconds) did serializing takequery_key
vmanomaly_writer_datapoints_sentCounterHow many datapoints were sent to VictoriaMetricsquery_key
vmanomaly_writer_timeseries_sentCounterHow many timeseries were sent to VictoriaMetricsquery_key
+ +### Reader Behaviour Metrics +Label names [description](#labelnames) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MetricTypeDescriptionLabelnames
vmanomaly_reader_request_duration_secondsSummaryHow much time (in seconds) did queries to VictoriaMetrics takeurl, query_key
vmanomaly_reader_response_countCounterResponse code counts we got from VictoriaMetricsurl, query_key, code
vmanomaly_reader_received_bytesCounterHow much bytes were received in responsesquery_key
vmanomaly_reader_response_parsing_secondsSummaryHow much time (in seconds) did parsing take for each stepstep
vmanomaly_reader_timeseries_receivedCounterHow many timeseries were received from VictoriaMetricsquery_key
vmanomaly_reader_datapoints_receivedCounterHow many rows were received from VictoriaMetricsquery_key
+ +### Labelnames +stage - stage of model - 'fit', 'infer' or 'fit_infer' for models that do it simultaneously. + +query_key - query alias from [`reader`](/anomaly-detection/components/reader.html) config section. + +url - writer or reader url endpoint. + +code - response status code or `connection_error`, `timeout`. + +step - json or dataframe reading step. \ No newline at end of file diff --git a/docs/anomaly-detection/components/reader.md b/docs/anomaly-detection/components/reader.md new file mode 100644 index 0000000000..1ce4ab4670 --- /dev/null +++ b/docs/anomaly-detection/components/reader.md @@ -0,0 +1,262 @@ +--- +# sort: 2 +title: Reader +weight: 2 +menu: + docs: + parent: "vmanomaly-components" + # sort: 2 + weight: 2 +aliases: + - /anomaly-detection/components/reader.html +--- + +# Reader + + + +VictoriaMetrics Anomaly Detection (`vmanomaly`) primarily uses [VmReader](#vm-reader) to ingest data. This reader focuses on fetching time-series data directly from VictoriaMetrics with the help of powerful [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html) expressions for aggregating, filtering and grouping your data, ensuring seamless integration and efficient data handling. + +Future updates will introduce additional readers, expanding the range of data sources `vmanomaly` can work with. + + +## VM reader + +### Config parameters + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterExampleDescription
class"reader.vm.VmReader"Name of the class needed to enable reading from VictoriaMetrics or Prometheus. VmReader is the default option, if not specified.
queries"ingestion_rate: 'sum(rate(vm_rows_inserted_total[5m])) by (type) > 0'"PromQL/MetricsQL query to select data in format: QUERY_ALIAS: "QUERY". As accepted by "/query_range?query=%s".
datasource_url"http://localhost:8481/"Datasource URL address
tenant_id"0:0"For cluster version only, tenants are identified by accountID or accountID:projectID
sampling_period"1h"Optional. Frequency of the points returned. Will be converted to "/query_range?step=%s" param (in seconds).
query_range_path"api/v1/query_range"Performs PromQL/MetricsQL range query. Default "api/v1/query_range"
health_path"health"Absolute or relative URL address where to check availability of the datasource. Default is "health".
user"USERNAME"BasicAuth username
password"PASSWORD"BasicAuth password
timeout"30s"Timeout for the requests, passed as a string. Defaults to "30s"
verify_tls"false"Allows disabling TLS verification of the remote certificate.
bearer_token"token"Token is passed in the standard format with header: "Authorization: bearer {token}"
extra_filters"[]"List of strings with series selector. See: Prometheus querying API enhancements
+ +Config file example: + +```yaml +reader: + class: "reader.vm.VmReader" + datasource_url: "http://localhost:8428/" + tenant_id: "0:0" + queries: + ingestion_rate: 'sum(rate(vm_rows_inserted_total[5m])) by (type) > 0' + sampling_period: '1m' +``` + +### Healthcheck metrics + +`VmReader` exposes [several healthchecks metrics](./monitoring.html#reader-behaviour-metrics). + + \ No newline at end of file diff --git a/docs/anomaly-detection/components/scheduler.md b/docs/anomaly-detection/components/scheduler.md new file mode 100644 index 0000000000..a737f29603 --- /dev/null +++ b/docs/anomaly-detection/components/scheduler.md @@ -0,0 +1,354 @@ +--- +# sort: 3 +title: Scheduler +weight: 3 +menu: + docs: + parent: "vmanomaly-components" + weight: 3 + # sort: 3 +aliases: + - /anomaly-detection/components/scheduler.html +--- + +# Scheduler + +Scheduler defines how often to run and make inferences, as well as what timerange to use to train the model. +Is specified in `scheduler` section of a config for VictoriaMetrics Anomaly Detection. + +## Parameters + +`class`: str, default=`"scheduler.periodic.PeriodicScheduler"`, +options={`"scheduler.periodic.PeriodicScheduler"`, `"scheduler.oneoff.OneoffScheduler"`, `"scheduler.backtesting.BacktestingScheduler"`} + +- `"scheduler.periodic.PeriodicScheduler"`: periodically runs the models on new data. Useful for consecutive re-trainings to counter [data drift](https://www.datacamp.com/tutorial/understanding-data-drift-model-drift) and model degradation over time. +- `"scheduler.oneoff.OneoffScheduler"`: runs the process once and exits. Useful for testing. +- `"scheduler.backtesting.BacktestingScheduler"`: imitates consecutive backtesting runs of OneoffScheduler. Runs the process once and exits. Use to get more granular control over testing on historical data. + +**Depending on selected class, different parameters should be used** + +## Periodic scheduler + +### Parameters + +For periodic scheduler parameters are defined as differences in times, expressed in difference units, e.g. days, hours, minutes, seconds. + +Examples: `"50s"`, `"4m"`, `"3h"`, `"2d"`, `"1w"`. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Time granularity
sseconds
mminutes
hhours
ddays
wweeks
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeExampleDescription
fit_windowstr"14d"What time range to use for training the models. Must be at least 1 second.
infer_everystr"1m"How often a model will write its conclusions on newly added data. Must be at least 1 second.
fit_everystr, Optional"1h"How often to completely retrain the models. If missing value of infer_every is used and retrain on every inference run.
+ +### Periodic scheduler config example + +```yaml +scheduler: + class: "scheduler.periodic.PeriodicScheduler" + fit_window: "14d" + infer_every: "1m" + fit_every: "1h" +``` + +This part of the config means that `vmanomaly` will calculate the time window of the previous 14 days and use it to train a model. Every hour model will be retrained again on 14 days’ data, which will include + 1 hour of new data. The time window is strictly the same 14 days and doesn't extend for the next retrains. Every minute `vmanomaly` will produce model inferences for newly added data points by using the model that is kept in memory at that time. + +## Oneoff scheduler + +### Parameters +For Oneoff scheduler timeframes can be defined in Unix time in seconds or ISO 8601 string format. +ISO format supported time zone offset formats are: +* Z (UTC) +* ±HH:MM +* ±HHMM +* ±HH + +If a time zone is omitted, a timezone-naive datetime is used. + +### Defining fitting timeframe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatParameterTypeExampleDescription
ISO 8601fit_start_isostr"2022-04-01T00:00:00Z", "2022-04-01T00:00:00+01:00", "2022-04-01T00:00:00+0100", "2022-04-01T00:00:00+01"Start datetime to use for training a model. ISO string or UNIX time in seconds.
UNIX timefit_start_sfloat1648771200
ISO 8601fit_end_isostr"2022-04-10T00:00:00Z", "2022-04-10T00:00:00+01:00", "2022-04-10T00:00:00+0100", "2022-04-10T00:00:00+01"End datetime to use for training a model. Must be greater than fit_start_*. ISO string or UNIX time in seconds.
UNIX timefit_end_sfloat1649548800
+ +### Defining inference timeframe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatParameterTypeExampleDescription
ISO 8601infer_start_isostr"2022-04-11T00:00:00Z", "2022-04-11T00:00:00+01:00", "2022-04-11T00:00:00+0100", "2022-04-11T00:00:00+01"Start datetime to use for a model inference. ISO string or UNIX time in seconds.
UNIX timeinfer_start_sfloat1649635200
ISO 8601infer_end_isostr"2022-04-14T00:00:00Z", "2022-04-14T00:00:00+01:00", "2022-04-14T00:00:00+0100", "2022-04-14T00:00:00+01"End datetime to use for a model inference. Must be greater than infer_start_*. ISO string or UNIX time in seconds.
UNIX timeinfer_end_sfloat1649894400
+ +### ISO format scheduler config example +```yaml +scheduler: + class: "scheduler.oneoff.OneoffScheduler" + fit_start_iso: "2022-04-01T00:00:00Z" + fit_end_iso: "2022-04-10T00:00:00Z" + infer_start_iso: "2022-04-11T00:00:00Z" + infer_end_iso: "2022-04-14T00:00:00Z" +``` + + +### UNIX time format scheduler config example +```yaml +scheduler: + class: "scheduler.oneoff.OneoffScheduler" + fit_start_iso: 1648771200 + fit_end_iso: 1649548800 + infer_start_iso: 1649635200 + infer_end_iso: 1649894400 +``` + +## Backtesting scheduler + +### Parameters +As for [Oneoff scheduler](#oneoff-scheduler), timeframes can be defined in Unix time in seconds or ISO 8601 string format. +ISO format supported time zone offset formats are: +* Z (UTC) +* ±HH:MM +* ±HHMM +* ±HH + +If a time zone is omitted, a timezone-naive datetime is used. + +### Defining overall timeframe + +This timeframe will be used for slicing on intervals `(fit_window, infer_window == fit_every)`, starting from the *latest available* time point, which is `to_*` and going back, until no full `fit_window + infer_window` interval exists within the provided timeframe. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatParameterTypeExampleDescription
ISO 8601from_isostr"2022-04-01T00:00:00Z", "2022-04-01T00:00:00+01:00", "2022-04-01T00:00:00+0100", "2022-04-01T00:00:00+01"Start datetime to use for backtesting.
UNIX timefrom_sfloat1648771200
ISO 8601to_isostr"2022-04-10T00:00:00Z", "2022-04-10T00:00:00+01:00", "2022-04-10T00:00:00+0100", "2022-04-10T00:00:00+01"End datetime to use for backtesting. Must be greater than from_start_*.
UNIX timeto_sfloat1649548800
+ +### Defining training timeframe +The same *explicit* logic as in [Periodic scheduler](#periodic-scheduler) + + + + + + + + + + + + + + + + + + + + + + + +
FormatParameterTypeExampleDescription
ISO 8601fit_windowstr"PT1M", "P1H"What time range to use for training the models. Must be at least 1 second.
Prometheus-compatible"1m", "1h"
+ +### Defining inference timeframe +In `BacktestingScheduler`, the inference window is *implicitly* defined as a period between 2 consecutive model `fit_every` runs. The *latest* inference window starts from `to_s` - `fit_every` and ends on the *latest available* time point, which is `to_s`. The previous periods for fit/infer are defined the same way, by shifting `fit_every` seconds backwards until we get the last full fit period of `fit_window` size, which start is >= `from_s`. + + + + + + + + + + + + + + + + + + + + + + + +
FormatParameterTypeExampleDescription
ISO 8601fit_everystr"PT1M", "P1H"What time range to use previously trained model to infer on new data until next retrain happens.
Prometheus-compatible"1m", "1h"
+ +### ISO format scheduler config example +```yaml +scheduler: + class: "scheduler.backtesting.BacktestingScheduler" + from_start_iso: '2021-01-01T00:00:00Z' + to_end_iso: '2021-01-14T00:00:00Z' + fit_window: 'P14D' + fit_every: 'PT1H' +``` + +### UNIX time format scheduler config example +```yaml +scheduler: + class: "scheduler.backtesting.BacktestingScheduler" + from_start_s: 167253120 + to_end_s: 167443200 + fit_window: '14d' + fit_every: '1h' +``` \ No newline at end of file diff --git a/docs/anomaly-detection/components/writer.md b/docs/anomaly-detection/components/writer.md new file mode 100644 index 0000000000..c5300677cc --- /dev/null +++ b/docs/anomaly-detection/components/writer.md @@ -0,0 +1,270 @@ +--- +# sort: 4 +title: Writer +weight: 4 +menu: + docs: + parent: "vmanomaly-components" + weight: 4 + # sort: 4 +aliases: + - /anomaly-detection/components/writer.html +--- + +# Writer + + +For exporting data, VictoriaMetrics Anomaly Detection (`vmanomaly`) primarily employs the [VmWriter](#vm-writer), which writes produces anomaly scores (preserving initial labelset and optionally applying additional ones) back to VictoriaMetrics. This writer is tailored for smooth data export within the VictoriaMetrics ecosystem. + +Future updates will introduce additional export methods, offering users more flexibility in data handling and integration. + +## VM writer + +### Config parameters + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterExampleDescription
class"writer.vm.VmWriter"Name of the class needed to enable writing to VictoriaMetrics or Prometheus. VmWriter is the default option, if not specified.
datasource_url"http://localhost:8481/"Datasource URL address
tenant_id"0:0"For cluster version only, tenants are identified by accountID or accountID:projectID
metric_format__name__: "vmanomaly_$VAR"Metrics to save the output (in metric names or labels). Must have __name__ key. Must have a value with $VAR placeholder in it to distinguish between resulting metrics. Supported placeholders: +
    +
  • $VAR -- Variables that model provides, all models provide the following set: {"anomaly_score", "y", "yhat", "yhat_lower", "yhat_upper"}. Description of standard output is here. Depending on model type it can provide more metrics, like "trend", "seasonality" etc.
  • +
  • $QUERY_KEY -- E.g. "ingestion_rate".
  • +
+ Other keys are supposed to be configured by the user to help identify generated metrics, e.g., specific config file name etc. + More details on metric formatting are here. +
for: "$QUERY_KEY"
run: "test_metric_format"
config: "io_vm_single.yaml"
import_json_path"/api/v1/import"Optional, to override the default import path
health_path"health"Absolute or relative URL address where to check the availability of the datasource. Optional, to override the default "/health" path.
user"USERNAME"BasicAuth username
password"PASSWORD"BasicAuth password
timeout"5s"Timeout for the requests, passed as a string. Defaults to "5s"
verify_tls"false"Allows disabling TLS verification of the remote certificate.
bearer_token"token"Token is passed in the standard format with the header: "Authorization: bearer {token}"
+ +Config example: +```yaml +writer: + class: "writer.vm.VmWriter" + datasource_url: "http://localhost:8428/" + tenant_id: "0:0" + metric_format: + __name__: "vmanomaly_$VAR" + for: "$QUERY_KEY" + run: "test_metric_format" + config: "io_vm_single.yaml" + import_json_path: "/api/v1/import" + health_path: "health" + user: "foo" + password: "bar" +``` + +### Healthcheck metrics + +`VmWriter` exposes [several healthchecks metrics](./monitoring.html#writer-behaviour-metrics). + +### Metrics formatting +There should be 2 mandatory parameters set in `metric_format` - `__name__` and `for`. +```yaml +__name__: PREFIX1_$VAR +for: PREFIX2_$QUERY_KEY +``` +* for `__name__` parameter it will name metrics returned by models as `PREFIX1_anomaly_score`, `PREFIX1_yhat_lower`, etc. Vmanomaly output metrics names described [here](anomaly-detection/components/models/models.html#vmanomaly-output) + +* for `for` parameter will add labels `PREFIX2_query_name_1`, `PREFIX2_query_name_2`, etc. Query names are set as aliases in config `reader` section in [`queries`](anomaly-detection/components/reader.html#config-parameters) parameter. + +It is possible to specify other custom label names needed. +For example: +```yaml +custom_label_1: label_name_1 +custom_label_2: label_name_2 +``` + +Apart from specified labels, output metrics will return labels inherited from input metrics returned by [queries](/anomaly-detection/components/reader.html#config-parameters). +For example if input data contains labels such as `cpu=1, device=eth0, instance=node-exporter:9100` all these labels will be present in vmanomaly output metrics. + +So if metric_format section was set up like this: +```yaml +metric_format: + __name__: "PREFIX1_$VAR" + for: "PREFIX2_$QUERY_KEY" + custom_label_1: label_name_1 + custom_label_2: label_name_2 +``` + +It will return metrics that will look like: +```yaml +{__name__="PREFIX1_anomaly_score", for="PREFIX2_query_name_1", custom_label_1="label_name_1", custom_label_2="label_name_2", cpu=1, device="eth0", instance="node-exporter:9100"} +{__name__="PREFIX1_yhat_lower", for="PREFIX2_query_name_1", custom_label_1="label_name_1", custom_label_2="label_name_2", cpu=1, device="eth0", instance="node-exporter:9100"} +{__name__="PREFIX1_anomaly_score", for="PREFIX2_query_name_2", custom_label_1="label_name_1", custom_label_2="label_name_2", cpu=1, device="eth0", instance="node-exporter:9100"} +{__name__="PREFIX1_yhat_lower", for="PREFIX2_query_name_2", custom_label_1="label_name_1", custom_label_2="label_name_2", cpu=1, device="eth0", instance="node-exporter:9100"} +``` + + \ No newline at end of file diff --git a/docs/anomaly-detection/guides/README.md b/docs/anomaly-detection/guides/README.md new file mode 100644 index 0000000000..301ab0c821 --- /dev/null +++ b/docs/anomaly-detection/guides/README.md @@ -0,0 +1,17 @@ +--- +title: Guides +weight: 2 +# sort: 2 +menu: + docs: + identifier: "anomaly-detection-guides" + parent: "anomaly-detection" + weight: 2 + sort: 2 +aliases: + - /anomaly-detection/guides.html +--- + +# Guides + +This section holds guides of how to set up and use VictoriaMetrics Anomaly Detection (or simply [`vmanomaly`](/vmanomaly.html)) service, integrating it with different observability components. \ No newline at end of file diff --git a/docs/guides/guide-vmanomaly-vmalert.md b/docs/anomaly-detection/guides/guide-vmanomaly-vmalert.md similarity index 99% rename from docs/guides/guide-vmanomaly-vmalert.md rename to docs/anomaly-detection/guides/guide-vmanomaly-vmalert.md index 196219309b..3918588af6 100644 --- a/docs/guides/guide-vmanomaly-vmalert.md +++ b/docs/anomaly-detection/guides/guide-vmanomaly-vmalert.md @@ -1,12 +1,13 @@ --- -weight: 6 +weight: 1 +~# sort: 1 title: Getting started with vmanomaly menu: docs: - parent: "guides" - weight: 6 + parent: "anomaly-detection-guides" + weight: 1 aliases: -- /guides/guide-vmanomaly-vmalert.html +- /anomaly-detection/guides/guide-vmanomaly-vmalert.html --- # Getting started with vmanomaly diff --git a/docs/guides/guide-vmanomaly-vmalert_alert-rule.webp b/docs/anomaly-detection/guides/guide-vmanomaly-vmalert_alert-rule.webp similarity index 100% rename from docs/guides/guide-vmanomaly-vmalert_alert-rule.webp rename to docs/anomaly-detection/guides/guide-vmanomaly-vmalert_alert-rule.webp diff --git a/docs/guides/guide-vmanomaly-vmalert_alerts-firing.webp b/docs/anomaly-detection/guides/guide-vmanomaly-vmalert_alerts-firing.webp similarity index 100% rename from docs/guides/guide-vmanomaly-vmalert_alerts-firing.webp rename to docs/anomaly-detection/guides/guide-vmanomaly-vmalert_alerts-firing.webp diff --git a/docs/guides/guide-vmanomaly-vmalert_anomaly-score.webp b/docs/anomaly-detection/guides/guide-vmanomaly-vmalert_anomaly-score.webp similarity index 100% rename from docs/guides/guide-vmanomaly-vmalert_anomaly-score.webp rename to docs/anomaly-detection/guides/guide-vmanomaly-vmalert_anomaly-score.webp diff --git a/docs/guides/guide-vmanomaly-vmalert_docker-compose.webp b/docs/anomaly-detection/guides/guide-vmanomaly-vmalert_docker-compose.webp similarity index 100% rename from docs/guides/guide-vmanomaly-vmalert_docker-compose.webp rename to docs/anomaly-detection/guides/guide-vmanomaly-vmalert_docker-compose.webp diff --git a/docs/guides/guide-vmanomaly-vmalert_files.webp b/docs/anomaly-detection/guides/guide-vmanomaly-vmalert_files.webp similarity index 100% rename from docs/guides/guide-vmanomaly-vmalert_files.webp rename to docs/anomaly-detection/guides/guide-vmanomaly-vmalert_files.webp diff --git a/docs/guides/guide-vmanomaly-vmalert_node-cpu-rate-graph.webp b/docs/anomaly-detection/guides/guide-vmanomaly-vmalert_node-cpu-rate-graph.webp similarity index 100% rename from docs/guides/guide-vmanomaly-vmalert_node-cpu-rate-graph.webp rename to docs/anomaly-detection/guides/guide-vmanomaly-vmalert_node-cpu-rate-graph.webp diff --git a/docs/guides/guide-vmanomaly-vmalert_yhat-lower-upper.webp b/docs/anomaly-detection/guides/guide-vmanomaly-vmalert_yhat-lower-upper.webp similarity index 100% rename from docs/guides/guide-vmanomaly-vmalert_yhat-lower-upper.webp rename to docs/anomaly-detection/guides/guide-vmanomaly-vmalert_yhat-lower-upper.webp diff --git a/docs/guides/guide-vmanomaly-vmalert_yhat.webp b/docs/anomaly-detection/guides/guide-vmanomaly-vmalert_yhat.webp similarity index 100% rename from docs/guides/guide-vmanomaly-vmalert_yhat.webp rename to docs/anomaly-detection/guides/guide-vmanomaly-vmalert_yhat.webp diff --git a/docs/vmanomaly.md b/docs/vmanomaly.md index 17f10f355f..31dd1a200f 100644 --- a/docs/vmanomaly.md +++ b/docs/vmanomaly.md @@ -12,12 +12,13 @@ aliases: # vmanomaly -**_vmanomaly is a part of [enterprise package](https://docs.victoriametrics.com/enterprise.html). You need to request a [free trial license](https://victoriametrics.com/products/enterprise/trial/) for evaluation. -Please [contact us](https://victoriametrics.com/contact-us/) to find out more._** +**_vmanomaly_ is a part of [enterprise package](https://docs.victoriametrics.com/enterprise.html). You need to request a [free trial license](https://victoriametrics.com/products/enterprise/trial/) for evaluation.** + +Please head to to [Anomaly Detection section](/anomaly-detection) to find out more. ## About -**VictoriaMetrics Anomaly Detection** is a service that continuously scans VictoriaMetrics time +**VictoriaMetrics Anomaly Detection** (or shortly, `vmanomaly`) is a service that continuously scans VictoriaMetrics time series and detects unexpected changes within data patterns in real-time. It does so by utilizing user-configurable machine learning models. @@ -48,9 +49,10 @@ processes in parallel, each using its own config. ## Models -Currently, vmanomaly ships with a few common models: +Currently, vmanomaly ships with a set of built-in models: +> For a detailed description, see [model section](/anomaly-detection/components/models) -1. **ZScore** +1. [**ZScore**](/anomaly-detection/components/models/models.html#z-score) _(useful for testing)_ @@ -58,7 +60,7 @@ Currently, vmanomaly ships with a few common models: from time-series mean (straight line). Keeps only two model parameters internally: `mean` and `std` (standard deviation). -1. **Prophet** +1. [**Prophet**](/anomaly-detection/components/models/models.html#prophet) _(simplest in configuration, recommended for getting starting)_ @@ -72,35 +74,40 @@ Currently, vmanomaly ships with a few common models: See [Prophet documentation](https://facebook.github.io/prophet/) -1. **Holt-Winters** +1. [**Holt-Winters**](/anomaly-detection/components/models/models.html#holt-winters) Very popular forecasting algorithm. See [statsmodels.org documentation]( https://www.statsmodels.org/stable/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing.html) for Holt-Winters exponential smoothing. -1. **Seasonal-Trend Decomposition** +1. [**Seasonal-Trend Decomposition**](/anomaly-detection/components/models/models.html#seasonal-trend-decomposition) Extracts three components: season, trend, and residual, that can be plotted individually for easier debugging. Uses LOESS (locally estimated scatterplot smoothing). See [statsmodels.org documentation](https://www.statsmodels.org/dev/examples/notebooks/generated/stl_decomposition.html) for LOESS STD. -1. **ARIMA** +1. [**ARIMA**](/anomaly-detection/components/models/models.html#arima) Commonly used forecasting model. See [statsmodels.org documentation](https://www.statsmodels.org/stable/generated/statsmodels.tsa.arima.model.ARIMA.html) for ARIMA. -1. **Rolling Quantile** +1. [**Rolling Quantile**](/anomaly-detection/components/models/models.html#rolling-quantile) A simple moving window of quantiles. Easy to use, easy to understand, but not as powerful as other models. -1. **Isolation Forest** +1. [**Isolation Forest**](/anomaly-detection/components/models/models.html#isolation-forest-multivariate) Detects anomalies using binary trees. It works for both univariate and multivariate data. Be aware of [the curse of dimensionality](https://en.wikipedia.org/wiki/Curse_of_dimensionality) in the case of multivariate data - we advise against using a single model when handling multiple time series *if the number of these series significantly exceeds their average length (# of data points)*. The algorithm has a linear time complexity and a low memory requirement, which works well with high-volume data. See [scikit-learn.org documentation](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html) for Isolation Forest. +1. [**MAD (Median Absolute Deviation)**](anomaly-detection/components/models/models.html#mad-median-absolute-deviation) + + A robust method for anomaly detection that is less sensitive to outliers in data compared to standard deviation-based models. It considers a point as an anomaly if the absolute deviation from the median is significantly large. + + ### Examples For example, here’s how Prophet predictions could look like on a real-data example (Prophet auto-detected seasonality interval): @@ -126,20 +133,22 @@ optionally preserving labels). ## Usage -> Starting from v1.5.0, vmanomaly requires a license key to run. You can obtain a trial license key [here](https://victoriametrics.com/products/enterprise/trial/). +> Starting from [v1.5.0](/anomaly-detection/CHANGELOG.html#v150), vmanomaly requires a license key to run. You can obtain a trial license key [here](https://victoriametrics.com/products/enterprise/trial/). -> See [Getting started guide](https://docs.victoriametrics.com/guides/guide-vmanomaly-vmalert.html). +> See [Getting started guide](anomaly-detection/guides/guide-vmanomaly-vmalert.html). ### Config file There are 4 required sections in config file: -* `scheduler` - defines how often to run and make inferences, as well as what timerange to use to train the model. -* `model` - specific model parameters and configurations, -* `reader` - how to read data and where it is located -* `writer` - where and how to write the generated output. +* [`scheduler`](/anomaly-detection/components/scheduler.html) - defines how often to run and make inferences, as well as what timerange to use to train the model. +* [`model`](/anomaly-detection/components/models) - specific model parameters and configurations, +* [`reader`](/anomaly-detection/components/reader.html) - how to read data and where it is located +* [`writer`](/anomaly-detection/components/writer.html) - where and how to write the generated output. [`monitoring`](#monitoring) - defines how to monitor work of *vmanomaly* service. This config section is *optional*. +> For a detailed description, see [config sections](/anomaly-detection/docs) + #### Config example Here is an example of config file that will run FB Prophet model, that will be retrained every 2 hours on 14 days of previous data. It will generate inference (including `anomaly_score` metric) every 1 minute. @@ -171,6 +180,8 @@ writer: *vmanomaly* can be monitored by using push or pull approach. It can push metrics to VictoriaMetrics or expose metrics in Prometheus exposition format. +> For a detailed description, see [monitoring section](/anomaly-detection/components/monitoring.html) + #### Push approach *vmanomaly* can push metrics to VictoriaMetrics single-node or cluster version.